summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicael Karlberg <bmk@erlang.org>2021-09-02 11:39:52 +0200
committerMicael Karlberg <bmk@erlang.org>2021-09-02 11:39:52 +0200
commit94d230be77ac1f8a26db869b16987e55795fc000 (patch)
tree03bb8dbe5b215d6c82b1d93e121322d2b44e5e61
parent8591132d91fce51eb7409b64c3d905aa8324f268 (diff)
parentecf6b31a8e28f523e3e88bd0a8c2f5ea52e4237a (diff)
downloaderlang-94d230be77ac1f8a26db869b16987e55795fc000.tar.gz
Merge branch 'bmk/megaco/20210830/use_inet_backend/OTP-17533' into maint
OTP-17533 (OTP-17156)
-rw-r--r--lib/kernel/src/gen_tcp_socket.erl66
-rw-r--r--lib/megaco/doc/src/megaco_tcp.xml38
-rw-r--r--lib/megaco/doc/src/megaco_udp.xml34
-rw-r--r--lib/megaco/src/tcp/megaco_tcp.erl93
-rw-r--r--lib/megaco/src/tcp/megaco_tcp.hrl9
-rw-r--r--lib/megaco/src/tcp/megaco_tcp_accept.erl22
-rw-r--r--lib/megaco/src/udp/megaco_udp.erl44
-rw-r--r--lib/megaco/src/udp/megaco_udp.hrl5
-rw-r--r--lib/megaco/src/udp/megaco_udp_server.erl31
-rw-r--r--lib/megaco/test/megaco_load_SUITE.erl125
-rw-r--r--lib/megaco/test/megaco_mreq_SUITE.erl123
-rw-r--r--lib/megaco/test/megaco_tcp_SUITE.erl197
-rw-r--r--lib/megaco/test/megaco_test_lib.erl92
-rw-r--r--lib/megaco/test/megaco_test_lib.hrl12
-rw-r--r--lib/megaco/test/megaco_test_mg.erl121
-rw-r--r--lib/megaco/test/megaco_test_mgc.erl107
-rw-r--r--lib/megaco/test/megaco_udp_SUITE.erl150
17 files changed, 934 insertions, 335 deletions
diff --git a/lib/kernel/src/gen_tcp_socket.erl b/lib/kernel/src/gen_tcp_socket.erl
index 1841623241..12e6e15f4c 100644
--- a/lib/kernel/src/gen_tcp_socket.erl
+++ b/lib/kernel/src/gen_tcp_socket.erl
@@ -50,7 +50,7 @@
-include("inet_int.hrl").
--define(DBG(T), erlang:display({{self(), ?MODULE, ?LINE, ?FUNCTION_NAME}, T})).
+%% -define(DBG(T), erlang:display({{self(), ?MODULE, ?LINE, ?FUNCTION_NAME}, T})).
%% -------------------------------------------------------------------------
@@ -1127,6 +1127,7 @@ server_opts() ->
-compile({inline, [meta/1]}).
meta(D) -> maps:with(maps:keys(server_write_opts()), D).
+
%%% ========================================================================
%%% State Machine
%%%
@@ -1249,7 +1250,7 @@ init({prepare, D, Owner}) ->
owner_mon = OwnerMon},
{ok, accept, {P, D#{type => undefined, buffer => <<>>}}};
init(Arg) ->
- error_logger:error_report([{badarg, {?MODULE, init, [Arg]}}]),
+ error_report([{badarg, {?MODULE, init, [Arg]}}]),
error(badarg, [Arg]).
@@ -1694,17 +1695,15 @@ handle_event(
%% Handle select done - try recv again
handle_event(
info, ?socket_select(Socket, SelectRef),
- #recv{info = ?select_info(SelectRef)},
+ #recv{info = ?select_info(SelectRef)} = _State,
{#params{socket = Socket} = P, D}) ->
- %%
%% ?DBG([info, {socket, Socket}, {ref, SelectRef}]),
handle_recv(P, D, []);
%%
handle_event(
info, ?socket_abort(Socket, SelectRef, Reason),
- #recv{info = ?select_info(SelectRef)},
+ #recv{info = ?select_info(SelectRef)} = _State,
{#params{socket = Socket} = P, D}) ->
- %%
%% ?DBG({abort, Reason}),
handle_connected(P, cleanup_recv_reply(P, D, [], Reason));
%%
@@ -1764,9 +1763,9 @@ handle_shutdown2(Socket, NextState, How) ->
handle_unexpected(Type, Content, State, {P, _D}) ->
- error_logger:warning_report(
- [{module, ?MODULE}, {socket, P#params.socket},
- {unknown_event, {Type, Content}}, {state, State}]),
+ warning_report([{socket, P#params.socket},
+ {unknown_event, {Type, Content}},
+ {state, State}]),
case Type of
{call, From} ->
{keep_state_and_data,
@@ -1781,9 +1780,9 @@ handle_closed(Type, Content, State, {P, _D}) ->
{keep_state_and_data,
[{reply, From, {error, closed}}]};
_ ->
- error_logger:warning_report(
- [{module, ?MODULE}, {socket, P#params.socket},
- {unknown_event, {Type, Content}}, {state, State}]),
+ warning_report([{socket, P#params.socket},
+ {unknown_event, {Type, Content}},
+ {state, State}]),
keep_state_and_data
end.
@@ -1999,14 +1998,14 @@ handle_buffered(P, #{packet_size := PacketSize} = D,
%% What do we do here?
%% Keep the buffer and hope that it will go better with more data?
%% Or discard it and continue as if nothing happened?
- error_logger:warning_msg("Failed decoding message"
- "~n Socket: ~p"
- "~n Socket server: ~p"
- "~n Packet type: ~p"
- "~n byte_size(Data): ~p"
- "~n Reason: ~p",
- [P#params.socket, self(),
- Type, byte_size(Data), Reason]),
+ warning_msg("Failed decoding message"
+ "~n Socket: ~p"
+ "~n Socket server: ~p"
+ "~n Packet type: ~p"
+ "~n byte_size(Data): ~p"
+ "~n Reason: ~p",
+ [P#params.socket, self(),
+ Type, byte_size(Data), Reason]),
D
end.
@@ -2557,6 +2556,7 @@ state_setopts_server(P, D, State, Opts, {Tag, Value}) ->
end.
state_setopts_active(P, D, State, Opts, Active) ->
+ %% ?DBG([{active, Active}]),
if
Active =:= once;
Active =:= true ->
@@ -2780,8 +2780,34 @@ timeout(EndTime) ->
-endif.
+
%% -------------------------------------------------------------------------
error_msg(F, A) ->
error_logger:error_msg(F ++ "~n", A).
+warning_msg(F, A) ->
+ error_logger:error_msg(F ++ "~n", A).
+
+error_report(Report) ->
+ error_logger:error_report(Report).
+
+warning_report(Report) ->
+ error_logger:warning_report([{module, ?MODULE}|Report]).
+
+
+
+%% -------------------------------------------------------------------------
+
+%% formated_timestamp() ->
+%% format_timestamp(os:timestamp()).
+
+%% format_timestamp(TS) ->
+%% megaco:format_timestamp(TS).
+
+%% d(F) ->
+%% d(F, []).
+
+%% d(F, A) ->
+%% io:format("*** [~s] ~p ~w " ++ F ++ "~n",
+%% [formated_timestamp(), self(), ?MODULE | A]).
diff --git a/lib/megaco/doc/src/megaco_tcp.xml b/lib/megaco/doc/src/megaco_tcp.xml
index 74a16eefab..eee44ef7f2 100644
--- a/lib/megaco/doc/src/megaco_tcp.xml
+++ b/lib/megaco/doc/src/megaco_tcp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2020</year>
+ <year>2000</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -56,7 +56,7 @@
<type>
<v>TransportRef = pid() | regname()</v>
<v>OptionListPerPort = [Option]</v>
- <v>Option = {port, integer()} |{options, list()} |{receive_handle, term()}</v>
+ <v>Option = {port, integer()} | {options, list()} | {receive_handle, term()} | {inet_backend, default | inet | socket}</v>
</type>
<desc>
<p>This function is used for starting new TPKT listening socket
@@ -64,25 +64,43 @@
definitions.</p>
</desc>
</func>
+
<func>
<name since="">connect(TransportRef, OptionList) -> {ok, Handle, ControlPid} | {error, Reason}</name>
<fsummary></fsummary>
<type>
<v>TransportRef = pid() | regname()</v>
<v>OptionList = [Option]</v>
- <v>Option = {host, Ipaddr} | {port, integer()} |{options, list()} |{receive_handle, term()} |{module, atom()}</v>
+ <v>Option = {host, IpAddr} |
+ {port, integer()} |
+ {options, list()} |
+ {receive_handle, term()} |
+ {module, atom()} |
+ {inet_backend, default | inet | socket}</v>
<v>Handle = socket_handle()</v>
<v>ControlPid = pid()</v>
<v>Reason = term()</v>
</type>
<desc>
- <p>This function is used to open a TPKT connection.</p>
- <p>The <c><![CDATA[module]]></c> option makes it possible for the user to provide
- their own callback module. The <c><![CDATA[receive_message/4]]></c> or
- <c><![CDATA[process_received_message/4]]></c> functions of this module is called
- when a new message is received (which one depends on the size of the
- message; small - receive_message, large - process_received_message).
- Default value is <em>megaco</em>.</p>
+ <p>This function is used to open a TPKT connection.</p>
+ <taglist>
+ <tag><c><![CDATA[module]]></c></tag>
+ <item>
+ <p>This option makes it possible for the user to provide
+ their own callback module.
+ The <c><![CDATA[receive_message/4]]></c>
+ or <c><![CDATA[process_received_message/4]]></c> functions of
+ this module is called when a new message is received.
+ Which one is called depends on the size of the message; </p>
+ <taglist>
+ <tag><c><![CDATA[small]]></c></tag>
+ <item><p>receive_message</p></item>
+ <tag><c><![CDATA[large]]></c></tag>
+ <item><p>process_received_message</p></item>
+ </taglist>
+ <p>Default value is <em>megaco</em>. </p>
+ </item>
+ </taglist>
</desc>
</func>
<func>
diff --git a/lib/megaco/doc/src/megaco_udp.xml b/lib/megaco/doc/src/megaco_udp.xml
index 2809bc8ce9..f9dc551f6c 100644
--- a/lib/megaco/doc/src/megaco_udp.xml
+++ b/lib/megaco/doc/src/megaco_udp.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2000</year><year>2020</year>
+ <year>2000</year><year>2021</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -56,20 +56,36 @@
<type>
<v>TransportRef = pid() | regname()</v>
<v>OptionList = [option()]</v>
- <v>option() = {port, integer()} |{options, list()} |{receive_handle, receive_handle()} |{module, atom()}</v>
+ <v>option() = {port, integer()} |
+ {options, list()} |
+ {receive_handle, receive_handle()} |
+ {module, atom()} |
+ {inet_backend, default | inet | socket}</v>
<v>Handle = socket_handle()</v>
<v>receive_handle() = term()</v>
<v>ControlPid = pid()</v>
<v>Reason = term()</v>
</type>
<desc>
- <p>This function is used to open an UDP/IP socket.</p>
- <p>The <c><![CDATA[module]]></c> option makes it possible for the user to provide
- their own callback module. The functions <c><![CDATA[receive_message/4]]></c> or
- <c><![CDATA[process_received_message/4]]></c> of this module is called when a new
- message is received (which one depends on the size of the message;
- small - receive_message, large - process_received_message).
- Default value is <em>megaco</em>.</p>
+ <p>This function is used to open an UDP/IP socket.</p>
+ <taglist>
+ <tag><c><![CDATA[module]]></c></tag>
+ <item>
+ <p>The option makes it possible for the user to provide
+ their own callback module.
+ The functions <c><![CDATA[receive_message/4]]></c> or
+ <c><![CDATA[process_received_message/4]]></c>
+ of this module is called when a new message is received.
+ Which one depends on the size of the message: </p>
+ <taglist>
+ <tag><c><![CDATA[small]]></c></tag>
+ <item><p>receive_message</p></item>
+ <tag><c><![CDATA[large]]></c></tag>
+ <item><p>process_received_message</p></item>
+ </taglist>
+ <p>Default value is <em>megaco</em>.</p>
+ </item>
+ </taglist>
</desc>
</func>
<func>
diff --git a/lib/megaco/src/tcp/megaco_tcp.erl b/lib/megaco/src/tcp/megaco_tcp.erl
index 1735439501..460e679efc 100644
--- a/lib/megaco/src/tcp/megaco_tcp.erl
+++ b/lib/megaco/src/tcp/megaco_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. 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.
@@ -66,6 +66,8 @@
reset_stats/0, reset_stats/1
]).
+%% -export([tcp_sockets/0]).
+
%%-----------------------------------------------------------------
%% Internal exports
@@ -177,11 +179,18 @@ connect(SupPid, Parameters) ->
?d1("connect -> options parsed: "
"~n Rec: ~p", [Rec]),
- #megaco_tcp{host = Host,
- port = Port,
- options = Options} = Rec,
+ #megaco_tcp{host = Host,
+ port = Port,
+ options = Options,
+ inet_backend = IB} = Rec,
- IpOpt = [binary, {packet, tpkt}, {active, once} | Options],
+ IpOpt =
+ case IB of
+ default ->
+ [];
+ _ ->
+ [{inet_backend, IB}]
+ end ++ [binary, {packet, tpkt}, {active, once} | Options],
%%------------------------------------------------------
%% Connect the other side
@@ -376,7 +385,7 @@ create_snmp_counters(Socket, [Counter|Counters]) ->
%%-----------------------------------------------------------------
init({SupPid, _}) ->
process_flag(trap_exit, true),
- {ok, #state{supervisor_pid = SupPid}}.
+ {ok, #state{supervisor_pid = SupPid, linkdb = []}}.
%%-----------------------------------------------------------------
%% Func: terminate/1
@@ -409,7 +418,11 @@ start_tcp_listener(P, State) ->
{error, Reason} ->
?d1("start_tcp_listener -> setup failed"
"~n Reason: ~p", [Reason]),
- {reply, {error, {could_not_start_listener, Reason}}, State}
+ DB = State#state.linkdb,
+ DBStatus = [{LPid, {LRec, LSock}, inet:info(LSock)} ||
+ {LPid, {LRec, LSock}} <- DB],
+ Reply = {error, {could_not_start_listener, Reason, DBStatus}},
+ {reply, Reply, State}
end.
@@ -480,10 +493,18 @@ setup(SupPid, Options) ->
%%------------------------------------------------------
%% Setup the listen socket
- IpOpts = [binary, {packet, tpkt}, {active, once},
- {reuseaddr, true} | TcpRec#megaco_tcp.options],
- case catch gen_tcp:listen(TcpRec#megaco_tcp.port, IpOpts) of
- {ok, Listen} ->
+ IpOpts =
+ case TcpRec#megaco_tcp.inet_backend of
+ default ->
+ [];
+ IB ->
+ [{inet_backend, IB}]
+ end ++
+ [binary, {packet, tpkt}, {active, once},
+ {reuseaddr, true} | TcpRec#megaco_tcp.options],
+ Port = TcpRec#megaco_tcp.port,
+ case catch gen_tcp:listen(Port, IpOpts) of
+ {ok, LSock} ->
?d1("setup -> listen ok"
"~n Listen: ~p", [Listen]),
@@ -491,14 +512,13 @@ setup(SupPid, Options) ->
%%-----------------------------------------------
%% Startup the accept process that will wait for
%% connect attempts
- case start_accept(SupPid, TcpRec, Listen) of
+ case start_accept(SupPid, TcpRec, LSock) of
{ok, Pid} ->
-
?d1("setup -> accept process started"
"~n Pid: ~p", [Pid]),
-
?tcp_debug(TcpRec, "tcp listen setup", []),
- {ok, Pid, {TcpRec, Listen}};
+ {ok, Pid, {TcpRec, LSock}};
+
{error, _Reason} = Error ->
?d1("setup -> failed starting accept process"
"~n Error: ~p", [Error]),
@@ -506,16 +526,17 @@ setup(SupPid, Options) ->
[Error]),
Error
end;
+
{error, Reason} ->
?d1("setup -> listen failed"
"~n Reason: ~p", [Reason]),
- Error = {error, {gen_tcp_listen, Reason}},
+ Error = {error, {gen_tcp_listen, Reason, [Port, IpOpts]}},
?tcp_debug(TcpRec, "tcp listen setup failed", [Error]),
Error;
{'EXIT', _Reason} = Exit ->
?d1("setup -> listen exited"
"~n Exit: ~p", [Exit]),
- Error = {error, {gen_tcp_listen, Exit}},
+ Error = {error, {gen_tcp_listen, Exit, [Port, IpOpts]}},
?tcp_debug(TcpRec, "tcp listen setup failed", [Error]),
Error
end;
@@ -642,6 +663,10 @@ parse_options([{Tag, Val} | T], TcpRec, Mand) ->
parse_options(T, TcpRec#megaco_tcp{module = Val}, Mand2);
serialize when (Val =:= true) orelse (Val =:= false) ->
parse_options(T, TcpRec#megaco_tcp{serialize = Val}, Mand2);
+ inet_backend when (Val =:= default) orelse
+ (Val =:= inet) orelse
+ (Val =:= socket) ->
+ parse_options(T, TcpRec#megaco_tcp{inet_backend = Val}, Mand2);
Bad ->
?d1("parse_options -> bad option: "
"~n Tag: ~p", [Tag]),
@@ -691,3 +716,37 @@ warning_msg(F, A) ->
call(Pid, Req) ->
gen_server:call(Pid, Req, infinity).
+
+
+%%-----------------------------------------------------------------
+
+%% formated_timestamp() ->
+%% format_timestamp(os:timestamp()).
+
+%% format_timestamp(TS) ->
+%% megaco:format_timestamp(TS).
+
+%% d(F) ->
+%% d(F, []).
+
+%% d(F, A) ->
+%% io:format("*** [~s] ~p ~w " ++ F ++ "~n",
+%% [formated_timestamp(), self(), ?MODULE | A]).
+
+
+%%-----------------------------------------------------------------
+
+%% tcp_sockets() ->
+%% port_list("tcp_inet") ++ gen_tcp_socket:which_sockets().
+
+
+%% %% Return all ports having the name 'Name'
+%% port_list(Name) ->
+%% lists:filter(
+%% fun(Port) ->
+%% case erlang:port_info(Port, name) of
+%% {name, Name} -> true;
+%% _ -> false
+%% end
+%% end, erlang:ports()).
+
diff --git a/lib/megaco/src/tcp/megaco_tcp.hrl b/lib/megaco/src/tcp/megaco_tcp.hrl
index 0c01f36b55..6d138eb2eb 100644
--- a/lib/megaco/src/tcp/megaco_tcp.hrl
+++ b/lib/megaco/src/tcp/megaco_tcp.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. 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.
@@ -34,12 +34,13 @@
proxy_pid,
receive_handle,
module = megaco,
- serialize = false % false: Spawn a new process for each message
+ serialize = false, % false: Spawn a new process for each message
+ inet_backend = default
}).
--define(GC_MSG_LIMIT,1000).
--define(HEAP_SIZE(S),5000 + 2*(S)).
+-define(GC_MSG_LIMIT, 1000).
+-define(HEAP_SIZE(S), 5000 + 2*(S)).
%%----------------------------------------------------------------------
diff --git a/lib/megaco/src/tcp/megaco_tcp_accept.erl b/lib/megaco/src/tcp/megaco_tcp_accept.erl
index 5fcff200aa..da163dcc10 100644
--- a/lib/megaco/src/tcp/megaco_tcp_accept.erl
+++ b/lib/megaco/src/tcp/megaco_tcp_accept.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. 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.
@@ -81,8 +81,7 @@ do_accept(Tcp, Sup, Fd) ->
{ok, S} ->
?d1("do_accept -> accepted: "
"~n S: ~p", [S]),
- case megaco_tcp:start_connection(Sup,
- Tcp#megaco_tcp{socket = S}) of
+ case megaco_tcp:start_connection(Sup, Tcp#megaco_tcp{socket = S}) of
{ok, Pid} ->
?d1("do_accept -> connection started"
"~n Pid: ~p", [Pid]),
@@ -122,3 +121,20 @@ tcp_clear(Socket) ->
after 0 ->
ok
end.
+
+
+
+%%-----------------------------------------------------------------
+
+%% formated_timestamp() ->
+%% format_timestamp(os:timestamp()).
+
+%% format_timestamp(TS) ->
+%% megaco:format_timestamp(TS).
+
+%% d(F) ->
+%% d(F, []).
+
+%% d(F, A) ->
+%% io:format("*** [~s] ~p ~w " ++ F ++ "~n",
+%% [formated_timestamp(), self(), ?MODULE | A]).
diff --git a/lib/megaco/src/udp/megaco_udp.erl b/lib/megaco/src/udp/megaco_udp.erl
index 01aaa90f6c..099f4b7455 100644
--- a/lib/megaco/src/udp/megaco_udp.erl
+++ b/lib/megaco/src/udp/megaco_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. 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.
@@ -114,9 +114,15 @@ open(SupPid, Options) ->
%%------------------------------------------------------
%% Setup the socket
- IpOpts = [binary, {reuseaddr, true}, {active, once} |
- UdpRec#megaco_udp.options],
-
+ IpOpts =
+ case UdpRec#megaco_udp.inet_backend of
+ default ->
+ [];
+ IB ->
+ [{inet_backend, IB}]
+ end ++
+ [binary, {reuseaddr, true}, {active, once} |
+ UdpRec#megaco_udp.options],
case (catch gen_udp:open(UdpRec#megaco_udp.port, IpOpts)) of
{ok, Socket} ->
?udp_debug(UdpRec, "udp open", []),
@@ -258,9 +264,9 @@ close(#send_handle{socket = Socket}) ->
close(Socket);
close(Socket) ->
?udp_debug({socket, Socket}, "udp close", []),
- case erlang:port_info(Socket, connected) of
- {connected, ControlPid} ->
- megaco_udp_server:stop(ControlPid);
+ case inet:info(Socket) of
+ #{owner := ControlPid} = _Info when is_pid(ControlPid) ->
+ (catch megaco_udp_server:stop(ControlPid));
undefined ->
{error, already_closed}
end.
@@ -294,8 +300,12 @@ parse_options([{Tag, Val} | T], UdpRec, Mand) ->
parse_options(T, UdpRec#megaco_udp{receive_handle = Val}, Mand2);
module when is_atom(Val) ->
parse_options(T, UdpRec#megaco_udp{module = Val}, Mand2);
- serialize when (Val =:= true) orelse (Val =:= false) ->
+ serialize when is_boolean(Val) ->
parse_options(T, UdpRec#megaco_udp{serialize = Val}, Mand2);
+ inet_backend when (Val =:= default) orelse
+ (Val =:= inet) orelse
+ (Val =:= socket) ->
+ parse_options(T, UdpRec#megaco_udp{inet_backend = Val}, Mand2);
Bad ->
{error, {bad_option, Bad}}
end;
@@ -321,5 +331,19 @@ incNumOutOctets(SH, NumOctets) ->
incCounter(Key, Inc) ->
ets:update_counter(megaco_udp_stats, Key, Inc).
-% incNumErrors(SH) ->
-% incCounter({SH, medGwyGatewayNumErrors}, 1).
+%% incNumErrors(SH) ->
+%% incCounter({SH, medGwyGatewayNumErrors}, 1).
+
+%%-----------------------------------------------------------------
+
+%% formated_timestamp() ->
+%% format_timestamp(os:timestamp()).
+
+%% format_timestamp(TS) ->
+%% megaco:format_timestamp(TS).
+
+%% d(F) ->
+%% d(F, []).
+
+%% d(F, A) ->
+%% io:format("*** [~s] ~p " ++ F ++ "~n", [formated_timestamp(), self() | A]).
diff --git a/lib/megaco/src/udp/megaco_udp.hrl b/lib/megaco/src/udp/megaco_udp.hrl
index b5422d28c9..2560b4ad96 100644
--- a/lib/megaco/src/udp/megaco_udp.hrl
+++ b/lib/megaco/src/udp/megaco_udp.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021. 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.
@@ -32,7 +32,8 @@
socket,
receive_handle,
module = megaco,
- serialize = false % false: Spawn a new process for each message
+ serialize = false, % false: Spawn a new process for each message
+ inet_backend = default
}).
diff --git a/lib/megaco/src/udp/megaco_udp_server.erl b/lib/megaco/src/udp/megaco_udp_server.erl
index 1df9a76671..5abb4165ae 100644
--- a/lib/megaco/src/udp/megaco_udp_server.erl
+++ b/lib/megaco/src/udp/megaco_udp_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2016. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. 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.
@@ -29,9 +29,11 @@
-behaviour(gen_server).
+
%%-----------------------------------------------------------------
%% Include files
%%-----------------------------------------------------------------
+
-include_lib("megaco/src/udp/megaco_udp.hrl").
-include_lib("megaco/src/app/megaco_internal.hrl").
@@ -39,6 +41,7 @@
%%-----------------------------------------------------------------
%% External exports
%%-----------------------------------------------------------------
+
-export([
start_link/1,
stop/1,
@@ -46,9 +49,11 @@
upgrade_receive_handle/2
]).
+
%%-----------------------------------------------------------------
%% Internal exports
%%-----------------------------------------------------------------
+
-export([
init/1,
handle_call/3,
@@ -60,6 +65,7 @@
handle_received_message/5
]).
+
%%-----------------------------------------------------------------
%% External interface functions
%%-----------------------------------------------------------------
@@ -71,6 +77,7 @@
start_link(Arg) ->
gen_server:start_link(?MODULE, Arg, []).
+
%%-----------------------------------------------------------------
%% Func: stop/1
%% Description: Stops the process that keeps track of an UDP
@@ -83,6 +90,7 @@ stop(Pid) ->
upgrade_receive_handle(Pid, NewHandle) ->
call(Pid, {upgrade_receive_handle, NewHandle}).
+
%%-----------------------------------------------------------------
%% Internal interface functions
%%-----------------------------------------------------------------
@@ -98,6 +106,7 @@ init(Arg) ->
?udp_debug(Arg, "udp server starting", [self()]),
{ok, Arg}.
+
%%-----------------------------------------------------------------
%% Func: terminate/2
%% Description: Termination function for the generic server
@@ -106,6 +115,7 @@ terminate(Reason, State) ->
?udp_debug(State, "udp server terminating", [self(), Reason]),
ok.
+
%%-----------------------------------------------------------------
%% Func: handle_call/3
%% Description: Handling call messages (really just stop and garbage)
@@ -120,6 +130,7 @@ handle_call(Req, From, UdpRec) ->
"~n~p", [From, Req]),
{reply, {error, {invalid_request, Req}}, UdpRec}.
+
%%-----------------------------------------------------------------
%% Func: handle_cast/2
%% Description: Handling cast messages (really just stop and garbage)
@@ -132,12 +143,13 @@ handle_cast(Msg, UdpRec) ->
"~n~w", [Msg]),
{noreply, UdpRec}.
+
%%-----------------------------------------------------------------
%% Func: handle_info/2
%% Description: Handling non call/cast messages. Incomming messages
%% from the socket and exit codes.
%%-----------------------------------------------------------------
-handle_info({udp, _UdpId, Ip, Port, Msg},
+handle_info({udp, _Socket, Ip, Port, Msg},
#megaco_udp{serialize = false} = UdpRec) ->
#megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec,
SH = megaco_udp:create_send_handle(Socket, Ip, Port),
@@ -150,9 +162,9 @@ handle_info({udp, _UdpId, Ip, Port, Msg},
Sz ->
receive_message(Mod, RH, SH, Sz, Msg)
end,
- inet:setopts(Socket, [{active, once}]),
+ activate(Socket),
{noreply, UdpRec};
-handle_info({udp, _UdpId, Ip, Port, Msg},
+handle_info({udp, _Socket, Ip, Port, Msg},
#megaco_udp{serialize = true} = UdpRec) ->
#megaco_udp{socket = Socket, module = Mod, receive_handle = RH} = UdpRec,
SH = megaco_udp:create_send_handle(Socket, Ip, Port),
@@ -160,7 +172,7 @@ handle_info({udp, _UdpId, Ip, Port, Msg},
incNumInMessages(SH),
incNumInOctets(SH, MsgSize),
process_received_message(Mod, RH, SH, Msg),
- inet:setopts(Socket, [{active, once}]),
+ activate(Socket),
{noreply, UdpRec};
handle_info(Info, UdpRec) ->
warning_msg("received unexpected info: "
@@ -203,6 +215,11 @@ do_stop(#megaco_udp{socket = Socket}) ->
gen_udp:close(Socket).
+-compile({inline, [activate/1]}).
+activate(Socket) ->
+ inet:setopts(Socket, [{active, once}]).
+
+
%%-----------------------------------------------------------------
%% Func: incNumInMessages/1, incNumInOctets/2, incNumErrors/1
%% Description: SNMP counter increment functions
@@ -217,8 +234,8 @@ incNumInOctets(SH, NumOctets) ->
incCounter(Key, Inc) ->
ets:update_counter(megaco_udp_stats, Key, Inc).
-% incNumErrors(SH) ->
-% incCounter({SH, medGwyGatewayNumErrors}, 1).
+%% incNumErrors(SH) ->
+%% incCounter({SH, medGwyGatewayNumErrors}, 1).
%% info_msg(F, A) ->
diff --git a/lib/megaco/test/megaco_load_SUITE.erl b/lib/megaco/test/megaco_load_SUITE.erl
index d033e137ec..42e1a122a4 100644
--- a/lib/megaco/test/megaco_load_SUITE.erl
+++ b/lib/megaco/test/megaco_load_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2021. 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.
@@ -62,7 +62,7 @@
-define(MGC_START(Node, Mid, ET, Conf, Verb),
megaco_test_mgc:start(Node, Mid, ET,
- [{megaco_trace, false}] ++ Conf, Verb)).
+ Conf ++ [{megaco_trace, false}], Verb)).
-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)).
-define(MGC_USER_INFO(Pid,Tag), megaco_test_mgc:user_info(Pid,Tag)).
-define(MGC_CONN_INFO(Pid,Tag), megaco_test_mgc:conn_info(Pid,Tag)).
@@ -70,8 +70,8 @@
-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb),
megaco_test_mg:start(Pid, Mid, Enc, Transp,
- [{megaco_trace, false},
- {transport_opts, [{serialize, true}]}] ++ Conf,
+ Conf ++ [{megaco_trace, false},
+ {transport_opts, [{serialize, true}]}],
Verb)).
-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)).
-define(MG_USER_INFO(Pid,Tag), megaco_test_mg:user_info(Pid,Tag)).
@@ -92,15 +92,47 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
+ %% This is a temporary messure to ensure that we can
+ %% test the socket backend without effecting *all*
+ %% applications on *all* machines.
+ %% This flag is set only for *one* host.
+ case ?TEST_INET_BACKENDS() of
+ true ->
+ [
+ {group, inet_backend_default},
+ {group, inet_backend_inet},
+ {group, inet_backend_socket}
+ ];
+ _ ->
+ [
+ {group, inet_backend_default}
+ ]
+ end.
+
+groups() ->
[
- {group, single},
- {group, multi}
+ {inet_backend_default, [], inet_backend_default_cases()},
+ {inet_backend_inet, [], inet_backend_inet_cases()},
+ {inet_backend_socket, [], inet_backend_socket_cases()},
+
+ {all, [], all_cases()},
+ {single, [], single_cases()},
+ {multi, [], multi_cases()}
].
-groups() ->
+inet_backend_default_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_inet_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_socket_cases() ->
+ [{all, [], all_cases()}].
+
+all_cases() ->
[
- {single, [], single_cases()},
- {multi, [], multi_cases()}
+ {group, single},
+ {group, multi}
].
single_cases() ->
@@ -174,10 +206,39 @@ end_per_suite(Config0) when is_list(Config0) ->
%% -----
%%
-init_per_group(_GroupName, Config) ->
+init_per_group(inet_backend_default = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ [{socket_create_opts, []} | Config];
+init_per_group(inet_backend_inet = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{socket_create_opts, [{inet_backend, inet}]} | Config]
+ end;
+init_per_group(inet_backend_socket = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{socket_create_opts, [{inet_backend, socket}]} | Config]
+ end;
+init_per_group(Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
Config.
-end_per_group(_GroupName, Config) ->
+end_per_group(Group, Config) when (inet_backend_default =:= Group) orelse
+ (inet_backend_init =:= Group) orelse
+ (inet_backend_socket =:= Group) ->
+ ?SLEEP(?SECS(5)),
+ Config;
+end_per_group(_Group, Config) ->
Config.
@@ -397,25 +458,28 @@ try_single_user_load(Name, Config, NumLoaders0) ->
single_user_load(State, Config, NumLoaders) ->
i("starting with ~w loader(s)", [NumLoaders]),
+ SCO = ?config(socket_create_opts, Config),
Res = load_controller(Config,
fun(Env) ->
populate(Env),
- exit( single_user_load(State, NumLoaders) )
+ exit( do_single_user_load(SCO,
+ State, NumLoaders) )
end),
i("done"),
Res.
-single_user_load([MgcNode, MgNode], NumLoaders) ->
+do_single_user_load(SCO,
+ [MgcNode, MgNode], NumLoaders) ->
%% Start the MGC and MGs
i("[MGC] start"),
MgcMid = {deviceName, "ctrl"},
ET = [{text, tcp, [{serialize, true}]}],
DSI = maybe_display_system_info(NumLoaders),
- {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, DSI, ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, SCO ++ DSI, ?MGC_VERBOSITY),
i("[MG] start"),
MgMid = {deviceName, "mg"},
- {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, DSI, ?MG_VERBOSITY),
+ {ok, Mg} = ?MG_START(MgNode, MgMid, text, tcp, SCO ++ DSI, ?MG_VERBOSITY),
d("MG user info: ~p", [?MG_USER_INFO(Mg, all)]),
@@ -501,17 +565,18 @@ try_multi_user_load(Name, Config, NumUsers, NumLoaders0) ->
multi_user_load(State, Config, NumUsers, NumLoaders) ->
i("starting with ~w loader(s)", [NumLoaders]),
+ SCO = ?config(socket_create_opts, Config),
Res = load_controller(
Config,
fun(Env) ->
populate(Env),
- exit( multi_user_load(State, NumUsers, NumLoaders) )
+ exit( do_multi_user_load(SCO, State, NumUsers, NumLoaders) )
end),
i("done"),
Res.
-multi_user_load([MgcNode | MgNodes], NumUsers, NumLoaders)
+do_multi_user_load(SCO, [MgcNode | MgNodes], NumUsers, NumLoaders)
when (is_integer(NumUsers) andalso (NumUsers > 1) andalso
is_integer(NumLoaders) andalso (NumLoaders >= 1)) ->
%% Start the MGC and MGs
@@ -519,7 +584,7 @@ multi_user_load([MgcNode | MgNodes], NumUsers, NumLoaders)
MgcMid = {deviceName, "ctrl"},
ET = [{text, tcp, [{serialize, false}]}],
DSI = maybe_display_system_info(2 * NumUsers * NumLoaders),
- {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, DSI, ?MGC_VERBOSITY),
+ {ok, Mgc} = ?MGC_START(MgcNode, MgcMid, ET, SCO ++ DSI, ?MGC_VERBOSITY),
megaco_test_mgc:update_user_info(Mgc,reply_timer,1000),
d("MGC user info: ~p", [?MGC_USER_INFO(Mgc, all)]),
@@ -527,7 +592,7 @@ multi_user_load([MgcNode | MgNodes], NumUsers, NumLoaders)
MgUsers = make_mids(MgNodes),
d("start MGs, apply the load and stop MGs"),
- ok = multi_load(MgUsers, DSI, NumLoaders, ?MULTI_USER_LOAD_NUM_REQUESTS),
+ ok = multi_load(MgUsers, SCO ++ DSI, NumLoaders, ?MULTI_USER_LOAD_NUM_REQUESTS),
i("flush the message queue: ~p", [megaco_test_lib:flush()]),
@@ -542,14 +607,14 @@ multi_user_load([MgcNode | MgNodes], NumUsers, NumLoaders)
ok.
-multi_load(MGs, DSI, NumLoaders, NumReqs) ->
+multi_load(MGs, Conf, NumLoaders, NumReqs) ->
d("multi_load -> entry with"
"~n MGs: ~p"
- "~n DSI: ~p"
+ "~n Conf: ~p"
"~n NumLoaders: ~p"
- "~n NumReqs: ~p", [MGs, DSI, NumLoaders, NumReqs]),
+ "~n NumReqs: ~p", [MGs, Conf, NumLoaders, NumReqs]),
- Pids = multi_load_collector_start(MGs, DSI, NumLoaders, NumReqs, []),
+ Pids = multi_load_collector_start(MGs, Conf, NumLoaders, NumReqs, []),
case timer:tc(?MODULE, do_multi_load, [Pids, NumLoaders, NumReqs]) of
{Time, {ok, OKs, []}} ->
Sec = Time / 1000000,
@@ -569,13 +634,13 @@ do_multi_load(Pids, _NumLoaders, _NumReqs) ->
lists:foreach(Fun, Pids),
await_multi_load_collectors(Pids, [], []).
-multi_load_collector_start([], _DSI, _NumLoaders, _NumReqs, Pids) ->
+multi_load_collector_start([], _Conf, _NumLoaders, _NumReqs, Pids) ->
Pids;
-multi_load_collector_start([{Mid, Node}|MGs], DSI, NumLoaders, NumReqs, Pids) ->
+multi_load_collector_start([{Mid, Node}|MGs], Conf, NumLoaders, NumReqs, Pids) ->
Env = get(),
Pid = spawn_link(?MODULE, multi_load_collector,
- [self(), Node, Mid, DSI, NumLoaders, NumReqs, Env]),
- multi_load_collector_start(MGs, DSI, NumLoaders, NumReqs, [{Pid,Mid}|Pids]).
+ [self(), Node, Mid, Conf, NumLoaders, NumReqs, Env]),
+ multi_load_collector_start(MGs, Conf, NumLoaders, NumReqs, [{Pid,Mid}|Pids]).
get_env(Key, Env) ->
case lists:keysearch(Key, 1, Env) of
@@ -585,13 +650,13 @@ get_env(Key, Env) ->
undefined
end.
-multi_load_collector(Parent, Node, Mid, DSI, NumLoaders, NumReqs, Env) ->
+multi_load_collector(Parent, Node, Mid, Conf, NumLoaders, NumReqs, Env) ->
put(verbosity, get_env(verbosity, Env)),
put(tc, get_env(tc, Env)),
put(sname, get_env(sname, Env) ++ "-loader"),
- case ?MG_START(Node, Mid, text, tcp, DSI, ?MG_VERBOSITY) of
+ case ?MG_START(Node, Mid, text, tcp, Conf, ?MG_VERBOSITY) of
{ok, Pid} ->
- d("MG ~p user info: ~n~p", [Mid, ?MG_USER_INFO(Pid,all)]),
+ d("MG ~p user info: ~n~p", [Mid, ?MG_USER_INFO(Pid, all)]),
ServChRes = ?MG_SERV_CHANGE(Pid),
d("service change result: ~p", [ServChRes]),
megaco_test_mg:update_conn_info(Pid,reply_timer,1000),
diff --git a/lib/megaco/test/megaco_mreq_SUITE.erl b/lib/megaco/test/megaco_mreq_SUITE.erl
index b53e99a995..12eb67f749 100644
--- a/lib/megaco/test/megaco_mreq_SUITE.erl
+++ b/lib/megaco/test/megaco_mreq_SUITE.erl
@@ -36,6 +36,7 @@
]).
+-include_lib("common_test/include/ct.hrl").
-include_lib("megaco/include/megaco.hrl").
-include_lib("megaco/include/megaco_message_v1.hrl").
-include("megaco_test_lib.hrl").
@@ -50,8 +51,8 @@
-define(A5555, ["11111111", "11111111", "00000000"]).
-define(A5556, ["11111111", "11111111", "11111111"]).
--define(MGC_START(Pid, Mid, ET, Verb),
- megaco_test_mgc:start(Pid, Mid, ET, Verb)).
+-define(MGC_START(Pid, Mid, ET, Conf, Verb),
+ megaco_test_mgc:start(Pid, Mid, ET, Conf, Verb)).
-define(MGC_STOP(Pid), megaco_test_mgc:stop(Pid)).
-define(MGC_GET_STATS(Pid, No), megaco_test_mgc:get_stats(Pid, No)).
-define(MGC_RESET_STATS(Pid), megaco_test_mgc:reset_stats(Pid)).
@@ -59,8 +60,8 @@
-define(MGC_REQ_PEND(Pid,To), megaco_test_mgc:request_pending(Pid,To)).
-define(MGC_REQ_HAND(Pid), megaco_test_mgc:request_handle(Pid)).
--define(MG_START(Pid, Mid, Enc, Transp, Verb),
- megaco_test_mg:start(Pid, Mid, Enc, Transp, Verb)).
+-define(MG_START(Pid, Mid, Enc, Transp, Conf, Verb),
+ megaco_test_mg:start(Pid, Mid, Enc, Transp, Conf, Verb)).
-define(MG_STOP(Pid), megaco_test_mg:stop(Pid)).
-define(MG_GET_STATS(Pid), megaco_test_mg:get_stats(Pid)).
-define(MG_RESET_STATS(Pid), megaco_test_mg:reset_stats(Pid)).
@@ -80,15 +81,48 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
+ %% This is a temporary messure to ensure that we can
+ %% test the socket backend without effecting *all*
+ %% applications on *all* machines.
+ %% This flag is set only for *one* host.
+ case ?TEST_INET_BACKENDS() of
+ true ->
+ [
+ {group, inet_backend_default},
+ {group, inet_backend_inet},
+ {group, inet_backend_socket}
+ ];
+ _ ->
+ [
+ {group, inet_backend_default}
+ ]
+ end.
+
+groups() ->
+ [
+ {inet_backend_default, [], inet_backend_default_cases()},
+ {inet_backend_inet, [], inet_backend_inet_cases()},
+ {inet_backend_socket, [], inet_backend_socket_cases()},
+
+ {all, [], all_cases()}
+ ].
+
+inet_backend_default_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_inet_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_socket_cases() ->
+ [{all, [], all_cases()}].
+
+all_cases() ->
[
req_and_rep,
req_and_pending,
req_and_cancel
].
-groups() ->
- [].
-
%%
@@ -144,10 +178,34 @@ end_per_suite(Config0) when is_list(Config0) ->
%% -----
%%
-init_per_group(_GroupName, Config) ->
+init_per_group(inet_backend_default = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ [{socket_create_opts, []} | Config];
+init_per_group(inet_backend_inet = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{socket_create_opts, [{inet_backend, inet}]} | Config]
+ end;
+init_per_group(inet_backend_socket = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{socket_create_opts, [{inet_backend, socket}]} | Config]
+ end;
+init_per_group(Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
Config.
-end_per_group(_GroupName, Config) ->
+end_per_group(_Group, Config) ->
Config.
@@ -200,7 +258,10 @@ req_and_rep(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun do_req_and_rep/1,
+ Case = fun(X) ->
+ SCO = ?config(socket_create_opts, Config),
+ do_req_and_rep(SCO, X)
+ end,
Post = fun(Nodes) ->
d("stop nodes (in the reverse order):"
"~n ~p", [Nodes]),
@@ -208,19 +269,19 @@ req_and_rep(Config) when is_list(Config) ->
end,
try_tc(req_and_rep, Pre, Case, Post).
-do_req_and_rep([MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]) ->
+do_req_and_rep(SCO, [MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]) ->
%% Start the MGC and MGs
i("start the MGC"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
{ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, SCO, ?MGC_VERBOSITY),
i("start and connect the MGs"),
MgConf0 = [{Mg1Node, "mg1", text, tcp, ?MG_VERBOSITY},
{Mg2Node, "mg2", text, udp, ?MG_VERBOSITY},
{Mg3Node, "mg3", binary, tcp, ?MG_VERBOSITY},
{Mg4Node, "mg4", binary, udp, ?MG_VERBOSITY}],
- MgConf = rar_connect_mg(MgConf0, []),
+ MgConf = rar_connect_mg(SCO, MgConf0, []),
%% Collect the (initial) MGs statistics
Stats1 = rar_get_mg_stats(MgConf, []),
@@ -309,19 +370,19 @@ do_req_and_rep([MgcNode, Mg1Node, Mg2Node, Mg3Node, Mg4Node]) ->
ok.
-rar_connect_mg([], Acc) ->
+rar_connect_mg(_, [], Acc) ->
lists:reverse(Acc);
-rar_connect_mg([{Node, Name, Coding, Trans, Verb}|Mg], Acc) ->
- Pid = rar_connect_mg(Node, Name, Coding, Trans, Verb),
- rar_connect_mg(Mg, [{Name, Pid}|Acc]).
+rar_connect_mg(SCO, [{Node, Name, Coding, Trans, Verb}|Mg], Acc) ->
+ Pid = rar_connect_mg(SCO, Node, Name, Coding, Trans, Verb),
+ rar_connect_mg(SCO, Mg, [{Name, Pid}|Acc]).
-rar_connect_mg(Node, Name, Coding, Trans, Verb) ->
+rar_connect_mg(SCO, Node, Name, Coding, Trans, Verb) ->
Mid = {deviceName, Name},
- {ok, Pid} = ?MG_START(Node, Mid, Coding, Trans, Verb),
+ {ok, Pid} = ?MG_START(Node, Mid, Coding, Trans, SCO, Verb),
%% Ask the MGs to do a service change
Res = ?MG_SERV_CHANGE(Pid),
- d("rar_connect_mg -> (~s) service change result: ~p", [Name,Res]),
+ d("rar_connect_mg -> (~s) service change result: ~p", [Name, Res]),
Pid.
@@ -396,7 +457,10 @@ req_and_pending(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun do_req_and_pending/1,
+ Case = fun(X) ->
+ SCO = ?config(socket_create_opts, Config),
+ do_req_and_pending(SCO, X)
+ end,
Post = fun(Nodes) ->
d("stop nodes (in the reverse order):"
"~n ~p", [Nodes]),
@@ -404,17 +468,17 @@ req_and_pending(Config) when is_list(Config) ->
end,
try_tc(req_and_pending, Pre, Case, Post).
-do_req_and_pending([MgcNode, MgNode]) ->
+do_req_and_pending(SCO, [MgcNode, MgNode]) ->
%% Start the MGC and MGs
i("try start the MGC"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
{ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, SCO, ?MGC_VERBOSITY),
i("try start the MG"),
{ok, Mg} =
- ?MG_START(MgNode, {deviceName, "mg"}, text, tcp, ?MG_VERBOSITY),
+ ?MG_START(MgNode, {deviceName, "mg"}, text, tcp, SCO, ?MG_VERBOSITY),
i("connect MG (to MFC)"),
Res1 = ?MG_SERV_CHANGE(Mg),
@@ -462,7 +526,10 @@ req_and_cancel(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun do_req_and_cancel/1,
+ Case = fun(X) ->
+ SCO = ?config(socket_create_opts, Config),
+ do_req_and_cancel(SCO, X)
+ end,
Post = fun(Nodes) ->
d("stop nodes (in the reverse order):"
"~n ~p", [Nodes]),
@@ -470,16 +537,16 @@ req_and_cancel(Config) when is_list(Config) ->
end,
try_tc(req_and_cancel, Pre, Case, Post).
-do_req_and_cancel([MgcNode, MgNode]) ->
+do_req_and_cancel(SCO, [MgcNode, MgNode]) ->
%% Start the MGC and MGs
i("start the MGC"),
ET = [{text,tcp}, {text,udp}, {binary,tcp}, {binary,udp}],
{ok, Mgc} =
- ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, ?MGC_VERBOSITY),
+ ?MGC_START(MgcNode, {deviceName, "ctrl"}, ET, SCO, ?MGC_VERBOSITY),
i("start the MG"),
{ok, Mg} =
- ?MG_START(MgNode, {deviceName, "mg"}, text, tcp, ?MG_VERBOSITY),
+ ?MG_START(MgNode, {deviceName, "mg"}, text, tcp, SCO, ?MG_VERBOSITY),
i("connect the MG"),
Res1 = ?MG_SERV_CHANGE(Mg),
diff --git a/lib/megaco/test/megaco_tcp_SUITE.erl b/lib/megaco/test/megaco_tcp_SUITE.erl
index 5792c6b380..88c7934894 100644
--- a/lib/megaco/test/megaco_tcp_SUITE.erl
+++ b/lib/megaco/test/megaco_tcp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021. 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.
@@ -70,6 +70,11 @@
-define(CH, megaco_test_command_handler).
-define(TEST_VERBOSITY, debug).
+%% We have some strange reuseaddr issue (*some* times we eaddrinuse),
+%% so this is intended to "ensure" we get no conflict.
+-define(SERVER_PORT(C, I),
+ 2944 + proplists:get_value(adjust_server_port, C) + (I-1)).
+
%%----------------------------------------------------------------------
%% Records
@@ -84,18 +89,51 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
+ %% This is a temporary messure to ensure that we can
+ %% test the socket backend without effecting *all*
+ %% applications on *all* machines.
+ %% This flag is set only for *one* host.
+ case ?TEST_INET_BACKENDS() of
+ true ->
+ [
+ {group, inet_backend_default},
+ {group, inet_backend_inet},
+ {group, inet_backend_socket}
+ ];
+ _ ->
+ [
+ {group, inet_backend_default}
+ ]
+ end.
+
+groups() ->
+ [
+ {inet_backend_default, [], inet_backend_default_cases()},
+ {inet_backend_inet, [], inet_backend_inet_cases()},
+ {inet_backend_socket, [], inet_backend_socket_cases()},
+
+ {all, [], all_cases()},
+ {start, [], start_cases()},
+ {sending, [], sending_cases()},
+ {error, [], error_cases()}
+ ].
+
+inet_backend_default_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_inet_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_socket_cases() ->
+ [{all, [], all_cases()}].
+
+all_cases() ->
[
{group, start},
{group, sending},
{group, error}
].
-groups() ->
- [
- {start, [], start_cases()},
- {sending, [], sending_cases()},
- {error, [], error_cases()}
- ].
start_cases() ->
[
@@ -173,10 +211,41 @@ end_per_suite(Config0) when is_list(Config0) ->
%% -----
%%
+init_per_group(inet_backend_default = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ [{adjust_server_port, 0},
+ {socket_create_opts, []} | Config];
+init_per_group(inet_backend_inet = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{adjust_server_port, 100},
+ {socket_create_opts, [{inet_backend, inet}]} | Config]
+ end;
+init_per_group(inet_backend_socket = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{adjust_server_port, 200},
+ {socket_create_opts, [{inet_backend, socket}]} | Config]
+ end;
init_per_group(Group, Config) ->
?ANNOUNCE_GROUP_INIT(Group),
Config.
+end_per_group(GroupName, Config) when (inet_backend_default =:= GroupName) orelse
+ (inet_backend_init =:= GroupName) orelse
+ (inet_backend_socket =:= GroupName) ->
+ ?SLEEP(?SECS(5)),
+ Config;
end_per_group(_GroupName, Config) ->
Config.
@@ -198,8 +267,9 @@ init_per_testcase(Case, Config) ->
end_per_testcase(Case, Config) ->
p("end_per_testcase -> entry with"
- "~n Config: ~p"
- "~n Nodes: ~p", [Config, erlang:nodes()]),
+ "~n Config: ~p"
+ "~n Nodes: ~p",
+ [Config, erlang:nodes()]),
p("system events during test: "
"~n ~p", [megaco_test_global_sys_monitor:events()]),
@@ -219,7 +289,7 @@ start_normal(Config) when is_list(Config) ->
put(sname, "start_normal"),
p("BEGIN TEST-CASE"),
Options = [{port, 20000}, {receive_handle, apa}],
- {ok, Pid} = start_case(Options, ok),
+ {ok, Pid} = start_case(Config, Options, ok),
megaco_tcp:stop_transport(Pid),
p("done"),
ok.
@@ -233,7 +303,7 @@ start_invalid_opt(Config) when is_list(Config) ->
put(sname, "start_invalid_opt"),
p("BEGIN TEST-CASE"),
Options = [{port, 20000}, {receivehandle, apa}],
- ok = start_case(Options, error),
+ ok = start_case(Config, Options, error),
p("done"),
ok.
@@ -254,20 +324,28 @@ start_and_stop(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun do_start_and_stop/1,
+ Case = fun(X) -> do_start_and_stop(Config, X) end,
+ %% Case = fun(X) -> do_start_and_stop(Config, X, 10) end,
Post = fun(Nodes) ->
p("stop nodes"),
?STOP_NODES(lists:reverse(Nodes))
end,
try_tc(start_and_stop, Pre, Case, Post).
-do_start_and_stop([ServerNode, ClientNode]) ->
+
+%% do_start_and_stop(_Config, _Nodes, 0) ->
+%% ok;
+%% do_start_and_stop(Config, Nodes, N) ->
+%% do_start_and_stop(Config, Nodes),
+%% do_start_and_stop(Config, Nodes, N-1).
+
+do_start_and_stop(Config, [ServerNode, ClientNode]) ->
%% Create command sequences
p("create command sequences"),
- ServerPort = 2944,
- ServerCmds = start_and_stop_server_commands(ServerPort),
+ ServerPort = ?SERVER_PORT(Config, 1), % 2944,
+ ServerCmds = start_and_stop_server_commands(Config, ServerPort),
{ok, ServerHost} = inet:gethostname(),
- ClientCmds = start_and_stop_client_commands(ServerPort, ServerHost),
+ ClientCmds = start_and_stop_client_commands(Config, ServerPort, ServerHost),
%% Start the test procs used in the test-case, one for each node
p("start command handlers"),
@@ -283,7 +361,7 @@ do_start_and_stop([ServerNode, ClientNode]) ->
ok.
-start_and_stop_server_commands(Port) ->
+start_and_stop_server_commands(Config, Port) ->
Opts = [{port, Port}],
Self = self(),
[
@@ -302,7 +380,7 @@ start_and_stop_server_commands(Port) ->
#{id => 3,
desc => "Listen",
cmd => fun(State) ->
- server_listen(State, Opts)
+ server_listen(Config, State, Opts)
end},
#{id => 4,
@@ -326,7 +404,7 @@ start_and_stop_server_commands(Port) ->
].
-start_and_stop_client_commands(ServerPort, ServerHost) ->
+start_and_stop_client_commands(Config, ServerPort, ServerHost) ->
Opts = [{port, ServerPort}, {host, ServerHost}],
Self = self(),
[
@@ -351,7 +429,7 @@ start_and_stop_client_commands(ServerPort, ServerHost) ->
#{id => 4,
desc => "Connect",
cmd => fun(State) ->
- client_connect(State, Opts)
+ client_connect(Config, State, Opts)
end},
#{id => 5,
@@ -389,20 +467,20 @@ sendreceive(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun do_sendreceive/1,
+ Case = fun(X) -> do_sendreceive(Config, X) end,
Post = fun(Nodes) ->
p("stop nodes"),
?STOP_NODES(lists:reverse(Nodes))
end,
try_tc(sendreceive, Pre, Case, Post).
-do_sendreceive([ServerNode, ClientNode]) ->
+do_sendreceive(Config, [ServerNode, ClientNode]) ->
%% Create command sequences
p("create command sequences"),
- ServerPort = 2944,
- ServerCmds = sendreceive_server_commands(ServerPort),
+ ServerPort = ?SERVER_PORT(Config, 2), % 2944,
+ ServerCmds = sendreceive_server_commands(Config, ServerPort),
{ok, ServerHost} = inet:gethostname(),
- ClientCmds = sendreceive_client_commands(ServerPort, ServerHost),
+ ClientCmds = sendreceive_client_commands(Config, ServerPort, ServerHost),
%% Start the test procs used in the test-case, one for each node
p("start command handlers"),
@@ -418,7 +496,7 @@ do_sendreceive([ServerNode, ClientNode]) ->
ok.
-sendreceive_server_commands(Port) ->
+sendreceive_server_commands(Config, Port) ->
Opts = [{port, Port}],
Self = self(),
[
@@ -437,7 +515,7 @@ sendreceive_server_commands(Port) ->
#{id => 3,
desc => "Listen",
cmd => fun(State) ->
- server_listen(State, Opts)
+ server_listen(Config, State, Opts)
end},
#{id => 4,
@@ -502,7 +580,7 @@ sendreceive_server_commands(Port) ->
].
-sendreceive_client_commands(ServerPort, ServerHost) ->
+sendreceive_client_commands(Config, ServerPort, ServerHost) ->
Opts = [{port, ServerPort}, {host, ServerHost}],
Self = self(),
[
@@ -527,7 +605,7 @@ sendreceive_client_commands(ServerPort, ServerHost) ->
#{id => 4,
desc => "Connect",
cmd => fun(State) ->
- client_connect(State, Opts)
+ client_connect(Config, State, Opts)
end},
#{id => 5,
@@ -594,20 +672,20 @@ block_unblock(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun do_block_unblock/1,
+ Case = fun(X) -> do_block_unblock(Config, X) end,
Post = fun(Nodes) ->
p("stop nodes"),
?STOP_NODES(lists:reverse(Nodes))
end,
try_tc(block_unblock, Pre, Case, Post).
-do_block_unblock([ServerNode, ClientNode]) ->
+do_block_unblock(Config, [ServerNode, ClientNode]) ->
%% Create command sequences
p("create command sequences"),
- ServerPort = 2944,
- ServerCmds = block_unblock_server_commands(ServerPort),
+ ServerPort = ?SERVER_PORT(Config, 3), % 2944,
+ ServerCmds = block_unblock_server_commands(Config, ServerPort),
{ok, ServerHost} = inet:gethostname(),
- ClientCmds = block_unblock_client_commands(ServerPort, ServerHost),
+ ClientCmds = block_unblock_client_commands(Config, ServerPort, ServerHost),
%% Start the test procs used in the test-case, one for each node
p("start command handlers"),
@@ -625,8 +703,8 @@ do_block_unblock([ServerNode, ClientNode]) ->
ok.
-block_unblock_server_commands(Port) ->
- Opts = [{port, Port}],
+block_unblock_server_commands(Config, Port) ->
+ Opts = [{port, Port}],
Self = self(),
[
#{id => 1,
@@ -644,7 +722,7 @@ block_unblock_server_commands(Port) ->
#{id => 3,
desc => "Listen",
cmd => fun(State) ->
- server_listen(State, Opts)
+ server_listen(Config, State, Opts)
end},
#{id => 4,
@@ -671,11 +749,11 @@ block_unblock_server_commands(Port) ->
server_await_continue_signal(State, 5000)
end},
- #{id => 9,
- desc => "Await nothing before sending a message (hejsan)",
- cmd => fun(State) ->
- server_await_nothing(State, 1000)
- end},
+ %% #{id => 9,
+ %% desc => "Await nothing before sending a message (hejsan)",
+ %% cmd => fun(State) ->
+ %% server_await_nothing(State, 1000)
+ %% end},
#{id => 10,
desc => "Send message (hejsan)",
@@ -715,7 +793,7 @@ block_unblock_server_commands(Port) ->
].
-block_unblock_client_commands(ServerPort, ServerHost) ->
+block_unblock_client_commands(Config, ServerPort, ServerHost) ->
Opts = [{port, ServerPort}, {host, ServerHost}],
Self = self(),
[
@@ -740,7 +818,7 @@ block_unblock_client_commands(ServerPort, ServerHost) ->
#{id => 4,
desc => "Connect",
cmd => fun(State) ->
- client_connect(State, Opts)
+ client_connect(Config, State, Opts)
end},
#{id => 5,
@@ -788,7 +866,7 @@ block_unblock_client_commands(ServerPort, ServerHost) ->
#{id => 12,
desc => "Await message (hejsan)",
cmd => fun(State) ->
- client_await_message(State, "hejsan", 100)
+ client_await_message(State, "hejsan", 500)
end},
#{id => 13,
@@ -895,33 +973,37 @@ tcp_server(Config) when is_list(Config) ->
%% Test functions
%%======================================================================
-start_case(Options, Expect) ->
+start_case(Config, Options, Expect) ->
p("start transport"),
case (catch megaco_tcp:start_transport()) of
{ok, Pid} ->
p("create listen socket"),
- case (catch megaco_tcp:listen(Pid, Options)) of
+ case (catch ?LISTEN(Config, Pid, Options)) of
ok when Expect =:= ok ->
p("extected listen result [ok]"),
{ok, Pid};
ok ->
- p("unextected listen result [ok] - stop transport"),
+ p("unexpected listen result [ok] - stop transport"),
megaco_tcp:stop_transport(Pid),
?ERROR(unexpected_start_sucesss);
- {error, _Reason} when Expect =:= error ->
- p("extected listen result [error] - stop transport"),
+ {error, Reason} when Expect =:= error ->
+ p("expected listen result [error] - stop transport: "
+ "~n Reason: ~p", [Reason]),
megaco_tcp:stop_transport(Pid),
ok;
{error, Reason} ->
- p("unextected listen result [error] - stop transport"),
+ p("unexpected listen result [error] - stop transport: "
+ "~n Reason: ~p", [Reason]),
megaco_tcp:stop_transport(Pid),
?ERROR({unexpected_start_failure, Reason});
Error ->
- p("unextected listen result"),
+ p("unexpected listen result: "
+ "~n Error: ~p", [Error]),
+ megaco_tcp:stop_transport(Pid),
?ERROR({unexpected_result, Error})
end;
{error, Reason} ->
- p("unextected start_transport result"),
+ p("unexpected start_transport result"),
?ERROR({failed_starting_transport, Reason})
end.
@@ -1019,10 +1101,11 @@ server_start_transport(State) when is_map(State) ->
Error
end.
-server_listen(#{transport_ref := Ref} = State, Options)
+server_listen(Config, #{transport_ref := Ref} = State, Options)
when is_list(Options) ->
+ ?SLEEP(1000),
Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
- case (catch megaco_tcp:listen(Ref, Opts)) of
+ case (catch ?LISTEN(Config, Ref, Opts)) of
ok ->
{ok, State};
Error ->
@@ -1110,10 +1193,10 @@ client_start_transport(State) when is_map(State) ->
Error
end.
-client_connect(#{transport_ref := Ref} = State, Options)
+client_connect(Config, #{transport_ref := Ref} = State, Options)
when is_list(Options) ->
Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
- case (catch megaco_tcp:connect(Ref, Opts)) of
+ case (catch ?CONNECT(Config, Ref, Opts)) of
{ok, Handle, ControlPid} ->
{ok, State#{control_pid => ControlPid,
handle => Handle}};
diff --git a/lib/megaco/test/megaco_test_lib.erl b/lib/megaco/test/megaco_test_lib.erl
index 10e7ed90c8..e39e1e3e8a 100644
--- a/lib/megaco/test/megaco_test_lib.erl
+++ b/lib/megaco/test/megaco_test_lib.erl
@@ -60,7 +60,13 @@
start_node/3, start_node/4,
stop_nodes/3,
- stop_node/3
+ stop_node/3,
+
+ is_socket_backend/1,
+ inet_backend_opts/1,
+ explicit_inet_backend/0, test_inet_backends/0,
+ open/3,
+ listen/3, connect/3
]).
-export([init_per_suite/1, end_per_suite/1,
@@ -475,6 +481,17 @@ pprint(F, A) ->
init_per_suite(Config) ->
+ p("megaco environment: "
+ "~n (megaco) app: ~p"
+ "~n (all) init: ~p"
+ "~n (megaco) init: ~p",
+ [application:get_all_env(megaco),
+ init:get_arguments(),
+ case init:get_argument(megaco) of
+ {ok, Args} -> Args;
+ error -> undefined
+ end]),
+
ct:timetrap(minutes(3)),
try analyze_and_print_host_info() of
@@ -2209,3 +2226,76 @@ p(F, A) ->
print(Pre, F, A) ->
io:format("*** [~s] [~s] ~p " ++ F ++ "~n", [?FTS(), Pre, self() | A]).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+explicit_inet_backend() ->
+ %% This is intentional!
+ %% This is a kernel flag, which if set disables
+ %% our own special handling of the inet_backend
+ %% in our test suites.
+ case application:get_all_env(kernel) of
+ Env when is_list(Env) ->
+ case lists:keysearch(inet_backend, 1, Env) of
+ {value, {inet_backend, _}} ->
+ true;
+ _ ->
+ false
+ end;
+ _ ->
+ false
+ end.
+
+test_inet_backends() ->
+ case init:get_argument(megaco) of
+ {ok, SnmpArgs} when is_list(SnmpArgs) ->
+ test_inet_backends(SnmpArgs, atom_to_list(?FUNCTION_NAME));
+ error ->
+ false
+ end.
+
+test_inet_backends([], _) ->
+ false;
+test_inet_backends([[Key, Val] | _], Key) ->
+ case list_to_atom(string:to_lower(Val)) of
+ Bool when is_boolean(Bool) ->
+ Bool;
+ _ ->
+ false
+ end;
+test_inet_backends([_|Args], Key) ->
+ test_inet_backends(Args, Key).
+
+
+inet_backend_opts(Config) when is_list(Config) ->
+ case lists:keysearch(socket_create_opts, 1, Config) of
+ {value, {socket_create_opts, InetBackendOpts}} ->
+ InetBackendOpts;
+ false ->
+ []
+ end.
+
+is_socket_backend(Config) when is_list(Config) ->
+ case lists:keysearch(socket_create_opts, 1, Config) of
+ {value, {socket_create_opts, [{inet_backend, socket}]}} ->
+ true;
+ _ ->
+ false
+ end.
+
+
+open(Config, Pid, Opts)
+ when is_list(Config) andalso is_pid(Pid) andalso is_list(Opts) ->
+ InetBackendOpts = inet_backend_opts(Config),
+ megaco_udp:open(Pid, InetBackendOpts ++ Opts).
+
+listen(Config, Pid, Opts)
+ when is_list(Config) andalso is_pid(Pid) andalso is_list(Opts) ->
+ InetBackendOpts = inet_backend_opts(Config),
+ megaco_tcp:listen(Pid, InetBackendOpts ++ Opts).
+
+connect(Config, Ref, Opts)
+ when is_list(Config) andalso is_list(Opts) ->
+ InetBackendOpts = inet_backend_opts(Config),
+ megaco_tcp:connect(Ref, InetBackendOpts ++ Opts).
+
diff --git a/lib/megaco/test/megaco_test_lib.hrl b/lib/megaco/test/megaco_test_lib.hrl
index 0777adbcd0..653af70da4 100644
--- a/lib/megaco/test/megaco_test_lib.hrl
+++ b/lib/megaco/test/megaco_test_lib.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2020. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2021. 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.
@@ -106,6 +106,16 @@
-define(FTS(TS), megaco:format_timestamp(TS)).
-define(F(F,A), lists:flatten(io_lib:format(F, A))).
+-define(INET_BACKEND_OPTS(C), ?LIB:inet_backend_opts(C)).
+-define(EXPLICIT_INET_BACKEND(), ?LIB:explicit_inet_backend()).
+-define(TEST_INET_BACKENDS(), ?LIB:test_inet_backends()).
+-define(IS_SOCKET_BACKEND(C), ?LIB:is_socket_backend(C)).
+
+-define(OPEN(C, P, O), ?LIB:open(C, P, O)).
+-define(LISTEN(C, P, O), ?LIB:listen(C, P, O)).
+-define(CONNECT(C, R, O), ?LIB:connect(C, R, O)).
+
+
-define(ANNOUNCE_SUITE_INIT(),
io:format(user, "~n*** ~s *** suite ~w init~n~n", [?FTS(), ?MODULE])).
-define(ANNOUNCE_GROUP_INIT(GR),
diff --git a/lib/megaco/test/megaco_test_mg.erl b/lib/megaco/test/megaco_test_mg.erl
index e84adc7de6..7fae24326a 100644
--- a/lib/megaco/test/megaco_test_mg.erl
+++ b/lib/megaco/test/megaco_test_mg.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2020. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2021. 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.
@@ -67,7 +67,9 @@
-define(A5555, tid(255*256*256 + 255*256) ).
-define(A5556, tid(255*256*256 + 255*256 + 255) ).
--record(mg, {mid = undefined,
+-record(mg, {parent = undefined,
+ inet_backend = default,
+ mid = undefined,
state = initiated,
req_handler = undefined,
call_mode = async,
@@ -78,7 +80,6 @@
load_counter = 0,
reply_counter = 0,
mload_info = undefined,
- parent = undefined,
dsi_timer,
evs = []}).
@@ -354,11 +355,16 @@ mg(Parent, Verbosity, Config) ->
case (catch init(Config)) of
{error, _} = Error ->
exit(Error);
+
{'EXIT', Reason} ->
exit({init_failed, Reason});
- {ok, Mid, DSITimer} ->
+
+ {ok, IB, Mid, DSITimer} ->
notify_started(Parent),
- MG = #mg{parent = Parent, mid = Mid, dsi_timer = DSITimer},
+ MG = #mg{parent = Parent,
+ inet_backend = IB,
+ mid = Mid,
+ dsi_timer = DSITimer},
i("mg -> started"),
put(verbosity, Verbosity),
case (catch loop(evs(MG, started))) of
@@ -380,12 +386,16 @@ init(Config) ->
"~n Config: ~p", [Config]),
random_init(),
d("init -> random initiated"),
- Mid = get_conf(local_mid, Config),
- d("init -> Mid: ~p", [Mid]),
+
+ IB = get_conf(inet_backend, Config, default),
+ Mid = get_conf(local_mid, Config),
RI = get_conf(receive_info, Config),
- d("init -> RI: ~p", [RI]),
- d("init -> maybe start the display system info timer"),
+ d("init -> "
+ "~n Inet Backend: ~p"
+ "~n Mid: ~p"
+ "~n RI: ~p", [IB, Mid, RI]),
+
DSITimer =
case get_conf(display_system_info, Config, undefined) of
Time when is_integer(Time) ->
@@ -395,6 +405,7 @@ init(Config) ->
undefined
end,
Conf0 = lists:keydelete(display_system_info, 1, Config),
+ Conf1 = lists:keydelete(inet_backend, 1, Conf0),
d("init -> start megaco"),
application:start(megaco),
@@ -411,12 +422,12 @@ init(Config) ->
_ ->
ok
end,
- Conf1 = lists:keydelete(megaco_trace, 1, Conf0),
+ Conf2 = lists:keydelete(megaco_trace, 1, Conf1),
d("init -> start megaco user"),
- Conf2 = lists:keydelete(local_mid, 1, Conf1),
- Conf3 = lists:keydelete(receive_info, 1, Conf2),
- ok = megaco:start_user(Mid, Conf3),
+ Conf3 = lists:keydelete(local_mid, 1, Conf2),
+ Conf4 = lists:keydelete(receive_info, 1, Conf3),
+ ok = megaco:start_user(Mid, Conf4),
d("init -> update user info (user_mod)"),
ok = megaco:update_user_info(Mid, user_mod, ?MODULE),
d("init -> update user info (user_args)"),
@@ -427,8 +438,8 @@ init(Config) ->
d("init -> parse receive info"),
{MgcPort, MgcHost, RH1, TO} = parse_receive_info(RI, RH),
d("init -> start transport (with ~p)", [TO]),
- {ok, _CH} = start_transport(MgcPort, MgcHost, RH1, TO),
- {ok, Mid, DSITimer}.
+ {ok, _CH} = start_transport(IB, MgcPort, MgcHost, RH1, TO),
+ {ok, IB, Mid, DSITimer}.
loop(#mg{parent = Parent, mid = Mid} = S) ->
@@ -936,39 +947,43 @@ parse_receive_info(RI, RH) ->
{TP, TH, RH1, TO}.
-start_transport(MgcPort, MgcHost,
- #megaco_receive_handle{send_mod = megaco_tcp} = RH, TO) ->
- start_tcp(MgcPort, MgcHost, RH, TO);
-start_transport(MgcPort, MgcHost,
- #megaco_receive_handle{send_mod = megaco_udp} = RH, TO) ->
- start_udp(MgcPort, MgcHost, RH, TO);
-start_transport(_, _, #megaco_receive_handle{send_mod = Mod}, _TO) ->
+start_transport(IB,
+ MgcPort, MgcHost,
+ #megaco_receive_handle{send_mod = megaco_tcp} = RH, TO) ->
+ start_tcp(IB, RH, TO, MgcPort, MgcHost);
+start_transport(IB,
+ MgcPort, MgcHost,
+ #megaco_receive_handle{send_mod = megaco_udp} = RH, TO) ->
+ start_udp(IB, RH, TO, MgcPort, MgcHost);
+start_transport(_, _, _, #megaco_receive_handle{send_mod = Mod}, _TO) ->
throw({error, {bad_send_mod, Mod}}).
-start_tcp(MgcPort, MgcHost, RH, TO) ->
+start_tcp(IB, RH, TO, MgcPort, MgcHost) ->
d("start tcp transport: "
+ "~n Inet Backend: ~p"
"~n MGC Port: ~p"
"~n MGC Host: ~p"
"~n Receive handle: ~p"
- "~n Transport options: ~p", [MgcPort, MgcHost, RH, TO]),
+ "~n Transport options: ~p", [IB, MgcPort, MgcHost, RH, TO]),
case megaco_tcp:start_transport() of
{ok, Sup} ->
d("tcp transport started: ~p", [Sup]),
- start_tcp_connect(TO, RH, MgcPort, MgcHost, Sup);
+ start_tcp_connect(IB, TO, RH, MgcPort, MgcHost, Sup);
{error, Reason} ->
throw({error, {megaco_tcp_start_transport, Reason}})
end.
-start_tcp_connect(TO, RH, Port, Host, Sup) ->
+start_tcp_connect(IB, TO, RH, Port, Host, Sup) ->
d("try tcp connecting to: ~p:~p", [Host, Port]),
- Opts = [{host, Host},
+ Opts = [{inet_backend, IB},
+ {host, Host},
{port, Port},
{receive_handle, RH},
{tcp_options, [{nodelay, true}]}] ++ TO,
- try_start_tcp_connect(RH, Sup, Opts, 250, noError).
+ try_start_tcp_connect(RH, Opts, Sup, 250, noError).
-try_start_tcp_connect(RH, Sup, Opts, Timeout, Error0) when (Timeout < 5000) ->
+try_start_tcp_connect(RH, Opts, Sup, Timeout, Error0) when (Timeout < 5000) ->
Sleep = random(Timeout) + 100,
d("try tcp connect (~p,~p)", [Timeout, Sleep]),
case megaco_tcp:connect(Sup, Opts) of
@@ -978,13 +993,13 @@ try_start_tcp_connect(RH, Sup, Opts, Timeout, Error0) when (Timeout < 5000) ->
Error1 when Error0 =:= noError -> % Keep the first error
d("failed connecting [1]: ~p", [Error1]),
sleep(Sleep),
- try_start_tcp_connect(RH, Sup, Opts, Timeout*2, Error1);
+ try_start_tcp_connect(RH, Opts, Sup, Timeout*2, Error1);
Error2 ->
d("failed connecting [2]: ~p", [Error2]),
sleep(Sleep),
- try_start_tcp_connect(RH, Sup, Opts, Timeout*2, Error0)
+ try_start_tcp_connect(RH, Opts, Sup, Timeout*2, Error0)
end;
-try_start_tcp_connect(_RH, Sup, _Opts, _Timeout, Error) ->
+try_start_tcp_connect(_RH, _Opts, Sup, _Timeout, Error) ->
megaco_tcp:stop_transport(Sup),
throw({error, {megaco_tcp_connect, Error}}).
@@ -995,25 +1010,45 @@ megaco_tcp_connect(RH, SendHandle, ControlPid) ->
d("megaco connected: ~p", [CH]),
{ok, CH}.
-start_udp(MgcPort, MgcHost, RH, TO) ->
+start_udp(IB, RH, TO, MgcPort, MgcHost) ->
d("start udp transport (~p)", [MgcPort]),
case megaco_udp:start_transport() of
{ok, Sup} ->
d("udp transport started: ~p", [Sup]),
- Opts = [{port, 0}, {receive_handle, RH}] ++ TO,
- d("udp open", []),
- case megaco_udp:open(Sup, Opts) of
- {ok, Handle, ControlPid} ->
- d("udp opened: ~p, ~p", [Handle, ControlPid]),
- megaco_udp_connect(MgcPort, MgcHost,
- RH, Handle, ControlPid);
- {error, Reason} ->
- throw({error, {megaco_udp_open, Reason}})
- end;
+ start_udp_open(IB, RH, TO, MgcPort, MgcHost, Sup);
+ %% Opts = [{inet_backend, IB}, {port, 0}, {receive_handle, RH}] ++ TO,
+ %% d("udp open", []),
+ %% case megaco_udp:open(Sup, Opts) of
+ %% {ok, Handle, ControlPid} ->
+ %% d("udp opened: ~p, ~p", [Handle, ControlPid]),
+ %% megaco_udp_connect(IB,
+ %% MgcPort, MgcHost,
+ %% RH, Handle, ControlPid);
+ %% {error, Reason} ->
+ %% throw({error, {megaco_udp_open, Reason}})
+ %% end;
{error, Reason} ->
throw({error, {megaco_udp_start_transport, Reason}})
end.
+start_udp_open(IB, RH, TO, MgcPort, MgcHost, Sup) ->
+ Opts = [{inet_backend, IB}, {port, 0}, {receive_handle, RH}] ++ TO,
+ try_start_udp_open(RH, Opts, MgcPort, MgcHost, Sup).
+
+try_start_udp_open(RH, Opts, MgcPort, MgcHost, Sup) ->
+ d("udp open", []),
+ case megaco_udp:open(Sup, Opts) of
+ {ok, Handle, ControlPid} ->
+ d("udp opened: ~p, ~p", [Handle, ControlPid]),
+ megaco_udp_connect(MgcPort, MgcHost,
+ RH, Handle, ControlPid);
+ {error, Reason} ->
+ megaco_udp:stop_transport(Sup),
+ throw({error, {megaco_udp_open, Reason}})
+ end.
+
+
+
megaco_udp_connect(MgcPort, MgcHost, RH, Handle, ControlPid) ->
MgcMid = preliminary_mid,
SendHandle = megaco_udp:create_send_handle(Handle, MgcHost, MgcPort),
diff --git a/lib/megaco/test/megaco_test_mgc.erl b/lib/megaco/test/megaco_test_mgc.erl
index a7d0731b0f..74fd9fc7fc 100644
--- a/lib/megaco/test/megaco_test_mgc.erl
+++ b/lib/megaco/test/megaco_test_mgc.erl
@@ -57,6 +57,8 @@
-include_lib("megaco/include/megaco.hrl").
-include_lib("megaco/include/megaco_message_v1.hrl").
+-define(NO_ERROR, 'no error').
+
-define(A4444, ["11111111", "00000000", "00000000"]).
-define(A4445, ["11111111", "00000000", "11111111"]).
-define(A5555, ["11111111", "11111111", "00000000"]).
@@ -65,18 +67,19 @@
-define(valid_actions,
[ignore, pending, pending_ignore, discard_ack, handle_ack, handle_pending_ack, handle_sloppy_ack]).
--record(mgc, {parent = undefined,
- tcp_sup = undefined,
- udp_sup = undefined,
- req_action = discard_ack,
- req_timeout = 0,
- mid = undefined,
- ack_info = undefined,
- abort_info = undefined,
- req_info = undefined,
- mg = [],
+-record(mgc, {parent = undefined,
+ inet_backend = default,
+ tcp_sup = undefined,
+ udp_sup = undefined,
+ req_action = discard_ack,
+ req_timeout = 0,
+ mid = undefined,
+ ack_info = undefined,
+ abort_info = undefined,
+ req_info = undefined,
+ mg = [],
dsi_timer,
- evs = []}).
+ evs = []}).
-define(EVS_MAX, 10).
@@ -330,13 +333,14 @@ mgc(Parent, Verbosity, Config) ->
case (catch init(Config)) of
{error, Reason} ->
exit(Reason);
- {Mid, TcpSup, UdpSup, DSITimer} ->
+ {IB, Mid, TcpSup, UdpSup, DSITimer} ->
notify_started(Parent),
- S = #mgc{parent = Parent,
- tcp_sup = TcpSup,
- udp_sup = UdpSup,
- mid = Mid,
- dsi_timer = DSITimer},
+ S = #mgc{parent = Parent,
+ tcp_sup = TcpSup,
+ udp_sup = UdpSup,
+ mid = Mid,
+ dsi_timer = DSITimer,
+ inet_backend = IB},
i("mgc -> started"),
display_system_info("at start "),
loop(evs(S, started))
@@ -345,10 +349,15 @@ mgc(Parent, Verbosity, Config) ->
init(Config) ->
d("init -> entry"),
random_init(),
- Mid = get_conf(local_mid, Config),
+
+ IB = get_conf(inet_backend, Config, default),
+ Mid = get_conf(local_mid, Config),
RI = get_conf(receive_info, Config),
- d("init -> maybe start the display system info timer"),
+ d("init -> "
+ "~n Inet Backend: ~p"
+ "~n Mid: ~p"
+ "~n RI: ~p", [IB, Mid, RI]),
DSITimer =
case get_conf(display_system_info, Config, undefined) of
Time when is_integer(Time) ->
@@ -358,6 +367,7 @@ init(Config) ->
undefined
end,
Conf0 = lists:keydelete(display_system_info, 1, Config),
+ Conf1 = lists:keydelete(inet_backend, 1, Conf0),
d("init -> start megaco"),
application:start(megaco),
@@ -373,12 +383,12 @@ init(Config) ->
_ ->
ok
end,
- Conf1 = lists:keydelete(megaco_trace, 1, Conf0),
+ Conf2 = lists:keydelete(megaco_trace, 1, Conf1),
d("init -> start megaco user"),
- Conf2 = lists:keydelete(local_mid, 1, Conf1),
- Conf3 = lists:keydelete(receive_info, 1, Conf2),
- ok = megaco:start_user(Mid, Conf3),
+ Conf3 = lists:keydelete(local_mid, 1, Conf2),
+ Conf4 = lists:keydelete(receive_info, 1, Conf3),
+ ok = megaco:start_user(Mid, Conf4),
d("init -> update user info (user_mod)"),
ok = megaco:update_user_info(Mid, user_mod, ?MODULE),
@@ -392,8 +402,8 @@ init(Config) ->
Transports = parse_receive_info(RI, RH),
d("init -> start transports"),
- {Tcp, Udp} = start_transports(Transports),
- {Mid, Tcp, Udp, DSITimer}.
+ {Tcp, Udp} = start_transports(IB, Transports),
+ {IB, Mid, Tcp, Udp, DSITimer}.
loop(S) ->
d("loop -> await request"),
@@ -722,11 +732,11 @@ parse_receive_info1(RI, RH) ->
%% send/receive port (udp).
%% The second step *may* need to be repeated!
%% --------------------------------------------------------
-start_transports([]) ->
+start_transports(_, []) ->
throw({error, no_transport});
-start_transports(Transports) when is_list(Transports) ->
+start_transports(IB, Transports) when is_list(Transports) ->
{Tcp, Udp} = start_transports1(Transports, undefined, undefined),
- ok = start_transports2(Transports, Tcp, Udp),
+ ok = start_transports2(IB, Transports, Tcp, Udp),
{Tcp, Udp}.
start_transports1([], Tcp, Udp) ->
@@ -760,28 +770,29 @@ start_transports1([{_TO, _Port, RH}|Transports], Tcp, Udp)
start_transports1([_|Transports], Tcp, Udp) ->
start_transports1(Transports, Tcp, Udp).
-start_transports2([], _, _) ->
+start_transports2(_, [], _, _) ->
ok;
-start_transports2([{TO, Port, RH}|Transports], Tcp, Udp)
+start_transports2(IB, [{TO, Port, RH}|Transports], Tcp, Udp)
when RH#megaco_receive_handle.send_mod =:= megaco_tcp ->
- start_tcp(TO, RH, Port, Tcp),
- start_transports2(Transports, Tcp, Udp);
-start_transports2([{TO, Port, RH}|Transports], Tcp, Udp)
+ start_tcp(IB, TO, RH, Port, Tcp),
+ start_transports2(IB, Transports, Tcp, Udp);
+start_transports2(IB, [{TO, Port, RH}|Transports], Tcp, Udp)
when RH#megaco_receive_handle.send_mod =:= megaco_udp ->
- start_udp(TO, RH, Port, Udp),
- start_transports2(Transports, Tcp, Udp).
+ start_udp(IB, TO, RH, Port, Udp),
+ start_transports2(IB, Transports, Tcp, Udp).
-start_tcp(TO, RH, Port, Sup) ->
+start_tcp(IB, TO, RH, Port, Sup) ->
d("start tcp transport"),
- start_tcp(TO, RH, Port, Sup, 250).
+ start_tcp(IB, TO, RH, Port, Sup, 250).
-start_tcp(TO, RH, Port, Sup, Timeout)
+start_tcp(IB, TO, RH, Port, Sup, Timeout)
when is_pid(Sup) andalso is_integer(Timeout) andalso (Timeout > 0) ->
d("tcp listen on ~p", [Port]),
- Opts = [{port, Port},
+ Opts = [{inet_backend, IB},
+ {port, Port},
{receive_handle, RH},
{tcp_options, [{nodelay, true}]}] ++ TO,
- try_start_tcp(Sup, Opts, Timeout, noError).
+ try_start_tcp(Sup, Opts, Timeout, ?NO_ERROR).
try_start_tcp(Sup, Opts, Timeout, Error0) when (Timeout < 5000) ->
Sleep = random(Timeout) + 100,
@@ -790,7 +801,7 @@ try_start_tcp(Sup, Opts, Timeout, Error0) when (Timeout < 5000) ->
ok ->
d("listen socket created", []),
Sup;
- Error1 when Error0 =:= noError -> % Keep the first error
+ Error1 when Error0 =:= ?NO_ERROR -> % Keep the first error
d("failed creating listen socket [1]: ~p", [Error1]),
sleep(Sleep),
try_start_tcp(Sup, Opts, Timeout*2, Error1);
@@ -809,14 +820,16 @@ try_start_tcp(Sup, _Opts, _Timeout, Error) ->
end.
-start_udp(TO, RH, Port, Sup) ->
+start_udp(IB, TO, RH, Port, Sup) ->
d("start udp transport"),
- start_udp(TO, RH, Port, Sup, 250).
+ start_udp(IB, TO, RH, Port, Sup, 250).
-start_udp(TO, RH, Port, Sup, Timeout) ->
+start_udp(IB, TO, RH, Port, Sup, Timeout) ->
d("udp open ~p", [Port]),
- Opts = [{port, Port}, {receive_handle, RH}] ++ TO,
- try_start_udp(Sup, Opts, Timeout, noError).
+ Opts = [{inet_backend, IB},
+ {port, Port},
+ {receive_handle, RH}] ++ TO,
+ try_start_udp(Sup, Opts, Timeout, ?NO_ERROR).
try_start_udp(Sup, Opts, Timeout, Error0) when (Timeout < 5000) ->
d("try open udp socket (~p)", [Timeout]),
@@ -824,7 +837,7 @@ try_start_udp(Sup, Opts, Timeout, Error0) when (Timeout < 5000) ->
{ok, _SendHandle, _ControlPid} ->
d("port opened", []),
Sup;
- Error1 when Error0 =:= noError -> % Keep the first error
+ Error1 when Error0 =:= ?NO_ERROR -> % Keep the first error
d("failed open port [1]: ~p", [Error1]),
sleep(Timeout),
try_start_udp(Sup, Opts, Timeout*2, Error1);
diff --git a/lib/megaco/test/megaco_udp_SUITE.erl b/lib/megaco/test/megaco_udp_SUITE.erl
index e8fea517f6..461b56fad4 100644
--- a/lib/megaco/test/megaco_udp_SUITE.erl
+++ b/lib/megaco/test/megaco_udp_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2000-2020 All Rights Reserved.
+%% Copyright Ericsson AB 2000-2021 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.
@@ -81,17 +81,49 @@ suite() ->
[{ct_hooks, [ts_install_cth]}].
all() ->
+ %% This is a temporary messure to ensure that we can
+ %% test the socket backend without effecting *all*
+ %% applications on *all* machines.
+ %% This flag is set only for *one* host.
+ case ?TEST_INET_BACKENDS() of
+ true ->
+ [
+ {group, inet_backend_default},
+ {group, inet_backend_inet},
+ {group, inet_backend_socket}
+ ];
+ _ ->
+ [
+ {group, inet_backend_default}
+ ]
+ end.
+
+groups() ->
[
- {group, start},
- {group, sending},
- {group, error}
+ {inet_backend_default, [], inet_backend_default_cases()},
+ {inet_backend_inet, [], inet_backend_inet_cases()},
+ {inet_backend_socket, [], inet_backend_socket_cases()},
+
+ {all, [], all_cases()},
+ {start, [], start_cases()},
+ {sending, [], sending_cases()},
+ {error, [], error_cases()}
].
-groups() ->
+inet_backend_default_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_inet_cases() ->
+ [{all, [], all_cases()}].
+
+inet_backend_socket_cases() ->
+ [{all, [], all_cases()}].
+
+all_cases() ->
[
- {start, [], start_cases()},
- {sending, [], sending_cases()},
- {error, [], error_cases()}
+ {group, start},
+ {group, sending},
+ {group, error}
].
start_cases() ->
@@ -167,6 +199,29 @@ end_per_suite(Config0) when is_list(Config0) ->
%% -----
%%
+init_per_group(inet_backend_default = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ [{socket_create_opts, []} | Config];
+init_per_group(inet_backend_inet = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{socket_create_opts, [{inet_backend, inet}]} | Config]
+ end;
+init_per_group(inet_backend_socket = Group, Config) ->
+ ?ANNOUNCE_GROUP_INIT(Group),
+ case ?EXPLICIT_INET_BACKEND() of
+ true ->
+ %% The environment trumps us,
+ %% so only the default group should be run!
+ {skip, "explicit inet backend"};
+ false ->
+ [{socket_create_opts, [{inet_backend, socket}]} | Config]
+ end;
init_per_group(Group, Config) ->
?ANNOUNCE_GROUP_INIT(Group),
Config.
@@ -203,7 +258,6 @@ end_per_testcase(Case, Config) ->
-
%% =================================================
%%
%% ------------------ start ------------------------
@@ -217,7 +271,7 @@ start_normal(suite) ->
start_normal(Config) when is_list(Config) ->
?ACQUIRE_NODES(1, Config),
Opts = [{port, 0}, {receive_handle, apa}],
- {ok, Pid} = start_case(Opts, ok),
+ {ok, Pid} = start_case(Config, Opts, ok),
megaco_udp:stop_transport(Pid),
ok.
@@ -229,7 +283,7 @@ start_invalid_opt(suite) ->
start_invalid_opt(Config) when is_list(Config) ->
?ACQUIRE_NODES(1, Config),
Opts = [{port, 0}, {receivehandle, apa}],
- start_case(Opts, error).
+ start_case(Config, Opts, error).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -250,22 +304,22 @@ start_and_stop(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun(X) -> do_start_and_stop(Factor, X) end,
+ Case = fun(X) -> do_start_and_stop(Config, Factor, X) end,
Post = fun(Nodes) ->
p("stop nodes"),
?STOP_NODES(lists:reverse(Nodes))
end,
try_tc(start_and_stop, Pre, Case, Post).
-do_start_and_stop(Factor, [ServerNode, ClientNode]) ->
+do_start_and_stop(Config, Factor, [ServerNode, ClientNode]) ->
%% Create command sequences
TOCalc = fun(BaseTO) -> to_calc(Factor, BaseTO) end,
TO = TOCalc(?SECS(5)),
p("create command sequences"),
ServerPort = 2944,
- ServerCmds = start_and_stop_server_commands(ServerPort),
+ ServerCmds = start_and_stop_server_commands(Config, ServerPort),
{ok, ServerHost} = inet:gethostname(),
- ClientCmds = start_and_stop_client_commands(TO, ServerPort, ServerHost),
+ ClientCmds = start_and_stop_client_commands(Config, TO, ServerPort, ServerHost),
%% Start the test procs used in the test-case, one for each node
p("start command handlers"),
@@ -294,7 +348,7 @@ do_start_and_stop(Factor, [ServerNode, ClientNode]) ->
ok.
-start_and_stop_server_commands(Port) ->
+start_and_stop_server_commands(Config, Port) ->
Opts = [{port, Port}],
Self = self(),
[
@@ -313,7 +367,7 @@ start_and_stop_server_commands(Port) ->
#{id => 3,
desc => "Open",
cmd => fun(State) ->
- server_open(State, Opts)
+ server_open(Config, State, Opts)
end},
#{id => 4,
@@ -342,7 +396,7 @@ start_and_stop_server_commands(Port) ->
].
-start_and_stop_client_commands(TO, ServerPort, _ServerHost) ->
+start_and_stop_client_commands(Config, TO, ServerPort, _ServerHost) ->
Opts = [{port, ServerPort}],
Self = self(),
[
@@ -361,7 +415,7 @@ start_and_stop_client_commands(TO, ServerPort, _ServerHost) ->
#{id => 3,
desc => "Open",
cmd => fun(State) ->
- client_open(State, Opts)
+ client_open(Config, State, Opts)
end},
#{id => 4,
@@ -414,22 +468,22 @@ sendreceive(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun(X) -> do_sendreceive(Factor, X) end,
+ Case = fun(X) -> do_sendreceive(Config, Factor, X) end,
Post = fun(Nodes) ->
p("stop nodes"),
?STOP_NODES(lists:reverse(Nodes))
end,
try_tc(sendreceive, Pre, Case, Post).
-do_sendreceive(Factor, [ServerNode, ClientNode]) ->
+do_sendreceive(Config, Factor, [ServerNode, ClientNode]) ->
%% Create command sequences
p("create command sequences"),
TOCalc = fun(BaseTO) -> to_calc(Factor, BaseTO) end,
TO = TOCalc(?SECS(5)),
ServerPort = 2944,
- ServerCmds = sendreceive_server_commands(TO, ServerPort),
+ ServerCmds = sendreceive_server_commands(Config, TO, ServerPort),
{ok, ServerHost} = inet:gethostname(),
- ClientCmds = sendreceive_client_commands(TO, ServerPort, ServerHost),
+ ClientCmds = sendreceive_client_commands(Config, TO, ServerPort, ServerHost),
%% Start the test procs used in the test-case, one for each node
p("start command handlers"),
@@ -458,7 +512,7 @@ do_sendreceive(Factor, [ServerNode, ClientNode]) ->
ok.
-sendreceive_server_commands(TO, Port) ->
+sendreceive_server_commands(Config, TO, Port) ->
Opts = [{port, Port}],
Self = self(),
[
@@ -477,7 +531,7 @@ sendreceive_server_commands(TO, Port) ->
#{id => 3,
desc => "Open",
cmd => fun(State) ->
- server_open(State, Opts)
+ server_open(Config, State, Opts)
end},
#{id => 4,
@@ -541,7 +595,7 @@ sendreceive_server_commands(TO, Port) ->
end}
].
-sendreceive_client_commands(TO, ServerPort, ServerHost) ->
+sendreceive_client_commands(Config, TO, ServerPort, ServerHost) ->
OwnPort = ServerPort+1,
Opts = [{port, OwnPort}],
Self = self(),
@@ -561,7 +615,7 @@ sendreceive_client_commands(TO, ServerPort, ServerHost) ->
#{id => 3,
desc => "Open",
cmd => fun(State) ->
- client_open(State, Opts)
+ client_open(Config, State, Opts)
end},
#{id => 4,
@@ -643,23 +697,23 @@ block_unblock(Config) when is_list(Config) ->
ok = ?START_NODES(Nodes),
Nodes
end,
- Case = fun(X) -> do_block_unblock(Factor, X) end,
+ Case = fun(X) -> do_block_unblock(Config, Factor, X) end,
Post = fun(Nodes) ->
p("stop nodes"),
?STOP_NODES(lists:reverse(Nodes))
end,
try_tc(block_unblock, Pre, Case, Post).
-do_block_unblock(Factor, [ServerNode, ClientNode]) ->
+do_block_unblock(Config, Factor, [ServerNode, ClientNode]) ->
%% Create command sequences
p("create command sequences"),
TOCalc = fun(BaseTO) -> to_calc(Factor, BaseTO) end,
TO = TOCalc(?SECS(5)),
ServerPort = 2944,
p("generated command sequences with timeout: ~w msec", [TO]),
- ServerCmds = block_unblock_server_commands(TO, ServerPort),
+ ServerCmds = block_unblock_server_commands(Config, TO, ServerPort),
{ok, ServerHost} = inet:gethostname(),
- ClientCmds = block_unblock_client_commands(TO, ServerPort, ServerHost),
+ ClientCmds = block_unblock_client_commands(Config, TO, ServerPort, ServerHost),
%% Start the test procs used in the test-case, one for each node
p("start command handlers"),
@@ -707,7 +761,7 @@ do_block_unblock(Factor, [ServerNode, ClientNode]) ->
ok.
-block_unblock_server_commands(TO, Port) ->
+block_unblock_server_commands(Config, TO, Port) ->
Opts = [{port, Port}],
Self = self(),
[
@@ -726,7 +780,7 @@ block_unblock_server_commands(TO, Port) ->
#{id => 3,
desc => "Open",
cmd => fun(State) ->
- server_open(State, Opts)
+ server_open(Config, State, Opts)
end},
#{id => 4,
@@ -791,7 +845,7 @@ block_unblock_server_commands(TO, Port) ->
].
-block_unblock_client_commands(TO, ServerPort, ServerHost) ->
+block_unblock_client_commands(Config, TO, ServerPort, ServerHost) ->
OwnPort = ServerPort+1,
Opts = [{port, OwnPort}],
Self = self(),
@@ -811,7 +865,7 @@ block_unblock_client_commands(TO, ServerPort, ServerHost) ->
#{id => 3,
desc => "Open",
cmd => fun(State) ->
- client_open(State, Opts)
+ client_open(Config, State, Opts)
end},
#{id => 4,
@@ -842,7 +896,7 @@ block_unblock_client_commands(TO, ServerPort, ServerHost) ->
desc => "Pre-Block info",
cmd => fun(#{socket := Socket} = State) ->
p("Socket Info: "
- "~n Port Info: ~p", [erlang:port_info(Socket)]),
+ "~n Port Info: ~p", [inet:info(Socket)]),
{ok, State}
end},
@@ -865,7 +919,7 @@ block_unblock_client_commands(TO, ServerPort, ServerHost) ->
p("Socket Info: "
"~n Active: ~p"
"~n Port Info: ~p",
- [Active, erlang:port_info(Socket)]),
+ [Active, inet:info(Socket)]),
{ok, State}
end},
@@ -890,7 +944,7 @@ block_unblock_client_commands(TO, ServerPort, ServerHost) ->
p("Socket Info: "
"~n Active: ~p"
"~n Port Info: ~p",
- [Active, erlang:port_info(Socket)]),
+ [Active, inet:info(Socket)]),
ok
end,
client_await_nothing(State, Fail, TO div 2)
@@ -909,7 +963,7 @@ block_unblock_client_commands(TO, ServerPort, ServerHost) ->
p("Socket Info: "
"~n Active: ~p"
"~n Port Info: ~p",
- [Active, erlang:port_info(Socket)]),
+ [Active, inet:info(Socket)]),
{ok, State}
end},
@@ -932,7 +986,7 @@ block_unblock_client_commands(TO, ServerPort, ServerHost) ->
p("Socket Info: "
"~n Active: ~p"
"~n Port Info: ~p",
- [Active, erlang:port_info(Socket)]),
+ [Active, inet:info(Socket)]),
{ok, State}
end},
@@ -991,10 +1045,10 @@ socket_failure(Config) when is_list(Config) ->
%% Test functions
%%======================================================================
-start_case(Opts, Expect) ->
+start_case(Config, Opts, Expect) ->
case (catch megaco_udp:start_transport()) of
{ok, Pid} ->
- case (catch megaco_udp:open(Pid, Opts)) of
+ case (catch ?OPEN(Config, Pid, Opts)) of
{ok, _Handle, _CtrlPid} when Expect =:= ok ->
{ok, Pid};
{ok, Handle, CtrlPid} ->
@@ -1048,16 +1102,20 @@ server_start_command_handler(Node, Commands) ->
server_start_transport(State) when is_map(State) ->
case (catch megaco_udp:start_transport()) of
{ok, Ref} ->
+ p("Transport started: ~p", [Ref]),
{ok, State#{transport_ref => Ref}};
Error ->
Error
end.
-server_open(#{transport_ref := Ref} = State, Options)
+server_open(Config, #{transport_ref := Ref} = State, Options)
when is_list(Options) ->
Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
- try megaco_udp:open(Ref, Opts) of
+ try ?OPEN(Config, Ref, Opts) of
{ok, Socket, ControlPid} ->
+ p("opened: "
+ "~n Socket: ~p"
+ "~n ControlPid: ~p", [Socket, ControlPid]),
{ok, State#{handle => {socket, Socket}, % Temporary
control_pid => ControlPid}};
{error, {could_not_open_udp_port, eaddrinuse}} ->
@@ -1167,10 +1225,10 @@ client_start_transport(State) when is_map(State) ->
Error
end.
-client_open(#{transport_ref := Ref} = State, Options)
+client_open(Config, #{transport_ref := Ref} = State, Options)
when is_list(Options) ->
Opts = [{receive_handle, self()}, {module, ?MODULE} | Options],
- try megaco_udp:open(Ref, Opts) of
+ try ?OPEN(Config, Ref, Opts) of
{ok, Socket, ControlPid} ->
{ok, State#{handle => {socket, Socket},
socket => Socket,