% chat_liason.erl % Copyright 2005 Michael Leonhard % All Rights Reserved. % http://tamale.net/ -module(chat_liason). -export([liason_start/0, deliver_socket/2, send_message/2, liason_reader_start/3]). -include_lib("kernel/include/inet.hrl"). send_message(String, PID) -> PID ! {message, String}. deliver_socket(Socket, PID) -> gen_tcp:controlling_process(Socket, PID), PID ! {socket, Socket}. receive_socket() -> receive {socket, Socket} -> Socket end. get_client_name(Socket) -> case inet:peername(Socket) of {error, _Reason} -> "?.?.?.?:?"; {ok, {{A,B,C,D}, Port}} -> case inet:gethostbyaddr({A,B,C,D}) of {error, _Reason} -> io_lib:fwrite("~B.~B.~B.~B:~B", [A,B,C,D, Port]); {ok, Hostent} -> io_lib:fwrite("~s:~B", [Hostent#hostent.h_name, Port]) end end. string_timestamp() -> {MegaSecs,Secs,_Microsecs} = now(), [integer_to_list(MegaSecs)|integer_to_list(Secs)]. liason_start() -> chat_supervisor:linkme(liason), Socket = receive_socket(), %inet:setopts(Socket, [binary, {packet, line}, {active, false}]), Name = get_client_name(Socket), spawn_link(chat_liason, liason_reader_start, [Socket, Name, self()]), chat_dispatcher:connected(), io:fwrite("~s ~s connected~n", [string_timestamp(), Name]), chat_dispatcher:dispatch([string_timestamp()|[" "|[Name|[" connected"]]]]), liason_loop(Socket, Name). liason_stop(Socket, Name) -> inet:close(Socket), io:fwrite("~s ~s disconnected~n", [string_timestamp(), Name]), chat_dispatcher:disconnected(), chat_dispatcher:dispatch([string_timestamp()|[" "|[Name|[" disconnected"]]]]). liason_loop(Socket, Name) -> receive stop -> io:fwrite("~s ~s received shutdown message~n", [string_timestamp(), Name]); socket_closed -> liason_stop(Socket, Name); {message, String} -> gen_tcp:send(Socket, [String|"\r\n"]), liason_loop(Socket, Name); M -> io:fwrite("~s ~s unknown message ~w~n", [string_timestamp(), Name, M]), liason_loop(Socket, Name) end. format_message(Name,B) -> [string_timestamp()|[" <"|[Name|["> "|lists:filter( fun(X) -> (X /= $\r) and (X /= $\n) end, binary_to_list(B))]]]]. liason_reader_start(Socket, Name, LiasonPID) -> liason_reader_loop(Socket, Name, LiasonPID). liason_reader_loop(Socket, Name, LiasonPID) -> case gen_tcp:recv(Socket, 0) of {ok, B} -> chat_dispatcher:dispatch(format_message(Name, B)), liason_reader_loop(Socket, Name, LiasonPID); {error, closed} -> unlink(LiasonPID), LiasonPID ! socket_closed end.