erlang网络库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

168 lines
5.2 KiB

-module(ntPptAcceptor).
-include("eNet.hrl").
-include("ntCom.hrl").
-include("proxyPt.hrl").
-compile(inline).
-compile({inline_size, 128}).
-export([
start_link/8
, pptAndHS/5
, init/1
, handleMsg/2
, init_it/2
, system_code_change/4
, system_continue/3
, system_get_state/1
, system_terminate/4
]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% genActor start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec start_link(list(), timeout(), boolean(), timeout(), inet:socket(), module(), term(), [proc_lib:spawn_option()]) -> {ok, pid()}.
start_link(SslOpts, SslHSTet, ProxyPt, ProxyPtTet, LSock, ConMod, ConArgs, SpawnOpts) ->
proc_lib:start_link(?MODULE, init_it, [self(), {SslOpts, SslHSTet, ProxyPt, ProxyPtTet, LSock, ConMod, ConArgs}], infinity, SpawnOpts).
init_it(Parent, Args) ->
process_flag(trap_exit, true),
modInit(Parent, Args).
-spec system_code_change(term(), module(), undefined | term(), term()) -> {ok, term()}.
system_code_change(State, _Module, _OldVsn, _Extra) ->
{ok, State}.
-spec system_continue(pid(), [], {module(), atom(), pid(), term()}) -> ok.
system_continue(_Parent, _Debug, {Parent, State}) ->
loop(Parent, State).
-spec system_get_state(term()) -> {ok, term()}.
system_get_state(State) ->
{ok, State}.
-spec system_terminate(term(), pid(), [], term()) -> none().
system_terminate(Reason, _Parent, _Debug, _State) ->
exit(Reason).
modInit(Parent, Args) ->
case init(Args) of
{ok, State} ->
proc_lib:init_ack(Parent, {ok, self()}),
loop(Parent, State);
{stop, Reason} ->
proc_lib:init_ack(Parent, {error, Reason}),
exit(Reason)
end.
loop(Parent, State) ->
receive
{system, From, Request} ->
sys:handle_system_msg(Request, From, Parent, ?MODULE, [], {Parent, State});
{'EXIT', Parent, Reason} ->
exit(Reason);
Msg ->
case handleMsg(Msg, State) of
{ok, NewState} ->
loop(Parent, NewState);
{stop, Reason} ->
exit(Reason)
end
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% genActor end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-record(state, {
lSock
, sslOpts
, sslHSTet
, proxyPt
, proxyPtTet
, ref
, conMod
, conArgs
, sockMod
}).
-spec init(Args :: term()) -> ok.
init({SslOpts, SslHSTet, ProxyPt, ProxyPtTet, LSock, ConMod, ConArgs}) ->
case prim_inet:async_accept(LSock, -1) of
{ok, Ref} ->
{ok, SockMod} = inet_db:lookup_socket(LSock),
{ok, #state{lSock = LSock, sslOpts = SslOpts, sslHSTet = SslHSTet, proxyPt = ProxyPt, proxyPtTet = ProxyPtTet, ref = Ref, conMod = ConMod, conArgs = ConArgs, sockMod = SockMod}};
{error, Reason} ->
?ntErr("init prim_inet:async_accept error ~p~n", [Reason]),
{stop, Reason}
end.
handleMsg({inet_async, LSock, Ref, Msg}, #state{lSock = LSock, sslOpts = SslOpts, sslHSTet = SslHSTet, proxyPt = ProxyPt, proxyPtTet = ProxyPtTet, ref = Ref, conMod = ConMod, conArgs = ConArgs, sockMod = SockMod} = State) ->
case Msg of
{ok, Sock} ->
%% make it look like gen_tcp:accept
inet_db:register_socket(Sock, SockMod),
try ConMod:newConn(Sock, ConArgs) of
{ok, Pid} ->
gen_tcp:controlling_process(Sock, Pid),
Pid ! {?mSockReady, Sock, SslOpts, SslHSTet, ProxyPt, ProxyPtTet},
newAsyncAccept(LSock, State);
{close, Reason} ->
?ntErr("handleMsg ConMod:newAcceptor return close ~p~n", [Reason]),
catch port_close(Sock),
newAsyncAccept(LSock, State);
_Ret ->
?ntErr("ConMod:newAcceptor return error ~p~n", [_Ret]),
{stop, error_ret}
catch
E:R:S ->
?ntErr("CliMod:newConnect crash: ~p:~p~n~p~n ~n ", [E, R, S]),
newAsyncAccept(LSock, State)
end;
{error, closed} ->
% ?ntErr("error, closed listen sock error ~p~n", [closed]),
{stop, normal};
{error, Reason} ->
?ntErr("listen sock error ~p~n", [Reason]),
{stop, {lsock, Reason}}
end;
handleMsg(_Msg, State) ->
?ntErr("~p receive unexpected ~p msg: ~p", [?MODULE, self(), _Msg]),
{ok, State}.
newAsyncAccept(LSock, State) ->
case prim_inet:async_accept(LSock, -1) of
{ok, Ref} ->
{ok, State#state{ref = Ref}};
{error, Reason} ->
?ntErr("~p prim_inet:async_accept error ~p~n", [?MODULE, Reason]),
{stop, Reason}
end.
pptAndHS(OSock, SslOpts, SslHSTet, ProxyPt, ProxyPtTet) ->
PptRet =
case ProxyPt of
true ->
nt_proxy_protocol:recv(OSock, ProxyPtTet);
_ ->
{ok, OSock, #proxy_socket{}}
end,
case PptRet of
{ok, TemSock, ProxySock} ->
case SslOpts /= undefined of
true ->
case ssl:handshake(TemSock, SslOpts, SslHSTet) of
{ok, SslSock} ->
{ok, SslSock, ProxySock};
{ok, SslSock, _Ext} -> %% OTP 21.0
{ok, SslSock, ProxySock};
{error, _} = Err -> Err
end;
_ ->
PptRet
end;
_ ->
PptRet
end.