Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 1.-module(chat_server).
- 2.
- 3.-export([start/0,loop/3]).
- 4.
- 5.start() ->
- 6. Pid = spawn(fun() -> loop([],[],[]) end),
- 7. Pid ! {server_up,5555,mod_hbchat},
- 8. Pid ! {server_up,6666,mod_hbchat},
- 9. Pid ! {server_up,7777,mod_hbchat},
- 10. Pid ! {room_up,<<"Room 1">>},
- 11. Pid ! {room_up,<<"Room 2">>},
- 12. Pid ! {room_up,<<"Room 3">>},
- 13. Pid.
- 14.
- 15.loop(Clients,Listeners,Rooms) ->
- 16. receive
- 17.
- 18.%%INTERNAL SERVER FUNCTIONS
- 19. {server_up,Port,Mod} ->
- 20. L = start_listener(Port,Mod,self()),
- 21. loop(Clients,[L|Listeners],Rooms);
- 22.
- 23. {room_up,Name} ->
- 24. R = start_room(Name,self()),
- 25. loop(Clients,Listeners,[{Name,R}|Rooms]);
- 26.
- 27. close_down ->
- 28. lists:foreach(fun(Pid) -> Pid ! close_down end,Listeners),
- 29. lists:foreach(fun({User,Pid}) -> Pid ! close_down end,Clients),
- 30. lists:foreach(fun({Name,Pid}) -> Pid ! close_down end,Rooms);
- 31.
- 32. list_clients ->
- 33. lists:foreach(fun({User,Pid}) -> io:fwrite("~w ~p~n",[User,Pid]) end,Clients),
- 34. loop(Clients,Listeners,Rooms);
- 35.
- 36. upgrade ->
- 37. ?MODULE:loop(Clients,Listeners,Rooms);
- 38.
- 39.%%CLIENT FUNCTIONS
- 40. {new_client,Pid} ->
- 41. loop([{<<>>,Pid}|Clients],Listeners,Rooms);
- 42.
- 43. {broadcast,Message} ->
- 44. lists:foreach(fun({User,Pid}) -> Pid ! {chat,{<<"PRVT">>,<<"Admin">>,Message}} end,Clients),
- 45. loop(Clients,Listeners,Rooms);
- 46.
- 47. {client_disconnect,Client} ->
- 48. L = lists:delete(Client,Clients),
- 49. loop(L,Listeners,Rooms);
- 50.
- 51.%%CLIENT -> SERVER HANDLERS
- 52. {server,{User1,Pid},{authenticate,User2,Pass}} ->
- 53. L = lists:delete({User1,Pid},Clients),
- 54. Pid ! {authenticated,User2},
- 55. loop([{User2,Pid}|L],Listeners,Rooms);
- 56.
- 57.%%CLIENT -> PRIVATE HANDLES
- 58.
- 59. {private,{FUser,FPid},{message,To,Message}} ->
- 60. case lists:keyfind(To,1,Clients) of
- 61. {_,Pid} ->
- 62. Pid ! {private,{message,FUser,Message}};
- 63. false ->
- 64. error
- 65. end,
- 66. loop(Clients,Listeners,Rooms);
- 67.
- 68.%%CLIENT -> ROOM HANDLES
- 69.
- 70. {room,{FUser,FPid},{join,Room}} ->
- 71. case lists:keyfind(Room,1,Rooms) of
- 72. {_,Pid} ->
- 73. Pid ! {room,{FUser,FPid},join};
- 74. false ->
- 75. error
- 76. end,
- 77. loop(Clients,Listeners,Rooms)
- 78.
- 79. end.
- 80.
- 81.start_listener(Port,Mod,Server) ->
- 82. Pid = Mod:start_listener(Port,Server),
- 83. Pid.
- 84.
- 85.start_room(Name,Server) ->
- 86. Pid = chat_room:start(Name,Server),
- 87. Pid.
- 88.
- 89.-module(chat_client).
- 90.
- 91.-export([start/3]).
- 92.
- 93.-record(state,
- 94. {state=new,
- 95. username = <<>>,
- 96. room}).
- 97.
- 98.start(Socket,Mod,Server) ->
- 99. loop(Socket,Mod,Server,#state{}).
- 100.
- 101.loop(Socket,HandlerMod,Server,State) ->
- 102. receive
- 103. {tcp,Socket,Data} ->
- 104. inet:setopts(Socket,[binary,{active,once},{packet,line}]),
- 105. io:fwrite(Data),
- 106. Packet = HandlerMod:handle_from_client(Data),
- 107. handle(Server,State,Packet),
- 108. loop(Socket,HandlerMod,Server,State);
- 109.
- 110. {tcp_closed,Socket} ->
- 111. Server ! {client_disconnect,{State#state.username,self()}};
- 112.
- 113. close_down ->
- 114. gen_tcp:send(Socket,"Sorry, the server is going down for maintenance."),
- 115. gen_tcp:close(Socket);
- 116.
- 117. {authenticated,User} ->
- 118. loop(Socket,HandlerMod,Server,State#state{username=User,state=authenticated});
- 119.
- 120. {room_joined,{Room,RPid}} ->
- 121. loop(Socket,HandlerMod,Server,State#state{room={Room,RPid},state=room});
- 122.
- 123. {private,Data} ->
- 124. Packet = HandlerMod:handle_from_server(private,Data),
- 125. gen_tcp:send(Socket,Packet),
- 126. loop(Socket,HandlerMod,Server,State);
- 127.
- 128. {room,Data} ->
- 129. Packet = HandlerMod:handle_from_server(room,Data),
- 130. gen_tcp:send(Socket,Packet),
- 131. loop(Socket,HandlerMod,Server,State);
- 132.
- 133. Other ->
- 134. io:fwrite("~p",[Other]),
- 135. loop(Socket,HandlerMod,Server,State)
- 136. end.
- 137.
- 138.handle(Server,State,{server,Message}) ->
- 139. Server ! {server,{State#state.username,self()},Message},
- 140. handled;
- 141.
- 142.handle(Server,State,{private,Message}) ->
- 143. Server ! {private,{State#state.username,self()},Message},
- 144. handled;
- 145.
- 146.handle(Server,State,{room,Message}) ->
- 147. case Message of
- 148. {join,Room} ->
- 149. Server ! {room,{State#state.username,self()},Message};
- 150. Other ->
- 151. {_,RPid} = State#state.room,
- 152. RPid ! {room,{State#state.username,self()},Message}
- 153. end,
- 154. handled;
- 155.
- 156.handle(Server,State,error) ->
- 157. handled.
- 158.
- 159.-module(chat_room).
- 160.
- 161.-export([start/2]).
- 162.
- 163.-record(state,
- 164. {clients=[],
- 165. roomname = <<>>
- 166. }).
- 167.
- 168.start(Name,Server) ->
- 169. Pid = spawn(fun() -> loop(Server,#state{roomname=Name}) end),
- 170. Pid.
- 171.
- 172.loop(Server,State) ->
- 173. receive
- 174. {room,{FUser,FPid},join} ->
- 175. FPid ! {room_joined,{State#state.roomname,self()}},
- 176. loop(Server,State#state{clients=[{FUser,FPid}|State#state.clients]});
- 177. {room,{FUser,FPid},{chat,Message}} ->
- 178. lists:foreach(fun({User,Pid}) -> Pid ! {room,{chat,FUser,Message}} end,State#state.clients),
- 179. loop(Server,State);
- 180. close_down ->
- 181. closed
- 182. end.
- 183.
- 184.-module(mod_hbchat).
- 185.
- 186.-export([start_listener/2,handle_from_server/2,handle_from_client/1]).
- 187.
- 188.start_listener(Port,Server) ->
- 189. Pid = mod_hbchat_listener:start(Port,Server),
- 190. Pid.
- 191.
- 192.%%HANDLE FROM SERVER
- 193.handle_from_server(private,{message,From,Message}) ->
- 194. Data = <<"PRVT ",From/binary," ",Message/binary,"\x0D\x0A">>,
- 195. Data;
- 196.
- 197.handle_from_server(room,{chat,From,Message}) ->
- 198. Data = <<"ROOM ",From/binary," ",Message/binary,"\x0D\x0A">>,
- 199. Data.
- 200.
- 201.%%HANDLE FROM CLIENTS
- 202.handle_from_client(Data) when size(Data) > 6 ->
- 203. <<Type:4/binary,_:1/binary,TheRest/binary>> = Data,
- 204. handle(Type,TheRest);
- 205.
- 206.handle_from_client(Data) when size(Data) =:= 6 ->
- 207. <<Type:4/binary,_/binary>> = Data,
- 208. handle(Type,<<>>);
- 209.
- 210.handle_from_client(Data) when size(Data) < 6 ->
- 211. error.
- 212.
- 213.handle(<<"AUTH">>,Packet) ->
- 214. L = parse(Packet,2),
- 215. User = lists:nth(1,L),
- 216. Pass = lists:nth(2,L),
- 217. {server,{authenticate,User,Pass}};
- 218.
- 219.handle(<<"PRVT">>,Packet) ->
- 220. L = parse(Packet,2),
- 221. To = lists:nth(1,L),
- 222. Message = lists:nth(2,L),
- 223. {private,{message,To,Message}};
- 224.
- 225.handle(<<"JOIN">>,Packet) ->
- 226. L = parse(Packet,1),
- 227. [Room] = L,
- 228. {room,{join,Room}};
- 229.
- 230.handle(<<"ROOM">>,Packet) ->
- 231. L = parse(Packet,1),
- 232. [Message] = L,
- 233. {room,{chat,Message}};
- 234.
- 235.handle(<<"LEAV">>,Packet) ->
- 236. {room,leave};
- 237.
- 238.handle(<<"PING">>,Packet) ->
- 239. {server,ping};
- 240.
- 241.handle(<<"EXIT">>,Packet) ->
- 242. {server,exit};
- 243.
- 244.handle(Other,Packet) ->
- 245. error.
- 246.
- 247.%%PARSE ROUTINES
- 248.
- 249.parse(Bin,Count) ->
- 250. parse(Bin,Count-1,[],[]).
- 251.
- 252.%%parse(<<TheRest/binary>>,0,Val,List) ->
- 253.%% lists:reverse([TheRest|List]);
- 254.
- 255.parse(<<"\x20",TheRest/binary>>,Count,Val,List) when Count > 0 ->
- 256. parse(TheRest,Count-1,[],[list_to_binary(lists:reverse(Val))|List]);
- 257.
- 258.parse(<<"\x0D",TheRest/binary>>,Count,Val,List) ->
- 259. parse(TheRest,Count,Val,List);
- 260.
- 261.parse(<<"\x0A",TheRest/binary>>,Count,Val,List) ->
- 262. parse(TheRest,Count,Val,List);
- 263.
- 264.parse(<<Char,TheRest/binary>>,Count,Val,List) ->
- 265. parse(TheRest,Count,[Char|Val],List);
- 266.
- 267.parse(<<>>,Count,Val,List) ->
- 268. lists:reverse([list_to_binary(lists:reverse(Val))|List]).
- 269.
- 270.-module(mod_hbchat_listener).
- 271.
- 272.-export([start/2]).
- 273.
- 274.start(Port,Server) ->
- 275. case gen_tcp:listen(Port,[binary,{active,false},{packet,0}]) of
- 276. {ok, ListenSock} ->
- 277. LPid = spawn(fun() -> loop(ListenSock,Server) end),
- 278. SPid = spawn(fun() -> accept_loop(ListenSock,Server) end),
- 279. LPid;
- 280. {error,Reason} ->
- 281. 0
- 282. end.
- 283.
- 284.accept_loop(Socket,Server) ->
- 285. case gen_tcp:accept(Socket) of
- 286. {ok,S} ->
- 287. Pid = spawn(fun() -> chat_client:start(S,mod_hbchat,Server) end ),
- 288. gen_tcp:controlling_process(S,Pid),
- 289. Server ! {new_client,Pid},
- 290. inet:setopts(S,[binary,{active,once},{packet,line}]),
- 291. accept_loop(Socket,Server);
- 292. Other ->
- 293. error
- 294. end.
- 295.
- 296.loop(Socket,Server) ->
- 297. receive
- 298. close_down ->
- 299. gen_tcp:close(Socket)
- 300. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement