diff options
Diffstat (limited to 'lib/orber/src/orber_socket.erl')
-rw-r--r-- | lib/orber/src/orber_socket.erl | 530 |
1 files changed, 0 insertions, 530 deletions
diff --git a/lib/orber/src/orber_socket.erl b/lib/orber/src/orber_socket.erl deleted file mode 100644 index 9b39dad928..0000000000 --- a/lib/orber/src/orber_socket.erl +++ /dev/null @@ -1,530 +0,0 @@ -%%-------------------------------------------------------------------- -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2015. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%%%% %CopyrightEnd% -%% -%% -%%----------------------------------------------------------------- -%% File: orber_socket.erl -%% -%% Description: -%% This file contains a standard interface to the sockets to handle the differences -%% between the implementations used. -%% -%%----------------------------------------------------------------- --module(orber_socket). - --include_lib("orber/include/corba.hrl"). --include_lib("orber/src/orber_iiop.hrl"). - - -%%----------------------------------------------------------------- -%% External exports -%%----------------------------------------------------------------- --export([start/0, connect/4, listen/3, listen/4, accept/2, accept/3, write/3, - controlling_process/3, close/2, peername/2, sockname/2, - peerdata/2, peercert/2, sockdata/2, setopts/3, - clear/2, shutdown/3, post_accept/2, post_accept/3, - get_ip_family_opts/1]). - -%%----------------------------------------------------------------- -%% Internal exports -%%----------------------------------------------------------------- --export([]). - -%%----------------------------------------------------------------- -%% Internal defines -%%----------------------------------------------------------------- --define(DEBUG_LEVEL, 6). - -%%----------------------------------------------------------------- -%% External functions -%%----------------------------------------------------------------- -start() -> - inet_db:start(). - -%%----------------------------------------------------------------- -%% Invoke the required setopts (i.e., inet or ssl) -setopts(normal, Socket, Opts) -> - inet:setopts(Socket, Opts); -setopts(ssl, Socket, Opts) -> - ssl:setopts(Socket, Opts). - -%%----------------------------------------------------------------- -%% Connect to IIOP Port at Host in CDR mode, in order to -%% establish a connection. -%% -connect(Type, Host, Port, Options) -> - Timeout = orber:iiop_setup_connection_timeout(), - Generation = orber_env:ssl_generation(), - Options1 = check_options(Type, Options, Generation), - Options2 = - case Type of - normal -> - [{keepalive, orber_env:iiop_out_keepalive()}|Options1]; - _ -> - Options1 - end, - case orber:iiop_out_ports() of - {Min, Max} when Type == normal -> - multi_connect(get_port_sequence(Min, Max), orber_env:iiop_out_ports_attempts(), - Type, Host, Port, [binary, {reuseaddr, true}, - {packet,cdr}| Options2], Timeout); - {Min, Max} when Generation > 2 -> - multi_connect(get_port_sequence(Min, Max), orber_env:iiop_out_ports_attempts(), - Type, Host, Port, [binary, {reuseaddr, true}, - {packet,cdr}| Options2], Timeout); - {Min, Max} -> - %% reuseaddr not available for older SSL versions - multi_connect(get_port_sequence(Min, Max), orber_env:iiop_out_ports_attempts(), - Type, Host, Port, [binary, {packet,cdr}| Options2], Timeout); - _ -> - connect(Type, Host, Port, [binary, {packet,cdr}| Options2], Timeout) - end. - -connect(normal, Host, Port, Options, Timeout) -> - case catch gen_tcp:connect(Host, Port, Options, Timeout) of - {ok, Socket} -> - Socket; - {error, timeout} -> - orber:dbg("[~p] orber_socket:connect(normal, ~p, ~p, ~p);~n" - "Timeout after ~p msec.", - [?LINE, Host, Port, Options, Timeout], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4), - completion_status=?COMPLETED_NO}); - Error -> - orber:dbg("[~p] orber_socket:connect(normal, ~p, ~p, ~p);~n" - "Failed with reason: ~p", - [?LINE, Host, Port, Options, Error], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end; -connect(ssl, Host, Port, Options, Timeout) -> - case catch ssl:connect(Host, Port, Options, Timeout) of - {ok, Socket} -> - Socket; - {error, timeout} -> - orber:dbg("[~p] orber_socket:connect(ssl, ~p, ~p, ~p);~n" - "Timeout after ~p msec.", - [?LINE, Host, Port, Options, Timeout], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4), - completion_status=?COMPLETED_NO}); - Error -> - orber:dbg("[~p] orber_socket:connect(ssl, ~p, ~p, ~p);~n" - "Failed with reason: ~p", - [?LINE, Host, Port, Options, Error], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end. - -multi_connect([], _Retries, Type, Host, Port, Options, _) -> - orber:dbg("[~p] orber_socket:multi_connect(~p, ~p, ~p, ~p);~n" - "Unable to use any of the sockets defined by 'iiop_out_ports'.~n" - "Either all ports are in use or to many connections already exists.", - [?LINE, Type, Host, Port, Options], ?DEBUG_LEVEL), - corba:raise(#'IMP_LIMIT'{minor=(?ORBER_VMCID bor 1), completion_status=?COMPLETED_NO}); -multi_connect([CurrentPort|Rest], Retries, normal, Host, Port, Options, Timeout) -> - case catch gen_tcp:connect(Host, Port, [{port, CurrentPort}|Options], Timeout) of - {ok, Socket} -> - Socket; - {error, timeout} when Retries =< 1 -> - orber:dbg("[~p] orber_socket:multi_connect(normal, ~p, ~p, ~p);~n" - "Timeout after ~p msec.", - [?LINE, Host, Port, [{port, CurrentPort}|Options], - Timeout], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4), - completion_status=?COMPLETED_NO}); - _ -> - multi_connect(Rest, Retries - 1, normal, Host, Port, Options, Timeout) - end; -multi_connect([CurrentPort|Rest], Retries, ssl, Host, Port, Options, Timeout) -> - case catch ssl:connect(Host, Port, [{port, CurrentPort}|Options], Timeout) of - {ok, Socket} -> - Socket; - {error, timeout} when Retries =< 1 -> - orber:dbg("[~p] orber_socket:multi_connect(ssl, ~p, ~p, ~p);~n" - "Timeout after ~p msec.", - [?LINE, Host, Port, [{port, CurrentPort}|Options], - Timeout], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{minor=(?ORBER_VMCID bor 4), - completion_status=?COMPLETED_NO}); - _ -> - multi_connect(Rest, Retries - 1, ssl, Host, Port, Options, Timeout) - end. - - -get_port_sequence(Min, Max) -> - case orber_env:iiop_out_ports_random() of - true -> - Seq = lists:seq(Min, Max), - random_sequence((Max - Min) + 1, Seq, []); - _ -> - lists:seq(Min, Max) - end. - -random_sequence(0, _, Acc) -> - Acc; -random_sequence(Length, Seq, Acc) -> - Nth = rand:uniform(Length), - Value = lists:nth(Nth, Seq), - NewSeq = lists:delete(Value, Seq), - random_sequence(Length-1, NewSeq, [Value|Acc]). - -%%----------------------------------------------------------------- -%% Create a listen socket at Port in CDR mode for -%% data connection. -%% -listen(Type, Port, Options) -> - listen(Type, Port, Options, true). - -listen(normal, Port, Options, Exception) -> - Options1 = check_options(normal, Options, 0), - Backlog = orber:iiop_backlog(), - Keepalive = orber_env:iiop_in_keepalive(), - Options2 = case orber:iiop_max_in_requests() of - infinity -> - Options1; - _MaxRequests -> - [{active, once}|Options1] - end, - Options3 = case orber_env:iiop_packet_size() of - infinity -> - Options2; - MaxSize -> - [{packet_size, MaxSize}|Options2] - end, - Options4 = [binary, {packet,cdr}, {keepalive, Keepalive}, - {reuseaddr,true}, {backlog, Backlog} | - Options3], - - case catch gen_tcp:listen(Port, Options4) of - {ok, ListenSocket} -> - {ok, ListenSocket, check_port(Port, normal, ListenSocket)}; - {error, Reason} when Exception == false -> - {error, Reason}; - {error, eaddrinuse} -> - orber:dbg("[~p] orber_socket:listen(normal, ~p, ~p);~n" - "Looks like the listen port is already in use.~n" - "Check if another Orber is started~n" - "on the same node and uses the same listen port (iiop_port). But it may also~n" - "be used by any other application; confirm with 'netstat'.", - [?LINE, Port, Options4], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}); - Error -> - orber:dbg("[~p] orber_socket:listen(normal, ~p, ~p);~n" - "Failed with reason: ~p", - [?LINE, Port, Options4, Error], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end; -listen(ssl, Port, Options, Exception) -> - Backlog = orber:iiop_ssl_backlog(), - Generation = orber_env:ssl_generation(), - Options1 = check_options(ssl, Options, Generation), - Options2 = case orber:iiop_max_in_requests() of - infinity -> - Options1; - _MaxRequests -> - [{active, once}|Options1] - end, - Options3 = case orber_env:iiop_packet_size() of - infinity -> - Options2; - MaxSize -> - [{packet_size, MaxSize}|Options2] - end, - Options4 = if - Generation > 2 -> - [{reuseaddr, true} |Options3]; - true -> - Options3 - end, - Options5 = [binary, {packet,cdr}, {backlog, Backlog} | Options4], - case catch ssl:listen(Port, Options5) of - {ok, ListenSocket} -> - {ok, ListenSocket, check_port(Port, ssl, ListenSocket)}; - {error, Reason} when Exception == false -> - {error, Reason}; - {error, eaddrinuse} -> - orber:dbg("[~p] orber_socket:listen(ssl, ~p, ~p);~n" - "Looks like the listen port is already in use. Check if~n" - "another Orber is started on the same node and uses the~n" - "same listen port (iiop_port). But it may also~n" - "be used by any other application; confirm with 'netstat'.", - [?LINE, Port, Options5], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}); - Error -> - orber:dbg("[~p] orber_socket:listen(ssl, ~p, ~p);~n" - "Failed with reason: ~p", - [?LINE, Port, Options5, Error], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end. - -%%----------------------------------------------------------------- -%% Wait in accept on the socket -%% -accept(Type, ListenSocket) -> - accept(Type, ListenSocket, infinity). - -accept(normal, ListenSocket, _Timeout) -> - case catch gen_tcp:accept(ListenSocket) of - {ok, S} -> - S; - Error -> - orber:dbg("[~p] orber_socket:accept(normal, ~p);~n" - "Failed with reason: ~p", - [?LINE, ListenSocket, Error], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end; -accept(ssl, ListenSocket, Timeout) -> - case catch ssl:transport_accept(ListenSocket, Timeout) of - {ok, S} -> - S; - Error -> - orber:dbg("[~p] orber_socket:accept(ssl, ~p);~n" - "Failed with reason: ~p", - [?LINE, ListenSocket, Error], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end. - -post_accept(Type, Socket) -> - post_accept(Type, Socket, infinity). - -post_accept(normal, _Socket, _Timeout) -> - ok; -post_accept(ssl, Socket, Timeout) -> - case catch ssl:ssl_accept(Socket, Timeout) of - ok -> - ok; - Error -> - orber:dbg("[~p] orber_socket:post_accept(ssl, ~p);~n" - "Failed with reason: ~p", - [?LINE, Socket, Error], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end. - - -%%----------------------------------------------------------------- -%% Close the socket -%% -close(normal, Socket) -> - (catch gen_tcp:close(Socket)); -close(ssl, Socket) -> - (catch ssl:close(Socket)). - -%%----------------------------------------------------------------- -%% Write to socket -%% -write(normal, Socket, Bytes) -> - gen_tcp:send(Socket, Bytes); -write(ssl, Socket, Bytes) -> - ssl:send(Socket, Bytes). - -%%----------------------------------------------------------------- -%% Change the controlling process for the socket -%% -controlling_process(normal, Socket, Pid) -> - gen_tcp:controlling_process(Socket, Pid); -controlling_process(ssl, Socket, Pid) -> - ssl:controlling_process(Socket, Pid). - -%%----------------------------------------------------------------- -%% Get peername -%% -peername(normal, Socket) -> - inet:peername(Socket); -peername(ssl, Socket) -> - ssl:peername(Socket). - -%%----------------------------------------------------------------- -%% Get peercert -%% -peercert(ssl, Socket) -> - ssl:peercert(Socket); -peercert(Type, _Socket) -> - orber:dbg("[~p] orber_socket:peercert(~p);~n" - "Only available for SSL sockets.", - [?LINE, Type], ?DEBUG_LEVEL), - {error, ebadsocket}. - -%%----------------------------------------------------------------- -%% Get peerdata -%% -peerdata(normal, Socket) -> - create_data(inet:peername(Socket)); -peerdata(ssl, Socket) -> - create_data(ssl:peername(Socket)). - -%%----------------------------------------------------------------- -%% Get sockname -%% -sockname(normal, Socket) -> - inet:sockname(Socket); -sockname(ssl, Socket) -> - ssl:sockname(Socket). - -%%----------------------------------------------------------------- -%% Get sockdata -%% -sockdata(normal, Socket) -> - create_data(inet:sockname(Socket)); -sockdata(ssl, Socket) -> - create_data(ssl:sockname(Socket)). - - -create_data({ok, {Addr, Port}}) -> - {orber_env:addr2str(Addr), Port}; -create_data(What) -> - orber:dbg("[~p] orber_socket:peername() or orber_socket:sockname();~n" - "Failed with reason: ~p", [?LINE, What], ?DEBUG_LEVEL), - {"Unable to lookup peer- or sockname", 0}. - - -%%----------------------------------------------------------------- -%% Shutdown Connection -%% How = read | write | read_write -shutdown(normal, Socket, How) -> - gen_tcp:shutdown(Socket, How); -shutdown(ssl, Socket, How) -> - Generation = orber_env:ssl_generation(), - if - Generation > 2 -> - ssl:shutdown(Socket, How); - How == read_write -> - %% Older versions of SSL do no support shutdown. - %% For now we'll use this solution instead. - close(ssl, Socket); - true -> - {error, undefined} - end. - -%%----------------------------------------------------------------- -%% Remove Messages from queue -%% -clear(normal, Socket) -> - tcp_clear(Socket); -clear(ssl, Socket) -> - ssl_clear(Socket). - - - -%% Inet also checks for the following messages: -%% * {S, {data, Data}} -%% * {inet_async, S, Ref, Status}, -%% * {inet_reply, S, Status} -%% SSL doesn't. -tcp_clear(Socket) -> - receive - {tcp, Socket, _Data} -> - tcp_clear(Socket); - {tcp_closed, Socket} -> - tcp_clear(Socket); - {tcp_error, Socket, _Reason} -> - tcp_clear(Socket) - after 0 -> - ok - end. - -ssl_clear(Socket) -> - receive - {ssl, Socket, _Data} -> - ssl_clear(Socket); - {ssl_closed, Socket} -> - ssl_clear(Socket); - {ssl_error, Socket, _Reason} -> - ssl_clear(Socket) - after 0 -> - ok - end. - - - -%%----------------------------------------------------------------- -%% Check Port. If the user supplies 0 we pick any vacant port. But then -%% we must change the associated environment variable -check_port(0, normal, Socket) -> - case inet:port(Socket) of - {ok, Port} -> - orber:configure_override(iiop_port, Port), - Port; - What -> - orber:dbg("[~p] orber_socket:check_port(~p);~n" - "Unable to extract the port number via inet:port/1~n", - [?LINE, What], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end; -check_port(0, ssl, Socket) -> - case ssl:sockname(Socket) of - {ok, {_Address, Port}} -> - orber:configure_override(iiop_ssl_port, Port), - Port; - What -> - orber:dbg("[~p] orber_socket:check_port(~p);~n" - "Unable to extract the port number via ssl:sockname/1~n", - [?LINE, What], ?DEBUG_LEVEL), - corba:raise(#'COMM_FAILURE'{completion_status=?COMPLETED_NO}) - end; -check_port(Port, _, _) -> - Port. - -%%----------------------------------------------------------------- -%% Check Options. -check_options(normal, Options, _Generation) -> - Options; -check_options(ssl, Options, Generation) -> - if - Generation > 2 -> - [{ssl_imp, new}|Options]; - true -> - [{ssl_imp, old}|Options] - end. - - -%%----------------------------------------------------------------- -%% Check IP Family. -get_ip_family_opts(Host) -> - case inet:parse_address(Host) of - {ok, {_,_,_,_}} -> - [inet]; - {ok, {_,_,_,_,_,_,_,_}} -> - [inet6]; - {error, einval} -> - check_family_for_name(Host, orber_env:ip_version()) - end. - -check_family_for_name(Host, inet) -> - case inet:getaddr(Host, inet) of - {ok, _Address} -> - [inet]; - {error, _} -> - case inet:getaddr(Host, inet6) of - {ok, _Address} -> - [inet6]; - {error, _} -> - [inet] - end - end; -check_family_for_name(Host, inet6) -> - case inet:getaddr(Host, inet6) of - {ok, _Address} -> - [inet6]; - {error, _} -> - case inet:getaddr(Host, inet) of - {ok, _Address} -> - [inet]; - {error, _} -> - [inet6] - end - end. - |