Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: d617d0ec70
Fetching contributors…

Cannot retrieve contributors at this time

148 lines (126 sloc) 3.292 kb
-module(irc_server).
%% very simple IRC server
%% Messages
%% USER UUUU : Real name
%% NICK NNNNN: real name
%% PRIVMSG Channel Text
-compile(export_all).
server() ->
process_flag(traop_exit, true),
S = self(),
{ok, Listen} = gen_tcp:listen(1234, [{packet,0},
{reuseaddr,true},
{active, true}]),
spawn_link(fun() -> par_connect(Listen, Self) end),
loop(Listen, dict:new()).
%% The state of the main server
%% is defined by a Key-Value store
%% Keys Value
%% Pid => #nick{nick=Nick,data="string"}
%% {user,Nick} => #user{pid=Pid, groups= [<<G>>]}
%% <<G>> => #group{mod="string", leader=Pid, pids=[Pid]}
loop(Listen, D) ->
receive
{connect, Pid} ->
%% Got a connection
D1 = dict:store(Pid, #nick{}, D),
Self = self(),
spawn_link(fun() -> par_connect(Listen, Self) end),
loop(Listen, D1);
{user, Pid, Data} ->
D1 = set_user_data(Pid, Data, D),
loop(Listen, D1);
{nick, Pid, Nick, Full} ->
D1 = change_nick(Pid, Full, D),
loop(Listen, D1);
{join, Pid, Group} ->
D1 = join_group(Pid, Group, D),
loop(Listen, D1);
end.
join_group(Pid, G, D) when is_binary(G) ->
try
begin
{ok, #nick{nick=N}} = dict:find(Pid, D),
{ok, U#user{groups=Gs}} = dict:find({user,N}, D),
case member(G, Gs) of
true ->
%% already a member nothing to do
D;
false ->
%% add the user to the groups
D1 = dict:store({user,N}, U#user{groups=[G|Gs]}),
case find(G, D) of
{ok, G1#group{pid=Pids}} ->
case member(Pid, Pids) of
true -> a
end
end
end
end
catch a ->
b
end.
set_user_data(Pid, Data, D) ->
case dict:find(Usr={user,Nick}, D) of
{ok, U = #user{data=undefined}} ->
U1 = U#user{data=Data],
store(Pid, Usr, U1);
D;
{ok, _} ->
%% some other Pid owns the nick
Pid ! {error, "Cannot change user"},
D;
error ->
%% zombie
exit(Pid, die),
D
end.
change_nick(Pid, Fill, D) ->
case dict:find({user,Nick}, D) of
{ok, #user{pid=Pid}} ->
%% strange this user is trying to change
%% to the same name ...
D;
{ok, _} ->
%% some other Pid owns the nick
Pid ! {send,"NICK in use~n"},
D;
error ->
%% The nick is unused
%% find out what we know about this user
case dicts:find(Pid, D) of
{ok, N} ->
OldNick = N#user.nick,
Groups = N#user.groups,
D1 = dict:store(Pid, #nick{nick=Nick,
full=Full}, D),
case OldNick of
undefined ->
void;
_ ->
broadcast_to_groups(Groups,
{OldNick,{changed,Nick}})
end,
D1;
error ->
%% zomby
exit(Pid, kill),
D
end
end.
broadcast_to_groups(Gs, M) ->
foreach(fun(G) ->
Pids = G#group.pids,
foreach(fun(Pid) ->
Pid ! {send, M}
end, Pids)
end, Gs).
%% hoorid code ...
%% {Nick, Pid} %% = Pids
%% {Nick, G} %% = Groups
broadcast_to_groups(G, Pids, Groups, Msg) ->
[ {Pid, Msg} || {Nick,G1} <- Groups, G1 =:= G, {Nick, Pid} <- Ps].
message(ToNick, Msg, Pids) ->
[ {Pid,Msg} || {Nick, Pid} <- Pids, Nick =:= ToNick].
update_nick(OldNick, NewNick, Pids, Groups) ->
a.
Jump to Line
Something went wrong with that request. Please try again.