Advertisement
Guest User

client.erl

a guest
Mar 7th, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 4.92 KB | None | 0 0
  1. -module(client).
  2. -export([handle/2, initial_state/2]).
  3. -include_lib("./defs.hrl").
  4.  
  5. %% inititial_state/2 and handle/2 are used togetger with the genserver module,
  6. %% explained in the lecture about Generic server.
  7.  
  8. %% Produce initial state
  9. initial_state(Nick, GUIName) ->
  10.     #client_st{ gui = GUIName, nickname = Nick, connected = false, channels = [] }.
  11.  
  12. %% ---------------------------------------------------------------------------
  13.  
  14. %% handle/2 handles each kind of request from GUI
  15.  
  16. %% All requests are processed by handle/2 receiving the request data (and the
  17. %% current state), performing the needed actions, and returning a tuple
  18. %% {reply, Reply, NewState}, where Reply is the reply to be sent to the
  19. %% requesting process and NewState is the new state of the client.
  20.  
  21. handle_connect_response(St, Server, Response) when Response==ok ->
  22.     { reply, Response, St#client_st{ server = Server, connected = true} };
  23.  
  24. handle_connect_response(St, _Server, Response) ->
  25.     { reply, Response, St }.
  26.  
  27. handle_disconnect_response(St, Response) when Response==ok ->
  28.     { reply, Response, St#client_st{ connected = false } };
  29.  
  30. handle_disconnect_response(St, Response) ->
  31.     { reply, Response, St }.
  32.  
  33. handle_join_response(St, Channel, Response) when Response==ok ->
  34.     NewChannels = St#client_st.channels ++ [Channel],
  35.     { reply, Response, St#client_st{ channels = NewChannels } };
  36.  
  37. handle_join_response(St, _Channel, Response) ->
  38.     { reply, Response, St }.
  39.  
  40. handle_leave_response(St, Channel, Response) when Response==ok ->
  41.     NewChannels = St#client_st.channels -- [Channel],
  42.     { reply, Response, St#client_st{ channels = NewChannels } };
  43.  
  44. handle_leave_response(St, _Channel, Response) ->
  45.     { reply, Response, St }.
  46.  
  47. handle_join(St, _Channel, true) ->
  48.     { reply, {error, user_already_joined, "Already joined"}, St };
  49.  
  50. handle_join(St, Channel, false) ->
  51.     Response = genserver:request(St#client_st.server, { join, self(), Channel }),
  52.     handle_join_response(St, Channel, Response).
  53.  
  54. %% Connect to server (but already connected)
  55. handle(St, {connect, _Server}) when St#client_st.connected==true ->
  56.     {reply, {error, user_already_connected, "Client already connected"}, St};
  57.  
  58. %% Connect to server (and not already connected)
  59. handle(St, {connect, Server}) when St#client_st.connected==false ->
  60.     try
  61.         ServerAtom = list_to_atom(Server),
  62.         handle_connect_response(St, ServerAtom, genserver:request(ServerAtom, { connect, self(), St#client_st.nickname }))
  63.     catch
  64.         _:_Reason -> {reply, {error, server_not_reached, "Could not reach server"}, St}
  65.     end;
  66.  
  67. %% Disconnect from server (when not connected)
  68. handle(St, disconnect) when St#client_st.connected==false ->
  69.     {reply, {error, user_not_connected, "Not connected"}, St};
  70.  
  71. %% Disconnect from server (but joined to a channel)
  72. handle(St, disconnect) when length(St#client_st.channels)>0 ->
  73.     { reply, {error, leave_channels_first, "Leave channels first" }, St };
  74.  
  75. %% Disconnect from server
  76. handle(St, disconnect) ->
  77.     Response = genserver:request(St#client_st.server, { disconnect, self() }),
  78.     handle_disconnect_response(St, Response);
  79.  
  80. % Join channel (when not connected)
  81. handle(St, {join, _Channel}) when St#client_st.connected==false ->
  82.     { reply, {error, user_not_connected, "Not connected to a server"}, St };
  83.  
  84. % Join channel (when connected)
  85. handle(St, {join, Channel}) ->
  86.     handle_join(St, Channel, lists:member(Channel, St#client_st.channels));
  87.  
  88. %% Leave channel
  89. handle(St, {leave, Channel}) ->
  90.     ChannelAtomName = re:replace(Channel, "#", "channel_", [global, {return, list}]),
  91.     ChannelAtom = list_to_atom(ChannelAtomName),
  92.     Response = genserver:request(ChannelAtom, { leave, self() }),
  93.     handle_leave_response(St, Channel, Response);
  94.  
  95. % Sending messages
  96. handle(St, {msg_from_GUI, Channel, Msg}) ->
  97.     ChannelAtomName = re:replace(Channel, "#", "channel_", [global, {return, list}]),
  98.     ChannelAtom = list_to_atom(ChannelAtomName),
  99.     Response = genserver:request(ChannelAtom, { msg, self(), Msg }),
  100.     { reply, Response, St };
  101.  
  102. %% Get current nick
  103. handle(St, whoami) ->
  104.     {reply, St#client_st.nickname, St} ;
  105.  
  106. %% Change nick (but not allowed when connected)
  107. handle(St, {nick, _Nick}) when St#client_st.connected==true ->
  108.     {reply, {error, user_already_connected, "Already connected"}, St} ;
  109.  
  110. %% Change nick (and is allowed)
  111. handle(St, {nick, Nick}) when St#client_st.connected==false ->
  112.     {reply, ok, St#client_st{nickname = Nick}} ;
  113.  
  114. %% Incoming message
  115. handle(St = #client_st { gui = GUIName }, {incoming_msg, Channel, Name, Msg}) ->
  116.     gen_server:call(list_to_atom(GUIName), {msg_to_GUI, Channel, Name++"> "++Msg}),
  117.     {reply, ok, St};
  118.  
  119. %% Incoming task
  120. handle(St, {incoming_task, DestinationPid, Task}) ->
  121.     %% Execute the task!
  122.     Result = Task(),
  123.     %% Send result to whoever requested the work
  124.     DestinationPid ! {task_result, self(), Result},
  125.     {reply, ok, St}.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement