Solution 11-4

Here is a suggested solution for Étude 11-4.

chatroom.erl

-module(chatroom).
-behaviour(gen_server).
-export([start_link/0]). % convenience call for startup
-export([init/1,
         handle_call/3,
         handle_cast/2,
         handle_info/2,
         terminate/2,
         code_change/3]). % gen_server callbacks

-define(SERVER, ?MODULE). % macro that defines this module as the server

% The server state consists of a list of tuples for each person in chat.
% Each tuple has the format {{UserName, UserServer}, PID of person}

%%% convenience method for startup
start_link() ->
  gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

%%% gen_server callbacks
init([]) ->
  {ok, []}.

%% Check to see if a user name/server pair is unique;
%% if so, add it to the server's state

handle_call({login, UserName, ServerRef}, From, State) ->
  {FromPid, _FromTag} = From,
  case lists:keymember({UserName, ServerRef}, 1, State) of
    true ->
      NewState = State,
      Reply = {error, "User " ++ UserName ++ " already in use."};
    false ->
      NewState = [{{UserName, ServerRef}, FromPid} | State],
      Reply = {ok, "Logged in."}
  end,
  {reply, Reply, NewState};

%% Log out the person sending the message, but only
%% if they're logged in already.

handle_call({logout}, From, State) ->
  {FromPid, _FromTag} = From,
  case lists:keymember(FromPid, 2, State) of
    true ->
      NewState = lists:keydelete(FromPid, 2, State),
      Reply  = {ok, logged_out};
    false ->
      NewState = State,
      Reply = {error, not_logged_in}
  end,
  {reply, Reply, NewState};

%% When receiving a message from a person, ...

Get Études for Erlang now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.