ssl_broker.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,206 行 · 第 1/3 页

ERL
1,206
字号
		    {reply, {ok, ThisSocket}, NSt};		{error, Reason, St} ->		    What = what(Reason),		    {stop, normal, {error, What}, St}	    end;	{error, Reason} ->	    What = what(Reason),	    {stop, normal, {error, What}, St}    end;%% ssl_accept %% %% Client = pid of client %% ListenSocket = sslsocket()%%handle_call({ssl_accept, Client, Socket, Timeout}, _From, St) ->    debug(St, "ssl_accept: client = ~w, socket = ~w~n", [Client, Socket]),    case ssl_accept_prim(ssl_server, gen_tcp, Client, Socket, Timeout, St) of	{ok, Socket, NSt} ->	    {reply, ok, NSt};	{error, Reason, St} ->	    What = what(Reason),	    {stop, normal, {error, What}, St}    end;%% connect%%%% Client = client pid%% Address = hostname | ipstring | IP%% Port = integer()%% Opts = options()%%handle_call({connect, Client, Address, Port, Opts, Timeout}, _From, St) ->    debug(St, "connect: client = ~w, address = ~p, port = ~w~n",	  [Client, Address, Port]),    case connect_prim(ssl_server, gen_tcp, Client, Address, Port, Opts, 		      Timeout, St) of	{ok, Res, NSt} ->	    {reply, {ok, Res}, NSt};	{error, Reason, NSt} ->	    What = what(Reason),	    {stop, normal, {error, What}, NSt}    end;%% connection_info%%handle_call({connection_info, Client}, _From, St) ->    debug(St, "connection_info: client = ~w~n", [Client]),    Reply = ssl_server:connection_info(St#st.fd),    {reply, Reply, St};%% close from client%%handle_call({close, Client}, _From, St) ->    debug(St, "close: client = ~w~n", [Client]),    %% Terminate    {stop, normal, ok, St#st{status = closed}};%%  listen%% %%  Client = pid of client%%  Port = int()%%  Opts = options()%%handle_call({listen, Client, Port, Opts}, _From, St) ->    debug(St, "listen: client = ~w, port = ~w~n",	  [Client, Port]),    case listen_prim(ssl_server, Client, Port, Opts, St) of	{ok, Res, NSt} ->	    {reply, {ok, Res}, NSt};	{error, Reason, NSt} ->	    What = what(Reason),	    {stop, normal, {error, What}, NSt}    end;%% peername%%handle_call({peername, Client}, _From, St) ->    debug(St, "peername: client = ~w~n", [Client]),    Reply = case ssl_server:peername(St#st.fd) of		{ok, {Address, Port}} ->		    {ok, At} = inet_parse:ipv4_address(Address),		    {ok, {At, Port}};		Error ->		    Error	    end,    {reply, Reply, St};%% setopts%%handle_call({setopts, Client, Opts0}, _From, St0) ->    debug(St0, "setopts: client = ~w~n", [Client]),    OptsOK = case St0#st.brokertype of		 listener ->		     are_opts(fun is_tcp_listen_opt/1, Opts0);		 acceptor ->		     are_opts(fun is_tcp_accept_opt/1, Opts0);		 connector ->		     are_opts(fun is_tcp_connect_opt/1, Opts0)	     end,    if 	OptsOK == false ->	    {reply, {error, eoptions}, St0};	true ->	    Opts1 = lists:keydelete(nodelay, 1, Opts0),	    case inet:setopts(St0#st.proxysock, Opts1) of		ok ->		    Opts2 = replace_opts(Opts1, St0#st.opts),		    Active = get_active(Opts2),		    St2 = St0#st{opts = Opts2, 				 active = Active},		    case get_nodelay(Opts0) of			empty ->			    {reply, ok, St2};			Bool ->			    case setnodelay(ssl_server, St0, Bool) of				ok ->				    Opts3 = replace_opts([{nodelay, Bool}],							 Opts2),				    St3 = St0#st{opts = Opts3, 						 active = Active},				    {reply, ok, St3};				{error, Reason} ->				    {reply, {error, Reason}, St2}			    end		    end;		{error, Reason} ->		    {reply, {error, Reason}, St0}	    end    end;%% sockname%%handle_call({sockname, Client}, _From, St) ->    debug(St, "sockname: client = ~w~n", [Client]),    Reply = case ssl_server:sockname(St#st.fd) of		{ok, {Address, Port}} ->		    {ok, At} = inet_parse:ipv4_address(Address),		    {ok, {At, Port}};		Error ->		    Error	    end,    {reply, Reply, St};%% peercert%%handle_call({peercert, Client}, _From, St) ->    debug(St, "peercert: client = ~w~n", [Client]),    Reply = ssl_server:peercert(St#st.fd),    {reply, Reply, St};%% inhibit msgs%%%%handle_call({inhibit_msgs, Client}, _From, St) when St#st.client == Client ->    debug(St, "inhibit_msgs: client = ~w~n", [Client]),    {ok, Collector} = start_collector(),    {reply, ok, St#st{collector = Collector}};%% release msgs%%%%handle_call({release_msgs, Client, NewClient}, _From, St)   when St#st.client == Client ->    debug(St, "release_msgs: client = ~w~n", [Client]),    unlink(Client),    link(NewClient),    release_collector(St#st.collector, NewClient),    NSt = St#st{client = NewClient, collector = NewClient},    {reply, ok, NSt};%% getopts%%%%handle_call({getopts, Client, OptTags}, _From, St) ->    debug(St, "getopts: client = ~w~n", [Client]),    Reply = case are_opt_tags(St#st.brokertype, OptTags) of		true ->		    {ok, extract_opts(OptTags, St#st.opts)};		_ ->		    {error, einval}	    end,    {reply, Reply, St};%% bad call%% %%handle_call(Request, _From, St) ->    debug(St, "++++ ssl_broker: bad call: ~w~n", [Request]),    {reply, {error, {badcall, Request}}, St}.%%%% HANDLE CAST%%handle_cast(Request, St) ->    debug(St, "++++ ssl_broker: bad cast: ~w~n", [Request]),    {stop, {error, {badcast, Request}}, St}.%% %% HANDLE INFO%%%% tcp - active mode%%%% The collector is different from client only during change of%% controlling process.%%handle_info({tcp, Socket, Data}, St)   when St#st.proxysock == Socket, St#st.status == open, St#st.active =/= false ->    debug(St, "tcp: socket = ~w~n", [Socket]),    Msg = {ssl, St#st.thissock, Data},    St#st.collector ! Msg,    if	St#st.active == once -> 	    {noreply, St#st{active = false}};	true -> 	    {noreply, St}    end;%% tcp_closed - from proxy socket, active mode%%%%handle_info({tcp_closed, Socket}, St)   when St#st.proxysock == Socket, St#st.active =/= false ->    debug(St, "tcp_closed: socket = ~w~n", [Socket]),    Msg = {ssl_closed, St#st.thissock},    St#st.collector ! Msg,    if	St#st.active == once -> 	    {noreply, St#st{status = closing, active = false}};	true ->	    {noreply, St#st{status = closing}}    end;%% tcp_error - from proxy socket, active mode%%%%handle_info({tcp_error, Socket, Reason}, St)   when St#st.proxysock == Socket, St#st.active =/= false ->    debug(St, "tcp_error: socket = ~w, reason = ~w~n", [Socket, Reason]),    Msg = {ssl_error, St#st.thissock, Reason},    St#st.collector ! Msg,    if	St#st.active == once -> 	    {noreply, St#st{status = closing, active = false}};	true ->	    {noreply, St#st{status = closing}}    end;%% EXIT - from client%% %%handle_info({'EXIT', Client, Reason}, St) when St#st.client == Client ->    debug(St, "exit client: client = ~w, reason = ~w~n", [Client, Reason]),    {stop, normal, St#st{status = closed}};	% do not make noise%% EXIT - from server%%%%handle_info({'EXIT', Server, Reason}, St) when St#st.server == Server ->    debug(St, "exit server: reason = ~w~n", [Reason]),    {stop, Reason, St};%% handle info catch all%%%%handle_info(Info, St) ->    debug(St, " bad info: ~w~n", [Info]),    {stop, {error, {badinfo, Info}}, St}.%% terminate%%%% terminate(Reason, St) ->    debug(St, "in terminate reason: ~w, state: ~w~n", [Reason, St]),    ok.%% code_change%%%%code_change(_OldVsn, State, _Extra) ->    {ok, State}.%%%% Primitive interface%%listen_prim(ServerName, Client, Port, Opts, St) ->    LOpts = get_tcp_listen_opts(Opts),    SSLOpts = get_ssl_opts(Opts),    FlagStr =mk_ssl_optstr(SSLOpts),    BackLog = get_backlog(LOpts),    IP = get_ip(LOpts),    case ssl_server:listen_prim(ServerName, IP, Port, FlagStr, BackLog) of	{ok, ListenFd, _Port0} ->	    ThisSocket = #sslsocket{fd = ListenFd, pid = self()},	    StOpts = add_default_tcp_listen_opts(LOpts) ++		add_default_ssl_opts(SSLOpts),	    NSt = St#st{fd = ListenFd, 			active = get_active(LOpts), % irrelevant for listen			opts = StOpts,			thissock = ThisSocket, 			status = open},	    debug(St, "listen: ok: client = ~w, listenfd = ~w~n", 		  [Client, ListenFd]),	    {ok, ThisSocket, NSt};	{error, Reason} ->	    {error, Reason, St}    end.connect_prim(ServerName, TcpModule, Client, FAddress, FPort, Opts, 	     Timeout, St) ->    COpts = get_tcp_connect_opts(Opts),    SSLOpts = get_ssl_opts(Opts),    FlagStr = mk_ssl_optstr(SSLOpts),    case inet:getaddr(FAddress, inet) of	{ok, FIP} ->	    %% Timeout is gen_server timeout - hence catch	    LIP = get_ip(COpts),	    LPort = get_port(COpts),	    case (catch ssl_server:connect_prim(ServerName, 						LIP, LPort, FIP, FPort, 						FlagStr, Timeout)) of		{ok, Fd, ProxyPort} ->		    case connect_proxy(ServerName, TcpModule, Fd, 				       ProxyPort, COpts, Timeout) of			{ok, Socket} ->			    ThisSocket = #sslsocket{fd = Fd, pid = self()}, 			    StOpts = add_default_tcp_connect_opts(COpts) ++				add_default_ssl_opts(SSLOpts),			    NSt = St#st{fd = Fd, 					active = get_active(COpts),					opts = StOpts,					thissock = ThisSocket, 					proxysock = Socket, 					status = open},			    case get_nodelay(COpts) of				true -> setnodelay(ServerName, NSt, true);				_ -> ok			    end,			    debug(St, "connect: ok: client = ~w, fd = ~w~n",				  [Client, Fd]),			    {ok, ThisSocket, NSt};			{error, Reason} ->			    {error, Reason, St}		    end;		{'EXIT', Reason} ->		    {error, Reason, St};		{error, Reason} ->		    {error, Reason, St}	    end;	{error, Reason} ->	    {error, Reason, St}    end.transport_accept_prim(ServerName, ListenFd, LOpts, Timeout, St) ->     AOpts = get_tcp_accept_opts(LOpts),    FlagStr = "",    %% Timeout is gen_server timeout - hence catch.    case (catch ssl_server:transport_accept_prim(ServerName, ListenFd,						 FlagStr, Timeout)) of 	{ok, Fd, ProxyPort} ->	    ThisSocket = #sslsocket{fd = Fd, pid = self()}, 	    NSt = St#st{fd = Fd, 			active = get_active(AOpts),			opts = AOpts,			thissock = ThisSocket,			proxyport = ProxyPort,			encrypted = false},	    debug(St, "transport_accept: ok: fd = ~w~n", [Fd]),	    {ok, ThisSocket, NSt};	{'EXIT', Reason} ->	    debug(St, "transport_accept: EXIT: Reason = ~w~n", [Reason]),	    {error, Reason, St};	{error, Reason} ->	    debug(St, "transport_accept: error: Reason = ~w~n", [Reason]),	    {error, Reason, St}    end.ssl_accept_prim(ServerName, TcpModule, Client, Socket, Timeout, St) ->     FlagStr = [],    SSLOpts = [],    %% Timeout is gen_server timeout - hence catch.    debug(St, "ssl_accept_prim: self() ~w Client ~w~n", [self(), Client]),    Fd = Socket#sslsocket.fd,    A = (catch ssl_server:ssl_accept_prim(ServerName, Fd, FlagStr, Timeout)),    debug(St, "ssl_accept_prim: ~w~n", [A]),    case A of 	ok ->	    AOpts = St#st.opts,	    B = connect_proxy(ServerName, TcpModule, Fd, 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?