Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -module(client).
- -export([handle/2, initial_state/2]).
- -include_lib("./defs.hrl").
- %% inititial_state/2 and handle/2 are used togetger with the genserver module,
- %% explained in the lecture about Generic server.
- %% Produce initial state
- initial_state(Nick, GUIName) ->
- #client_st{ gui = GUIName, nickname = Nick, connected = false, channels = [] }.
- %% ---------------------------------------------------------------------------
- %% handle/2 handles each kind of request from GUI
- %% All requests are processed by handle/2 receiving the request data (and the
- %% current state), performing the needed actions, and returning a tuple
- %% {reply, Reply, NewState}, where Reply is the reply to be sent to the
- %% requesting process and NewState is the new state of the client.
- handle_connect_response(St, Server, Response) when Response==ok ->
- { reply, Response, St#client_st{ server = Server, connected = true} };
- handle_connect_response(St, _Server, Response) ->
- { reply, Response, St }.
- handle_disconnect_response(St, Response) when Response==ok ->
- { reply, Response, St#client_st{ connected = false } };
- handle_disconnect_response(St, Response) ->
- { reply, Response, St }.
- handle_join_response(St, Channel, Response) when Response==ok ->
- NewChannels = St#client_st.channels ++ [Channel],
- { reply, Response, St#client_st{ channels = NewChannels } };
- handle_join_response(St, _Channel, Response) ->
- { reply, Response, St }.
- handle_leave_response(St, Channel, Response) when Response==ok ->
- NewChannels = St#client_st.channels -- [Channel],
- { reply, Response, St#client_st{ channels = NewChannels } };
- handle_leave_response(St, _Channel, Response) ->
- { reply, Response, St }.
- handle_join(St, _Channel, true) ->
- { reply, {error, user_already_joined, "Already joined"}, St };
- handle_join(St, Channel, false) ->
- Response = genserver:request(St#client_st.server, { join, self(), Channel }),
- handle_join_response(St, Channel, Response).
- %% Connect to server (but already connected)
- handle(St, {connect, _Server}) when St#client_st.connected==true ->
- {reply, {error, user_already_connected, "Client already connected"}, St};
- %% Connect to server (and not already connected)
- handle(St, {connect, Server}) when St#client_st.connected==false ->
- try
- ServerAtom = list_to_atom(Server),
- handle_connect_response(St, ServerAtom, genserver:request(ServerAtom, { connect, self(), St#client_st.nickname }))
- catch
- _:_Reason -> {reply, {error, server_not_reached, "Could not reach server"}, St}
- end;
- %% Disconnect from server (when not connected)
- handle(St, disconnect) when St#client_st.connected==false ->
- {reply, {error, user_not_connected, "Not connected"}, St};
- %% Disconnect from server (but joined to a channel)
- handle(St, disconnect) when length(St#client_st.channels)>0 ->
- { reply, {error, leave_channels_first, "Leave channels first" }, St };
- %% Disconnect from server
- handle(St, disconnect) ->
- Response = genserver:request(St#client_st.server, { disconnect, self() }),
- handle_disconnect_response(St, Response);
- % Join channel (when not connected)
- handle(St, {join, _Channel}) when St#client_st.connected==false ->
- { reply, {error, user_not_connected, "Not connected to a server"}, St };
- % Join channel (when connected)
- handle(St, {join, Channel}) ->
- handle_join(St, Channel, lists:member(Channel, St#client_st.channels));
- %% Leave channel
- handle(St, {leave, Channel}) ->
- ChannelAtomName = re:replace(Channel, "#", "channel_", [global, {return, list}]),
- ChannelAtom = list_to_atom(ChannelAtomName),
- Response = genserver:request(ChannelAtom, { leave, self() }),
- handle_leave_response(St, Channel, Response);
- % Sending messages
- handle(St, {msg_from_GUI, Channel, Msg}) ->
- ChannelAtomName = re:replace(Channel, "#", "channel_", [global, {return, list}]),
- ChannelAtom = list_to_atom(ChannelAtomName),
- Response = genserver:request(ChannelAtom, { msg, self(), Msg }),
- { reply, Response, St };
- %% Get current nick
- handle(St, whoami) ->
- {reply, St#client_st.nickname, St} ;
- %% Change nick (but not allowed when connected)
- handle(St, {nick, _Nick}) when St#client_st.connected==true ->
- {reply, {error, user_already_connected, "Already connected"}, St} ;
- %% Change nick (and is allowed)
- handle(St, {nick, Nick}) when St#client_st.connected==false ->
- {reply, ok, St#client_st{nickname = Nick}} ;
- %% Incoming message
- handle(St = #client_st { gui = GUIName }, {incoming_msg, Channel, Name, Msg}) ->
- gen_server:call(list_to_atom(GUIName), {msg_to_GUI, Channel, Name++"> "++Msg}),
- {reply, ok, St};
- %% Incoming task
- handle(St, {incoming_task, DestinationPid, Task}) ->
- %% Execute the task!
- Result = Task(),
- %% Send result to whoever requested the work
- DestinationPid ! {task_result, self(), Result},
- {reply, ok, St}.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement