Skip to content

Instantly share code, notes, and snippets.

@Mani-RRI
Forked from ingrid/mini_chat.erl
Created December 28, 2018 09:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mani-RRI/bd82e2fc00e7b3882e1d3ef6fee77ebe to your computer and use it in GitHub Desktop.
Save Mani-RRI/bd82e2fc00e7b3882e1d3ef6fee77ebe to your computer and use it in GitHub Desktop.
Erlang Chat
-module(mini_chat).
-compile(export_all).
-define(ACTIVE_OPTIONS, [{reuseaddr, true}]).
% Commands start with "/", char 47
is_command(Str) -> hd(Str) =:= 47.
chatroom(Users) ->
process_flag(trap_exit, true),
receive
{users, Requester} ->
io:format("~p~n", [Users]),
Requester ! Users,
chatroom(Users);
{join, Username, Pid} ->
link(Pid),
self() ! {dispatch_msg, "SYSTEM", string:concat(Username, " has joined the channel.\n")},
chatroom([{Username, Pid} | Users]);
{remove, User} ->
chatroom(Users -- [User]);
{dispatch_msg, From, Msg} ->
case lists:keyfind(From, 1, Users) of
{FromName, _FromPid} = User ->
FormatMsg = io_lib:format(string:join(["~s: ", Msg], ""),
[FromName]),
F = fun({_,Pid}) -> Pid ! {message, FormatMsg} end,
Rest = lists:delete(User, Users),
lists:foreach(F, Rest);
false ->
ok
end,
chatroom(Users);
stop ->
ok
end.
user(Username) ->
chat ! {join, Username, self()},
user(Username, chat).
user(Username, Chatroom) ->
receive
{send, Msg} ->
Chatroom ! {dispatch_msg, Username, Msg},
user(Username, Chatroom);
{message, Msg} ->
io:fwrite(Msg),
user(Username, Chatroom)
end.
tcp_user(Socket) ->
receive
{tcp, Socket, "/nick " ++ Username} ->
tcp_user(Socket, string:strip(Username, right, $\n));
{tcp, Socket, _Data} ->
gen_tcp:send(Socket, "Set a nickname with /nick.\n"),
tcp_user(Socket)
end.
tcp_user(Socket, Username) ->
chat ! {join, Username, self()},
tcp_user(Socket, Username, chat).
tcp_user(Socket, Username, Chatroom) ->
receive
{tcp, Socket, Data} ->
Chatroom ! {dispatch_msg, Username, Data},
tcp_user(Socket, Username, Chatroom);
{message, Msg} ->
gen_tcp:send(Socket, lists:flatten(Msg)),
tcp_user(Socket, Username, Chatroom)
end.
listen() ->
{ok, LSock} = gen_tcp:listen(6667, ?ACTIVE_OPTIONS),
listen(LSock).
listen(LSock) ->
{ok, Socket} = gen_tcp:accept(LSock),
TcpUser = spawn(?MODULE, tcp_user, [Socket]),
gen_tcp:controlling_process(Socket, TcpUser),
listen(LSock).
start() ->
register(tcp, spawn(?MODULE, listen, [])),
register(chat, spawn(?MODULE, chatroom, [[{"SYSTEM", spawn(fun() -> timer:sleep(infinity) end)}]])).
stop() ->
exit(whereis(tcp), kill),
exit(whereis(chat), kill).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment