Skip to content

Instantly share code, notes, and snippets.

@zachallaun
Created July 21, 2012 20:42
Show Gist options
  • Save zachallaun/3157095 to your computer and use it in GitHub Desktop.
Save zachallaun/3157095 to your computer and use it in GitHub Desktop.

Here's some erlang.

-module(mini_chat).
-compile(export_all).

-define(ACTIVE_OPTIONS, [{reuseaddr, true}]).

% Commands start with "/", char 47
is_command(Str) -> hd(Str) =:= 47.

chatroom(Users) ->
    receive
        {users, Requester} ->
            io:format("~p~n", [Users]),
            Requester ! Users,
            chatroom(Users);
        {join, Username, Pid} ->
            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} ->
            io:format(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, [[]])).

stop() ->
    exit(whereis(chat), kill),
    exit(whereis(tcp), kill).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment