Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Provide a nick registry and use it to handle nick clashes.

  • Loading branch information...
commit 3cd9a61d0e9ea0624568e819f7217a291ed7eaba 1 parent dde9d77
@jlouis jlouis authored
View
8 src/pony_client.erl
@@ -137,7 +137,13 @@ handle_message(Prefix, Command, Args, #state { nickname = CurNick } = State) ->
send_numeric('ERR_NONICKNAMEGIVEN', [pony:me(), CurNick]),
State;
{<<>>, nick, [NickName]} ->
- State#state { nickname = NickName };
+ case pony_nick_srv:register(NickName) of
+ ok ->
+ State#state { nickname = NickName };
+ nick_in_use ->
+ send_numeric('ERR_ERRONEUSNICKNAME', [pony:me(), CurNick]),
+ State
+ end;
{<<>>, user, L} when is_list(L), length(L) < 4 ->
send_numeric('ERR_NEEDMOREPARAMS', [pony:me(), CurNick, "USER"]),
State;
View
2  src/pony_core_sup.erl
@@ -24,5 +24,5 @@ start_link() ->
%% ===================================================================
init([]) ->
- {ok, { {one_for_one, 5, 10}, []} }.
+ {ok, { {one_for_one, 5, 10}, [?CHILD(pony_nick_srv, worker)]} }.
View
96 src/pony_nick_srv.erl
@@ -0,0 +1,96 @@
+%%%-------------------------------------------------------------------
+%%% @author Jesper Louis Andersen <>
+%%% @copyright (C) 2012, Jesper Louis Andersen
+%%% @doc A Nick Registry handler
+%%%
+%%% @end
+%%% Created : 4 Jul 2012 by Jesper Louis Andersen <>
+%%%-------------------------------------------------------------------
+-module(pony_nick_srv).
+
+-behaviour(gen_server).
+
+%% API
+-export([start_link/0, register/1, unregister/1]).
+
+%% gen_server callbacks
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-define(TAB, pony_nick_registry).
+-define(SERVER, ?MODULE).
+
+-record(state, {}).
+
+%%%===================================================================
+
+%% @doc
+%% Starts the server
+%% @end
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+register(Name) ->
+ case ets:lookup(?TAB, Name) of
+ [] ->
+ gen_server:call(?SERVER, {register, Name});
+ [_|_] ->
+ nick_in_use
+ end.
+
+unregister(Name) ->
+ gen_server:call(?SERVER, {unregister, Name}).
+
+%%%===================================================================
+
+
+%% @private
+init([]) ->
+ ets:new(?TAB, [named_table, protected]),
+ {ok, #state{}}.
+
+%% @private
+handle_call({register, Name}, {Pid, _Tag}, State) ->
+ case ets:lookup(?TAB, Name) of
+ [] ->
+ Ref = erlang:monitor(process, Pid),
+ ets:insert(?TAB, {Name, Ref}),
+ {reply, ok, State};
+ [_|_] ->
+ {reply, nick_in_use, State}
+ end;
+handle_call({unregister, Name}, _From, State) ->
+ case ets:lookup(?TAB, Name) of
+ [{Name, MonitorRef}] ->
+ erlang:demonitor(MonitorRef, [flush]),
+ ets:delete(?TAB, Name),
+ {reply, ok, State};
+ [] ->
+ {reply, {error, {no_such_nick, Name}}, State}
+ end;
+handle_call(Request, _From, State) ->
+ lager:warning("Unknown call request: ~p", [Request]),
+ Reply = ok,
+ {reply, Reply, State}.
+
+%% @private
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+%% @private
+handle_info({'DOWN', Ref, process, _Pid, _Reason}, State) ->
+ [{Name, Ref}] = ets:match_object(?TAB, {'_', Ref}),
+ ets:delete(?TAB, Name),
+ {noreply, State};
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%% @private
+terminate(_Reason, _State) ->
+ ok.
+
+%% @private
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%===================================================================
Please sign in to comment.
Something went wrong with that request. Please try again.