Skip to content

Instantly share code, notes, and snippets.

@gilons
Last active May 6, 2019 09:24
Show Gist options
  • Save gilons/e9b4f595a50ec1627178eac630979e78 to your computer and use it in GitHub Desktop.
Save gilons/e9b4f595a50ec1627178eac630979e78 to your computer and use it in GitHub Desktop.
-module(tcp).
-export([connect/1, handle_connection/0,
handle_system_msg/6, init/1, listen/0, loop/2,
start_link/0, system_continue/3, system_replace_state/2,
system_terminate/4, write_debug/3]).
-include("./rec.hrl").
-define(LOG_ERROR, "~p Crashed Deu to: ~p").
start_link() ->
proc_lib:start_link(tcp, init, [self()]).
init(Parent) ->
process_flag(trap_exit, true),
Debs = sys:debug_options([]),
proc_lib:init_ack(Parent, {ok, self()}),
case erlang:whereis(tcp) of
undefined ->
erlang:register(tcp, self()),
erlang:register(listerner,
spawn_link(tcp, listen, [])),
loop(Parent, Debs);
_Pid -> ok
end.
loop(Parent, Debs) ->
receive
{tcp_closed, _} ->
%% TODO :: LOGGER Implementation OF LOGGING MESSAGES TO Files
Debs2 = sys:handle_debug(Debs,
fun tcp:write_debug/3, bleashup_tcp,
{in, tcp_closed, self()}),
case erlang:whereis(listerner) of
undefined ->
case catch erlang:unregister(listerner) of
_ -> ok
end,
erlang:register(listerner,
spawn_link(tcp, listen, []));
_ -> ok
end,
loop(Parent, Debs2);
{system, From, Request} ->
sys:handle_system_msg(Request, From, Parent,
bleashup_tcp, Debs, []);
{'EXIT', Parent, _Reason} ->
%%TODO :: LOGGER implmentation of messages
case erlang:whereis(listerner) of
undefined ->
io:format("exiting signal from parent", []);
Pid ->
exit(Pid, kill),
io:format("exiting signal from parent", [])
end;
{'EXIT', Pid, _Reason} ->
Debs2 = sys:handle_debug(Debs,
fun tcp:write_debug/3, bleashup_tcp,
{in, listerner_exit, self()}),
%%TODO :: LOGGER implmentation of messages
case erlang:whereis(listerner) of
undefined ->
case catch erlang:unregister(listerner) of
_ -> ok
end,
erlang:register(listerner,
spawn_link(tcp, listen, []));
Pid ->
case catch erlang:unregister(listerner) of
_ -> ok
end,
exit(Pid, kill),
erlang:register(listerner,
spawn_link(tcp, listen, []))
end,
loop(Parent, Debs2);
terminate ->
case erlang:whereis(listerner) of
undefined -> exit(normal);
Pid -> exit(Pid, kill), exit(normal)
end
end.
listen() ->
{ok, Port} = application:get_env(tcp,
port),
{ok, Host} = application:get_env(tcp,
host),
{ok, ListenSocket} = gen_tcp:listen(Port,
[{ip, BleashupHost}, {active, true},
{reuseaddr, true}, {keepalive, true}]),
%% the original implementation was :
%% connect(Listen).
%% the above was changed to the one below in attempt to have a pool of 40 acceptors
spawn_multiple_acceptors(ListenSocket, 40).
spawn_multiple_acceptors(_ListenSocket, 0) -> ok;
spawn_multiple_acceptors(ListenSocket, N) ->
spawn_link(tcp, connect, [ListenSocket]),
spawn_multiple_acceptors(ListenSocket, N - 1).
handle_connection() ->
io:format("entring into handle func~n", []),
receive
{tcp, Socket, Data} ->
spawn_link(tcp_handler, forward_connection,
[Data, Socket]);
{'EXIT', Pid, Err} when Err /= normal ->
logger:error(?LOG_ERROR, [Pid, Err]);
{tcp_closed, _} -> stop
end,
handle_connection().
connect(ListenSocket) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
%% handler is the registered name of the main TCP connection handler
%% So this function tries to get the pid of the main handle process
%% If it does not succeed it goes forward and spawn his own implementation of that handle process
Pid = case erlang:whereis(handler) of
undefined ->
case erlang:whereis(handle_secondary) of
undefined ->
case catch erlang:unregister(handle_secondary) of
_ -> ok
end,
erlang:register(handle_secondary,
Pider = spawn_link(tcp,
handle_connection,
[])),
Pider;
Pider -> Pider
end;
Pider -> Pider
end,
gen_tcp:controlling_process(Socket, Pid),
connect(ListenSocket).
write_debug(Dev, Event, Name) ->
io:format(Dev, "~p event = ~p~n", [Name, Event]).
system_continue(Parent, Deb, _Misc) ->
loop(Parent, Deb).
system_terminate(Reason, _Parent, _Deb, _Chs) ->
exit(Reason).
system_replace_state(StateFun, Chs) ->
NChs = StateFun(Chs), {ok, NChs, NChs}.
handle_system_msg(_Msg, _From, Parent, Module, Debs,
_Mics) ->
Module:system_continue(Parent, Debs, []).
@gilons
Copy link
Author

gilons commented May 6, 2019

I'm implementing listener as a special otp application

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment