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 + -
显示快捷键?