Last active
May 6, 2019 09:24
-
-
Save gilons/e9b4f595a50ec1627178eac630979e78 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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, []). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm implementing listener as a special otp application