diff options
Diffstat (limited to 'lib/ssl/inet_proxy_dist.erl')
-rw-r--r-- | lib/ssl/inet_proxy_dist.erl | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/lib/ssl/inet_proxy_dist.erl b/lib/ssl/inet_proxy_dist.erl new file mode 100644 index 0000000000..6308deabe6 --- /dev/null +++ b/lib/ssl/inet_proxy_dist.erl @@ -0,0 +1,228 @@ +%%%------------------------------------------------------------------- +%%% @author Dan Gudmundsson <[email protected]> +%%% @copyright (C) 2010, Dan Gudmundsson +%%% @doc +%%% +%%% @end +%%% Created : 22 Jun 2010 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- +-module(inet_proxy_dist). + +-export([childspecs/0, listen/1, accept/1, accept_connection/5, + setup/5, close/1, select/1, is_node_name/1, tick/1]). + +-include_lib("kernel/src/net_address.hrl"). +-include_lib("kernel/src/dist.hrl"). +-include_lib("kernel/src/dist_util.hrl"). + +-import(error_logger,[error_msg/2]). + +childspecs() -> + io:format("childspecs called~n",[]), + {ok, [{proxy_server,{proxy_server, start_link, []}, + permanent, 2000, worker, [proxy_server]}]}. + +select(Node) -> + io:format("Select called~n",[]), + inet_ssl_dist:select(Node). + +is_node_name(Name) -> + io:format("is_node_name~n",[]), + inet_ssl_dist:is_node_name(Name). + +listen(Name) -> + io:format("listen called~n",[]), + gen_server:call(proxy_server, {listen, Name}, infinity). + +accept(Listen) -> + io:format("accept called~n",[]), + gen_server:call(proxy_server, {accept, Listen}, infinity). + +accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> + io:format("accept_connection called ~n",[]), + Kernel = self(), + spawn_link(fun() -> do_accept(Kernel, AcceptPid, Socket, + MyNode, Allowed, SetupTime) end). + +setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> + io:format("setup called~n",[]), + Kernel = self(), + spawn(fun() -> do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end). + +do_setup(Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> + [Name, Address] = splitnode(Node, LongOrShortNames), + case inet:getaddr(Address, inet) of + {ok, Ip} -> + Timer = dist_util:start_timer(SetupTime), + case erl_epmd:port_please(Name, Ip) of + {port, TcpPort, Version} -> + ?trace("port_please(~p) -> version ~p~n", + [Node,Version]), + dist_util:reset_timer(Timer), + case gen_server:call(proxy_server, {connect, Ip, TcpPort}, infinity) of + {ok, Socket} -> + HSData = #hs_data{ + kernel_pid = Kernel, + other_node = Node, + this_node = MyNode, + socket = Socket, + timer = Timer, + this_flags = 0, + other_version = Version, + f_send = fun(S,D) -> + io:format("Kernel call send~n",[]), + gen_tcp:send(S,D) + end, + f_recv = fun(S,N,T) -> + io:format("Kernel call receive~n",[]), + gen_tcp:recv(S,N,T) + end, + f_setopts_pre_nodeup = + fun(S) -> + io:format("Kernel pre nodeup~n",[]), + inet:setopts(S, [{active, false}, {packet, 4}]) + end, + f_setopts_post_nodeup = + fun(S) -> + io:format("Kernel post nodeup~n",[]), + inet:setopts(S, [{deliver, port},{active, true}]) + end, + f_getll = fun(S) -> inet:getll(S) end, + f_address = + fun(_,_) -> + #net_address{address = {Ip,TcpPort}, + host = Address, + protocol = proxy, + family = inet} + end, + mf_tick = fun(S) -> gen_tcp:send(S, <<>>) end, + mf_getstat = fun(S) -> + {ok, Stats} = inet:getstat(S, [recv_cnt, send_cnt, send_pend]), + R = proplists:get_value(recv_cnt, Stats, 0), + W = proplists:get_value(send_cnt, Stats, 0), + P = proplists:get_value(send_pend, Stats, 0), + {ok, R,W,P} + end, + request_type = Type + }, + dist_util:handshake_we_started(HSData); + _ -> + %% Other Node may have closed since + %% port_please ! + ?trace("other node (~p) " + "closed since port_please.~n", + [Node]), + ?shutdown(Node) + end; + _ -> + ?trace("port_please (~p) " + "failed.~n", [Node]), + ?shutdown(Node) + end; + _Other -> + ?trace("inet_getaddr(~p) " + "failed (~p).~n", [Node,Other]), + ?shutdown(Node) + end. + +close(Socket) -> + io:format("close called~n",[]), + gen_tcp:close(Socket), + ok. + +do_accept(Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> + process_flag(priority, max), + io:format("~p: in do_accept~n", [self()]), + receive + {AcceptPid, controller} -> + io:format("~p: do_accept controller~n", [self()]), + Timer = dist_util:start_timer(SetupTime), + case check_ip(Socket) of + true -> + HSData = #hs_data{ + kernel_pid = Kernel, + this_node = MyNode, + socket = Socket, + timer = Timer, + this_flags = 0, + allowed = Allowed, + f_send = fun(S,D) -> + io:format("Kernel call send~n",[]), + gen_tcp:send(S,D) end, + f_recv = fun(S,N,T) -> + io:format("Kernel call receive~n",[]), + gen_tcp:recv(S,N,T) end, + f_setopts_pre_nodeup = + fun(S) -> + io:format("Kernel pre nodeup~n",[]), + inet:setopts(S, [{active, false}, {packet, 4}]) + end, + f_setopts_post_nodeup = + fun(S) -> + io:format("Kernel post nodeup~n",[]), + inet:setopts(S, [{deliver, port},{active, true}]) + end, + f_getll = fun(S) -> inet:getll(S) end, + f_address = fun get_remote_id/2, + mf_tick = fun(S) -> gen_tcp:send(S, <<>>) end, + mf_getstat = fun(S) -> + {ok, Stats} = inet:getstat(S, [recv_cnt, send_cnt, send_pend]), + R = proplists:get_value(recv_cnt, Stats, 0), + W = proplists:get_value(send_cnt, Stats, 0), + P = proplists:get_value(send_pend, Stats, 0), + {ok, R,W,P} + end + }, + dist_util:handshake_other_started(HSData); + {false,IP} -> + error_logger:error_msg("** Connection attempt from " + "disallowed IP ~w ** ~n", [IP]), + ?shutdown(no_node) + end + end. + +get_remote_id(Socket, Node) -> + gen_server:call(proxy_server, {get_remote_id, {Socket,Node}}, infinity). + +tick(Socket) -> + gen_tcp:send(Socket, <<>>). + +check_ip(_) -> + true. + + +%% If Node is illegal terminate the connection setup!! +splitnode(Node, LongOrShortNames) -> + case split_node(atom_to_list(Node), $@, []) of + [Name|Tail] when Tail =/= [] -> + Host = lists:append(Tail), + case split_node(Host, $., []) of + [_] when LongOrShortNames == longnames -> + error_msg("** System running to use " + "fully qualified " + "hostnames **~n" + "** Hostname ~s is illegal **~n", + [Host]), + ?shutdown(Node); + [_, _ | _] when LongOrShortNames == shortnames -> + error_msg("** System NOT running to use fully qualified " + "hostnames **~n" + "** Hostname ~s is illegal **~n", + [Host]), + ?shutdown(Node); + _ -> + [Name, Host] + end; + [_] -> + error_msg("** Nodename ~p illegal, no '@' character **~n", + [Node]), + ?shutdown(Node); + _ -> + error_msg("** Nodename ~p illegal **~n", [Node]), + ?shutdown(Node) + end. + +split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])]; +split_node([H|T], Chr, Ack) -> split_node(T, Chr, [H|Ack]); +split_node([], _, Ack) -> [lists:reverse(Ack)]. + |