ssl_broker.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,206 行 · 第 1/3 页
ERL
1,206 行
St#st.proxyport, AOpts, Timeout), debug(St, "ssl_accept_prim: connect_proxy ~w~n", [B]), case B of {ok, Socket2} -> StOpts = add_default_tcp_accept_opts(AOpts) ++ add_default_ssl_opts(SSLOpts), NSt = St#st{opts = StOpts, proxysock = Socket2, encrypted = true, status = open}, case get_nodelay(AOpts) of true -> setnodelay(ServerName, NSt, true); _ -> ok end, debug(St, "transport_accept: ok: client = ~w, fd = ~w~n", [Client, Fd]), {ok, St#st.thissock, NSt}; {error, Reason} -> {error, Reason, St} end; {'EXIT', Reason} -> {error, Reason, St}; {error, Reason} -> {error, Reason, St} end.%%%% LOCAL FUNCTIONS%%%% %% connect_proxy(Fd, ProxyPort, TOpts, Timeout) -> {ok, Socket} | %% {error, Reason}%%connect_proxy(ServerName, TcpModule, Fd, ProxyPort, TOpts, Timeout) -> case TcpModule:connect({127, 0, 0, 1}, ProxyPort, TOpts, Timeout) of {ok, Socket} -> {ok, Port} = inet:port(Socket), A = ssl_server:proxy_join_prim(ServerName, Fd, Port), case A of ok -> {ok, Socket}; Error -> Error end; Error -> Error end.setnodelay(ServerName, St, Bool) -> case ssl_server:setnodelay_prim(ServerName, St#st.fd, Bool) of ok -> case inet:setopts(St#st.proxysock, [{nodelay, Bool}]) of ok -> ok; {error, Reason} -> {error, Reason} end; {error, Reason} -> {error, Reason} end.%%%% start_collector()%%%% A collector is a little process that keeps messages during change of%% controlling process. %% XXX This is not gen_server compliant :-(.%%start_collector() -> Pid = spawn_link(?MODULE, collector_init, [self()]), {ok, Pid}.%%%% release_collector(Collector, NewOwner)%%release_collector(Collector, NewOwner) -> Collector ! {release, self(), NewOwner}, receive %% Reap collector {'EXIT', Collector, normal} -> ok end.%%%% collector_init(Broker) -> void()%%collector_init(Broker) -> receive {release, Broker, NewOwner} -> transfer_messages(Broker, NewOwner) end.%% %% transfer_messages(Pid, NewOwner) -> void()%%transfer_messages(Pid, NewOwner) -> receive {ssl, Sock, Data} -> NewOwner ! {ssl, Sock, Data}, transfer_messages(Pid, NewOwner); {ssl_closed, Sock} -> NewOwner ! {ssl_closed, Sock}, transfer_messages(Pid, NewOwner); {ssl_error, Sock, Reason} -> NewOwner ! {ssl_error, Sock, Reason}, transfer_messages(Pid, NewOwner) after 0 -> ok end.%%%% debug(St, Format, Args) -> void() - printouts%%debug(St, Format, Args) -> debug1(St#st.debug, St#st.brokertype, Format, Args).debug1(true, Type, Format0, Args) -> {_MS, S, MiS} = erlang:now(), Secs = S rem 100, MiSecs = MiS div 1000, Format = "++++ ~3..0w:~3..0w ssl_broker (~w)[~w]: " ++ Format0, io:format(Format, [Secs, MiSecs, self(), Type| Args]);debug1(_, _, _, _) -> ok.%%%% what(Reason) -> What%% what(Reason) when is_atom(Reason) -> Reason;what({'EXIT', Reason}) -> what(Reason);what({What, _Where}) when is_atom(What) -> What;what(Reason) -> Reason.%%%% OPTIONS%%%% Note that `accept' has no options when invoked, but get all its options%% by inheritance from `listen'. %%are_opt_tags(listener, OptTags) -> is_subset(OptTags, listen_opt_tags());are_opt_tags(acceptor, OptTags) -> is_subset(OptTags, accept_opt_tags());are_opt_tags(connector, OptTags) -> is_subset(OptTags, connect_opt_tags()).listen_opt_tags() -> tcp_listen_opt_tags() ++ ssl_opt_tags().accept_opt_tags() -> tcp_gen_opt_tags().connect_opt_tags() -> tcp_gen_opt_tags() ++ ssl_opt_tags().tcp_listen_opt_tags() -> tcp_gen_opt_tags() ++ tcp_listen_only_opt_tags().tcp_gen_opt_tags() -> %% All except `reuseaddr' and `deliver'. [nodelay, active, packet, mode, header]. tcp_listen_only_opt_tags() -> [ip, backlog].ssl_opt_tags() -> %% XXX Should remove cachetimeout. [verify, depth, certfile, password, cacertfile, ciphers, cachetimeout].%% Options%%%% are_*_opts(Opts) -> true | false%%are_connect_opts(Opts) -> are_opts(fun is_connect_opt/1, Opts).are_listen_opts(Opts) -> are_opts(fun is_listen_opt/1, Opts).are_opts(F, Opts) -> lists:all(F, transform_opts(Opts)).%%%% get_*_opts(Opts) -> Value%%get_tcp_accept_opts(Opts) -> lists:filter(fun is_tcp_accept_opt/1, transform_opts(Opts)).get_tcp_connect_opts(Opts) -> lists:filter(fun is_tcp_connect_opt/1, transform_opts(Opts)).get_tcp_listen_opts(Opts) -> lists:filter(fun is_tcp_listen_opt/1, transform_opts(Opts)).get_ssl_opts(Opts) -> lists:filter(fun is_ssl_opt/1, transform_opts(Opts)).get_active(Opts) -> get_tagged_opt(active, Opts, true).get_backlog(Opts) -> get_tagged_opt(backlog, Opts, ?DEF_BACKLOG).get_ip(Opts) -> get_tagged_opt(ip, Opts, {0, 0, 0, 0}).get_port(Opts) -> get_tagged_opt(port, Opts, 0).get_nodelay(Opts) -> get_tagged_opt(nodelay, Opts, empty).%%%% add_default_*_opts(Opts) -> NOpts%%add_default_tcp_accept_opts(Opts) -> add_default_opts(Opts, default_tcp_accept_opts()).add_default_tcp_connect_opts(Opts) -> add_default_opts(Opts, default_tcp_connect_opts()).add_default_tcp_listen_opts(Opts) -> add_default_opts(Opts, default_tcp_listen_opts()).add_default_ssl_opts(Opts) -> add_default_opts(Opts, default_ssl_opts()).add_default_opts(Opts, DefOpts) -> TOpts = transform_opts(Opts), TOpts ++ [{DTag, DVal} || {DTag, DVal} <- DefOpts, not lists:keymember(DTag, 1, TOpts)].default_tcp_accept_opts() -> lists:filter(fun is_tcp_accept_opt/1, default_opts()).default_tcp_connect_opts() -> lists:filter(fun is_tcp_connect_opt/1, default_opts()).default_tcp_listen_opts() -> lists:filter(fun is_tcp_listen_opt/1, default_opts()).default_ssl_opts() -> lists:filter(fun is_ssl_opt/1, default_opts()).default_opts() -> [{mode, list}, {packet, 0}, {nodelay, false}, {active, true}, {backlog, ?DEF_BACKLOG}, {ip, {0, 0, 0, 0}}, {verify, 0}, {depth, 1}].%% Transform from old to new options, and also from old gen_tcp%% options to new ones. All returned options are tagged options.%%transform_opts(Opts) -> lists:flatmap(fun transform_opt/1, Opts).transform_opt(binary) -> [{mode, binary}];transform_opt(list) -> [{mode, list}];transform_opt({packet, raw}) -> [{packet, 0}];transform_opt(raw) -> [];transform_opt(Opt) -> [Opt].%% NOTE: The is_*_opt/1 functions must be applied on transformed options%% only.is_connect_opt(Opt) -> is_tcp_connect_opt(Opt) or is_ssl_opt(Opt).is_listen_opt(Opt) -> is_tcp_listen_opt(Opt) or is_ssl_opt(Opt).is_tcp_accept_opt(Opt) -> is_tcp_gen_opt(Opt) or is_ssl_opt(Opt).is_tcp_connect_opt(Opt) -> is_tcp_gen_opt(Opt) or is_tcp_connect_only_opt(Opt).is_tcp_listen_opt(Opt) -> is_tcp_gen_opt(Opt) or is_tcp_listen_only_opt(Opt).%% General options supported by gen_tcp: All except `reuseaddr' and%% `deliver'.is_tcp_gen_opt({mode, list}) -> true;is_tcp_gen_opt({mode, binary}) -> true;is_tcp_gen_opt({header, Sz}) when is_integer(Sz), 0 =< Sz -> true; is_tcp_gen_opt({packet, Sz}) when is_integer(Sz), 0 =< Sz, Sz =< 4-> true;is_tcp_gen_opt({packet, sunrm}) -> true;is_tcp_gen_opt({packet, asn1}) -> true;is_tcp_gen_opt({packet, cdr}) -> true;is_tcp_gen_opt({packet, fcgi}) -> true;is_tcp_gen_opt({packet, line}) -> true;is_tcp_gen_opt({packet, tpkt}) -> true;is_tcp_gen_opt({packet, http}) -> true;is_tcp_gen_opt({packet, httph}) -> true;is_tcp_gen_opt({nodelay, true}) -> true;is_tcp_gen_opt({nodelay, false}) -> true;is_tcp_gen_opt({active, true}) -> true;is_tcp_gen_opt({active, false}) -> true;is_tcp_gen_opt({active, once}) -> true;is_tcp_gen_opt({keepalive, true}) -> true;is_tcp_gen_opt({keepalive, false}) -> true;is_tcp_gen_opt({ip, Addr}) -> is_ip_address(Addr);is_tcp_gen_opt(_Opt) -> false.is_tcp_listen_only_opt({backlog, Size}) when is_integer(Size), 0 =< Size -> true;is_tcp_listen_only_opt(_Opt) -> false.is_tcp_connect_only_opt({port, Port}) when is_integer(Port), 0 =< Port -> true;is_tcp_connect_only_opt(_Opt) -> false.%% SSL optionsis_ssl_opt({verify, Code}) when 0 =< Code, Code =< 2 -> true;is_ssl_opt({depth, Depth}) when 0 =< Depth -> true;is_ssl_opt({certfile, String}) -> is_string(String);is_ssl_opt({keyfile, String}) -> is_string(String);is_ssl_opt({password, String}) -> is_string(String);is_ssl_opt({cacertfile, String}) -> is_string(String);is_ssl_opt({ciphers, String}) -> is_string(String);is_ssl_opt({cachetimeout, Timeout}) when Timeout >= 0 -> true;is_ssl_opt(_Opt) -> false.%% Various typesis_string(String) when is_list(String) -> lists:all(fun (C) when is_integer(C), 0 =< C, C =< 255 -> true; (_C) -> false end, String);is_string(_) -> false.is_ip_address(Addr) when is_tuple(Addr), size(Addr) == 4 -> is_string(tuple_to_list(Addr));is_ip_address(Addr) when is_list(Addr) -> is_string(Addr);is_ip_address(_) -> false.get_tagged_opt(Tag, Opts, Default) -> case lists:keysearch(Tag, 1, Opts) of {value, {_, Value}} -> Value; _Other -> Default end.%%%% mk_ssl_optstr(Opts) -> string()%%%% Makes a "command line" string of SSL options%%mk_ssl_optstr(Opts) -> lists:flatten(lists:map(fun mk_one_ssl_optstr/1, Opts)).mk_one_ssl_optstr({verify, Code}) -> [" -verify ", integer_to_list(Code)];mk_one_ssl_optstr({depth, Depth}) -> [" -depth ", integer_to_list(Depth)];mk_one_ssl_optstr({certfile, String}) -> [" -certfile ", String];mk_one_ssl_optstr({keyfile, String}) -> [" -keyfile ", String];mk_one_ssl_optstr({password, String}) -> [" -password ", String];mk_one_ssl_optstr({cacertfile, String}) -> [" -cacertfile ", String];mk_one_ssl_optstr({ciphers, String}) -> [" -ciphers ", String];mk_one_ssl_optstr({cachetimeout, Timeout}) -> [" -cachetimeout ", integer_to_list(Timeout)];mk_one_ssl_optstr(_) -> "".extract_opts(OptTags, Opts) -> lists:filter(fun ({Tag, _}) -> lists:member(Tag, OptTags) end, Opts).replace_opts(NOpts, Opts) -> lists:foldl(fun({Key, Val}, Acc) -> lists:keyreplace(Key, 1, Acc, {Key, Val}); %% XXX Check. Patch from Chandrashekhar Mullaparthi. (binary, Acc) -> lists:keyreplace(mode, 1, Acc, {mode, binary}) end, Opts, NOpts).%% Miscis_subset(A, B) -> [] == A -- B.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?