Advertisement
Guest User

Untitled

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