%%%---------------------------------------------------------------------- %%% File : rpc_listen.erl %%% Author : shinde local account %%% Purpose : Act as a tcp/ip server and spawn processes for socket connections %%% Created : 26 May 1999 by ottuser local account %%%---------------------------------------------------------------------- -module(rpc_listen). -vsn(1). -author('shinde@one2one.co.uk'). -export([start_link/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([create/2]). -behaviour(gen_server). -record(state,{listen_socket = []}). % Listener socket reference %%%---------------------------------------------------------------------- %%% API %%%---------------------------------------------------------------------- start_link(Port) -> Name = list_to_atom(lists:flatten(io_lib:format("rpc_server_~w",[Port]))), gen_server:start_link({local, Name}, ?MODULE, Port, []). %% Access to this server from socket servers create(ServerPid, Pid) -> gen_server:cast(ServerPid, {create, Pid}). %%%---------------------------------------------------------------------- %%% Callback functions from gen_server %%%---------------------------------------------------------------------- %%---------------------------------------------------------------------- %% Func: init/1 %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%---------------------------------------------------------------------- init(Port) -> process_flag(trap_exit, true), case gen_tcp:listen(Port,[binary,{packet,2},{active, true}, {reuseaddr,true}]) of {ok, ListenSocket} -> {ok, Pid} = rpc_socket:start(self(), ListenSocket), % Start acceptor process rpc_socket:get_connection(Pid), % Tell it to start accepting {ok, #state{listen_socket = ListenSocket}}; {error, Reason} -> {stop, Reason} end. %%---------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_call(Request,From,State) -> {reply,ok,State}. %%---------------------------------------------------------------------- %% Func: handle_cast/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- handle_cast({create,Pid}, State) -> {ok, NewPid} = rpc_socket:start(self(), State#state.listen_socket), rpc_socket:get_connection(NewPid), {noreply, State}. %%---------------------------------------------------------------------- %% Func: handle_info/2 %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%---------------------------------------------------------------------- % handle_info({'EXIT', Pid, {error, accept_failed}}, State) -> create(self(), self()), % Start off new acceptor as listen socket is still open {noreply,State}; % normal shutdown of socket process handle_info({'EXIT', Pid, normal}, State) -> {noreply,State}; handle_info(Info, State) -> io:format("Unexpected info: ~p~n",[Info]), {noreply,State}. %%---------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server %% Returns: any (ignored by gen_server) %%---------------------------------------------------------------------- terminate(Reason,State) -> gen_tcp:close(State#state.listen_socket), ok. %%---------------------------------------------------------------------- %% Func: code_change/3 %% Purpose: Convert process state when code is changed %% Returns: {ok, NewState} %%---------------------------------------------------------------------- code_change(OldVsn, State, Extra) -> {ok, State}. %%%---------------------------------------------------------------------- %%% Internal functions %%%----------------------------------------------------------------------