-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchatroom.erl
68 lines (59 loc) · 2.61 KB
/
chatroom.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
-module(chatroom).
-include_lib("./defs.hrl").
-export([start_chatroom/1]).
-spec start_chatroom(_ChatName) -> _.
-spec loop(_State) -> _.
-spec do_register(_State, _Ref, _ClientPID, _ClientNick) -> _NewState.
-spec do_unregister(_State, _ClientPID) -> _NewState.
-spec do_update_nick(_State, _ClientPID, _NewNick) -> _NewState.
-spec do_propegate_message(_State, _Ref, _ClientPID, _Message) -> _NewState.
start_chatroom(ChatName) ->
loop(#chat_st{name = ChatName,
registrations = maps:new(), history = []}),
ok.
loop(State) ->
NewState =
receive
%% Server tells this chatroom to register a client
{_ServerPID, Ref, register, ClientPID, ClientNick} ->
do_register(State, Ref, ClientPID, ClientNick);
%% Server tells this chatroom to unregister a client
{_ServerPID, _Ref, unregister, ClientPID} ->
do_unregister(State, ClientPID);
%% Server tells this chatroom to update the nickname for a certain client
{_ServerPID, _Ref, update_nick, ClientPID, NewNick} ->
do_update_nick(State, ClientPID, NewNick);
%% Client sends a new message to the chatroom, and the chatroom must
%% propegate to other registered clients
{ClientPID, Ref, message, Message} ->
do_propegate_message(State, Ref, ClientPID, Message);
{TEST_PID, get_state} ->
TEST_PID!{get_state, State},
loop(State)
end,
loop(NewState).
%% This function should register a new client to this chatroom
do_register(State, Ref, ClientPID, ClientNick) ->
NewState = State#chat_st{registrations = maps:put(ClientPID, ClientNick, State#chat_st.registrations)},
ClientPID!{self(), Ref, connect, State#chat_st.history},
NewState
.
%% This function should unregister a client from this chatroom
do_unregister(State, ClientPID) ->
NewState = State#chat_st{registrations = maps:remove(ClientPID, State#chat_st.registrations)},
NewState
.
%% This function should update the nickname of specified client.
do_update_nick(State, ClientPID, NewNick) ->
NewState = State#chat_st{registrations = maps:update(ClientPID, NewNick, State#chat_st.registrations)},
NewState.
%% This function should update all clients in chatroom with new message
%% (read assignment specs for details)
do_propegate_message(State, Ref, ClientPID, Message) ->
ClientPID!{self(), Ref, ack_msg},
ClientNick = maps:get(ClientPID, State#chat_st.registrations),
ReceivingPids = maps:keys(maps:remove(ClientPID, State#chat_st.registrations)),
[Pid!{request, self(), Ref,{incoming_msg, ClientNick, State#chat_st.name, Message}} || Pid <- ReceivingPids],
NewState = State#chat_st{history = State#chat_st.history++[{ClientNick, Message}]},
NewState
.