1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1998-2021. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20-module(gen_tcp_misc_SUITE).
21
22-include_lib("common_test/include/ct.hrl").
23-include("kernel_test_lib.hrl").
24
25-export([
26	 all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
27	 init_per_group/2,end_per_group/2,
28	 controlling_process/1, controlling_process_self/1,
29	 no_accept/1, close_with_pending_output/1, active_n/1,
30         active_n_closed/1,
31	 data_before_close/1,
32	 iter_max_socks/0, iter_max_socks/1,
33	 get_status/1,
34	 passive_sockets/1, accept_closed_by_other_process/1,
35	 init_per_testcase/2, end_per_testcase/2,
36	 otp_3924/1, closed_socket/1,
37	 shutdown_active/1, shutdown_passive/1, shutdown_pending/1,
38	 show_econnreset_active/1, show_econnreset_active_once/1,
39	 show_econnreset_passive/1, econnreset_after_sync_send/1,
40	 econnreset_after_async_send_active/1,
41	 econnreset_after_async_send_active_once/1,
42	 econnreset_after_async_send_passive/1,
43         linger_zero/1, linger_zero_sndbuf/1,
44	 default_options/1, http_bad_packet/1,
45	 busy_send/1, busy_disconnect_passive/1, busy_disconnect_active/1,
46	 fill_sendq/1, partial_recv_and_close/1,
47	 partial_recv_and_close_2/1,partial_recv_and_close_3/1,so_priority/1,
48         recvtos/1, recvttl/1, recvtosttl/1, recvtclass/1,
49	 %% Accept tests
50	 primitive_accept/1,multi_accept_close_listen/1,accept_timeout/1,
51	 accept_timeouts_in_order/1,accept_timeouts_in_order2/1,
52	 accept_timeouts_in_order3/1,accept_timeouts_in_order4/1,
53	 accept_timeouts_in_order5/1,accept_timeouts_in_order6/1,
54	 accept_timeouts_in_order7/1,accept_timeouts_mixed/1,
55	 killing_acceptor/1,
56         killing_multi_acceptors/1,
57         killing_multi_acceptors2/1,
58	 several_accepts_in_one_go/1, accept_system_limit/1,
59	 active_once_closed/1, send_timeout/1, send_timeout_active/1,
60         otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1,
61         wrapping_oct/0, wrapping_oct/1, otp_9389/1, otp_13939/1,
62         otp_12242/1, delay_send_error/1, bidirectional_traffic/1,
63	 socket_monitor1/1,
64	 socket_monitor1_manys/1,
65	 socket_monitor1_manyc/1,
66	 socket_monitor1_demon_after/1,
67	 socket_monitor2/1,
68	 socket_monitor2_manys/1,
69	 socket_monitor2_manyc/1,
70	 otp_17492/1
71	]).
72
73%% Internal exports.
74-export([sender/4,
75         not_owner/1,
76         passive_sockets_server/3,
77         priority_server/2,
78	 %% oct_acceptor/1,
79         otp_3924_sender/5,
80	 otp_7731_server/2,
81         zombie_server/3,
82         do_iter_max_socks/3]).
83
84init_per_testcase(_Func, Config) ->
85    ?P("init_per_testcase -> entry with"
86       "~n   Config:   ~p"
87       "~n   Nodes:    ~p"
88       "~n   Links:    ~p"
89       "~n   Monitors: ~p",
90       [Config, erlang:nodes(), pi(links), pi(monitors)]),
91
92    kernel_test_global_sys_monitor:reset_events(),
93
94    ?P("init_per_testcase -> done when"
95       "~n   Nodes:    ~p"
96       "~n   Links:    ~p"
97       "~n   Monitors: ~p", [erlang:nodes(), pi(links), pi(monitors)]),
98    Config.
99
100end_per_testcase(_Func, Config) ->
101    ?P("end_per_testcase -> entry with"
102       "~n   Config:   ~p"
103       "~n   Nodes:    ~p"
104       "~n   Links:    ~p"
105       "~n   Monitors: ~p",
106       [Config, erlang:nodes(), pi(links), pi(monitors)]),
107
108    SysEvs = kernel_test_global_sys_monitor:events(),
109
110    ?P("system events during test: "
111       "~n   ~p", [SysEvs]),
112
113    ?P("end_per_testcase -> done with"
114       "~n   Nodes:    ~p"
115       "~n   Links:    ~p"
116       "~n   Monitors: ~p", [erlang:nodes(), pi(links), pi(monitors)]),
117    ok.
118
119suite() ->
120    [{ct_hooks,[ts_install_cth]},
121     {timetrap,{minutes,4}}].
122
123all() ->
124    %% This is a temporary messure to ensure that we can
125    %% test the socket backend without effecting *all*
126    %% applications on *all* machines.
127    %% This flag is set only for *one* host.
128    case ?TEST_INET_BACKENDS() of
129        true ->
130            [
131             {group, inet_backend_default},
132             {group, inet_backend_inet},
133             {group, inet_backend_socket}
134            ];
135        _ ->
136            [
137             {group, inet_backend_default}
138            ]
139    end.
140
141groups() ->
142    [
143     {inet_backend_default,   [], inet_backend_default_cases()},
144     {inet_backend_inet,      [], inet_backend_inet_cases()},
145     {inet_backend_socket,    [], inet_backend_socket_cases()},
146
147     {ctrl_proc,              [], ctrl_proc_cases()},
148     {close,                  [], close_cases()},
149     {active,                 [], active_cases()},
150     {shutdown,               [], shutdown_cases()},
151     {econnreset,             [], econnreset_cases()},
152     {linger_zero,            [], linger_zero_cases()},
153     {busy_disconnect,        [], busy_disconnect_cases()},
154     {partial_recv_and_close, [], partial_recv_and_close_cases()},
155     {pktoptions,             [], pktoptions_cases()},
156     {accept,                 [], accept_cases()},
157     {send_timeout,           [], send_timeout_cases()},
158     {socket_monitor,         [], socket_monitor_cases()}
159    ].
160
161inet_backend_default_cases() ->
162    all_cases().
163
164inet_backend_inet_cases() ->
165    all_cases().
166
167inet_backend_socket_cases() ->
168    all_cases().
169
170all_cases() ->
171    [
172     {group, ctrl_proc},
173     iter_max_socks,
174     {group, close},
175     {group, active},
176     {group, shutdown},
177     {group, econnreset},
178     {group, linger_zero},
179     default_options, http_bad_packet, busy_send,
180     {group, busy_disconnect},
181     fill_sendq,
182     {group, partial_recv_and_close},
183     so_priority,
184     {group, pktoptions},
185     {group, accept},
186     {group, send_timeout},
187     otp_7731,
188     wrapping_oct,
189     zombie_sockets,
190     otp_7816,
191     otp_8102, otp_9389,
192     otp_12242, delay_send_error,
193     bidirectional_traffic,
194     {group, socket_monitor},
195     otp_17492
196    ].
197
198close_cases() ->
199    [
200     no_accept,
201     close_with_pending_output,
202     data_before_close,
203     accept_closed_by_other_process,
204     otp_3924,
205     closed_socket
206    ].
207
208ctrl_proc_cases() ->
209    [
210     controlling_process,
211     controlling_process_self
212    ].
213
214active_cases() ->
215    [
216     passive_sockets,
217     active_n,
218     active_n_closed,
219     active_once_closed
220    ].
221
222shutdown_cases() ->
223    [
224     shutdown_active,
225     shutdown_passive,
226     shutdown_pending
227    ].
228
229econnreset_cases() ->
230    [
231     show_econnreset_active,
232     show_econnreset_active_once,
233     show_econnreset_passive,
234     econnreset_after_sync_send,
235     econnreset_after_async_send_active,
236     econnreset_after_async_send_active_once,
237     econnreset_after_async_send_passive
238    ].
239
240linger_zero_cases() ->
241    [
242     linger_zero,
243     linger_zero_sndbuf
244    ].
245
246busy_disconnect_cases() ->
247    [
248     busy_disconnect_passive,
249     busy_disconnect_active
250    ].
251
252partial_recv_and_close_cases() ->
253    [
254     partial_recv_and_close,
255     partial_recv_and_close_2,
256     partial_recv_and_close_3
257    ].
258
259pktoptions_cases() ->
260    [
261     recvtos,
262     recvttl,
263     recvtosttl,
264     recvtclass
265    ].
266
267accept_cases() ->
268    [
269     primitive_accept,
270     multi_accept_close_listen,
271     accept_timeout,
272     accept_timeouts_in_order,
273     accept_timeouts_in_order2,
274     accept_timeouts_in_order3,
275     accept_timeouts_in_order4,
276     accept_timeouts_in_order5,
277     accept_timeouts_in_order6,
278     accept_timeouts_in_order7,
279     accept_timeouts_mixed,
280     killing_acceptor,
281     killing_multi_acceptors,
282     killing_multi_acceptors2,
283     several_accepts_in_one_go,
284     accept_system_limit
285    ].
286
287send_timeout_cases() ->
288    [
289     send_timeout,
290     send_timeout_active
291    ].
292
293socket_monitor_cases() ->
294    [
295     socket_monitor1,
296     socket_monitor1_manys,
297     socket_monitor1_manyc,
298     socket_monitor1_demon_after,
299     socket_monitor2,
300     socket_monitor2_manys,
301     socket_monitor2_manyc
302    ].
303
304init_per_suite(Config0) ->
305
306    ?P("init_per_suite -> entry with"
307       "~n      Config: ~p"
308       "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
309
310    case ?LIB:init_per_suite(Config0) of
311        {skip, _} = SKIP ->
312            SKIP;
313
314        Config1 when is_list(Config1) ->
315
316            ?P("init_per_suite -> end when "
317               "~n      Config: ~p", [Config1]),
318
319            %% We need a monitor on this node also
320            kernel_test_sys_monitor:start(),
321
322            Config1
323    end.
324
325end_per_suite(Config0) ->
326
327    ?P("end_per_suite -> entry with"
328       "~n      Config: ~p"
329       "~n      Nodes:  ~p", [Config0, erlang:nodes()]),
330
331    %% Stop the local monitor
332    kernel_test_sys_monitor:stop(),
333
334    Config1 = ?LIB:end_per_suite(Config0),
335
336    ?P("end_per_suite -> "
337       "~n      Nodes: ~p", [erlang:nodes()]),
338
339    Config1.
340
341init_per_group(inet_backend_default = _GroupName, Config) ->
342    [{socket_create_opts, []} | Config];
343init_per_group(inet_backend_inet = _GroupName, Config) ->
344    case ?EXPLICIT_INET_BACKEND() of
345        true ->
346            %% The environment trumps us,
347            %% so only the default group should be run!
348            {skip, "explicit inet backend"};
349        false ->
350            [{socket_create_opts, [{inet_backend, inet}]} | Config]
351    end;
352init_per_group(inet_backend_socket = _GroupName, Config) ->
353    case ?EXPLICIT_INET_BACKEND() of
354        true ->
355            %% The environment trumps us,
356            %% so only the default group should be run!
357            {skip, "explicit inet backend"};
358        false ->
359            [{socket_create_opts, [{inet_backend, socket}]} | Config]
360    end;
361init_per_group(_GroupName, Config) ->
362    Config.
363
364end_per_group(_GroupName, Config) ->
365    Config.
366
367-define(UNIQ_NODE_NAME,
368  list_to_atom(?MODULE_STRING ++ "__" ++
369               atom_to_list(?FUNCTION_NAME) ++ "_" ++
370	       integer_to_list(erlang:unique_integer([positive])))).
371
372%% Tests kernel application variables inet_default_listen_options and
373%% inet_default_connect_options.
374default_options(Config) when is_list(Config) ->
375    ?TC_TRY(default_options, fun() -> do_default_options(Config) end).
376
377do_default_options(Config) ->
378    %% First check the delay_send option
379    {true,true,true}=do_delay_send_1(Config),
380    {false,false,false}=do_delay_send_2(Config),
381    {true,false,false}=do_delay_send_3(Config),
382    {false,false,false}=do_delay_send_4(Config),
383    {false,false,false}=do_delay_send_5(Config),
384    {false,true,true}=do_delay_send_6(Config),
385    %% Now lets start some nodes with different combinations of options:
386    {true,true,true} =
387        do_delay_on_other_node("", fun() -> do_delay_send_1(Config) end),
388    {true,false,false} =
389	do_delay_on_other_node("-kernel inet_default_connect_options "
390			       "\"[{delay_send,true}]\"",
391			       fun() -> do_delay_send_2(Config) end),
392
393    {false,true,true} =
394	do_delay_on_other_node("-kernel inet_default_listen_options "
395			       "\"[{delay_send,true}]\"",
396			       fun() -> do_delay_send_2(Config) end),
397
398    {true,true,true} =
399	do_delay_on_other_node("-kernel inet_default_listen_options "
400			       "\"[{delay_send,true}]\"",
401			       fun() -> do_delay_send_3(Config) end),
402    {true,true,true} =
403	do_delay_on_other_node("-kernel inet_default_connect_options "
404			       "\"[{delay_send,true}]\"",
405			       fun() -> do_delay_send_6(Config) end),
406    {false,false,false} =
407	do_delay_on_other_node("-kernel inet_default_connect_options "
408			       "\"[{delay_send,true}]\"",
409			       fun() -> do_delay_send_5(Config) end),
410    {false,true,true} =
411	do_delay_on_other_node("-kernel inet_default_connect_options "
412			       "\"[{delay_send,true}]\" "
413			       "-kernel inet_default_listen_options "
414			       "\"[{delay_send,true}]\"",
415			       fun() -> do_delay_send_5(Config) end),
416    {true,false,false} =
417	do_delay_on_other_node("-kernel inet_default_connect_options "
418			       "\"[{delay_send,true}]\" "
419			       "-kernel inet_default_listen_options "
420			       "\"[{delay_send,true}]\"",
421			       fun() -> do_delay_send_4(Config) end),
422    {true,true,true} =
423	do_delay_on_other_node("-kernel inet_default_connect_options "
424			       "\"{delay_send,true}\" "
425			       "-kernel inet_default_listen_options "
426			       "\"{delay_send,true}\"",
427			       fun() -> do_delay_send_2(Config) end),
428    %% Active is to dangerous and is supressed
429    {true,true,true} =
430	do_delay_on_other_node("-kernel inet_default_connect_options "
431			       "\"{active,false}\" "
432			       "-kernel inet_default_listen_options "
433			       "\"{active,false}\"",
434			       fun() -> do_delay_send_7(Config) end),
435    {true,true,true} =
436	do_delay_on_other_node("-kernel inet_default_connect_options "
437			       "\"[{active,false},{delay_send,true}]\" "
438			       "-kernel inet_default_listen_options "
439			       "\"[{active,false},{delay_send,true}]\"",
440			       fun() -> do_delay_send_7(Config) end),
441    {true,true,true} =
442	do_delay_on_other_node("-kernel inet_default_connect_options "
443			       "\"[{active,false},{delay_send,true}]\" "
444			       "-kernel inet_default_listen_options "
445			       "\"[{active,false},{delay_send,true}]\"",
446			       fun() -> do_delay_send_2(Config) end),
447    ok.
448
449
450do_delay_on_other_node(XArgs, Function) ->
451    Dir = filename:dirname(code:which(?MODULE)),
452    {ok, Node} = ?START_SLAVE_NODE(?UNIQ_NODE_NAME,
453                                   "-pa " ++ Dir ++ " " ++ XArgs),
454    Res = rpc:call(Node,erlang,apply,[Function,[]]),
455    ?STOP_NODE(Node),
456    Res.
457
458do_delay_send_1(Config) ->
459    {ok,LS} = ?LISTEN(Config, 0, [{delay_send,true}]),
460    {ok,{{0,0,0,0},PortNum}}=inet:sockname(LS),
461    S = case ?CONNECT(Config, "localhost", PortNum, [{delay_send,true}]) of
462            {ok, Sock} ->
463                Sock;
464            {error, eaddrnotavail = Reason} ->
465                ?SKIPT(connect_failed_str(Reason))
466        end,
467    {ok,S2}= gen_tcp:accept(LS),
468    {ok,[{delay_send,B1}]}=inet:getopts(S,[delay_send]),
469    {ok,[{delay_send,B2}]}=inet:getopts(LS,[delay_send]),
470    {ok,[{delay_send,B3}]}=inet:getopts(S2,[delay_send]),
471    gen_tcp:close(S2),
472    gen_tcp:close(S),
473    gen_tcp:close(LS),
474    {B1,B2,B3}.
475
476do_delay_send_2(Config) ->
477    {ok, LS} = ?LISTEN(Config),
478    {ok, {{0,0,0,0},PortNum}} = inet:sockname(LS),
479    {ok, S}  = ?CONNECT(Config, "localhost",PortNum,[]),
480    {ok, S2} = gen_tcp:accept(LS),
481    {ok, [{delay_send,B1}]} = inet:getopts(S,[delay_send]),
482    {ok, [{delay_send,B2}]} = inet:getopts(LS,[delay_send]),
483    {ok, [{delay_send,B3}]} = inet:getopts(S2,[delay_send]),
484    gen_tcp:close(S2),
485    gen_tcp:close(S),
486    gen_tcp:close(LS),
487    {B1,B2,B3}.
488
489do_delay_send_3(Config) ->
490    {ok, LS} = ?LISTEN(Config, 0, []),
491    {ok,{{0,0,0,0},PortNum}}=inet:sockname(LS),
492    {ok,S} = ?CONNECT(Config, "localhost", PortNum, [{delay_send,true}]),
493    {ok,S2}= gen_tcp:accept(LS),
494    {ok,[{delay_send,B1}]}=inet:getopts(S,[delay_send]),
495    {ok,[{delay_send,B2}]}=inet:getopts(LS,[delay_send]),
496    {ok,[{delay_send,B3}]}=inet:getopts(S2,[delay_send]),
497    gen_tcp:close(S2),
498    gen_tcp:close(S),
499    gen_tcp:close(LS),
500    {B1,B2,B3}.
501
502do_delay_send_4(Config) ->
503    {ok,LS} = ?LISTEN(Config, 0, [{delay_send,false}]),
504    {ok,{{0,0,0,0},PortNum}}=inet:sockname(LS),
505    {ok,S}  = ?CONNECT(Config, "localhost", PortNum, []),
506    {ok,S2}= gen_tcp:accept(LS),
507    {ok,[{delay_send,B1}]}=inet:getopts(S,[delay_send]),
508    {ok,[{delay_send,B2}]}=inet:getopts(LS,[delay_send]),
509    {ok,[{delay_send,B3}]}=inet:getopts(S2,[delay_send]),
510    gen_tcp:close(S2),
511    gen_tcp:close(S),
512    gen_tcp:close(LS),
513    {B1,B2,B3}.
514
515do_delay_send_5(Config) ->
516    {ok,LS} = ?LISTEN(Config, 0, []),
517    {ok,{{0,0,0,0},PortNum}}=inet:sockname(LS),
518    {ok,S} = ?CONNECT(Config, "localhost",PortNum,[{delay_send,false}]),
519    {ok,S2}= gen_tcp:accept(LS),
520    {ok,[{delay_send,B1}]}=inet:getopts(S,[delay_send]),
521    {ok,[{delay_send,B2}]}=inet:getopts(LS,[delay_send]),
522    {ok,[{delay_send,B3}]}=inet:getopts(S2,[delay_send]),
523    gen_tcp:close(S2),
524    gen_tcp:close(S),
525    gen_tcp:close(LS),
526    {B1,B2,B3}.
527
528do_delay_send_6(Config) ->
529    {ok,LS} = ?LISTEN(Config, 0, [{delay_send,true}]),
530    {ok,{{0,0,0,0},PortNum}}=inet:sockname(LS),
531    {ok,S} = ?CONNECT(Config, "localhost", PortNum, []),
532    {ok,S2}= gen_tcp:accept(LS),
533    {ok,[{delay_send,B1}]}=inet:getopts(S,[delay_send]),
534    {ok,[{delay_send,B2}]}=inet:getopts(LS,[delay_send]),
535    {ok,[{delay_send,B3}]}=inet:getopts(S2,[delay_send]),
536    gen_tcp:close(S2),
537    gen_tcp:close(S),
538    gen_tcp:close(LS),
539    {B1,B2,B3}.
540
541do_delay_send_7(Config) ->
542    {ok,LS} = ?LISTEN(Config, 0, []),
543    {ok,{{0,0,0,0},PortNum}}=inet:sockname(LS),
544    {ok,S}  = ?CONNECT(Config, "localhost", PortNum, []),
545    {ok,S2} = gen_tcp:accept(LS),
546    {ok,[{active,B1}]}=inet:getopts(S,[active]),
547    {ok,[{active,B2}]}=inet:getopts(LS,[active]),
548    {ok,[{active,B3}]}=inet:getopts(S2,[active]),
549    gen_tcp:close(S2),
550    gen_tcp:close(S),
551    gen_tcp:close(LS),
552    {B1,B2,B3}.
553
554%% Open a listen port and change controlling_process for it
555%% The result should be ok of done by the owner process,
556%% Otherwise is should return {error,not_owner} or similar.
557controlling_process(Config) when is_list(Config) ->
558    {ok, S} = ?LISTEN(Config, 0,[]),
559    Pid2    = spawn(?MODULE, not_owner, [S]),
560    Pid2 ! {self(),2,control},
561    {error, E} = receive {2,_E} ->
562			      _E
563		      after 10000 -> timeout
564		      end,
565    io:format("received ~p~n",[E]),
566    Pid = spawn(?MODULE,not_owner,[S]),
567    ok = gen_tcp:controlling_process(S,Pid),
568    Pid ! {self(),1,control},
569    ok = receive {1,ok} ->
570                     ok
571         after 1000 -> timeout
572         end,
573    Pid ! close.
574
575not_owner(S) ->
576    receive
577	{From,Tag,control} ->
578	    From ! {Tag,gen_tcp:controlling_process(S,self())};
579	close ->
580	    gen_tcp:close(S)
581    after 1000 ->
582	    ok
583    end.
584
585%% Open a listen port and assign the controlling process to
586%% it self, then exit and make sure the port is closed properly.
587controlling_process_self(Config) when is_list(Config) ->
588    S = self(),
589    process_flag(trap_exit,true),
590    spawn_link(fun() ->
591		       {ok,Sock} = ?LISTEN(Config, 0, []),
592		       S ! {socket, Sock},
593		       ok = gen_tcp:controlling_process(Sock,self()),
594		       S ! done
595	       end),
596    receive
597	done ->
598	    receive
599		{socket,Sock} ->
600		    process_flag(trap_exit,false),
601		    %% Make sure the port is invalid after process crash
602                    receive after 500 -> ok end,
603                    case inet:port(Sock) of
604                        {error,einval} -> ok;
605                        {error,closed} -> ok % XXX gen_tcp_socket
606                    end
607
608	    end;
609	Msg when element(1,Msg) /= socket ->
610	    process_flag(trap_exit,false),
611	    exit({unknown_msg,Msg})
612    end.
613
614
615%% Open a listen port and connect to it, then close the listen port
616%% without doing any accept.  The connected socket should receive
617%% a tcp_closed message.
618no_accept(Config) when is_list(Config) ->
619    {ok, L}         = ?LISTEN(Config, 0, []),
620    {ok, {_, Port}} = inet:sockname(L),
621    {ok, Client}    = ?CONNECT(Config, localhost, Port, []),
622    ok = gen_tcp:close(L),
623    receive
624        {tcp_closed, Client} ->
625            ok
626    after 5000 ->
627            ct:fail(never_closed)
628
629    end.
630
631%% Send several packets to a socket and close it.  All packets should
632%% arrive to the other end.
633close_with_pending_output(Config) when is_list(Config) ->
634    {ok, L} = ?LISTEN(Config, 0, [binary, {active, false}]),
635    {ok, {_, Port}} = inet:sockname(L),
636    Packets = 16,
637    Total = 2048*Packets,
638    case start_remote(close_pending) of
639	{ok, Node} ->
640	    {ok, Host} = inet:gethostname(),
641	    spawn_link(Node, ?MODULE, sender, [Config, Port, Packets, Host]),
642	    {ok, A} = gen_tcp:accept(L),
643	    case gen_tcp:recv(A, Total) of
644		      {ok, Bin} when byte_size(Bin) == Total ->
645			  gen_tcp:close(A),
646			  gen_tcp:close(L);
647		      {ok, Bin} ->
648			  ct:fail({small_packet,
649                                                  byte_size(Bin)});
650		      Error ->
651			  ct:fail({unexpected, Error})
652		  end,
653	    ok;
654	{error, no_remote_hosts} ->
655	    {skipped,"No remote hosts"};
656	{error, Other} ->
657	    ct:fail({failed_to_start_slave_node, Other})
658    end.
659
660sender(Config, Port, Packets, Host) ->
661    X256 = lists:seq(0, 255),
662    X512 = [X256|X256],
663    X1K = [X512|X512],
664    Bin = list_to_binary([X1K|X1K]),
665    {ok, Sock} = ?CONNECT(Config, Host, Port, []),
666    send_loop(Sock, Bin, Packets),
667    ok = gen_tcp:close(Sock).
668
669send_loop(_Sock, _Data, 0) -> ok;
670send_loop(Sock, Data, Left) ->
671    ok = gen_tcp:send(Sock, Data),
672    send_loop(Sock, Data, Left-1).
673
674%% Test {active,N} option
675%% Verify operation of the {active,N} option.
676active_n(Config) when is_list(Config) ->
677    ?TC_TRY(active_n, fun() -> do_active_n(Config) end).
678
679do_active_n(Config) ->
680    N = 3,
681    LS = ok(?LISTEN(Config, 0, [{active,N}])),
682    [{active,N}] = ok(inet:getopts(LS, [active])),
683    ok = inet:setopts(LS, [{active,-N}]),
684    receive
685        {tcp_passive, LS} -> ok
686    after
687        5000 ->
688            exit({error,tcp_passive_failure})
689    end,
690    [{active,false}] = ok(inet:getopts(LS, [active])),
691    ok = inet:setopts(LS, [{active,0}]),
692    receive
693        {tcp_passive, LS} -> ok
694    after
695        5000 ->
696            exit({error,tcp_passive_failure})
697    end,
698    ok = inet:setopts(LS, [{active,32767}]),
699    {error,einval} = inet:setopts(LS, [{active,1}]),
700    {error,einval} = inet:setopts(LS, [{active,-32769}]),
701    ok = inet:setopts(LS, [{active,-32768}]),
702    receive
703        {tcp_passive, LS} -> ok
704    after
705        5000 ->
706            exit({error,tcp_passive_failure})
707    end,
708    [{active,false}] = ok(inet:getopts(LS, [active])),
709    ok = inet:setopts(LS, [{active,N}]),
710    ok = inet:setopts(LS, [{active,true}]),
711    [{active,true}] = ok(inet:getopts(LS, [active])),
712    receive
713        _ -> exit({error,active_n})
714    after
715        0 ->
716            ok
717    end,
718    ok = inet:setopts(LS, [{active,N}]),
719    ok = inet:setopts(LS, [{active,once}]),
720    [{active,once}] = ok(inet:getopts(LS, [active])),
721    receive
722        _ -> exit({error,active_n})
723    after
724        0 ->
725            ok
726    end,
727    {error,einval} = inet:setopts(LS, [{active,32768}]),
728    ok = inet:setopts(LS, [{active,false}]),
729    [{active,false}] = ok(inet:getopts(LS, [active])),
730    Port = ok(inet:port(LS)),
731    C = case ?CONNECT(Config, "localhost", Port, [{active,N}]) of
732            {ok, CS} ->
733                CS;
734            {error, eaddrnotavail = Reason} ->
735                ?SKIPT(connect_failed_str(Reason))
736        end,
737    [{active,N}] = ok(inet:getopts(C, [active])),
738    S = ok(gen_tcp:accept(LS)),
739    ok = inet:setopts(S, [{active,N}]),
740    [{active,N}] = ok(inet:getopts(S, [active])),
741    repeat(3,
742           fun(I) ->
743                   Msg = "message "++integer_to_list(I),
744                   ok = gen_tcp:send(C, Msg),
745                   receive
746                       {tcp,S,Msg} ->
747                           ok = gen_tcp:send(S, Msg)
748                   after
749                       5000 ->
750                           exit({error,timeout})
751                   end,
752                   receive
753                       {tcp,C,Msg} ->
754                           ok
755                   after
756                       5000 ->
757                           exit({error,timeout})
758                   end
759           end),
760    receive
761        {tcp_passive,S} ->
762            [{active,false}] = ok(inet:getopts(S, [active]))
763    after
764        5000 ->
765            exit({error,tcp_passive})
766    end,
767    receive
768        {tcp_passive,C} ->
769            [{active,false}] = ok(inet:getopts(C, [active]))
770    after
771        5000 ->
772            exit({error,tcp_passive})
773    end,
774    LS2 = ok(?LISTEN(Config, 0, [{active,0}])),
775    receive
776        {tcp_passive,LS2} ->
777            [{active,false}] = ok(inet:getopts(LS2, [active]))
778    after
779        5000 ->
780            exit({error,tcp_passive})
781    end,
782    ok = gen_tcp:close(LS2),
783    ok = gen_tcp:close(C),
784    ok = gen_tcp:close(S),
785    ok = gen_tcp:close(LS),
786    ok.
787
788-define(OTP_3924_MAX_DELAY, 100).
789%% Taken out of the blue, but on intra host connections
790%% I expect propagation of a close to be quite fast
791%% so 100 ms seems reasonable.
792
793%% Tests that a socket can be closed fast enough.
794otp_3924(Config) when is_list(Config) ->
795    MaxDelay = (case has_superfluous_schedulers() of
796	    true -> 4;
797	    false -> 1
798	end
799	* case {erlang:system_info(debug_compiled),
800		erlang:system_info(lock_checking)} of
801	    {true, _} -> 6;
802	    {_, true} -> 2;
803	    _ -> 1
804	end * ?OTP_3924_MAX_DELAY),
805    otp_3924_1(Config, MaxDelay).
806
807otp_3924_1(Config, MaxDelay) ->
808    {ok, Node} = start_node(otp_3924),
809    DataLen = 100*1024,
810    Data = otp_3924_data(DataLen),
811    %% Repeat the test a couple of times to prevent the test from passing
812    %% by chance.
813    repeat(10, fun(N) ->
814                       ok = otp_3924(Config, MaxDelay, Node, Data, DataLen, N)
815               end),
816    ?STOP_NODE(Node),
817    ok.
818
819otp_3924(Config, MaxDelay, Node, Data, DataLen, N) ->
820    {ok, L} = ?LISTEN(Config, 0, [list, {active, false}]),
821    {ok, {_, Port}} = inet:sockname(L),
822    {ok, Host} = inet:gethostname(),
823    Sender = spawn_link(Node,
824                        ?MODULE,
825                        otp_3924_sender,
826                        [Config, self(), Host, Port, Data]),
827    Data = otp_3924_receive_data(L, Sender, MaxDelay, DataLen, N),
828    ok = gen_tcp:close(L).
829
830otp_3924_receive_data(LSock, Sender, MaxDelay, Len, N) ->
831    OP = process_flag(priority, max),
832    OTE = process_flag(trap_exit, true),
833    TimeoutRef = make_ref(),
834    Data = (catch begin
835                      Sender ! start,
836                      {ok, Sock} = gen_tcp:accept(LSock),
837                      D = otp_3924_receive_data(Sock,
838                                                TimeoutRef,
839                                                MaxDelay,
840                                                Len,
841                                                [],
842                                                0),
843                      ok = gen_tcp:close(Sock),
844                      D
845                  end),
846    unlink(Sender),
847    process_flag(trap_exit, OTE),
848    process_flag(priority, OP),
849    receive
850	{'EXIT', _, TimeoutRef} ->
851	    ct:fail({close_not_fast_enough,MaxDelay,N});
852	{'EXIT', Sender, Reason} ->
853	    ct:fail({sender_exited, Reason});
854	{'EXIT', _Other, Reason} ->
855	    ct:fail({linked_process_exited, Reason})
856    after 0 ->
857	    case Data of
858		{'EXIT', {A,B}} ->
859		    ct:fail({A,B,N});
860		{'EXIT', Failure} ->
861		    ct:fail(Failure);
862		_ ->
863		    Data
864	    end
865    end.
866
867
868otp_3924_receive_data(Sock, TimeoutRef, MaxDelay, Len, Acc, AccLen) ->
869    case gen_tcp:recv(Sock, 0) of
870	{ok, Data} ->
871	    NewAccLen = AccLen + length(Data),
872	    if
873		NewAccLen == Len ->
874		    {ok, TRef} = timer:exit_after(MaxDelay,
875							self(),
876							TimeoutRef),
877		    {error, closed} = gen_tcp:recv(Sock, 0),
878		    timer:cancel(TRef),
879		    lists:flatten([Acc, Data]);
880		NewAccLen > Len ->
881		    exit({received_too_much, NewAccLen});
882		true ->
883		    otp_3924_receive_data(Sock,
884					  TimeoutRef,
885					  MaxDelay,
886					  Len,
887					  [Acc, Data],
888					  NewAccLen)
889	    end;
890	{error, closed} ->
891	    exit({premature_close, AccLen});
892	Error ->
893	    exit({unexpected_error, Error})
894    end.
895
896otp_3924_data(Size) ->
897    Block =
898	"This is a sequence of characters that will be repeated "
899	"again and again and again and again and again and ...  ",
900    L = length(Block),
901    otp_3924_data(Block, [], Size div L, Size rem L).
902
903otp_3924_data(_, Acc, 0, 0) ->
904    lists:flatten(Acc);
905otp_3924_data(_, Acc, 0, SingleLeft) ->
906    otp_3924_data(false, ["."|Acc], 0, SingleLeft-1);
907otp_3924_data(Block, Acc, BlockLeft, SingleLeft) ->
908    otp_3924_data(Block, [Block|Acc], BlockLeft-1, SingleLeft).
909
910otp_3924_sender(Config, Receiver, Host, Port, Data) ->
911    receive
912	start ->
913	    {ok, Sock} = ?CONNECT(Config, Host, Port, [list]),
914	    gen_tcp:send(Sock, Data),
915	    ok = gen_tcp:close(Sock),
916	    unlink(Receiver)
917    end.
918
919
920%% Tests that a huge amount of data can be received before a close.
921data_before_close(Config) when is_list(Config) ->
922    {ok, L} = ?LISTEN(Config, 0, [binary]),
923    {ok, {_, TcpPort}} = inet:sockname(L),
924    Bytes = 256*1024,
925    spawn_link(fun() -> huge_sender(Config, TcpPort, Bytes) end),
926    {ok, A} = gen_tcp:accept(L),
927    case count_bytes_recv(A, 0) of
928        {Bytes, Result} ->
929            io:format("Result: ~p", [Result]);
930        {Wrong, Result} ->
931            io:format("Result: ~p", [Result]),
932            ct:fail({wrong_count, Wrong})
933    end,
934    ok.
935
936count_bytes_recv(Sock, Total) ->
937    receive
938	{tcp, Sock, Bin} ->
939	    count_bytes_recv(Sock, Total+byte_size(Bin));
940	Other ->
941	    {Total, Other}
942    end.
943
944huge_sender(Config, TcpPort, Bytes) ->
945    {ok, Client} = ?CONNECT(Config, localhost, TcpPort, []),
946    receive after 500 -> ok end,
947    gen_tcp:send(Client, make_zero_packet(Bytes)),
948    gen_tcp:close(Client).
949
950make_zero_packet(0) -> [];
951make_zero_packet(N) when N rem 2 == 0 ->
952    P = make_zero_packet(N div 2),
953    [P|P];
954make_zero_packet(N) ->
955    P = make_zero_packet(N div 2),
956    [0, P|P].
957
958%% OTP-2924. Test that the socket process does not crash when
959%% sys:get_status(Pid) is called.
960get_status(Config) when is_list(Config) ->
961    {ok,{socket,Pid,_,_}} = ?LISTEN(Config, 5678,[]),
962    {status,Pid,_,_} = sys:get_status(Pid).
963
964-define(RECOVER_SLEEP, 60000).
965-define(RETRY_SLEEP, 15000).
966
967iter_max_socks() ->
968    [{timetrap,{minutes,30}}].
969
970%% Open as many sockets as possible. Do this several times and check
971%% that we get the same number of sockets every time.
972iter_max_socks(Config) when is_list(Config) ->
973    %% This is not *nearly* enough
974    %% We have some crap machines, which we need to "handle with care"...
975    Tries =
976        case os:type() of
977            {win32, _} ->
978                10;
979            {unix, darwin} ->
980                10;
981            _ ->
982                20
983        end,
984    %% Run on a different node in order to limit the effect if this test fails.
985    Dir = filename:dirname(code:which(?MODULE)),
986    {ok, Node} = ?START_SLAVE_NODE(test_iter_max_socks, "+Q 2048 -pa " ++ Dir),
987    %% L = rpc:call(Node,?MODULE,do_iter_max_socks,[N, initalize]),
988    L = iter_max_socks_run(Node,
989                           fun() ->
990                                   exit(do_iter_max_socks(Config, Tries, initalize))
991                           end),
992    ?STOP_NODE(Node),
993
994    io:format("Result: ~p", [L]),
995    all_equal(L),
996    {comment, "Max sockets: " ++ integer_to_list(hd(L))}.
997
998iter_max_socks_run(Node, F) ->
999    try erlang:spawn_opt(Node, F, [monitor]) of
1000        {Pid, MRef} when is_pid(Pid) andalso is_reference(MRef) ->
1001            receive
1002                {'DOWN', MRef, process, Pid, Res} ->
1003                    Res
1004            end;
1005        _Any ->
1006            ?P("Unexpected process start result: "
1007               "~n   ~p", [_Any]),
1008            {skip, "Failed starting iterator (slave) process"}
1009    catch
1010        C:E:S ->
1011            ?P("Failed starting iterator (slave) process: "
1012               "~n   Class: ~p"
1013               "~n   Error: ~p"
1014               "~n   Stack: ~p", [C, E, S]),
1015            {skip, "Failed starting iterator (slave) process"}
1016    end.
1017
1018
1019do_iter_max_socks(_Config, 0, _) ->
1020    ?P("do_iter_max_socks(0,-) -> done"),
1021    [];
1022do_iter_max_socks(Config, N, initalize = First) ->
1023    ?P("do_iter_max_socks(~w,~w) -> entry", [N, First]),
1024    MS = max_socks(Config),
1025    [MS|do_iter_max_socks(Config, N-1, MS)];
1026do_iter_max_socks(Config, N, failed = First) ->
1027    ?P("do_iter_max_socks(~w,~w) -> entry", [N, First]),
1028    MS = max_socks(Config),
1029    [MS|do_iter_max_socks(Config, N-1, failed)];
1030do_iter_max_socks(Config, N, First) when is_integer(First) ->
1031    ?P("do_iter_max_socks(~w,~w) -> entry", [N, First]),
1032    MS = max_socks(Config),
1033    if
1034        (MS =:= First) ->
1035	    [MS|do_iter_max_socks(Config, N-1, First)];
1036       true ->
1037	    ?P("~w =/= ~w => sleeping for ~p seconds...",
1038               [MS, First, ?RETRY_SLEEP/1000]),
1039	    ct:sleep(?RETRY_SLEEP),
1040	    ?P("Trying again...", []),
1041	    RetryMS = max_socks(Config),
1042	    if RetryMS == First ->
1043                    [RetryMS|do_iter_max_socks(Config, N-1, First)];
1044               true ->
1045                    [RetryMS|do_iter_max_socks(Config, N-1, failed)]
1046		  end
1047    end.
1048
1049all_equal([]) ->
1050    ok;
1051all_equal([Rule | T]) ->
1052    all_equal(Rule, T).
1053
1054all_equal(Rule, [Rule | T]) ->
1055    all_equal(Rule, T);
1056all_equal(_, [_ | _]) ->
1057    ct:sleep(?RECOVER_SLEEP), % Wait a while and *hope* that we'll
1058                              % recover so other tests won't be
1059                              % affected.
1060    ct:fail(max_socket_mismatch);
1061all_equal(_Rule, []) ->
1062    ok.
1063
1064max_socks(Config) ->
1065    Socks = open_socks(Config),
1066    N = length(Socks),
1067    lists:foreach(fun(S) -> ok = gen_tcp:close(S) end, Socks),
1068    ?P("Got ~p sockets", [N]),
1069    N.
1070
1071open_socks(Config) ->
1072    case ?LISTEN(Config, 0, []) of
1073	{ok, L} ->
1074	    {ok, {_, Port}} = inet:sockname(L),
1075	    [L| connect_accept(Config, L, Port)];
1076	_ ->
1077	    []
1078    end.
1079
1080connect_accept(Config, L, Port) ->
1081    case ?CONNECT(Config, localhost, Port, []) of
1082	{ok, C} ->
1083	    [C| do_accept(Config, L, Port)];
1084	_ ->
1085	    []
1086    end.
1087
1088do_accept(Config, L, Port) ->
1089    case gen_tcp:accept(L) of
1090	{ok, A} -> [A| connect_accept(Config, L, Port)];
1091	_ -> []
1092    end.
1093
1094start_node(Name) ->
1095    Pa = filename:dirname(code:which(?MODULE)),
1096    ?START_SLAVE_NODE(Name, "-pa " ++ Pa).
1097
1098start_remote(Name) ->
1099    Pa = filename:dirname(code:which(?MODULE)),
1100    ?START_SLAVE_NODE(Name, "-pa " ++ Pa, [{remote, true}]).
1101
1102%% Tests that when 'the other side' on a passive socket closes, the
1103%% connecting side can still read until the end of data.
1104passive_sockets(Config) when is_list(Config) ->
1105    spawn_link(?MODULE, passive_sockets_server,
1106               [Config, [{active, false}], self()]),
1107    receive
1108        {socket,Port} -> ok
1109    end,
1110    ct:sleep(500),
1111    case ?CONNECT(Config, "localhost", Port, [{active, false}]) of
1112        {ok, Sock} ->
1113            passive_sockets_read(Sock);
1114        {error, eaddrnotavail = Reason} ->
1115            {skip, connect_failed_str(Reason)};
1116        Error ->
1117            ct:fail({"Could not connect to server", Error})
1118    end.
1119
1120%%
1121%% Read until we get an {error, closed}. If we get another error, this test case
1122%% should fail.
1123%%
1124passive_sockets_read(Sock) ->
1125    case gen_tcp:recv(Sock, 0, 2000) of
1126	{ok, Data} ->
1127	    io:format("Received ~p bytes~n", [length(Data)]),
1128	    passive_sockets_read(Sock);
1129	{error, closed} ->
1130	    gen_tcp:close(Sock);
1131	Error ->
1132	    gen_tcp:close(Sock),
1133	    ct:fail({"Did not get {error, closed} before other error", Error})
1134    end.
1135
1136passive_sockets_server(Config, Opts, Parent) ->
1137    case ?LISTEN(Config, 0, Opts) of
1138        {ok, LSock} ->
1139            {ok,{_,Port}} = inet:sockname(LSock),
1140            Parent ! {socket,Port},
1141            passive_sockets_server_accept(LSock);
1142        Error ->
1143            ct:fail({"Could not create listen socket", Error})
1144    end.
1145
1146passive_sockets_server_accept(Sock) ->
1147    case gen_tcp:accept(Sock) of
1148        {ok, Socket} ->
1149            timer:sleep(500),			% Simulate latency
1150            passive_sockets_server_send(Socket, 5),
1151            passive_sockets_server_accept(Sock);
1152        Error ->
1153            ct:fail({"Could not accept connection", Error})
1154    end.
1155
1156passive_sockets_server_send(Socket, 0) ->
1157    io:format("Closing other end..~n", []),
1158    gen_tcp:close(Socket);
1159passive_sockets_server_send(Socket, X) ->
1160    Data = lists:duplicate(1024*X, $a),
1161    case gen_tcp:send(Socket, Data) of
1162        ok ->
1163            ct:sleep(50),   % Simulate some processing.
1164            passive_sockets_server_send(Socket, X-1);
1165        {error, _Reason} ->
1166            ct:fail("Failed to send data")
1167    end.
1168
1169
1170%% Tests the return value from gen_tcp:accept when
1171%% the socket is closed from another process. (OTP-3817)
1172accept_closed_by_other_process(Config) when is_list(Config) ->
1173    Parent = self(),
1174    {ok, ListenSocket} = ?LISTEN(Config, 0, []),
1175    Child =
1176	spawn_link(
1177	  fun() ->
1178		  Parent ! {self(), gen_tcp:accept(ListenSocket)}
1179	  end),
1180    receive after 1000 -> ok end,
1181    ok = gen_tcp:close(ListenSocket),
1182    receive
1183        {Child, {error, closed}} ->
1184            ok;
1185        {Child, Other} ->
1186            ct:fail({"Wrong result of gen_tcp:accept", Other})
1187    end.
1188
1189repeat(N, Fun) ->
1190    repeat(N, N, Fun).
1191
1192repeat(N, T, Fun) when is_integer(N), N > 0 ->
1193    Fun(T-N),
1194    repeat(N-1, T, Fun);
1195repeat(_, _, _) ->
1196    ok.
1197
1198
1199%% Tests the response when using a closed socket as argument.
1200closed_socket(Config) when is_list(Config) ->
1201    {ok, LS1} = ?LISTEN(Config, 0, []),
1202    erlang:yield(),
1203    ok = gen_tcp:close(LS1),
1204    %% If the following delay is uncommented, the result error values
1205    %% below will change from {error, einval} to {error, closed} since
1206    %% inet_db then will have noticed that the socket is closed.
1207    %% This is a scheduling issue, i.e when the gen_server in
1208    %% in inet_db processes the 'EXIT' message from the port,
1209    %% the socket is unregistered.
1210    %%
1211    %% ct:sleep({seconds,2})
1212    %%
1213    {error, R_send} = gen_tcp:send(LS1, "data"),
1214    {error, R_recv} = gen_tcp:recv(LS1, 17),
1215    {error, R_accept} = gen_tcp:accept(LS1),
1216    {error, R_controlling_process} =
1217	gen_tcp:controlling_process(LS1, self()),
1218    %%
1219    ok = ?P("R_send = ~p", [R_send]),
1220    ok = ?P("R_recv = ~p", [R_recv]),
1221    ok = ?P("R_accept = ~p", [R_accept]),
1222    ok = ?P("R_controlling_process = ~p", [R_controlling_process]),
1223    ok.
1224
1225%%%
1226%%% Test using the gen_tcp:shutdown/2 function using a sort server.
1227%%%
1228
1229shutdown_active(Config) when is_list(Config) ->
1230    ?TC_TRY(shutdown_active, fun() -> shutdown_common(Config, true) end).
1231
1232shutdown_passive(Config) when is_list(Config) ->
1233    ?TC_TRY(shutdown_passive, fun() -> shutdown_common(Config, false) end).
1234
1235shutdown_common(Config, Active) ->
1236    ?P("start sort server"),
1237    P = sort_server(Config, Active),
1238    ?P("Sort server port: ~p", [P]),
1239
1240
1241    do_sort(Config, P, []),
1242    do_sort(Config, P, ["glurf"]),
1243    do_sort(Config, P, ["abc","nisse","dum"]),
1244
1245    do_sort(Config, P, [lists:reverse(integer_to_list(I)) || I <- lists:seq(25, 255)]),
1246    do_sort(Config, P, [lists:reverse(integer_to_list(I)) || I <- lists:seq(77, 999)]),
1247    do_sort(Config, P, [lists:reverse(integer_to_list(I)) || I <- lists:seq(25, 55)]),
1248    do_sort(Config, P, []),
1249    do_sort(Config, P, ["apa"]),
1250    do_sort(Config, P, ["kluns","gorilla"]),
1251    do_sort(Config, P, [lists:reverse(integer_to_list(I)) || I <- lists:seq(25, 1233)]),
1252    do_sort(Config, P, []),
1253    receive
1254	Any ->
1255	    ct:fail({unexpected_message,Any})
1256    after 0 -> ok
1257    end.
1258
1259do_sort(Config, P, List0) ->
1260    ?P("Sort: "
1261       "~n   ~p", [List0]),
1262    List = [El++"\n" || El <- List0],
1263    S = case ?CONNECT(Config, localhost, P, [{packet,line}]) of
1264            {ok, Socket} ->
1265                Socket;
1266            {error, eaddrnotavail = Reason} ->
1267                ?SKIPT(connect_failed_str(Reason))
1268        end,
1269    send_lines(S, List),
1270    ok = gen_tcp:shutdown(S, write),
1271    Lines = collect_lines(S, true),
1272    ?P("Collected: "
1273       "~n   ~p", [Lines]),
1274    SortedLines = lists:sort(List),
1275    ?P("Sorted: "
1276       "~n   ~p", [SortedLines]),
1277    Lines = SortedLines,
1278    ok = gen_tcp:close(S).
1279
1280sort_server(Config, Active) ->
1281    Opts = [{exit_on_close,false},{packet,line},{active,Active}],
1282    {ok,L} = ?LISTEN(Config, 0, Opts),
1283    Go = make_ref(),
1284    Pid = spawn_link(fun() ->
1285                             receive Go -> sort_server_1(L, Active) end
1286                     end),
1287    ok = gen_tcp:controlling_process(L, Pid),
1288    Pid ! Go,
1289    {ok,Port} = inet:port(L),
1290    Port.
1291
1292sort_server_1(L, Active) ->
1293    {ok,S} = gen_tcp:accept(L),
1294    Go = make_ref(),
1295    Sorter = spawn(fun() -> receive Go -> sorter(S, Active) end end),
1296    ok = gen_tcp:controlling_process(S, Sorter),
1297    Sorter ! Go,
1298    sort_server_1(L, Active).
1299
1300sorter(S, Active) ->
1301    Lines = collect_lines(S, Active),
1302    send_lines(S, lists:sort(Lines)),
1303    gen_tcp:shutdown(S, write),
1304    gen_tcp:close(S).
1305
1306collect_lines(S, true) ->
1307    collect_lines_1(S, []);
1308collect_lines(S, false) ->
1309    passive_collect_lines_1(S, []).
1310
1311collect_lines_1(S, Acc) ->
1312    receive
1313	{tcp,S,Line} ->
1314            ?P("collect_lines_1(~w): ~p", [S, Line]),
1315            collect_lines_1(S, [Line|Acc]);
1316	{tcp_closed,S} ->
1317            ?P("collect_lines_1(~w): tcp_closed", [S]),
1318            lists:reverse(Acc)
1319    end.
1320
1321passive_collect_lines_1(S, Acc) ->
1322    case gen_tcp:recv(S, 0) of
1323	{ok,Line} -> passive_collect_lines_1(S, [Line|Acc]);
1324	{error,closed} -> lists:reverse(Acc)
1325    end.
1326
1327
1328send_lines(S, Lines) ->
1329    lists:foreach(fun(Line) ->
1330                          ?P("send_line(~w): ~p", [S, Line]),
1331			  ok = gen_tcp:send(S, Line)
1332		  end, Lines).
1333
1334%%%
1335%%% Shutdown pending.
1336%%%
1337
1338shutdown_pending(Config) when is_list(Config) ->
1339    ?TC_TRY(shutdown_pending, fun() -> do_shutdown_pending(Config) end).
1340
1341do_shutdown_pending(Config) ->
1342    N = 512*1024+17,
1343    ?P("N: ~p", [N]),
1344    Data = [<<N:32>>,ones(N),42],
1345    {Port, Pid} = a_server(Config),
1346    ?P("try connect to server (port: ~p)", [Port]),
1347    S = case ?CONNECT(Config, localhost, Port, []) of
1348            {ok, Socket} ->
1349                ?P("connected"),
1350                Socket;
1351            {error, eaddrnotavail = Reason} ->
1352                ?SKIPT(connect_failed_str(Reason))
1353        end,
1354    ?P("send"),
1355    gen_tcp:send(S, Data),
1356    ?P("shutdown(write)"),
1357    gen_tcp:shutdown(S, write),
1358    ?P("await data message"),
1359    case sp_await_data(Pid, S) of
1360        N ->
1361            ok;
1362        InvalidN ->
1363            ?P("Invalid message: "
1364               "~n   Expected: ~p"
1365               "~n   Received: ~p", [N, InvalidN]),
1366            ct:fail({unexpected_msg, N, InvalidN})
1367    end,
1368    ?P("done"),
1369    ok.
1370
1371sp_await_data(Pid, Sock) ->
1372    receive
1373        {tcp, Sock, Msg} ->
1374            ?P("got tcp (data) message: ~p", [Msg]),
1375            list_to_integer(Msg) - 5;
1376        {'EXIT', Pid, normal} ->
1377            ?P("server exited normal"),
1378            sp_await_data(Pid, Sock);
1379        Other ->
1380            ?P("UNEXPECTED: "
1381               "~n   ~p", [Other]),
1382            ct:fail({unexpected, Other})
1383    end.
1384
1385 ones(0) -> [];
1386 ones(1) -> [1];
1387 ones(N) ->
1388     Half = N div 2,
1389     Ones = ones(Half),
1390     case 2*Half of
1391	 N -> [Ones|Ones];
1392	 _ -> [1,Ones|Ones]
1393     end.
1394
1395 a_server(Config) ->
1396     {ok, L}    = ?LISTEN(Config, 0, [{exit_on_close,false},{active,false}]),
1397     Pid        = spawn_link(fun() -> a_server2(L) end),
1398     ok         = gen_tcp:controlling_process(L, Pid),
1399     {ok, Port} = inet:port(L),
1400     {Port, Pid}.
1401
1402a_server2(L) ->
1403     {ok,S} = gen_tcp:accept(L),
1404     do_recv(S, []).
1405
1406 do_recv(S, Bs0) ->
1407     case gen_tcp:recv(S, 0) of
1408	 {ok,B} ->
1409	     do_recv(S, [Bs0,B]);
1410	 {error,closed} ->
1411	     Bs = list_to_binary(Bs0),
1412	     gen_tcp:send(S, integer_to_list(byte_size(Bs))),
1413	     gen_tcp:close(S)
1414     end.
1415
1416%%
1417%% Test 'show_econnreset' option
1418%%
1419
1420show_econnreset_active(Config) when is_list(Config) ->
1421    ?TC_TRY(show_econnreset_active,
1422            fun() -> do_show_econnreset_active(Config) end).
1423
1424do_show_econnreset_active(Config) ->
1425    %% First confirm everything works with option turned off.
1426    ?P("test with option switched off (default)"),
1427    {ok, L0} = ?LISTEN(Config, 0, []),
1428    {ok, Port0} = inet:port(L0),
1429    Client0 = case ?CONNECT(Config, localhost, Port0, [{active, false}]) of
1430                 {ok, CSock0} ->
1431                     CSock0;
1432                  {error, eaddrnotavail = Reason0} ->
1433                      ?SKIPT(connect_failed_str(Reason0))
1434              end,
1435    {ok, S0} = gen_tcp:accept(L0),
1436    ok = gen_tcp:close(L0),
1437    ok = inet:setopts(Client0, [{linger, {true, 0}}]),
1438    ok = gen_tcp:close(Client0),
1439    receive
1440       {tcp_closed, S0} ->
1441	   ok;
1442       Other0 ->
1443	   ct:fail({unexpected, off, closed, Other0})
1444    after 1000 ->
1445	ct:fail({timeout, {server, no_tcp_closed}})
1446    end,
1447
1448    %% Now test with option switched on.
1449    %% Note: We are also testing that the show_econnreset option is
1450    %% inherited from the listening socket by the accepting socket.
1451    ?P("test with option explicitly switched on"),
1452    {ok, L1} = ?LISTEN(Config, 0, [{show_econnreset, true}]),
1453    {ok, Port1} = inet:port(L1),
1454    Client1 = case ?CONNECT(Config, localhost, Port1, [{active, false}]) of
1455                  {ok, CSock1} ->
1456                      CSock1;
1457                  {error, eaddrnotavail = Reason1} ->
1458                      ?SKIPT(connect_failed_str(Reason1))
1459              end,
1460    {ok, S1} = gen_tcp:accept(L1),
1461    ok = gen_tcp:close(L1),
1462    ok = inet:setopts(Client1, [{linger, {true, 0}}]),
1463    ok = gen_tcp:close(Client1),
1464    receive
1465	{tcp_error, S1, econnreset} ->
1466	    receive
1467		{tcp_closed, S1} ->
1468                    ?P("done"),
1469		    ok;
1470		Other1 ->
1471                    ?P("UNEXPECTED (expected closed):"
1472                       "~n   ~p", [Other1]),
1473		    ct:fail({unexpected, on, closed, Other1})
1474	    after 1 ->
1475                    ?P("UNEXPECTED timeout (expected closed)"),
1476                    ct:fail({timeout, {server, no_tcp_closed}})
1477	    end;
1478	Other2 ->
1479            ?P("UNEXPECTED (expected error:econnreset):"
1480               "~n   ~p", [Other2]),
1481	    ct:fail({unexpected, on, econnreset, Other2})
1482    after 1000 ->
1483            ?P("UNEXPECTED timeout (expected error:econnreset)"),
1484            ct:fail({timeout, {server, no_tcp_error}})
1485    end.
1486
1487show_econnreset_active_once(Config) when is_list(Config) ->
1488    ?TC_TRY(show_econnreset_active_once,
1489            fun() -> do_show_econnreset_active_once(Config) end).
1490
1491do_show_econnreset_active_once(Config) ->
1492    %% Now test using {active, once}
1493    {ok, L} = ?LISTEN(Config, 0,
1494			   [{active, false},
1495			    {show_econnreset, true}]),
1496    {ok, Port} = inet:port(L),
1497    Client = case ?CONNECT(Config, localhost, Port, [{active, false}]) of
1498                 {ok, CSock} ->
1499                     CSock;
1500                  {error, eaddrnotavail = Reason} ->
1501                      ?SKIPT(connect_failed_str(Reason))
1502              end,
1503    {ok, S} = gen_tcp:accept(L),
1504    ok = gen_tcp:close(L),
1505    ok = inet:setopts(Client, [{linger, {true, 0}}]),
1506    ok = gen_tcp:close(Client),
1507    ok = ct:sleep(20),
1508    ok = receive Msg -> {unexpected_msg, Msg} after 0 -> ok end,
1509    ok = inet:setopts(S, [{active, once}]),
1510    receive
1511	{tcp_error, S, econnreset} ->
1512	    receive
1513		{tcp_closed, S} ->
1514		    ok;
1515		Other1 ->
1516		    ct:fail({unexpected1, Other1})
1517	    after 1 ->
1518		ct:fail({timeout, {server, no_tcp_closed}})
1519	    end;
1520	Other2 ->
1521	    ct:fail({unexpected2, Other2})
1522    after 1000 ->
1523	ct:fail({timeout, {server, no_tcp_error}})
1524    end.
1525
1526show_econnreset_passive(Config) when is_list(Config) ->
1527    ?TC_TRY(show_econnreset_passive,
1528            fun() -> do_show_econnreset_passive(Config) end).
1529
1530do_show_econnreset_passive(Config) ->
1531    %% First confirm everything works with option turned off.
1532    {ok, L} = ?LISTEN(Config, 0, [{active, false}]),
1533    {ok, Port} = inet:port(L),
1534    Client = case ?CONNECT(Config, localhost, Port, [{active, false}]) of
1535                 {ok, CSock} ->
1536                     CSock;
1537                 {error, eaddrnotavail = Reason} ->
1538                     ?SKIPT(connect_failed_str(Reason))
1539             end,
1540    {ok, S} = gen_tcp:accept(L),
1541    ok = gen_tcp:close(L),
1542    ok = inet:setopts(S, [{linger, {true, 0}}]),
1543    ok = gen_tcp:close(S),
1544    ok = ct:sleep(1),
1545    {error, closed} = gen_tcp:recv(Client, 0),
1546
1547    %% Now test with option switched on.
1548    {ok, L1} = ?LISTEN(Config, 0, [{active, false}]),
1549    {ok, Port1} = inet:port(L1),
1550    Client1 =
1551        case ?CONNECT(Config, localhost, Port1,
1552                             [{active, false}, {show_econnreset, true}]) of
1553            {ok, CSock1} ->
1554                CSock1;
1555            {error, eaddrnotavail = Reason1} ->
1556                ?SKIPT(connect_failed_str(Reason1))
1557        end,
1558    {ok, S1} = gen_tcp:accept(L1),
1559    ok = gen_tcp:close(L1),
1560    ok = inet:setopts(S1, [{linger, {true, 0}}]),
1561    ok = gen_tcp:close(S1),
1562    ok = ct:sleep(1),
1563    {error, econnreset} = gen_tcp:recv(Client1, 0).
1564
1565econnreset_after_sync_send(Config) when is_list(Config) ->
1566    ?TC_TRY(econnreset_after_sync_send,
1567            fun() -> do_econnreset_after_sync_send(Config) end).
1568
1569do_econnreset_after_sync_send(Config) ->
1570    %% First confirm everything works with option turned off.
1571    ?P("test with option switched off (default)"),
1572    {ok, L} = ?LISTEN(Config, 0, [{active, false}]),
1573    {ok, Port} = inet:port(L),
1574    Client = case ?CONNECT(Config, localhost, Port, [{active, false}]) of
1575                 {ok, CSock} ->
1576                     CSock;
1577            {error, eaddrnotavail = Reason} ->
1578                ?SKIPT(connect_failed_str(Reason))
1579        end,
1580    {ok, S} = gen_tcp:accept(L),
1581    ok = gen_tcp:close(L),
1582    ok = inet:setopts(S, [{linger, {true, 0}}]),
1583    ok = gen_tcp:close(S),
1584    ok = ct:sleep(20),
1585    {error, closed} = gen_tcp:send(Client, "Whatever"),
1586
1587    %% Now test with option switched on.
1588    ?P("test with option explicitly switched on"),
1589    {ok, L1} = ?LISTEN(Config, 0, [{active, false}]),
1590    {ok, Port1} = inet:port(L1),
1591    Client1 =
1592        case ?CONNECT(Config, localhost, Port1,
1593                             [{active, false}, {show_econnreset, true}]) of
1594            {ok, CSock1} ->
1595                CSock1;
1596            {error, eaddrnotavail = Reason1} ->
1597                ?SKIPT(connect_failed_str(Reason1))
1598        end,
1599    {ok, S1} = gen_tcp:accept(L1),
1600    ok = gen_tcp:close(L1),
1601    ok = inet:setopts(S1, [{linger, {true, 0}}]),
1602    ok = gen_tcp:close(S1),
1603    ok = ct:sleep(20),
1604    {error, econnreset} = gen_tcp:send(Client1, "Whatever").
1605
1606econnreset_after_async_send_active(Config) when is_list(Config) ->
1607    ?TC_TRY(econnreset_after_async_send_active,
1608            fun() -> do_econnreset_after_async_send_active(Config) end).
1609
1610do_econnreset_after_async_send_active(Config) ->
1611    {OS, _}  = os:type(),
1612    CPayload = craasa_mk_payload(),
1613    SPayload = "Whatever",
1614
1615    %% First confirm everything works with option turned off.
1616    ?P("pre 1 (default)"),
1617    {Client1, Server1} = craasa_pre(Config, default),
1618
1619    ?P("populate 1 (default)"),
1620    {ok, Sender1} = craasa_populate(OS, default,
1621                                    Client1, Server1, CPayload, SPayload),
1622    ?P("sleep some"),
1623    ok = ct:sleep(20),
1624
1625    ?P("[server] set linger true:0"),
1626    ok = inet:setopts(Server1, [{linger, {true, 0}}]),
1627    ?P("[server] close socket"),
1628    ok = gen_tcp:close(Server1),
1629    ?P("sleep some"),
1630    ok = ct:sleep(20),
1631
1632    ?P("verify 1 (default)"),
1633    craasa_verify(default, Client1, SPayload),
1634
1635    ?P("cleanup 1 (default)"),
1636    craasa_cleanup(Client1, Sender1),
1637
1638    %% Now test with option switched on.
1639    ?P("pre 2 (true)"),
1640    {Client2, Server2} = craasa_pre(Config, true),
1641
1642    ?P("populate 2 (true)"),
1643    {ok, Sender2} = craasa_populate(OS, true,
1644                                    Client2, Server2, CPayload, SPayload),
1645    ?P("sleep some"),
1646    ok = ct:sleep(20),
1647
1648    ?P("[server] set linger true:0"),
1649    ok = inet:setopts(Server2, [{linger, {true, 0}}]),
1650    ?P("[server] close socket"),
1651    ok = gen_tcp:close(Server2),
1652    ?P("sleep some"),
1653    ok = ct:sleep(20),
1654
1655    ?P("verify 2 (true)"),
1656    craasa_verify(true, Client2, SPayload),
1657
1658    ?P("cleanup 2 (true)"),
1659    craasa_cleanup(Client2, Sender2),
1660
1661    ?P("done"),
1662    ok.
1663
1664craasa_mk_payload() ->
1665    list_to_binary(lists:duplicate(1024 * 1024, $.)).
1666
1667craasa_pre(Config, EConnReset)
1668  when is_boolean(EConnReset) orelse (EConnReset =:= default) ->
1669    ?P("create listen socket (server) with active = false"),
1670    {ok, L}    = ?LISTEN(Config, 0, [{active, false}, {recbuf, 4096}]),
1671    {ok, Port} = inet:port(L),
1672    ?P("[client] create connect socket with show_econnreset: ~p", [EConnReset]),
1673    Opts = if (EConnReset =:= default) -> [];
1674              is_boolean(EConnReset)   -> [{show_econnreset, EConnReset}]
1675           end,
1676    Client = case ?CONNECT(Config, localhost, Port, [{sndbuf, 4096}] ++ Opts) of
1677                 {ok, CSock} ->
1678                     CSock;
1679            {error, eaddrnotavail = Reason} ->
1680                ?SKIPT(connect_failed_str(Reason))
1681        end,
1682    ?P("create accept socket (server)"),
1683    {ok, S} = gen_tcp:accept(L),
1684    ?P("close listen socket"),
1685    ok = gen_tcp:close(L),
1686    {Client, S}.
1687
1688craasa_populate(OS, _EConnReset, Client, Server, CPayload, SPayload)
1689  when is_port(Client) andalso is_port(Server) ->
1690    ?P("send payload (~w bytes) from client to server", [byte_size(CPayload)]),
1691    ok = gen_tcp:send(Client, CPayload),
1692    ?P("verify client socket queue size"),
1693    case erlang:port_info(Client, queue_size) of
1694	{queue_size, N} when N > 0 -> ok;
1695	{queue_size, 0} when OS =:= win32 -> ok;
1696	{queue_size, 0} = T -> ct:fail(T)
1697    end,
1698    ?P("[server] send something"),
1699    ok = gen_tcp:send(Server, SPayload),
1700    {ok, undefined};
1701craasa_populate(_OS, EConnReset, Client, Server, CPayload, SPayload) ->
1702    ExpectedSendRes = if (EConnReset =:= default) -> closed;
1703                         (EConnReset =:= true)    -> econnreset
1704                      end,
1705    Sender = spawn_link(fun() ->
1706                                craasa_populate_sender(Client,
1707                                                       ExpectedSendRes,
1708                                                       CPayload)
1709                        end),
1710    receive
1711        {'EXIT', Sender, Reason} ->
1712            {error, {unexpected_exit, Sender, Reason}}
1713    after 2000 ->
1714            ?P("[server] send something"),
1715            ok = gen_tcp:send(Server, SPayload),
1716            {ok, Sender}
1717    end.
1718
1719craasa_populate_sender(Client, ExpectedSendRes, Payload) ->
1720    ?P("[socket] send payload (expect failure)"),
1721    case gen_tcp:send(Client, Payload) of
1722        {error, ExpectedSendRes} ->
1723            ?P("[socket] payload send failure (as expected)"),
1724            exit(normal);
1725        Unexpected ->
1726            exit({unexpected, Unexpected})
1727    end.
1728
1729craasa_cleanup(Client, Sender) ->
1730    (catch gen_tcp:close(Client)),
1731    craasa_cleanup(Sender).
1732
1733craasa_cleanup(Sender) when is_pid(Sender) ->
1734    exit(Sender, kill),
1735    receive
1736        {'EXIT', Sender, _} ->
1737            ok
1738    after 0 ->
1739            ok
1740    end;
1741craasa_cleanup(_) ->
1742    ok.
1743
1744craasa_verify(default, Client, Payload) ->
1745    ?P("[verify-default] client await server data"),
1746    receive
1747	{tcp, Client, Payload} ->
1748            ?P("[verify-default] "
1749               "client received expected server data - "
1750               "now await socket closed"),
1751	    receive
1752		{tcp_closed, Client} ->
1753                    ?P("[verify-default] "
1754                       "received client socket closed"),
1755		    ok;
1756		Other1 ->
1757                    ?P("[verify-default] "
1758                       "awaiting client socket closed - received upexpected: "
1759                       "~n      ~p", [Other1]),
1760		    ct:fail({unexpected, tcp_closed, Other1})
1761	    end;
1762	Other2 ->
1763            ?P("[verify-default] "
1764               "awaiting client socket data - received upexpected: "
1765               "~n      ~p", [Other2]),
1766	    ct:fail({unexpected, tcp, Other2})
1767    end;
1768craasa_verify(true, Client, Payload) ->
1769    ?P("[verify-true] client await server data"),
1770    receive
1771	{tcp, Client, Payload} ->
1772            ?P("[verify-true] "
1773               "client received expected server data - now await socket error"),
1774	    receive
1775		{tcp_error, Client, econnreset} ->
1776                    ?P("[verify-true] "
1777                       "client received expected socket error - "
1778                       "now await socket closed"),
1779		    receive
1780			{tcp_closed, Client} ->
1781                            ?P("[verify-true] "
1782                               "client received expected socket closed"),
1783			    ok;
1784			Other1 ->
1785                            ?P("[verify-true] "
1786                               "client awaiting socket closed - "
1787                               "received upexpected: "
1788                               "~n      ~p", [Other1]),
1789			    ct:fail({unexpected, tcp_closed, Other1})
1790		    end;
1791		Other2 ->
1792                    ?P("[verify-true] "
1793                       "client awaiting socket error - received upexpected: "
1794                       "~n      ~p", [Other2]),
1795		    ct:fail({unexpected, tcp_error, Other2})
1796	    end;
1797	Other3 ->
1798            ?P("[verify-true] "
1799               "client awaiting socket data - received upexpected: "
1800               "~n      ~p", [Other3]),
1801	    ct:fail({unexpected, tcp, Other3})
1802    end.
1803
1804
1805%% --------------------------------------------------------------------------
1806
1807econnreset_after_async_send_active_once(Config) when is_list(Config) ->
1808    ?TC_TRY(econnreset_after_async_send_active_once,
1809            fun() -> do_econnreset_after_async_send_active_once(Config) end).
1810
1811do_econnreset_after_async_send_active_once(Config) ->
1812    ?P("pre"),
1813    {Client, Server, CPayload, SPayload} = craasao_pre(Config),
1814
1815    ?P("populate"),
1816    {ok, Sender} = craasao_populate(Client, Server, CPayload, SPayload),
1817
1818    ?P("set server socket option linger: {true, 0}"),
1819    ok = inet:setopts(Server, [{linger, {true, 0}}]),
1820    ?P("close server socket"),
1821    ok = gen_tcp:close(Server),
1822    ?P("sleep some"),
1823    ok = ct:sleep(20),
1824
1825    ?P("verify"),
1826    craasao_verify(Client, Sender, SPayload),
1827
1828    ?P("cleanup"),
1829    craasao_cleanup(Client),
1830
1831    ?P("done"),
1832    ok.
1833
1834craasao_pre(Config) ->
1835    ?P("[pre] create listen socket with active = false"),
1836    {ok, L}    = ?LISTEN(Config, 0, [{active, false}, {recbuf, 4096}]),
1837    ?P("[pre] listen socket: "
1838       "~n      ~p", [L]),
1839    {ok, Port} = inet:port(L),
1840    ?P("[pre] create connect socket (~w)", [Port]),
1841    Client     = case ?CONNECT(Config, localhost, Port,
1842                               [{active,          false},
1843                                {sndbuf,          4096},
1844                                {show_econnreset, true}]) of
1845                     {ok, CSock} ->
1846                         ?P("[pre] connect socket created:"
1847                              "~n      ~p", [CSock]),
1848                         CSock;
1849                     {error, eaddrnotavail = Reason} ->
1850                         ?SKIPT(connect_failed_str(Reason))
1851                 end,
1852    ?P("[pre] create accept socket"),
1853    {ok, Server} = gen_tcp:accept(L),
1854    ?P("[pre] close listen socket"),
1855    ok = gen_tcp:close(L),
1856    {Client, Server, craasao_mk_payload(), "Whatever"}.
1857
1858craasao_populate(Client, Server, CPayload, SPayload)
1859  when is_port(Client) andalso is_port(Server) ->
1860    ?P("[populate,inet] client send data when"
1861       "~n      Client: ~p"
1862       "~n      Server: ~p", [Client, Server]),
1863    ok      = gen_tcp:send(Client, CPayload),
1864    ?P("[populate,inet] verify client socket queue size"),
1865    {OS, _} = os:type(),
1866    case erlang:port_info(Client, queue_size) of
1867	{queue_size, N} when N > 0 -> ok;
1868	{queue_size, 0} when OS =:= win32 -> ok;
1869	{queue_size, 0} = T -> ct:fail(T)
1870    end,
1871    ?P("[populate,inet] server send data"),
1872    ok = gen_tcp:send(Server, SPayload),
1873    ?P("[populate,inet] sleep some"),
1874    ok = ct:sleep(20),
1875    {ok, undefined};
1876craasao_populate(Client, Server, CPayload, SPayload) ->
1877    ?P("[populate,socket] entry when"
1878       "~n      Client: ~p"
1879       "~n      Server: ~p", [Client, Server]),
1880    Sender = spawn_link(fun() ->
1881                                craasao_populate_sender(Client, CPayload)
1882                        end),
1883    receive
1884        {'EXIT', Sender, Reason} ->
1885            {error, {unexpected_exit, Sender, Reason}}
1886    after 2000 ->
1887            ?P("[populate,socket] send something"),
1888            ok = gen_tcp:send(Server, SPayload),
1889            {ok, Sender}
1890    end.
1891
1892craasao_populate_sender(Client, Payload) ->
1893    ?P("[populate,sender] send payload (expect failure)"),
1894    {error, econnreset} = gen_tcp:send(Client, Payload),
1895    ?P("[populate,sender] payload send failure (as expected)"),
1896    exit(normal).
1897
1898craasao_mk_payload() ->
1899    list_to_binary(lists:duplicate(1024 * 1024, $.)).
1900
1901craasao_verify(Client, _Sender, _Payload) when is_port(Client) ->
1902    ?P("[verify] ensure no 'unexpected messages' received"),
1903    ok = receive Msg -> {unexpected_msg, Msg} after 0 -> ok end,
1904    ?P("[verify] set client socket option active: once"),
1905    ok = inet:setopts(Client, [{active, once}]),
1906    ?P("[verify] expect client econnreset"),
1907    receive
1908	{tcp_error, Client, econnreset} ->
1909            ?P("[verify] received client econnreset -> "
1910               "expect client closed message"),
1911	    receive
1912		{tcp_closed, Client} ->
1913                    ?P("[verify] "
1914                       "received expected client closed message - done"),
1915		    ok;
1916		Other1 ->
1917                    ?P("[verify] client received unexpected message "
1918                         "(expected closed): "
1919                       "~n      ~p", [Other1]),
1920		    ct:fail({unexpected, tcp_closed, Other1})
1921	    end;
1922	Other2 ->
1923            ?P("[verify] client received unexpected message (expected error): "
1924               "~n      Unexpected: ~p"
1925               "~n      Flushed:    ~p", [Other2, craasao_flush()]),
1926	    ct:fail({unexpected, tcp_error, Other2})
1927    end;
1928craasao_verify(Client, Sender, Payload) when is_pid(Sender) ->
1929    ?P("[verify] begin with"
1930       "~n      Client: ~p"
1931       "~n      Sender: ~p", [Client, Sender]),
1932    craasao_verify_sender(Sender),
1933    ?P("[verify] ensure no 'unexpected messages' received"),
1934    ok = receive Msg -> {unexpected_msg, Msg} after 0 -> ok end,
1935    ?P("[verify] set client socket option active once (1)"),
1936    ok = inet:setopts(Client, [{active, once}]),
1937    ?P("[verify] client expect (server) data"),
1938    receive
1939        {tcp, Client, Payload} ->
1940            ?P("[verify] client received expected data"),
1941            ok
1942    end,
1943    ?P("[verify] set client socket option active once (2)"),
1944    ok = inet:setopts(Client, [{active, once}]),
1945    ?P("[verify] await client econnreset"),
1946    receive
1947	{tcp_error, Client, econnreset} ->
1948            ?P("[verify] client received expected econnreset -> "
1949               "expect socket close message"),
1950	    receive
1951		{tcp_closed, Client} ->
1952		    ?P("[verify] client received expected closed message"),
1953                    ok;
1954		Other1 ->
1955		    ?P("[verify] client received unexpected message "
1956                         "(expected closed): "
1957		       "~n      Unexpected: ~p"
1958		       "~n      Flushed:    ~p", [Other1, craasao_flush()]),
1959		    ct:fail({unexpected, tcp_closed, Other1})
1960	    end;
1961	Other2 ->
1962            ?P("[verify] client received unexpected message (expected error): "
1963               "~n      Unexpected: ~p"
1964               "~n      Flushed:    ~p", [Other2, craasao_flush()]),
1965	    ct:fail({unexpected, tcp_error, Other2})
1966    after 10000 ->
1967            ?P("[verify] client received unexpected timeout (expected error): "
1968               "~n      Flushed: ~p", [craasao_flush()]),
1969	    ct:fail({unexpected_timeout, tcp_error})
1970    end.
1971
1972craasao_flush() ->
1973    craasao_flush([]).
1974
1975craasao_flush(Acc) ->
1976    erlang:yield(),
1977    receive Msg    -> craasao_flush([Msg|Acc])
1978    after     1000 -> lists:reverse(Acc)
1979    end.
1980
1981craasao_verify_sender(Sender) when is_pid(Sender) ->
1982    ?P("await sender termination"),
1983    receive
1984        {'EXIT', Sender, normal} ->
1985	    ?P("expected normal sender termination received"),
1986            ok;
1987        {'EXIT', Sender, Reason} ->
1988            ?P("unexpected sender termination: "
1989               "~n      ~p", [Reason]),
1990	    ct:fail({unexpected_sender_termination, Sender, Reason})
1991    after infinity ->
1992            ok
1993    end;
1994craasao_verify_sender(_) ->
1995    ok.
1996
1997craasao_cleanup(Client) ->
1998    (catch gen_tcp:close(Client)).
1999
2000
2001%% --------------------------------------------------------------------------
2002
2003econnreset_after_async_send_passive(Config) when is_list(Config) ->
2004    ?TC_TRY(econnreset_after_async_send_passive,
2005            fun() -> do_econnreset_after_async_send_passive(Config) end).
2006
2007do_econnreset_after_async_send_passive(Config) ->
2008    CPayload = craasp_mk_payload(),
2009    SPayload = "Whatever",
2010
2011    %% First confirm everything works with option turned off.
2012    ?P("pre 1 (default)"),
2013    {Client1, Server1} = craasp_pre(Config, default),
2014
2015    ?P("populate 1 (default)"),
2016    {ok, Sender1} = craasp_populate(default,
2017                                    Client1, Server1, CPayload, SPayload),
2018
2019    ?P("close server socket (1)"),
2020    ok = gen_tcp:close(Server1),
2021    ?P("sleep some"),
2022    ok = ct:sleep(20),
2023
2024    ?P("verify 1 (default)"),
2025    ?line ok = craasp_verify(Client1, default, SPayload),
2026
2027    ?P("cleanup 1 (default)"),
2028    craasp_cleanup(Client1, Sender1),
2029
2030    %% Now test with option switched on.
2031    ?P("pre 2 (true)"),
2032    {Client2, Server2} = craasp_pre(Config, true),
2033
2034    ?P("populate 2 (default)"),
2035    {ok, Sender2} = craasp_populate(true,
2036                                    Client2, Server2, CPayload, SPayload),
2037
2038
2039    ?P("close server socket 2"),
2040    ok = gen_tcp:close(Server2),
2041    ?P("sleep some"),
2042    ok = ct:sleep(20),
2043
2044    ?P("verify 2 (default)"),
2045    ?line ok = craasp_verify(Client2, true, SPayload),
2046
2047    ?P("cleanup 2 (default)"),
2048    craasp_cleanup(Client2, Sender2),
2049
2050    ?P("done"),
2051    ok.
2052
2053
2054craasp_pre(Config, EConnReset)
2055  when is_boolean(EConnReset) orelse (EConnReset =:= default) ->
2056    ?P("create listen socket *** with option switched off (default)"),
2057    {ok, L}    = ?LISTEN(Config, 0, [{active, false}, {recbuf, 4096}]),
2058    {ok, Port} = inet:port(L),
2059    ?P("[client] create connect socket with show_econnreset: ~p", [EConnReset]),
2060    COpts = [{active, false}, {sndbuf, 4096}] ++
2061        if (EConnReset =:= default) -> [];
2062           is_boolean(EConnReset)   -> [{show_econnreset, EConnReset}]
2063        end,
2064    Client = case ?CONNECT(Config, localhost, Port, COpts) of
2065                 {ok, CSock} ->
2066                     CSock;
2067            {error, eaddrnotavail = Reason} ->
2068                ?SKIPT(connect_failed_str(Reason))
2069        end,
2070    ?P("accept connection"),
2071    {ok, Server} = gen_tcp:accept(L),
2072    ?P("close listen socket"),
2073    ok = gen_tcp:close(L),
2074    {Client, Server}.
2075
2076craasp_mk_payload() ->
2077    list_to_binary(lists:duplicate(1024 * 1024, $.)).
2078
2079craasp_populate(_EConnReset, Client, Server, CPayload, SPayload)
2080  when is_port(Client) andalso is_port(Server) ->
2081    ?P("[server] set linger: true:0"),
2082    ok = inet:setopts(Server, [{linger, {true, 0}}]),
2083    ?P("[server] send some data to client"),
2084    ok = gen_tcp:send(Server, SPayload),
2085    ?P("[client] send some data to server"),
2086    ok = gen_tcp:send(Client, CPayload),
2087    {OS, _} = os:type(),
2088    ?P("[client] verify (port) queue-size"),
2089    case erlang:port_info(Client, queue_size) of
2090	{queue_size, N} when N > 0 -> ok;
2091	{queue_size, 0} when OS =:= win32 -> ok;
2092	{queue_size, 0} = T -> ct:fail(T)
2093    end,
2094    {ok, undefined};
2095craasp_populate(EConnReset, Client, Server, CPayload, SPayload) ->
2096    ExpectedSendRes = if (EConnReset =:= default) -> closed;
2097                         (EConnReset =:= true)    -> econnreset
2098                      end,
2099    Sender = spawn_link(fun() ->
2100                                craasp_populate_sender(Client,
2101                                                       ExpectedSendRes,
2102                                                       CPayload)
2103                        end),
2104    receive
2105        {'EXIT', Sender, Reason} ->
2106            {error, {unexpected_exit, Sender, Reason}}
2107    after 2000 ->
2108            ?P("[server] send something"),
2109            ok = gen_tcp:send(Server, SPayload),
2110            {ok, Sender}
2111    end.
2112
2113craasp_populate_sender(Client, ExpectedSendRes, Payload) ->
2114    ?P("[socket] send payload (expect failure)"),
2115    {error, ExpectedSendRes} = gen_tcp:send(Client, Payload),
2116    ?P("[socket] payload send failure (as expected)"),
2117    exit(normal).
2118
2119craasp_verify(Client, EConnReset, _Payload)
2120  when is_port(Client) andalso
2121       ((EConnReset =:= default) orelse is_boolean(EConnReset)) ->
2122    ?P("[client,~w] attempt receive and expect error (closed): "
2123       "~n   Port Info:     ~p"
2124       "~n   Socket Status: ~s",
2125       [EConnReset,
2126        try erlang:port_info(Client)
2127        catch
2128            _:_:_ ->
2129                "-"
2130        end,
2131        try prim_inet:getstatus(Client) of
2132            {ok, CStatus} -> ?F("~p", [CStatus]);
2133            _             -> "-"
2134        catch
2135            _:_:_ ->
2136                "-"
2137        end]),
2138    case gen_tcp:recv(Client, 0) of
2139        {error, closed}     when (EConnReset =:= default) ->
2140            ok;
2141        {error, econnreset} when (EConnReset =:= true)    ->
2142            ok;
2143        {error, Reason} ->
2144            {error, {unexpected_error, Reason}};
2145        ok ->
2146            {error, unexpected_success}
2147    end;
2148craasp_verify(Client, EConnReset, Payload)
2149  when (EConnReset =:= default) orelse is_boolean(EConnReset) ->
2150    ?P("[client] attempt first recv and expect success"),
2151    case gen_tcp:recv(Client, 0) of
2152        {ok, Payload} ->
2153            ?P("[client] attempt second recv and expect failure (~w)",
2154               [EConnReset]),
2155            case gen_tcp:recv(Client, 0) of
2156		{error, closed}     when (EConnReset =:= default) ->
2157                    ?P("[client] expected failure (closed)"),
2158		    ok;
2159		{error, econnreset} when (EConnReset =:= true)    ->
2160                    ?P("[client] expected failure (econnreset)"),
2161		    ok;
2162                {error, Reason2} ->
2163                    ?P("[client] unexpected failure:"
2164                       "~n      EConnReset: ~p"
2165                       "~n      Reason:     ~p", [EConnReset, Reason2]),
2166                    {error, {unexpected_error2, EConnReset, Reason2}};
2167                {ok, _} ->
2168                    ?P("[client] unexpected success"),
2169                    {error, unexpected_recv2}
2170            end;
2171        {ok, _} ->
2172            ?P("[client] unexpected first recv success (wrong payload)"),
2173            {error, unexpected_recv1};
2174        {error, Reason1} ->
2175            ?P("[client] unexpected first recv failure: "
2176               "~n      Reason: ~p", [Reason1]),
2177            {error, {unexpected_error1, Reason1}}
2178    end.
2179
2180craasp_cleanup(Client, Sender) ->
2181    (catch gen_tcp:close(Client)),
2182    craasp_cleanup(Sender).
2183
2184craasp_cleanup(Sender) when is_pid(Sender) ->
2185    exit(Sender, kill),
2186    receive
2187        {'EXIT', Sender, _} ->
2188            ok
2189    after 0 ->
2190            ok
2191    end;
2192craasp_cleanup(_) ->
2193    ok.
2194
2195
2196
2197%%
2198%% Test {linger {true, 0}} aborts a connection
2199%%
2200
2201linger_zero(Config) when is_list(Config) ->
2202    ?TC_TRY(linger_zero, fun() -> do_linger_zero(Config) end).
2203
2204do_linger_zero(Config) ->
2205    %% All the econnreset tests will prove that {linger, {true, 0}} aborts
2206    %% a connection when the driver queue is empty. We will test here
2207    %% that it also works when the driver queue is not empty.
2208    {OS, Client, Server} = lz_pre(Config),
2209
2210    PayloadSize  = 1024 * 1024,
2211    {ok, Sender} = lz_populate(Client, OS, PayloadSize),
2212
2213    ?P("set linger: {true, 0}"),
2214    ok = inet:setopts(Client, [{linger, {true, 0}}]),
2215    ?P("close client socket"),
2216    ok = gen_tcp:close(Client),
2217    ?P("sleep some"),
2218    ok = ct:sleep(1),
2219
2220    lz_verify(Client, Server, PayloadSize),
2221
2222    ?P("cleanup"), % Just in case
2223    (catch gen_tcp:close(Server)),
2224    if is_pid(Sender) -> exit(Sender, kill);
2225       true           -> ok
2226    end,
2227
2228    ?P("done"),
2229    ok.
2230
2231lz_pre(Config) ->
2232    {OS, _} = os:type(),
2233    ?P("create listen socket"),
2234    {ok, L} = ?LISTEN(Config, 0, [{active, false},
2235                                  {recbuf, 4096},
2236                                  {show_econnreset, true}]),
2237    ?P("listen socket created"),
2238    %% inet_backend = inet
2239    {ok, Port} = inet:port(L),
2240    ?P("connect (create client socket)"),
2241    Client = case ?CONNECT(Config, localhost, Port,
2242                           [{nodelay, true},
2243                            {active,  false},
2244                            {sndbuf,  4096}]) of
2245                 {ok, CSock} ->
2246                     CSock;
2247                 {error, eaddrnotavail = Reason} ->
2248                     ?SKIPT(connect_failed_str(Reason))
2249             end,
2250    ?P("accept"),
2251    {ok, Server} = gen_tcp:accept(L),
2252    ?P("close listen socket"),
2253    ok = gen_tcp:close(L),
2254    {OS, Client, Server}.
2255
2256lz_populate(Client, OS, PayloadSize) when is_port(Client) ->
2257    ?P("[inet] create payload"),
2258    Payload = lz_make_payload(PayloadSize),
2259    ?P("[inet] ensure non-empty queue"),
2260    lz_ensure_non_empty_queue(Client, Payload, OS),
2261    {ok, undefined};
2262lz_populate(Client, _OS, PayloadSize) ->
2263    ?P("[socket] send payload"),
2264    Sender = spawn_link(fun() -> lz_populate_sender(Client, PayloadSize) end),
2265    receive
2266        {'EXIT', Sender, Reason} ->
2267            {error, {unexpected_exit, Sender, Reason}}
2268    after 2000 ->
2269            {ok, Sender}
2270    end.
2271
2272lz_populate_sender(Client, PayloadSize) ->
2273    ?P("[socket] create payload"),
2274    Payload = lz_make_payload(PayloadSize),
2275    ?P("[socket] send payload (expect failure)"),
2276    {error, closed} = gen_tcp:send(Client, Payload),
2277    ?P("[socket] payload send failed (as expected)"),
2278    exit(normal).
2279
2280lz_verify(Client, Server, PayloadSize)
2281  when is_port(Client) andalso is_port(Server) ->
2282    ?P("[inet] verify client socket (port) not connected"),
2283    undefined = erlang:port_info(Client, connected),
2284    ?P("[inet] try (and fail) recv (on accepted socket)"),
2285    {error, econnreset} = gen_tcp:recv(Server, PayloadSize),
2286    ok;
2287lz_verify(_Client, Server, PayloadSize) ->
2288    ?P("[socket] try (and fail) recv (on accepted socket)"),
2289    {error, econnreset} = gen_tcp:recv(Server, PayloadSize),
2290    ok.
2291
2292lz_make_payload(PayloadSize) ->
2293    list_to_binary(lists:duplicate(PayloadSize, $.)).
2294
2295%% THIS DOES NOT WORK FOR 'SOCKET'
2296lz_ensure_non_empty_queue(Sock, Payload, OS) when is_port(Sock) ->
2297    lz_ensure_non_empty_queue(Sock, Payload, OS, 1).
2298
2299-define(LZ_MAX_SENDS, 3).
2300
2301lz_ensure_non_empty_queue(Sock, _Payload, _OS, N) when (N > ?LZ_MAX_SENDS) ->
2302    ?P("queue size verification failed - port info: "
2303       "~n   Socket:      ~p"
2304       "~n   Socket info: ~p", [Sock, erlang:port_info(Sock)]),
2305    ct:fail("Queue size verification failed");
2306lz_ensure_non_empty_queue(Sock, Payload, OS, N) ->
2307    ?P("try send payload (~w bytes) ~w (on client socket) when port info:"
2308       "~n   ~p", [byte_size(Payload), N, erlang:port_info(Sock)]),
2309    ok = gen_tcp:send(Sock, Payload),
2310    ?P("try verify client socket queue size"),
2311    case erlang:port_info(Sock, queue_size) of
2312	{queue_size, QSz} when QSz > 0 ->
2313            ?P("queue size verification *successfull* (~p) - port info: "
2314               "~n   ~p", [QSz, erlang:port_info(Sock)]),
2315            ok;
2316	{queue_size, 0} when OS =:= win32 ->
2317            ?P("queue size verification *successfull* - port info: "
2318               "~n   ~p", [erlang:port_info(Sock)]),
2319            ok;
2320	{queue_size, 0} ->
2321            ?P("queue size verification failed - port info: "
2322               "~n   ~p", [erlang:port_info(Sock)]),
2323            lz_ensure_non_empty_queue(Sock, Payload, OS, N+1)
2324    end.
2325
2326
2327linger_zero_sndbuf(Config) when is_list(Config) ->
2328    ?TC_TRY(linger_zero_sndbuf, fun() -> do_linger_zero_sndbuf(Config) end).
2329
2330do_linger_zero_sndbuf(Config) ->
2331    %% All the econnreset tests will prove that {linger, {true, 0}} aborts
2332    %% a connection when the driver queue is empty. We will test here
2333    %% that it also works when the driver queue is not empty
2334    %% and the linger zero option is set on the listen socket.
2335    {OS, Client, Server} = lzs_pre(Config),
2336
2337    PayloadSize = 1024 * 1024,
2338    {ok, Sender} = lzs_populate(Client, OS, PayloadSize),
2339
2340    ?P("verify linger: {true, 0}"),
2341    {ok, [{linger, {true, 0}}]} = inet:getopts(Server, [linger]),
2342    ?P("close client socket"),
2343    ok = gen_tcp:close(Server),
2344    ok = ct:sleep(1),
2345
2346    lzs_verify(Client, Server, PayloadSize),
2347
2348    ?P("cleanup"), % Just in case
2349    (catch gen_tcp:close(Server)),
2350    if is_pid(Sender) -> exit(Sender, kill);
2351       true           -> ok
2352    end,
2353
2354    ?P("done"),
2355    ok.
2356
2357lzs_pre(Config) ->
2358    {OS, _} = os:type(),
2359    ?P("create listen socket"),
2360    {ok, Listen} = ?LISTEN(Config, 0, [{active,          false},
2361                                       {recbuf,          4096},
2362                                       {show_econnreset, true},
2363                                       {linger,          {true, 0}}]),
2364    {ok, Port} = inet:port(Listen),
2365    ?P("connect (create client socket)"),
2366    Client = case ?CONNECT(Config, localhost, Port,
2367                           [{nodelay, true},
2368                            {active,  false},
2369                            {sndbuf,  4096}]) of
2370            {ok, CSock} ->
2371                CSock;
2372            {error, eaddrnotavail = CReason} ->
2373                ?SKIPT(connect_failed_str(CReason))
2374        end,
2375    ?P("accept"),
2376    {ok, Server} = gen_tcp:accept(Listen),
2377    %% On *some* platforms, the linger is inherited,
2378    %% but not all so do not assume...
2379    ?P("check if linger option was inherited"),
2380    case inet:getopts(Server, [linger]) of
2381	{ok, [{linger, {true, 0}}]} ->
2382	    ?P("linger option was inherited"),
2383	    ok;
2384	{ok, [{linger, {true, TO}}]} ->
2385	    ?P("linger option was *not* inherited: ~p", [TO]),
2386	    ok = inet:setopts(Server, [{linger, {true, 0}}]),
2387	    ok;
2388	{error, SReason} ->
2389	    ?P("FAILED reading linger option: ~p", [SReason]),
2390	    ok = inet:setopts(Server, [{linger, {true, 0}}]),
2391	    ok
2392    end,
2393    ?P("close listen socket"),
2394    ok = gen_tcp:close(Listen),
2395    {OS, Client, Server}.
2396
2397lzs_populate(Client, OS, PayloadSize) when is_port(Client) ->
2398    ?P("[inet] create payload"),
2399    Payload = lzs_make_payload(PayloadSize),
2400    ?P("[inet] ensure non-empty queue"),
2401    lz_ensure_non_empty_queue(Client, Payload, OS),
2402    {ok, undefined};
2403lzs_populate(Client, _OS, PayloadSize) ->
2404    ?P("[socket] send payload ( = start payload sender)"),
2405    Sender = spawn(fun() -> lzs_populate_sender(Client, PayloadSize) end),
2406    receive
2407        {'EXIT', Sender, Reason} ->
2408            {error, {unexpected_exit, Sender, Reason}}
2409    after 2000 ->
2410            {ok, Sender}
2411    end.
2412
2413lzs_populate_sender(Client, PayloadSize) ->
2414    ?P("[socket] create payload"),
2415    Payload = lzs_make_payload(PayloadSize),
2416    ?P("[socket] send payload (expect failure)"),
2417    {error, closed} = gen_tcp:send(Client, Payload),
2418    ?P("[socket] payload send failed (as expected)"),
2419    exit(normal).
2420
2421lzs_make_payload(PayloadSize) ->
2422    Payload = binary:copy(<<"0123456789ABCDEF">>, 64 * 1024), % 1 MB
2423    if (PayloadSize =:= byte_size(Payload)) ->
2424            Payload;
2425       true ->
2426            exit({payload_size, PayloadSize, byte_size(Payload)})
2427    end.
2428
2429lzs_verify(Client, Server, PayloadSize)
2430  when is_port(Client) andalso is_port(Server) ->
2431    ?P("[inet] verify client socket (port) not connected"),
2432    undefined = erlang:port_info(Server, connected),
2433    ?P("[inet] try (and fail) recv (on accepted socket)"),
2434    {error, closed} = gen_tcp:recv(Client, PayloadSize),
2435    ok;
2436lzs_verify(Client, _Server, PayloadSize) ->
2437    ?P("[socket] try (and fail) recv (on accepted socket)"),
2438    {error, closed} = gen_tcp:recv(Client, PayloadSize),
2439    ok.
2440
2441%% Thanks to Luke Gorrie. Tests for a very specific problem with
2442%% corrupt data. The testcase will be killed by the timetrap timeout
2443%% if the bug is present.
2444http_bad_packet(Config) when is_list(Config) ->
2445    {ok,L} = ?LISTEN(Config, 0, [{active, false},
2446                                binary,
2447                                {reuseaddr, true},
2448                                {packet, http}]),
2449    {ok,Port} = inet:port(L),
2450    spawn_link(fun() -> erlang:yield(), http_bad_client(Config, Port) end),
2451    case gen_tcp:accept(L) of
2452        {ok,S} ->
2453            http_worker(S);
2454        Err ->
2455            exit({accept,Err})
2456    end.
2457
2458http_worker(S) ->
2459    case gen_tcp:recv(S, 0, 30000) of
2460	{ok,{http_error,Error}} ->
2461	     io:format("Http error: ~s\n", [Error]);
2462	{ok,Data} ->
2463	    io:format("Data: ~p\n", [Data]),
2464	    http_worker(S)
2465    end.
2466
2467http_bad_client(Config, Port) ->
2468    {ok,S} = ?CONNECT(Config, "localhost", Port, [{active,false}, binary]),
2469    ok = gen_tcp:send(S, "\r\n"),
2470    ok = gen_tcp:close(S).
2471
2472
2473%% Fill send queue and then start receiving.
2474%%
2475busy_send(Config) when is_list(Config) ->
2476    ?TC_TRY(busy_send, fun() -> do_busy_send(Config) end).
2477
2478do_busy_send(Config) ->
2479    OldFlag = process_flag(trap_exit, true),
2480    Master  = self(),
2481    Msg     = <<"the quick brown fox jumps over a lazy dog~n">>,
2482    ?P("[master] start server"),
2483    ServerF =
2484        fun() ->
2485                ?P("[server] create listen socket"),
2486                case ?LISTEN(Config, 0, [{active,false},binary,
2487                                         {reuseaddr,true},
2488                                         {packet,0},
2489                                         {recbuf,4096},
2490                                         {sndbuf,4096}]) of
2491                    {ok, L} ->
2492                        ?P("[server] listen socket created"),
2493                        {ok, Port} = inet:port(L),
2494                        Master ! {self(), listen_port, Port},
2495                        ?P("[server] await continue"),
2496                        receive
2497                            {Master, continue} ->
2498                                ?P("[server] received continue"),
2499                                busy_send_srv(L, Master, Msg)
2500                        end;
2501                    {error, Reason} ->
2502                        ?P("[server] UNEXPECTED: ~w", [Reason]),
2503                        ?SKIPE(listen_failed_str(Reason))
2504                end
2505        end,
2506    Server = spawn_link(ServerF),
2507    ?P("[master] server: ~p", [Server]),
2508    ListenPort =
2509        receive
2510            {'EXIT', Server, {skip, _} = SKIP} ->
2511                ?P("[master] server issued skip: "
2512                   "~n      ~p", [SKIP]),
2513                throw(SKIP);
2514
2515            {'EXIT', Server, Reason} ->
2516                ?P("[master] server crashed: "
2517                   "~n      ~p", [Reason]),
2518                exit({server, Reason});
2519
2520            {Server, listen_port, LP} ->
2521                ?P("listen port: ~p", [LP]),
2522                LP
2523        end,
2524    ?P("[master] start client"),
2525    ClientF =
2526      fun () ->
2527              ?P("[client] await (connect) server port"),
2528              Port =
2529                  receive
2530                      {Master, connect, P} ->
2531                          P
2532                  end,
2533              ?P("[client] connect to ~w", [Port]),
2534	      case ?CONNECT(Config, "localhost", Port,
2535                                   [{active,false},
2536                                    binary,
2537                                    {packet,0},
2538                                    {recbuf,4096},
2539                                    {sndbuf,4096}]) of
2540                  {ok, Socket} ->
2541                      Master ! {self(), connected},
2542                      ?P("[client] connected - await recv"),
2543                      receive
2544                          {Master, recv, N} ->
2545                              ?P("[client] received recv:~w", [N]),
2546                              busy_send_client_loop(Socket, Master, Msg, N)
2547                      end;
2548                  {error, eaddrnotavail = CReason} ->
2549                      ?P("[client] UNEXPECTED: ~w", [CReason]),
2550                      ?SKIPE(connect_failed_str(CReason))
2551              end
2552      end,
2553    Client = spawn_link(ClientF),
2554    ?P("[master] client: ~p", [Client]),
2555    Server ! {self(), continue},
2556    Client ! {self(), connect, ListenPort},
2557    receive
2558        {Client, connected} ->
2559            ?P("[master] client connected"),
2560            ok
2561    end,
2562    busy_send_loop(Server, Client, 0),
2563    process_flag(trap_exit, OldFlag),
2564    ?P("[master] done"),
2565    ok.
2566
2567busy_send_loop(Server, Client, N) ->
2568    %% Master
2569    %%
2570    receive
2571        {Server, send} ->
2572            busy_send_loop(Server, Client, N+1)
2573
2574    after 2000 ->
2575            ?P("[master] send timeout: server send queue full (N = ~w+1)", [N]),
2576            %% Send queue full, sender blocked
2577            %% -> stop sender and release client
2578            Server ! {self(), close},
2579            Client ! {self(), recv, N+1},
2580            ?P("[master] await server 'send'..."),
2581            receive
2582                {Server, send} ->
2583                    busy_send_2(Server, Client, N+1)
2584            after 10000 ->
2585                    %% If this happens, see busy_send_srv
2586                    ?P("[master] UNEXPECTED: server send timeout"),
2587                    ct:fail({timeout,{server,not_send,flush([])}})
2588            end
2589    end.
2590
2591busy_send_2(Server, Client, _N) ->
2592    %% Master
2593    %%
2594    ?P("[master] await (server) closed"),
2595    receive
2596        {Server, [closed]} ->
2597            ?P("[master] received expected (server) closed - "
2598               "await client closed"),
2599            receive
2600                {Client, [0,{error,closed}]} ->
2601                    ?P("[master] received expected (client) closed"),
2602                    ok
2603            end
2604    after 10000 ->
2605            ?P("[master] UNEXPECTED: server closed timeout"),
2606            ct:fail({timeout, {server, not_closed, flush([])}})
2607    end.
2608
2609busy_send_srv(L, Master, Msg) ->
2610    %% Server
2611    %% Sometimes this accept does not return, do not really know why
2612    %% but it causes the timeout error in busy_send_loop to be
2613    %% triggered. Only happens on OS X Leopard?!?
2614    ?P("[server] try accept"),
2615    case gen_tcp:accept(L) of
2616        {ok, Socket} ->
2617            ?P("[server] accepted"),
2618            busy_send_srv_loop(Socket, Master, Msg);
2619        {error, Reason} ->
2620            ?P("UNEXPECTED: server accept failure: ~p", [Reason]),
2621            ?SKIPE(accept_failed_str(Reason))
2622    end.
2623
2624busy_send_srv_loop(Socket, Master, Msg) ->
2625    %% Server
2626    %%
2627    receive
2628	{Master, close} ->
2629            ?P("[server] received close"),
2630	    ok = gen_tcp:close(Socket),
2631	    Master ! {self(),flush([closed])}
2632    after 0 ->
2633	    ok = gen_tcp:send(Socket, Msg),
2634	    Master ! {self(), send},
2635	    busy_send_srv_loop(Socket, Master, Msg)
2636    end.
2637
2638busy_send_client_loop(Socket, Master, Msg, N) ->
2639    %% Client
2640    %%
2641    Size = byte_size(Msg),
2642    case gen_tcp:recv(Socket, Size) of
2643	{ok, Msg} ->
2644	    busy_send_client_loop(Socket, Master, Msg, N-1);
2645	Other ->
2646            ?P("[client] recv response: "
2647               "~n      ~p", [Other]),
2648	    Master ! {self(), flush([Other,N])}
2649    end.
2650
2651%%%
2652%%% Send to a socket whose other end does not read until the port gets busy.
2653%%% Then close the other end. The writer should get an {error,closed} error.
2654%%% (Passive mode.)
2655%%%
2656
2657busy_disconnect_passive(Config) when is_list(Config) ->
2658    ?TC_TRY(busy_disconnect_passive,
2659            fun() -> do_busy_disconnect_passive(Config) end).
2660
2661do_busy_disconnect_passive(Config) ->
2662    ?P("[passive] begin"),
2663    MuchoData = list_to_binary(ones(64*1024)),
2664    [do_busy_disconnect_passive2(Config, MuchoData, N) || N <- lists:seq(1, 10)],
2665    ?P("[passive] done"),
2666    ok.
2667
2668do_busy_disconnect_passive2(Config, MuchoData, N) ->
2669    ?P("[passive,~w] *** prepare server *** ", [N]),
2670    {_Server, S} = busy_disconnect_prepare_server(Config, [{active,false}]),
2671    ?P("[passive,~w] server prepared - start sending", [N]),
2672    {_OSFam, OSName} = os:type(),
2673    busy_disconnect_passive_send(S, MuchoData, OSName).
2674
2675busy_disconnect_passive_send(S, Data, OS) ->
2676    case gen_tcp:send(S, Data) of
2677	ok ->
2678            busy_disconnect_passive_send(S, Data, OS);
2679	{error, closed} ->
2680            ok;
2681	{error, eprototype = Reason} when (OS =:= darwin) ->
2682	    ?P("send failed with ~w", [Reason]),
2683            ok
2684    end.
2685
2686%%%
2687%%% Send to a socket whose other end does not read until the port gets busy.
2688%%% Then close the other end. The writer should get an {error,closed} error and
2689%%% a {tcp_closed,Socket} message. (Active mode.)
2690%%%
2691busy_disconnect_active(Config) when is_list(Config) ->
2692    ?TC_TRY(busy_disconnect_active,
2693            fun() -> do_busy_disconnect_active(Config) end).
2694
2695do_busy_disconnect_active(Config) ->
2696    ?P("[active] begin"),
2697    MuchoData = list_to_binary(ones(64*1024)),
2698    [do_busy_disconnect_active2(Config, MuchoData, N) || N <- lists:seq(1, 10)],
2699    ?P("[active] done"),
2700    ok.
2701
2702do_busy_disconnect_active2(Config, MuchoData, N) ->
2703    ?P("[active,~w] *** prepare server *** ", [N]),
2704    {Server, S} = busy_disconnect_prepare_server(Config, [{active,true}]),
2705    ?P("[active,~w] server prepared - start sending", [N]),
2706    busy_disconnect_active_send(Server, S, MuchoData).
2707
2708busy_disconnect_active_send(Server, S, Data) ->
2709    {_OSFam, OSName} = os:type(),
2710    busy_disconnect_active_send(Server, S, Data, 1, OSName).
2711
2712busy_disconnect_active_send(Server, S, Data, Iter, OS) ->
2713    case gen_tcp:send(S, Data) of
2714	ok ->
2715            busy_disconnect_active_send(Server, S, Data, Iter+1, OS);
2716	{error, closed} ->
2717            ?P("[active-sender,~w] send failed with closed - await tcp-closed",
2718	       [Iter]),
2719            busy_disconnect_active_send_await_closed(Server, S);
2720
2721	{error, eprototype = Reason} when (OS =:= darwin) ->
2722            ?P("[active-sender,~w] send failed with ~w - await tcp-closed",
2723	       [Iter, Reason]),
2724            busy_disconnect_active_send_await_closed(Server, S);
2725
2726        {error, einval = Reason} ->
2727            ?P("[active-sender,~w] UNEXPECTED send failure:"
2728               "~n   ~p", [Iter, Reason]),
2729            ?SKIPT(send_failed_str(Reason));
2730
2731        {error, Reason} ->
2732            ?P("[active-sender,~w] UNEXPECTED send failure:"
2733               "~n   ~p", [Iter, Reason]),
2734            ct:fail({unexpected_send_result, Reason, Iter})
2735    end.
2736
2737busy_disconnect_active_send_await_closed(Server, S) ->
2738    busy_disconnect_active_send_await_closed(Server, S, false, false).
2739busy_disconnect_active_send_await_closed(Server, S, Closed, Stopped) ->
2740    receive
2741        {tcp_closed, S} when (Stopped =:= true) ->
2742            ?P("[active-sender] received tcp-closed - done"),
2743            ok;
2744
2745        {tcp_closed, S} ->
2746            ?P("[active-sender] received tcp-closed"),
2747            busy_disconnect_active_send_await_closed(Server, S, true, Stopped);
2748
2749        {'EXIT', Server, normal} when (Closed =:= true) ->
2750            ?P("[active-sender] received server (normal) exit - done"),
2751            ok;
2752
2753        {'EXIT', Server, normal} ->
2754            ?P("[active-sender] received server (normal) exit"),
2755            busy_disconnect_active_send_await_closed(Server, S, Closed, true);
2756
2757        Other ->
2758            ?P("[active-sender] received UNEXPECTED message:"
2759               "~n   Expected tcp-close of ~p"
2760               "~n   Server:               ~p"
2761               "~n   Unexpected message:   ~p", [S, Server, Other]),
2762            ct:fail({unexpected, Other, S, flush([])})
2763    end.
2764
2765
2766busy_disconnect_prepare_server(Config, ConnectOpts) ->
2767    Sender = self(),
2768    ?P("[prep-server] create server"),
2769    Server = spawn_link(fun() -> busy_disconnect_server(Config, Sender) end),
2770    ?P("[prep-server] await port (from server)"),
2771    receive {port, Server, Port} -> ok end,
2772    ?P("[prep-server] connect to ~w", [Port]),
2773    case ?CONNECT(Config, localhost, Port, ConnectOpts) of
2774        {ok, S} ->
2775            ?P("[prep-server] connected - order server start sending"),
2776            Server ! {Sender, sending},
2777            ?P("[prep-server] done"),
2778            {Server, S};
2779        {error, eaddrnotavail = Reason} ->
2780            ?SKIPT(connect_failed_str(Reason))
2781    end.
2782
2783busy_disconnect_server(Config, Sender) ->
2784    ?P("[server] create listen socket"),
2785    {ok, L} = ?LISTEN(Config, 0,
2786                             [{active,false},
2787                              binary,
2788                              {reuseaddr,true},
2789                              {packet,0}]),
2790    ?P("[server] created - get port number"),
2791    {ok,Port} = inet:port(L),
2792    ?P("[server] send port ~w (to sender)", [Port]),
2793    Sender ! {port,self(),Port},
2794    ?P("[server] try accept"),
2795    {ok,S} = gen_tcp:accept(L),
2796    ?P("[server] connection accepted"),
2797    receive
2798	{Sender, sending} ->
2799            ?P("[server] received sending (from sender)"),
2800	    busy_disconnect_server_wait_for_busy(Sender, S)
2801    end.
2802
2803%% Close the socket as soon as the Sender process can't send because of
2804%% a busy port.
2805busy_disconnect_server_wait_for_busy(Sender, S) ->
2806    case process_info(Sender, status) of
2807	{status, waiting = Status} ->
2808	    %% We KNOW that the sender will be in state 'waiting' only
2809	    %% if the port has become busy. (Fallback solution if the
2810	    %% implementation changes: Watch Sender's reduction count;
2811	    %% when it stops changing, wait 2 seconds and then close.)
2812	    ?P("[server] sender status ~p => close socket", [Status]),
2813	    gen_tcp:close(S);
2814	{status, Status} ->
2815	    ?P("[server] sender status ~p", [Status]),
2816	    timer:sleep(100),
2817	    busy_disconnect_server_wait_for_busy(Sender, S);
2818	Other ->
2819	    ?P("[server] sender status ~p", [Other]),
2820	    timer:sleep(100),
2821	    busy_disconnect_server_wait_for_busy(Sender, S)
2822    end.
2823
2824
2825%%%
2826%%% Fill send queue
2827%%%
2828fill_sendq(Config) when is_list(Config) ->
2829    ?TC_TRY(fill_sendq, fun() -> do_fill_sendq(Config) end).
2830
2831do_fill_sendq(Config) ->
2832    OldFlag = process_flag(trap_exit, true),
2833    Master  = self(),
2834    ServerF =
2835        fun () ->
2836                ?P("[server] try listen"),
2837                case ?LISTEN(Config, 0, [{active,false},binary,
2838                                        {reuseaddr,true},{packet,0}]) of
2839                    {ok, L} ->
2840                        ?P("[server] try port"),
2841                        case inet:port(L) of
2842                            {ok, Port} ->
2843                                Master ! {self(), listen_port, Port},
2844                                fill_sendq_srv(L, Master);
2845                            {error, PReason} ->
2846                                ?SKIPE(port_failed_str(PReason))
2847                        end;
2848                    {error, LReason} ->
2849                        ?SKIPE(listen_failed_str(LReason))
2850                end
2851        end,
2852    Server  = spawn_link(ServerF),
2853    ?P("[master] server: ~p", [Server]),
2854    ClientF =
2855        fun () ->
2856                ?P("[client] await server port"),
2857                ServerPort =
2858                    receive
2859                        {Master, server_port, SP} ->
2860                            ?P("[client] server port: ~w", [SP]),
2861                            SP
2862                    end,
2863                %% Just close on order
2864                ?P("[client] try connect"),
2865                case ?CONNECT(Config,
2866                       "localhost", ServerPort,
2867                       [{active,false},binary,{packet,0}]) of
2868                    {ok, S} ->
2869                        ?P("[client] connected"),
2870                        Master ! {self(), connected},
2871                        receive
2872                            {Master, close} ->
2873                                ?P("[client] received close"),
2874                                ok = gen_tcp:close(S)
2875                        end;
2876                    {error, eaddrnotavail = Reason} ->
2877                        ?SKIPE(connect_failed_str(Reason))
2878                end
2879        end,
2880    Client = spawn_link(ClientF),
2881    ?P("[master] client: ~p", [client]),
2882    ListenPort =
2883        receive
2884            {Server, listen_port, LP} ->
2885                ?P("[master] listen port: ~w", [LP]),
2886                LP
2887        end,
2888    Client ! {self(), server_port, ListenPort},
2889    ?P("[master] await client connected"),
2890    receive {Client, connected} -> ok end,
2891    ?P("[master] await reader"),
2892    Res = receive
2893              {Server, reader, Reader} ->
2894                  ?P("[master] reader: ~p", [Reader]),
2895                  fill_sendq_loop(Server, Client, Reader)
2896          end,
2897    process_flag(trap_exit, OldFlag),
2898    ?P("[master] done"),
2899    Res.
2900
2901fill_sendq_loop(Server, Client, Reader) ->
2902    %% Master
2903    %%
2904    receive
2905        {Server, send} ->
2906	    fill_sendq_loop(Server, Client, Reader)
2907    after 2000 ->
2908	    %% Send queue full, sender blocked -> close client.
2909	    ?P("[master] send timeout, closing client"),
2910	    Client ! {self(), close},
2911	    receive
2912                {Server, [{error,closed}] = SErrors} ->
2913                    ?P("[master] got expected server closed"),
2914                    receive
2915                        {Reader, [{error,closed}]} ->
2916                            ?P("[master] got expected reader closed"),
2917                            ok;
2918                        {Reader, RErrors} when is_list(RErrors) ->
2919                            ct:fail([{server, SErrors}, {reader, RErrors}])
2920                    after 3000 ->
2921                            ct:fail({timeout,{closed,reader}})
2922                    end;
2923
2924                {Server, SErrors} when is_list(SErrors) ->
2925                    ?P("UNEXPECTED SERVER ERROR(S): "
2926                       "~n   ~p"
2927                       "~n   ~p", [SErrors, flush([])]),
2928                    ct:fail([{server, SErrors}, {reader, []}]);
2929
2930                {Reader, [{error,closed}] = RErrors} ->
2931                    ?P("[master] got expected reader closed"),
2932                    receive
2933                        {Server, [{error,closed}]} ->
2934                            ?P("[master] got expected server closed"),
2935                            ok;
2936                        {Server, SErrors} when is_list(SErrors) ->
2937                            ct:fail([{server, SErrors}, {reader, RErrors}])
2938                    after 3000 ->
2939                            ct:fail({timeout,{closed,server}})
2940                    end;
2941
2942                {Reader, RErrors} when is_list(RErrors) ->
2943                    ?P("UNEXPECTED READER ERROR(S): "
2944                       "~n   ~p"
2945                       "~n   ~p", [RErrors, flush([])]),
2946                    ct:fail([{server, []}, {reader, RErrors}])
2947
2948            after 3000 ->
2949                    Msgs = flush([]),
2950                    ct:fail({timeout,{closed,[server,reader]}, Msgs})
2951            end
2952    end.
2953
2954fill_sendq_srv(L, Master) ->
2955    %% Server
2956    %%
2957    ?P("[server] await accept"),
2958    case gen_tcp:accept(L) of
2959	{ok, S} ->
2960            ?P("[server] accepted ~p", [S]),
2961	    Master ! {self(), reader,
2962		      spawn_link(fun () -> fill_sendq_read(S, Master) end)},
2963	    Msg = "the quick brown fox jumps over a lazy dog~n",
2964	    fill_sendq_write(S, Master, [Msg,Msg,Msg,Msg,Msg,Msg,Msg,Msg]);
2965	E ->
2966            Error = flush([E]),
2967	    ?P("[server] accept error: ~p", [E]),
2968	    Master ! {self(), Error}
2969    end.
2970
2971fill_sendq_write(S, Master, Msg) ->
2972    %% Server
2973    %%
2974    %% ?P("[server] sending..."),
2975    case gen_tcp:send(S, Msg) of
2976	ok ->
2977            Master ! {self(), send},
2978	    %% ?P("[server] ok."),
2979	    fill_sendq_write(S, Master, Msg);
2980	{error, _} = E ->
2981	    Error = flush([E]),
2982	    ?P("[server] send error: ~p", [Error]),
2983	    Master ! {self(), Error}
2984    end.
2985
2986fill_sendq_read(S, Master) ->
2987    %% Reader
2988    %%
2989    ?P("[reader] read infinity..."),
2990    case gen_tcp:recv(S, 0, infinity) of
2991	{ok, Data} ->
2992	    ?P("[reader] recv: ~p", [Data]),
2993	    fill_sendq_read(S, Master);
2994	E ->
2995	    Error = flush([E]),
2996	    ?P("[reader] recv error: ~p", [Error]),
2997	    Master ! {self(), Error}
2998    end.
2999
3000
3001%%% Try to receive more than available number of bytes from
3002%%% a closed socket.
3003%%%
3004partial_recv_and_close(Config) when is_list(Config) ->
3005    try do_partial_recv_and_close(Config)
3006    catch
3007        throw:{skip, _} = SKIP ->
3008            SKIP
3009    end.
3010
3011do_partial_recv_and_close(Config) ->
3012    Msg = "the quick brown fox jumps over a lazy dog 0123456789\n",
3013    Len = length(Msg),
3014    {ok,L} = ?LISTEN(Config, 0, [{active,false}]),
3015    {ok,P} = inet:port(L),
3016    Sock =
3017        case ?CONNECT(Config, "localhost", P, [{active,false}]) of
3018            {ok, S} ->
3019                S;
3020        {error, eaddrnotavail = Reason} ->
3021            ?SKIPT(connect_failed_str(Reason))
3022    end,
3023    {ok, A} = gen_tcp:accept(L),
3024    ok = gen_tcp:send(Sock, Msg),
3025    ok = gen_tcp:close(Sock),
3026    {error, closed} = gen_tcp:recv(A, Len+1),
3027    ok.
3028
3029%%% Try to receive more than available number of bytes from
3030%%% a closed socket, this time waiting in the recv before closing.
3031%%%
3032partial_recv_and_close_2(Config) when is_list(Config) ->
3033    OldFlag = process_flag(trap_exit, true),
3034    Res = try do_partial_recv_and_close_2(Config)
3035          catch
3036              exit:{skip, _} = SKIP ->
3037                  SKIP
3038          end,
3039    process_flag(trap_exit, OldFlag),
3040    Res.
3041
3042do_partial_recv_and_close_2(Config) ->
3043    Msg = "the quick brown fox jumps over a lazy dog 0123456789\n",
3044    Len = length(Msg),
3045    {ok,L} = ?LISTEN(Config, 0, [{active,false}]),
3046    {ok,P} = inet:port(L),
3047    Server = self(),
3048    Client =
3049	spawn_link(
3050	  fun () ->
3051		  receive after 2000 -> ok end,
3052		  case ?CONNECT(Config, "localhost", P, [{active,false}]) of
3053                      {ok, S} ->
3054                          ok = gen_tcp:send(S, Msg),
3055                          receive {Server,close} -> ok end,
3056                          receive after 2000 -> ok end,
3057                          ok = gen_tcp:close(S);
3058                      {error, eaddrnotavail = Reason} ->
3059                          ?SKIPE(connect_failed_str(Reason))
3060                  end
3061	  end),
3062    {ok, A} = gen_tcp:accept(L),
3063    Client ! {Server, close},
3064    {error, closed} = gen_tcp:recv(A, Len+1),
3065    ok.
3066
3067%%% Here we tests that gen_tcp:recv/2 will return {error,closed} following
3068%%% a send operation of a huge amount data when the other end closed the socket.
3069%%%
3070partial_recv_and_close_3(Config) when is_list(Config) ->
3071    OldFlag = process_flag(trap_exit, true),
3072    Res = try do_partial_recv_and_close_3(Config)
3073          catch
3074              throw:{skip, _} = SKIP ->
3075                  SKIP
3076          end,
3077    process_flag(trap_exit, OldFlag),
3078    Res.
3079
3080do_partial_recv_and_close_3(Config) ->
3081    [do_partial_recv_and_close_4(Config) || _ <- lists:seq(0, 20)],
3082    ok.
3083
3084do_partial_recv_and_close_4(Config) ->
3085    Parent = self(),
3086    spawn_link(fun() ->
3087		       {ok,L} = ?LISTEN(Config, 0, [{active,false}]),
3088		       {ok,{_,Port}} = inet:sockname(L),
3089		       Parent ! {port,Port},
3090		       {ok,S} = gen_tcp:accept(L),
3091		       gen_tcp:recv(S, 1),
3092		       gen_tcp:close(S)
3093	       end),
3094    receive
3095	{port,Port} -> ok
3096    end,
3097    Much = ones(8*64*1024),
3098    S = case ?CONNECT(Config, localhost, Port, [{active, false}]) of
3099            {ok, Sock} ->
3100                Sock;
3101        {error, eaddrnotavail = Reason} ->
3102            ?SKIPT(connect_failed_str(Reason))
3103    end,
3104
3105    %% Send a lot of data (most of it will be queued).
3106    %% The receiver will read one byte and close the connection.
3107    %% The write operation will fail.
3108    gen_tcp:send(S, Much),
3109
3110    %% We should always get {error,closed} here.
3111    {error, closed} = gen_tcp:recv(S, 0).
3112
3113
3114test_prio_put_get(Config) ->
3115    Tos = 3 bsl 5,
3116    ?P("test_prio_put_get -> create listen socket"),
3117    {ok,L1} = ?LISTEN(Config, 0, [{active,false}]),
3118    ?P("test_prio_put_get -> set opts prio (= 3)"),
3119    ok = inet:setopts(L1,[{priority,3}]),
3120    ?P("test_prio_put_get -> set opts tos (= ~p)", [Tos]),
3121    ok = inet:setopts(L1,[{tos,Tos}]),
3122    ?P("test_prio_put_get -> verify opts prio and tos"),
3123    {ok,[{priority,3},{tos,Tos}]} = inet:getopts(L1,[priority,tos]),
3124    ?P("test_prio_put_get -> set opts prio (= 3)"),
3125    ok = inet:setopts(L1,[{priority,3}]), % Dont destroy each other
3126    ?P("test_prio_put_get -> verify opts prio and tos"),
3127    {ok,[{priority,3},{tos,Tos}]} = inet:getopts(L1,[priority,tos]),
3128    ?P("test_prio_put_get -> set opts reuseaddr (= true)"),
3129    ok = inet:setopts(L1,[{reuseaddr,true}]), % Dont let others destroy
3130    ?P("test_prio_put_get -> verify opts prio and tos"),
3131    {ok,[{priority,3},{tos,Tos}]} = inet:getopts(L1,[priority,tos]),
3132    ?P("test_prio_put_get -> close listen socket"),
3133    gen_tcp:close(L1),
3134    ?P("test_prio_put_get -> done"),
3135    ok.
3136
3137test_prio_accept(Config) ->
3138    ?P("test_prio_accept -> create listen socket"),
3139    {ok, Sock} = ?LISTEN(Config, 0, [binary,{packet,0},{active,false},
3140                                     {reuseaddr,true},{priority,4}]),
3141    ?P("test_prio_accept -> get port number of listen socket"),
3142    {ok, Port} = inet:port(Sock),
3143    ?P("test_prio_accept -> connect to port ~p", [Port]),
3144    Sock2 = case ?CONNECT(Config, "localhost",Port,[binary,{packet,0},
3145                                                   {active,false},
3146                                                   {reuseaddr,true},
3147                                                   {priority,4}]) of
3148                {ok, S2} ->
3149                    S2;
3150                {error, eaddrnotavail = Reason} ->
3151                    ?SKIPT(connect_failed_str(Reason))
3152            end,
3153    ?P("test_prio_accept -> connected => accept connection"),
3154    {ok, Sock3} = gen_tcp:accept(Sock),
3155    ?P("test_prio_accept -> accepted => getopts prio for listen socket"),
3156    {ok, [{priority,4}]} = inet:getopts(Sock,  [priority]),
3157    ?P("test_prio_accept -> getopts prio for connected socket"),
3158    {ok, [{priority,4}]} = inet:getopts(Sock2, [priority]),
3159    ?P("test_prio_accept -> getopts prio for accepted socket"),
3160    {ok, [{priority,4}]} = inet:getopts(Sock3, [priority]),
3161    ?P("test_prio_accept -> close listen socket"),
3162    gen_tcp:close(Sock),
3163    ?P("test_prio_accept -> close connected socket"),
3164    gen_tcp:close(Sock2),
3165    ?P("test_prio_accept -> close accepted socket"),
3166    gen_tcp:close(Sock3),
3167    ?P("test_prio_accept -> done"),
3168    ok.
3169
3170test_prio_accept2(Config) ->
3171    Tos1 = 4 bsl 5,
3172    Tos2 = 3 bsl 5,
3173    ?P("test_prio_accept2 -> create listen socket"),
3174    {ok, Sock} = ?LISTEN(Config, 0,[binary,{packet,0},{active,false},
3175                                    {reuseaddr,true},{priority,4},
3176                                    {tos,Tos1}]),
3177    ?P("test_prio_accept2 -> get port number of listen socket"),
3178    {ok, Port} = inet:port(Sock),
3179    ?P("test_prio_accept2 -> connect to port ~p", [Port]),
3180    Sock2 = case ?CONNECT(Config, "localhost",Port,[binary,{packet,0},
3181                                                   {active,false},
3182                                                   {reuseaddr,true},
3183                                                   {priority,4},
3184                                                   {tos,Tos2}]) of
3185                {ok, S2} ->
3186                    S2;
3187                {error, eaddrnotavail = Reason} ->
3188                    ?SKIPT(connect_failed_str(Reason))
3189            end,
3190    ?P("test_prio_accept2 -> connected => accept connection"),
3191    {ok, Sock3} = gen_tcp:accept(Sock),
3192    ?P("test_prio_accept2 -> accepted => getopts prio and tos for listen socket"),
3193    {ok,[{priority,4},{tos,Tos1}]} = inet:getopts(Sock,[priority,tos]),
3194    ?P("test_prio_accept2 -> getopts prio and tos for connected socket"),
3195    {ok,[{priority,4},{tos,Tos2}]} = inet:getopts(Sock2,[priority,tos]),
3196    ?P("test_prio_accept2 -> getopts prio and tos for accepted socket"),
3197    {ok,[{priority,4},{tos,Tos1}]} = inet:getopts(Sock3,[priority,tos]),
3198    ?P("test_prio_accept2 -> close listen socket"),
3199    gen_tcp:close(Sock),
3200    ?P("test_prio_accept2 -> close connected socket"),
3201    gen_tcp:close(Sock2),
3202    ?P("test_prio_accept2 -> close accepted socket"),
3203    gen_tcp:close(Sock3),
3204    ?P("test_prio_accept2 -> done"),
3205    ok.
3206
3207test_prio_accept3(Config) ->
3208    Tos1 = 4 bsl 5,
3209    Tos2 = 3 bsl 5,
3210    ?P("test_prio_accept3 -> create listen socket"),
3211    {ok, Sock} = ?LISTEN(Config, 0,[binary,{packet,0},{active,false},
3212                                    {reuseaddr,true},
3213                                    {tos,Tos1}]),
3214    ?P("test_prio_accept3 -> get port number of listen socket"),
3215    {ok,Port} = inet:port(Sock),
3216    ?P("test_prio_accept3 -> connect to port ~p", [Port]),
3217    Sock2 = case ?CONNECT(Config, "localhost",Port,[binary,{packet,0},
3218                                                   {active,false},
3219                                                   {reuseaddr,true},
3220                                                   {tos,Tos2}]) of
3221                {ok, S2} ->
3222                    S2;
3223        {error, eaddrnotavail = Reason} ->
3224            ?SKIPT(connect_failed_str(Reason))
3225    end,
3226    ?P("test_prio_accept3 -> connected => accept connection"),
3227    {ok, Sock3} = gen_tcp:accept(Sock),
3228    ?P("test_prio_accept3 -> "
3229       "accepted => getopts prio and tos for listen socket"),
3230    {ok, [{priority,0},{tos,Tos1}]} = inet:getopts(Sock,  [priority,tos]),
3231    ?P("test_prio_accept3 -> getopts prio and tos for connected socket"),
3232    {ok, [{priority,0},{tos,Tos2}]} = inet:getopts(Sock2, [priority,tos]),
3233    ?P("test_prio_accept3 -> getopts prio and tos for accepted socket"),
3234    {ok, [{priority,0},{tos,Tos1}]} = inet:getopts(Sock3, [priority,tos]),
3235    ?P("test_prio_accept3 -> close listen socket"),
3236    gen_tcp:close(Sock),
3237    ?P("test_prio_accept3 -> close connected socket"),
3238    gen_tcp:close(Sock2),
3239    ?P("test_prio_accept3 -> close accepted socket"),
3240    gen_tcp:close(Sock3),
3241    ?P("test_prio_accept3 -> done"),
3242    ok.
3243
3244test_prio_accept_async(Config) ->
3245    Tos1 = 4 bsl 5,
3246    Tos2 = 3 bsl 5,
3247    Ref = make_ref(),
3248    ?P("test_prio_accept_async -> create prio server"),
3249    spawn(?MODULE, priority_server, [Config, {self(),Ref}]),
3250    Port = receive
3251               {Ref,P} -> P
3252           after 5000 -> ct:fail({error,"helper process timeout"})
3253           end,
3254    receive
3255    after 3000 -> ok
3256    end,
3257    ?P("test_prio_accept_async -> connect to port ~p", [Port]),
3258    Sock2 = case ?CONNECT(Config, "localhost",Port,[binary,{packet,0},
3259                                                   {active,false},
3260                                                   {reuseaddr,true},
3261                                                   {priority,4},
3262                                                   {tos,Tos2}]) of
3263                {ok, S2} ->
3264                    S2;
3265                {error, eaddrnotavail = Reason} ->
3266                    ?SKIPT(connect_failed_str(Reason))
3267            end,
3268    ?P("test_prio_accept_async -> "
3269       "connected => await prio and tos for listen socket"),
3270    receive
3271        {Ref,{ok,[{priority,4},{tos,Tos1}]}} ->
3272            ok;
3273        {Ref,Error} ->
3274            ct:fail({missmatch,Error})
3275    after 5000 -> ct:fail({error,"helper process timeout"})
3276    end,
3277    ?P("test_prio_accept_async -> await prio and tos for accepted socket"),
3278    receive
3279        {Ref,{ok,[{priority,4},{tos,Tos1}]}} ->
3280            ok;
3281        {Ref,Error2} ->
3282            ct:fail({missmatch,Error2})
3283    after 5000 -> ct:fail({error,"helper process timeout"})
3284    end,
3285
3286    ?P("test_prio_accept_async -> getopts prio and tos for connected socket"),
3287    {ok,[{priority,4},{tos,Tos2}]} = inet:getopts(Sock2, [priority,tos]),
3288    ?P("test_prio_accept_async -> close connected socket"),
3289    catch gen_tcp:close(Sock2),
3290    ?P("test_prio_accept_async -> done"),
3291    ok.
3292
3293priority_server(Config, {Parent,Ref}) ->
3294    Tos1 = 4 bsl 5,
3295    {ok,Sock}=?LISTEN(Config, 0,[binary,{packet,0},{active,false},
3296                                {reuseaddr,true},{priority,4},
3297                                {tos,Tos1}]),
3298    {ok,Port} = inet:port(Sock),
3299    Parent ! {Ref,Port},
3300    {ok,Sock3}=gen_tcp:accept(Sock),
3301    Parent ! {Ref, inet:getopts(Sock,[priority,tos])},
3302    Parent ! {Ref, inet:getopts(Sock3,[priority,tos])},
3303    ok.
3304
3305test_prio_fail(Config) ->
3306    ?P("test_prio_fail -> create listen socket"),
3307    {ok,L} = ?LISTEN(Config, 0, [{active,false}]),
3308    ?P("test_prio_fail -> try set (and fail) opts prio (= 1000)"),
3309    {error,_} = inet:setopts(L,[{priority,1000}]),
3310    ?P("test_prio_fail -> close listen socket"),
3311    gen_tcp:close(L),
3312    ?P("test_prio_fail -> done"),
3313    ok.
3314
3315test_prio_udp() ->
3316    Tos = 3 bsl 5,
3317    ?P("test_prio_udp -> create UDP socket (open)"),
3318    {ok,S} = gen_udp:open(0,[{active,false},binary,{tos, Tos},
3319                             {priority,3}]),
3320    ?P("test_prio_udp -> getopts prio and tos"),
3321    {ok,[{priority,3},{tos,Tos}]} = inet:getopts(S,[priority,tos]),
3322    ?P("test_prio_fail -> close socket"),
3323    gen_udp:close(S),
3324    ?P("test_prio_fail -> done"),
3325    ok.
3326
3327%% Tests the so_priority and ip_tos options on sockets when applicable.
3328so_priority(Config) when is_list(Config) ->
3329    ?TC_TRY(so_priority,
3330	    %% Normally we should have the condition funm here,
3331	    %% but since we are (currently) not platform independant,
3332	    %% we can't...check in the test case instead.
3333	    fun() -> do_so_priority(Config) end).
3334
3335do_so_priority(Config) ->
3336    ?P("create listen socket"),
3337    L = case ?LISTEN(Config, 0, [{active,false}]) of
3338	    {ok, LSock} when not is_port(LSock) ->
3339		try socket:is_supported(options, socket, priority) of
3340		    true ->
3341			LSock;
3342		    false ->
3343			(catch gen_tcp:close(LSock)),
3344			?SKIPT("Option 'priority' not supported")
3345                catch
3346                    _:_:_ ->
3347			(catch gen_tcp:close(LSock)),
3348			?SKIPT("Option 'priority' not supported")
3349		end;
3350	    {ok, LSock} when is_port(LSock) ->
3351		LSock
3352	end,
3353    ?P("set opts on listen socket: prio to 1"),
3354    ok = inet:setopts(L,[{priority,1}]),
3355    ?P("verify prio"),
3356    case inet:getopts(L,[priority]) of
3357	{ok,[{priority,1}]} ->
3358            ?P("close listen socket"),
3359	    gen_tcp:close(L),
3360	    test_prio_put_get(Config),
3361	    test_prio_accept(Config),
3362	    test_prio_accept2(Config),
3363	    test_prio_accept3(Config),
3364	    test_prio_accept_async(Config),
3365	    test_prio_fail(Config),
3366	    test_prio_udp(),
3367            ?P("done"),
3368	    ok;
3369	_X ->
3370	    case os:type() of
3371		{unix,linux} ->
3372		    case os:version() of
3373			{X,Y,_} when (X > 2) or ((X =:= 2) and (Y >= 4)) ->
3374                            ?P("so prio should work on this version: "
3375                               "~n      ~p", [_X]),
3376			    ct:fail({error,
3377					   "so_priority should work on this "
3378					   "OS, but does not"});
3379			_ ->
3380			    {skip, "SO_PRIORITY not suppoorted"}
3381		    end;
3382		_ ->
3383		   {skip, "SO_PRIORITY not suppoorted"}
3384	    end
3385    end.
3386
3387
3388
3389%% IP_RECVTOS and IP_RECVTCLASS for IP_PKTOPTIONS
3390%% does not seem to be implemented in Linux until kernel 3.1
3391%%
3392%% It seems pktoptions does not return valid values
3393%% for IPv4 connect sockets.  On the accept socket
3394%% we get valid values, but on the connect socket we get
3395%% the default values for TOS and TTL.
3396%%
3397%% Therefore the argument CheckConnect that enables
3398%% checking the returned values for the connect socket.
3399%% It is only used for recvtclass that is an IPv6 option
3400%% and there we get valid values from both socket ends.
3401
3402has_support_ip_pktoptions() ->
3403    has_support_ip_option(pktoptions).
3404
3405has_support_ip_recvtos() ->
3406    has_support_ip_option(recvtos).
3407
3408has_support_ip_recvttl() ->
3409    has_support_ip_option(recvttl).
3410
3411has_support_ipv6_pktoptions() ->
3412    has_support_ipv6_option(pktoptions).
3413
3414has_support_ipv6_tclass() ->
3415    has_support_ipv6_option(tclass).
3416
3417has_support_ip_option(Opt) ->
3418    has_support_option(ip, Opt).
3419
3420has_support_ipv6_option(Opt) ->
3421    has_support_option(ipv6, Opt).
3422
3423has_support_option(Level, Option) ->
3424    try socket:is_supported(options, Level, Option)
3425    catch
3426	_:_:_ -> false % Any platform that does not support socket!
3427    end.
3428
3429has_os_support_recvtos() ->
3430    has_os_support_recvtos(os:type(), os:version()).
3431
3432has_os_support_recvtos({unix, linux}, Version) ->
3433    not semver_lt(Version, {3,1,0});
3434has_os_support_recvtos(_, _) ->
3435    true.
3436
3437has_os_support_recvttl() ->
3438    has_os_support_recvttl(os:type(), os:version()).
3439
3440has_os_support_recvttl({unix, linux}, Version) ->
3441    not semver_lt(Version, {2,7,0});
3442has_os_support_recvttl(_, _) ->
3443    %% We should not even get here, but just in case...
3444    false.
3445
3446has_os_support_recvtclass() ->
3447    has_os_support_recvtclass(os:type(), os:version()).
3448
3449has_os_support_recvtclass({unix, linux}, Version) ->
3450    not semver_lt(Version, {3,1,0});
3451has_os_support_recvtclass(_, _) ->
3452    true.
3453
3454semver_lt({X1,Y1,Z1} = V1, {X2,Y2,Z2} = V2) ->
3455    ?P("semver_lt -> OS version check:"
3456       "~n   (Actual)  Version 1: ~p"
3457       "~n   (Request) Version 2: ~p", [V1, V2]),
3458    if
3459        X1 > X2 -> ?P("semver_lt -> X1 > X2: ~p > ~p", [X1, X2]), false;
3460        X1 < X2 -> ?P("semver_lt -> X1 < X2: ~p < ~p", [X1, X2]), true;
3461        Y1 > Y2 -> ?P("semver_lt -> Y1 > Y2: ~p > ~p", [Y1, Y2]), false;
3462        Y1 < Y2 -> ?P("semver_lt -> Y1 < Y2: ~p < ~p", [Y1, Y2]), true;
3463        Z1 > Z2 -> ?P("semver_lt -> Z1 > Z2: ~p > ~p", [Z1, Z2]), false;
3464        Z1 < Z2 -> ?P("semver_lt -> Z1 < Z2: ~p < ~p", [Z1, Z2]), true;
3465        true    -> ?P("semver_lt -> default"), false
3466    end;
3467semver_lt(V1, {_,_,_} = V2) ->
3468    ?P("semver_lt -> fallback OS version check when: "
3469       "~n   Version 1: ~p"
3470       "~n   Version 2: ~p", [V1, V2]),
3471    false.
3472
3473recvtos(Config) ->
3474    test_pktoptions(
3475      Config,
3476      inet, [{recvtos,tos,96}],
3477      fun() ->
3478              has_support_ip_recvtos() andalso
3479                  has_os_support_recvtos()
3480     end,
3481      "recvtos",
3482      false).
3483
3484recvtosttl(Config) ->
3485    test_pktoptions(
3486      Config,
3487      inet, [{recvtos,tos,96},{recvttl,ttl,33}],
3488      fun() ->
3489              has_support_ip_recvtos() andalso
3490		  has_support_ip_recvttl() andalso
3491                  has_os_support_recvtos() andalso
3492                  has_os_support_recvttl()
3493      end,
3494      "recvtos and/or recvttl",
3495      false).
3496
3497recvttl(Config) ->
3498    test_pktoptions(
3499      Config,
3500      inet, [{recvttl,ttl,33}],
3501      fun() ->
3502              has_support_ip_recvttl() andalso
3503                  has_os_support_recvttl()
3504      end,
3505      "recvttl",
3506      false).
3507
3508recvtclass(Config) ->
3509    {ok,IFs} = inet:getifaddrs(),
3510    case
3511        [Name ||
3512            {Name,Opts} <- IFs,
3513            lists:member({addr,{0,0,0,0,0,0,0,1}}, Opts)]
3514    of
3515        [_] ->
3516            test_pktoptions(
3517              Config,
3518              inet6, [{recvtclass,tclass,224}],
3519              fun() ->
3520                      has_support_ipv6_tclass() andalso
3521                          has_os_support_recvtclass()
3522              end,
3523              "tclass",
3524              true);
3525        [] ->
3526            {skip,{ipv6_not_supported,IFs}}
3527    end.
3528
3529test_pktoptions(Config, Family, Spec, OptCond, OptStr, CheckConnect) ->
3530    ?P("test_pktoptions -> begin test with"
3531       "~n   Config:       ~p"
3532       "~n   Family:       ~p"
3533       "~n   Spec:         ~p"
3534       "~n   CheckConnect: ~p",
3535       [Config, Family, Spec, CheckConnect]),
3536    PktOptsCond = fun(inet)  -> has_support_ip_pktoptions();
3537		     (inet6) -> has_support_ipv6_pktoptions()
3538		  end,
3539    try PktOptsCond(Family) of
3540	true ->
3541	    ?P("pktoptions supported for family ~w", [Family]),
3542	    case OptCond() of
3543		true ->
3544		    ?P("options supported: "
3545		       "~n   ~p", [Spec]),
3546		    test_pktoptions(Config, Family, Spec, CheckConnect);
3547		false ->
3548		    {skip, ?F("Option(s) ~s not supported", [OptStr])}
3549	    end;
3550        false ->
3551            {skip,
3552             ?F("Option 'pktoptions' not supported for family ~w", [Family])}
3553    catch
3554        _:_:_ ->
3555            {skip,
3556             ?F("Option 'pktoptions' not supported for family ~w", [Family])}
3557    end.
3558%%
3559test_pktoptions(Config, Family, Spec, CheckConnect) ->
3560    ?P("test_pktoptions -> begin test with"
3561       "~n   Config:       ~p"
3562       "~n   Family:       ~p"
3563       "~n   Spec:         ~p"
3564       "~n   CheckConnect: ~p",
3565       [Config, Family, Spec, CheckConnect]),
3566    Timeout = 5000,
3567    RecvOpts = [RecvOpt || {RecvOpt,_,_} <- Spec],
3568    TrueRecvOpts = [{RecvOpt,true} || {RecvOpt,_,_} <- Spec],
3569    FalseRecvOpts = [{RecvOpt,false} || {RecvOpt,_,_} <- Spec],
3570    Opts = [Opt || {_,Opt,_} <- Spec],
3571    OptsVals = [{Opt,Val} || {_,Opt,Val} <- Spec],
3572    Address =
3573        case Family of
3574            inet ->
3575                {127,0,0,1};
3576            inet6 ->
3577                {0,0,0,0,0,0,0,1}
3578        end,
3579    %%
3580    %% Set RecvOpts on listen socket
3581    ?P("try create listen socket with: ~p", [TrueRecvOpts]),
3582    {ok, L} =
3583        ?LISTEN(Config,
3584                0,
3585                [Family,binary,{active,false},{send_timeout,Timeout}
3586                 |TrueRecvOpts]),
3587    {ok, P} = inet:port(L),
3588    ?P("get (recv) options for listen socket: "
3589       "~n   ~p", [RecvOpts]),
3590    {ok, TrueRecvOpts} = inet:getopts(L, RecvOpts),
3591    ?P("get options for listen socket: "
3592       "~n   ~p", [Opts]),
3593    {ok, OptsValsDefault} = inet:getopts(L, Opts),
3594
3595    %%
3596    %% Set RecvOpts and Option values on connect socket
3597    ?P("create connect socket with"
3598       "~n   ~p", [TrueRecvOpts ++ OptsVals]),
3599    {ok, S2} =
3600        ?CONNECT(Config,
3601                 Address, P,
3602                 [Family,binary,{active,false},{send_timeout,Timeout}
3603                  |TrueRecvOpts ++ OptsVals],
3604                 Timeout),
3605    ?P("get (recv) options for connect socket: "
3606       "~n   ~p", [RecvOpts]),
3607    {ok, TrueRecvOpts} = inet:getopts(S2, RecvOpts),
3608    ?P("get options for connect socket: "
3609       "~n   ~p", [Opts]),
3610    {ok, OptsVals} = inet:getopts(S2, Opts),
3611
3612    %%
3613    %% Accept socket inherits the options from listen socket
3614    ?P("try create accept socket"),
3615    {ok, S1} = gen_tcp:accept(L, Timeout),
3616    ?P("get (recv) options for accept socket: "
3617       "~n   ~p", [RecvOpts]),
3618    {ok, TrueRecvOpts} = inet:getopts(S1, RecvOpts),
3619
3620    ?P("get options for accept socket: "
3621       "~n   ~p", [Opts]),
3622    {ok, OptsValsDefault} = inet:getopts(S1, Opts),
3623    ?P("accept socket option values: "
3624       "~n   ~p", [OptsValsDefault]),
3625
3626%%%    %%
3627%%%    %% Handshake
3628%%%    ok = gen_tcp:send(S1, <<"hello">>),
3629%%%    {ok,<<"hello">>} = gen_tcp:recv(S2, 5, Timeout),
3630%%%    ok = gen_tcp:send(S2, <<"hi">>),
3631%%%    {ok,<<"hi">>} = gen_tcp:recv(S1, 2, Timeout),
3632
3633    %%
3634    %% Verify returned remote options
3635    VerifyRemOpts =
3636        fun(S, Role) ->
3637                case inet:getopts(S, [pktoptions]) of
3638                    {ok, []} ->
3639                        ?SKIPT("pktoptions not supported");
3640                    {ok, [{pktoptions, PktOpts1}]} ->
3641                        ?P("PktOptions (~w): "
3642                           "~n      ~p", [Role, PktOpts1]),
3643                        PktOpts1;
3644                    {ok, UnexpOK1} ->
3645                        ?P("Unexpected OK (~w): "
3646                           "~n   ~p"
3647                           "~n", [Role, UnexpOK1]),
3648                        exit({unexpected_getopts_ok,
3649                              Role,
3650                              Spec,
3651                              TrueRecvOpts,
3652                              OptsVals,
3653                              OptsValsDefault,
3654                              UnexpOK1});
3655                    {error, UnexpERR1} ->
3656                        ?P("Unexpected ERROR (~w): "
3657                           "~n   ~p"
3658                           "~n", [Role, UnexpERR1]),
3659                        exit({unexpected_getopts_failure,
3660                              Role,
3661                              Spec,
3662                              TrueRecvOpts,
3663                              OptsVals,
3664                              OptsValsDefault,
3665                              UnexpERR1})
3666                end
3667        end,
3668    ?P("verify dest (accept)"),
3669    OptsVals1 = VerifyRemOpts(S1, dest),
3670    ?P("verify orig (connect)"),
3671    OptsVals2 = VerifyRemOpts(S2, orig),
3672    %% {ok,[{pktoptions,OptsVals1}]} = inet:getopts(S1, [pktoptions]),
3673    %% {ok,[{pktoptions,OptsVals2}]} = inet:getopts(S2, [pktoptions]),
3674    (Result1 = sets_eq(OptsVals1, OptsVals))
3675        orelse ?P("Accept differs: ~p neq ~p", [OptsVals1,OptsVals]),
3676    (Result2 = sets_eq(OptsVals2, OptsValsDefault))
3677        orelse ?P("Connect differs: ~p neq ~p",
3678                  [OptsVals2, OptsValsDefault]),
3679    %%
3680    ?P("close connect socket"),
3681    ok = gen_tcp:close(S2),
3682    ?P("close accept socket"),
3683    ok = gen_tcp:close(S1),
3684    %%
3685    %%
3686    %% Clear RecvOpts on listen socket and set Option values
3687    ?P("clear (recv) options on listen socket"),
3688    ok = inet:setopts(L, FalseRecvOpts ++ OptsVals),
3689    {ok,FalseRecvOpts} = inet:getopts(L, RecvOpts),
3690    ?P("set  options on listen socket"),
3691    {ok,OptsVals} = inet:getopts(L, Opts),
3692
3693    %%
3694    %% Set RecvOpts on connecting socket
3695    %%
3696    ?P("create connect socket with"
3697       "~n   ~p", [TrueRecvOpts]),
3698    {ok,S4} =
3699        ?CONNECT(Config,
3700          Address, P,
3701          [Family,binary,{active,false},{send_timeout,Timeout}
3702          |TrueRecvOpts],
3703          Timeout),
3704    ?P("get (recv) options on connect socket"),
3705    {ok,TrueRecvOpts} = inet:getopts(S4, RecvOpts),
3706    ?P("get options on connect socket"),
3707    {ok,OptsValsDefault} = inet:getopts(S4, Opts),
3708
3709    %%
3710    %% Accept socket inherits the options from listen socket
3711    ?P("create accept socket"),
3712    {ok,S3} = gen_tcp:accept(L, Timeout),
3713    ?P("get (recv) options on accept socket"),
3714    {ok,FalseRecvOpts} = inet:getopts(S3, RecvOpts),
3715    {ok,OptsVals} = inet:getopts(S3, Opts),
3716    %%
3717    %% Verify returned remote options
3718    ?P("verify pktoptions on accept socket"),
3719    {ok,[{pktoptions,[]}]} = inet:getopts(S3, [pktoptions]),
3720    ?P("verify pktoptions on connect socket"),
3721    {ok,[{pktoptions,OptsVals4}]} = inet:getopts(S4, [pktoptions]),
3722    ?P("verify options set"),
3723    (Result3 = sets_eq(OptsVals4, OptsVals))
3724        orelse ?P("Accept2 differs: ~p neq ~p", [OptsVals4, OptsVals]),
3725    %%
3726    ?P("close connect socket"),
3727    ok = gen_tcp:close(S4),
3728    ?P("close accept socket"),
3729    ok = gen_tcp:close(S3),
3730    ?P("close listen socket"),
3731    ok = gen_tcp:close(L),
3732    ?P("verify final result"
3733       "~n   Result1:       ~p"
3734       "~n   Check Connect: ~p"
3735       "~n   Result2:       ~p"
3736       "~n   Result3:       ~p",
3737      [Result1, CheckConnect, Result2, Result3]),
3738    (Result1 and ((not CheckConnect) or (Result2 and Result3)))
3739        orelse
3740        exit({failed,
3741              [{OptsVals1,OptsVals4,OptsVals},
3742               {OptsVals2,OptsValsDefault}]}),
3743    ?P("done"),
3744    ok.
3745
3746sets_eq(L1, L2) ->
3747    lists:sort(L1) == lists:sort(L2).
3748
3749
3750
3751%% Accept test utilities (suites are below)
3752
3753millis() ->
3754    erlang:monotonic_time(millisecond).
3755
3756collect_accepts(0,_) -> [];
3757collect_accepts(N,Tmo) ->
3758    A = millis(),
3759    receive
3760	{accepted, P, {error, eaddrnotavail = Reason}} ->
3761            ?P("~p Failed accept: ~p", [P, Reason]),
3762            ?SKIPT(accept_failed_str(Reason));
3763
3764        {accepted,P,Msg} ->
3765            ?P("received accepted from ~p: "
3766               "~n      ~p", [P, Msg]),
3767            NextN = if N =:= infinity -> N; true -> N - 1 end,
3768	    [{P,Msg}] ++ collect_accepts(NextN, Tmo - (millis()-A))
3769
3770    after Tmo ->
3771            ?P("accept timeout (~w)", [Tmo]),
3772	    []
3773    end.
3774
3775-define(EXPECT_ACCEPTS(Pattern,N,Timeout),
3776	(fun() ->
3777                 case collect_accepts((N), (Timeout)) of
3778		     Pattern ->
3779			 ok;
3780		     Other__ ->
3781			 {error,{unexpected,{Other__,process_info(self(),messages)}}}
3782		 end
3783	 end)()).
3784
3785collect_connects(Tmo) ->
3786    A = millis(),
3787    receive
3788	{connected, P, {error, eaddrnotavail = Reason}} ->
3789            ?P("~p Failed connect: ~p", [P, Reason]),
3790            ?SKIPT(connect_failed_str(Reason));
3791
3792	{connected,P,Msg} ->
3793            ?P("received connected from ~p: "
3794               "~n      ~p", [P, Msg]),
3795	    [{P,Msg}] ++ collect_connects(Tmo-(millis() - A))
3796
3797    after Tmo ->
3798	    []
3799    end.
3800
3801-define(EXPECT_CONNECTS(Pattern,Timeout),
3802	(fun() ->
3803		 case collect_connects(Timeout) of
3804		     Pattern ->
3805			 ok;
3806		     Other ->
3807			 {error,{unexpected,Other}}
3808		 end
3809	 end)()).
3810
3811mktmofun(Tmo,Parent,LS) ->
3812    fun() -> Parent ! {accepted,self(), catch gen_tcp:accept(LS,Tmo)} end.
3813
3814%% Accept tests
3815%% Test singular accept.
3816primitive_accept(Config) when is_list(Config) ->
3817    try do_primitive_accept(Config)
3818    catch
3819        throw:{skip, _} = SKIP ->
3820            SKIP
3821    end.
3822
3823do_primitive_accept(Config) ->
3824    LSock =
3825        case ?LISTEN(Config, 0,[]) of
3826            {ok, LS} ->
3827                LS;
3828            {error, LReason} ->
3829                ?SKIPT(listen_failed_str(LReason))
3830        end,
3831    {ok, PortNo} = inet:port(LSock),
3832    Parent = self(),
3833    F = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LSock)} end,
3834    P = spawn(F),
3835    case ?CONNECT(Config, "localhost", PortNo, []) of
3836        {ok, _} ->
3837            ok;
3838        {error, eaddrnotavail = CReason} ->
3839            ?SKIPT(connect_failed_str(CReason))
3840    end,
3841    receive
3842        {accepted,P,{ok,P0}} when is_port(P0) ->
3843            ok;
3844        {accepted,P,Other0} ->
3845            {error,Other0}
3846    after 500 ->
3847              {error,timeout}
3848    end.
3849
3850
3851%% Closing listen socket when multi-accepting.
3852multi_accept_close_listen(Config) when is_list(Config) ->
3853    ?TC_TRY(multi_accept_close_listen,
3854            fun() -> do_multi_accept_close_listen(Config) end).
3855
3856do_multi_accept_close_listen(Config) ->
3857    ?P("try create listen socket"),
3858    LS = case ?LISTEN(Config, 0,[]) of
3859             {ok, LSocket} ->
3860                 LSocket;
3861             {error, eaddrnotavail = Reason} ->
3862                 ?SKIPT(listen_failed_str(Reason))
3863         end,
3864    Parent = self(),
3865    F = fun() ->
3866                ?P("started"),
3867                Accepted = gen_tcp:accept(LS),
3868                ?P("accept result: ~p", [Accepted]),
3869                Parent ! {accepted,self(),Accepted}
3870        end,
3871    ?P("create acceptor processes"),
3872    spawn(F),
3873    spawn(F),
3874    spawn(F),
3875    spawn(F),
3876    ?P("sleep some"),
3877    ct:sleep(?SECS(2)),
3878    ?P("close (listen) socket"),
3879    gen_tcp:close(LS),
3880    ?P("await accepts"),
3881    ok = ?EXPECT_ACCEPTS([{_,{error,closed}},{_,{error,closed}},
3882                          {_,{error,closed}},{_,{error,closed}}],4,500),
3883    ?P("done"),
3884    ok.
3885
3886%% Single accept with timeout.
3887accept_timeout(Config) when is_list(Config) ->
3888    try do_accept_timeout(Config)
3889    catch
3890        throw:{skip, _} = SKIP ->
3891            SKIP
3892    end.
3893
3894do_accept_timeout(Config) ->
3895    LS = case ?LISTEN(Config, 0,[]) of
3896             {ok, LSocket} ->
3897                 LSocket;
3898             {error, eaddrnotavail = Reason} ->
3899                 ?SKIPT(listen_failed_str(Reason))
3900         end,
3901    Parent = self(),
3902    F = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LS,1000)} end,
3903    P = spawn(F),
3904    ok = ?EXPECT_ACCEPTS([{P,{error,timeout}}],1,2000).
3905
3906%% Check that multi-accept timeouts happen in the correct order.
3907accept_timeouts_in_order(Config) when is_list(Config) ->
3908    try do_accept_timeouts_in_order(Config)
3909    catch
3910        throw:{skip, _} = SKIP ->
3911            SKIP
3912    end.
3913
3914do_accept_timeouts_in_order(Config) ->
3915    LS = case ?LISTEN(Config, 0,[]) of
3916             {ok, LSocket} ->
3917                 LSocket;
3918             {error, eaddrnotavail = Reason} ->
3919                 ?SKIPT(listen_failed_str(Reason))
3920         end,
3921    Parent = self(),
3922    P1 = spawn(mktmofun(1000,Parent,LS)),
3923    P2 = spawn(mktmofun(1200,Parent,LS)),
3924    P3 = spawn(mktmofun(1300,Parent,LS)),
3925    P4 = spawn(mktmofun(1400,Parent,LS)),
3926    ok = ?EXPECT_ACCEPTS([{P1,{error,timeout}},{P2,{error,timeout}},
3927                          {P3,{error,timeout}},{P4,{error,timeout}}],infinity,2000).
3928
3929%% Check that multi-accept timeouts happen in the correct order (more).
3930accept_timeouts_in_order2(Config) when is_list(Config) ->
3931    try do_accept_timeouts_in_order2(Config)
3932    catch
3933        throw:{skip, _} = SKIP ->
3934            SKIP
3935    end.
3936
3937do_accept_timeouts_in_order2(Config) ->
3938    LS = case ?LISTEN(Config, 0,[]) of
3939             {ok, LSocket} ->
3940                 LSocket;
3941             {error, eaddrnotavail = Reason} ->
3942                 ?SKIPT(listen_failed_str(Reason))
3943         end,
3944    Parent = self(),
3945    P1 = spawn(mktmofun(1400,Parent,LS)),
3946    P2 = spawn(mktmofun(1300,Parent,LS)),
3947    P3 = spawn(mktmofun(1200,Parent,LS)),
3948    P4 = spawn(mktmofun(1000,Parent,LS)),
3949    ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P3,{error,timeout}},
3950                          {P2,{error,timeout}},{P1,{error,timeout}}],infinity,2000).
3951
3952%% Check that multi-accept timeouts happen in the correct order (even more).
3953accept_timeouts_in_order3(Config) when is_list(Config) ->
3954    try do_accept_timeouts_in_order3(Config)
3955    catch
3956        throw:{skip, _} = SKIP ->
3957            SKIP
3958    end.
3959
3960do_accept_timeouts_in_order3(Config) ->
3961    LS = case ?LISTEN(Config, 0,[]) of
3962             {ok, LSocket} ->
3963                 LSocket;
3964             {error, eaddrnotavail = Reason} ->
3965                 ?SKIPT(listen_failed_str(Reason))
3966         end,
3967    Parent = self(),
3968    P1 = spawn(mktmofun(1200,Parent,LS)),
3969    P2 = spawn(mktmofun(1400,Parent,LS)),
3970    P3 = spawn(mktmofun(1300,Parent,LS)),
3971    P4 = spawn(mktmofun(1000,Parent,LS)),
3972    ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P1,{error,timeout}},
3973                          {P3,{error,timeout}},{P2,{error,timeout}}],infinity,2000).
3974
3975%% Check that multi-accept timeouts happen in the correct order after
3976%% mixing millsec and sec timeouts.
3977accept_timeouts_in_order4(Config) when is_list(Config) ->
3978    try do_accept_timeouts_in_order4(Config)
3979    catch
3980        throw:{skip, _} = SKIP ->
3981            SKIP
3982    end.
3983
3984do_accept_timeouts_in_order4(Config) ->
3985    LS = case ?LISTEN(Config, 0,[]) of
3986             {ok, LSocket} ->
3987                 LSocket;
3988             {error, eaddrnotavail = Reason} ->
3989                 ?SKIPT(listen_failed_str(Reason))
3990         end,
3991    Parent = self(),
3992    P1 = spawn(mktmofun(200,Parent,LS)),
3993    P2 = spawn(mktmofun(400,Parent,LS)),
3994    P3 = spawn(mktmofun(1000,Parent,LS)),
3995    P4 = spawn(mktmofun(600,Parent,LS)),
3996    ok = ?EXPECT_ACCEPTS([{P1,{error,timeout}},{P2,{error,timeout}},
3997			  {P4,{error,timeout}},{P3,{error,timeout}}],infinity,2000).
3998
3999%% Check that multi-accept timeouts happen in the correct order after
4000%% mixing millsec and sec timeouts (more).
4001accept_timeouts_in_order5(Config) when is_list(Config) ->
4002    try do_accept_timeouts_in_order5(Config)
4003    catch
4004        throw:{skip, _} = SKIP ->
4005            SKIP
4006    end.
4007
4008do_accept_timeouts_in_order5(Config) ->
4009    LS = case ?LISTEN(Config, 0,[]) of
4010             {ok, LSocket} ->
4011                 LSocket;
4012             {error, eaddrnotavail = Reason} ->
4013                 ?SKIPT(listen_failed_str(Reason))
4014         end,
4015    Parent = self(),
4016    P1 = spawn(mktmofun(400,Parent,LS)),
4017    P2 = spawn(mktmofun(1000,Parent,LS)),
4018    P3 = spawn(mktmofun(600,Parent,LS)),
4019    P4 = spawn(mktmofun(200,Parent,LS)),
4020    ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P1,{error,timeout}},
4021			  {P3,{error,timeout}},{P2,{error,timeout}}],infinity,2000).
4022
4023%% Check that multi-accept timeouts happen in the correct order after
4024%% mixing millsec and sec timeouts (even more).
4025accept_timeouts_in_order6(Config) when is_list(Config) ->
4026    try do_accept_timeouts_in_order6(Config)
4027    catch
4028        throw:{skip, _} = SKIP ->
4029            SKIP
4030    end.
4031
4032do_accept_timeouts_in_order6(Config) ->
4033    LS = case ?LISTEN(Config, 0,[]) of
4034             {ok, LSocket} ->
4035                 LSocket;
4036             {error, eaddrnotavail = Reason} ->
4037                 ?SKIPT(listen_failed_str(Reason))
4038         end,
4039    Parent = self(),
4040    P1 = spawn(mktmofun(1000,Parent,LS)),
4041    P2 = spawn(mktmofun(400,Parent,LS)),
4042    P3 = spawn(mktmofun(600,Parent,LS)),
4043    P4 = spawn(mktmofun(200,Parent,LS)),
4044    ok = ?EXPECT_ACCEPTS([{P4,{error,timeout}},{P2,{error,timeout}},
4045			  {P3,{error,timeout}},{P1,{error,timeout}}],infinity,2000).
4046
4047%% Check that multi-accept timeouts happen in the correct order after
4048%% mixing millsec and sec timeouts (even more++).
4049accept_timeouts_in_order7(Config) when is_list(Config) ->
4050    try do_accept_timeouts_in_order7(Config)
4051    catch
4052        throw:{skip, _} = SKIP ->
4053            SKIP
4054    end.
4055
4056do_accept_timeouts_in_order7(Config) ->
4057    LS = case ?LISTEN(Config, 0,[]) of
4058             {ok, LSocket} ->
4059                 LSocket;
4060             {error, eaddrnotavail = Reason} ->
4061                 ?SKIPT(listen_failed_str(Reason))
4062         end,
4063    Parent = self(),
4064    P1 = spawn(mktmofun(1000,Parent,LS)),
4065    P2 = spawn(mktmofun(200,Parent,LS)),
4066    P3 = spawn(mktmofun(1200,Parent,LS)),
4067    P4 = spawn(mktmofun(600,Parent,LS)),
4068    P5 = spawn(mktmofun(400,Parent,LS)),
4069    P6 = spawn(mktmofun(800,Parent,LS)),
4070    P7 = spawn(mktmofun(1600,Parent,LS)),
4071    P8 = spawn(mktmofun(1400,Parent,LS)),
4072    ok = ?EXPECT_ACCEPTS([{P2,{error,timeout}},{P5,{error,timeout}},
4073			  {P4,{error,timeout}},{P6,{error,timeout}},
4074			  {P1,{error,timeout}},{P3,{error,timeout}},
4075			  {P8,{error,timeout}},{P7,{error,timeout}}],infinity,2000).
4076
4077%% Check that multi-accept timeouts behave correctly when
4078%% mixed with successful timeouts.
4079accept_timeouts_mixed(Config) when is_list(Config) ->
4080    ?TC_TRY(accept_timeouts_mixed,
4081	    fun() -> do_accept_timeouts_mixed(Config) end).
4082
4083do_accept_timeouts_mixed(Config) ->
4084    ?P("create listen socket"),
4085    LS = case ?LISTEN(Config, 0,[]) of
4086             {ok, LSocket} ->
4087                 LSocket;
4088             {error, eaddrnotavail = Reason} ->
4089                 ?SKIPT(listen_failed_str(Reason))
4090         end,
4091    Parent = self(),
4092    {ok,PortNo}=inet:port(LS),
4093
4094    ?P("create acceptor process 1 (with timeout 1000)"),
4095    P1 = spawn(mktmofun(1000,Parent,LS)),
4096
4097    ?P("await ~p accepting", [P1]),
4098    wait_until_accepting(P1,500),
4099
4100    ?P("create acceptor process 2 (with timeout 2000)"),
4101    P2 = spawn(mktmofun(2000,Parent,LS)),
4102
4103    ?P("await ~p accepting", [P2]),
4104    wait_until_accepting(P2,500),
4105
4106    ?P("create acceptor process 3 (with timeout 3000)"),
4107    P3 = spawn(mktmofun(3000,Parent,LS)),
4108
4109    ?P("await ~p accepting", [P3]),
4110    wait_until_accepting(P3,500),
4111
4112    ?P("create acceptor process 4 (with timeout 4000)"),
4113    P4 = spawn(mktmofun(4000,Parent,LS)),
4114
4115    ?P("await ~p accepting", [P4]),
4116    wait_until_accepting(P4,500),
4117
4118    ?P("expect accept from 1 (~p) with timeout", [P1]),
4119    ok = ?EXPECT_ACCEPTS([{P1,{error,timeout}}],infinity,1500),
4120
4121    ?P("connect"),
4122    case ?CONNECT(Config, "localhost", PortNo, []) of
4123        {ok, _} ->
4124            ok;
4125        {error, eaddrnotavail = Reason1} ->
4126            ?SKIPT(connect_failed_str(Reason1))
4127    end,
4128
4129    ?P("expect accept from 2 (~p) with success", [P2]),
4130    if is_port(LS) ->
4131            ok = ?EXPECT_ACCEPTS([{P2,{ok,Port0}}] when is_port(Port0),
4132                                                        infinity,100);
4133       true ->
4134            ok = ?EXPECT_ACCEPTS([{P2,{ok,_}}],infinity,100)
4135    end,
4136
4137    ?P("expect accept from 3 (~p) with timeout", [P3]),
4138    ok = ?EXPECT_ACCEPTS([{P3,{error,timeout}}],infinity,2000),
4139
4140    ?P("connect"),
4141    case ?CONNECT(Config, "localhost", PortNo, []) of
4142        {error, eaddrnotavail = Reason2} ->
4143            ?SKIPT(connect_failed_str(Reason2));
4144        _  ->
4145            ok
4146    end,
4147
4148    ?P("expect accept from 4 (~p) with success", [P4]),
4149    if is_port(LS) ->
4150            ok = ?EXPECT_ACCEPTS([{P4,{ok,Port1}}] when is_port(Port1),
4151                                                        infinity,100);
4152       true ->
4153            ok = ?EXPECT_ACCEPTS([{P4,{ok,_Port1}}],infinity,100)
4154    end,
4155
4156    ?P("done"),
4157    ok.
4158
4159%% Check that single acceptor behaves as expected when killed.
4160killing_acceptor(Config) when is_list(Config) ->
4161    ?TC_TRY(killing_acceptor, fun() -> do_killing_acceptor(Config) end).
4162
4163do_killing_acceptor(Config) ->
4164    ?P("create listen socket"),
4165    case ?LISTEN(Config, 0,[]) of
4166        {ok, LSocket} when is_port(LSocket) ->
4167            do_killing_acceptor_inet(LSocket);
4168        {ok, LSocket} ->
4169            do_killing_acceptor_socket(LSocket);
4170        {error, eaddrnotavail = Reason} ->
4171            ?SKIPT(listen_failed_str(Reason))
4172    end,
4173    ?P("done"),
4174    ok.
4175
4176do_killing_acceptor_inet(LS) ->
4177    ?P("validate state - listening"),
4178    validate_acceptor_state(LS, [listen], []),
4179
4180    ?P("create acceptor process"),
4181    Pid = spawn(
4182            fun() ->
4183                    erlang:display({accepted,self(),gen_tcp:accept(LS)})
4184            end),
4185    ?P("sleep some"),
4186    receive after 100 -> ok
4187    end,
4188
4189    ?P("validate state - accepting"),
4190    validate_acceptor_state(LS, [accepting], []),
4191
4192    ?P("kill acceptor"),
4193    exit(Pid, kill),
4194    ?P("sleep some"),
4195    receive after 100 -> ok
4196    end,
4197
4198    ?P("validate state - listening"),
4199    validate_acceptor_state(LS, [listen], [accepting]),
4200
4201    ?P("cleanup"),
4202    (catch gen_tcp:close(LS)),
4203    ok.
4204
4205do_killing_acceptor_socket(LS) ->
4206    ?P("validate state - listening"),
4207    validate_acceptor_state(LS, 0, [listening], []),
4208
4209    ?P("create acceptor process"),
4210    Pid = spawn(
4211            fun() ->
4212                    erlang:display({accepted,self(),gen_tcp:accept(LS)})
4213            end),
4214    ?P("sleep some"),
4215    ct:sleep(100),
4216
4217    ?P("validate state - accepting"),
4218    validate_acceptor_state(LS, 1, [accepting], []),
4219
4220    ?P("kill acceptor"),
4221    exit(Pid, kill),
4222    ?P("sleep some"),
4223    ct:sleep(100),
4224
4225    ?P("validate state - listening"),
4226    validate_acceptor_state(LS, 0, [listening], [accepting]),
4227
4228    ?P("cleanup"),
4229    (catch gen_tcp:close(LS)),
4230    ok.
4231
4232validate_acceptor_state(LS, ExpStates, ExpNotStates) when is_port(LS) ->
4233    case inet:info(LS) of
4234        #{states := States} ->
4235
4236            ?P("try validate state when: "
4237               "~n   Exp States:     ~p"
4238               "~n   Exp Not States: ~p"
4239               "~n   States:         ~p", [ExpStates, ExpNotStates, States]),
4240
4241            %% State *shall* contain ExpStates => States1 =/= States
4242            States1 = States -- ExpStates,
4243
4244            %% State shall *not* contain ExpNotStates => States2 =:= States
4245            States2 = States -- ExpNotStates,
4246
4247            if
4248                (States1 =/= States) andalso
4249                (States2 =:= States) ->
4250                    ?P("validated: "
4251                       "~n    Expected States:     ~p"
4252                       "~n    Expected Not States: ~p",
4253                       [ExpStates, ExpNotStates]),
4254                    ok;
4255               true ->
4256                    ?P("invalid states: "
4257                       "~n   Expected States:     ~p"
4258                       "~n   Expected Not States: ~p"
4259                       "~n   States:              ~p",
4260                       [ExpStates, ExpNotStates, States]),
4261                    ct:fail("Invalid state(s)")
4262            end;
4263
4264        InvalidInfo ->
4265            ?P("invalid info: "
4266               "~n   Expected States:     ~p"
4267               "~n   Expected Not States: ~p"
4268               "~n   Invalid Info:        ~p",
4269               [ExpStates, ExpNotStates, InvalidInfo]),
4270            ct:fail("Invalid state")
4271    end.
4272
4273validate_acceptor_state(LS, ExpNumAcc, ExpState, ExpNotState) ->
4274    case inet:info(LS) of
4275        #{num_acceptors := ExpNumAcc, rstates := States} ->
4276            ?P("try validate state when: "
4277               "~n   Expected State:     ~p"
4278               "~n   Expected Not State: ~p"
4279               "~n   RStates:            ~p", [ExpState, ExpNotState, States]),
4280
4281            %% States *shall* contain ExpState => States1 =/= States
4282            States1 = States -- ExpState,
4283
4284            %% States shall *not* contain ExpNotState => States2 =:= States
4285            States2 = States -- ExpNotState,
4286
4287            if
4288                (States1 =/= States) andalso
4289                (States2 =:= States) ->
4290                    ?P("validated: "
4291                       "~n    Expected States:     ~p"
4292                       "~n    Expected Not States: ~p",
4293                       [ExpState, ExpNotState]),
4294                    ok;
4295               true ->
4296                    ?P("invalid states: "
4297                       "~n   Expected State:     ~p"
4298                       "~n   Expected Not State: ~p"
4299                       "~n   States:             ~p",
4300                       [ExpState, ExpNotState, States]),
4301                    ct:fail("Invalid state(s)")
4302            end;
4303
4304        #{num_acceptors := NumAcc, rstates := RStates, wstates := WStates} ->
4305            ?P("invalid state: "
4306               "~n   Expected Num Acceptors: ~w"
4307               "~n   Num Acceptors:          ~w"
4308               "~n   Expected State:         ~p"
4309               "~n   Expected Not State:     ~p"
4310               "~n   RStates:                ~p"
4311               "~n   WStates:                ~p",
4312               [ExpNumAcc, NumAcc, ExpState, RStates, WStates]),
4313            ct:fail("Invalid state");
4314
4315        InvalidInfo ->
4316            ?P("invalid info: "
4317               "~n   Expected Num Acceptors: ~w"
4318               "~n   Expected State:         ~p"
4319               "~n   Expected Not State:     ~p"
4320               "~n   Invalid Info:           ~p",
4321               [ExpNumAcc, ExpNumAcc, ExpState, InvalidInfo]),
4322            ct:fail("Invalid state")
4323    end.
4324
4325
4326%% Check that multi acceptors behaves as expected when killed.
4327killing_multi_acceptors(Config) when is_list(Config) ->
4328    ?TC_TRY(killing_multi_acceptors,
4329            fun() -> do_killing_multi_acceptors(Config) end).
4330
4331do_killing_multi_acceptors(Config) ->
4332    ?P("create listen socket"),
4333    case ?LISTEN(Config, 0,[]) of
4334        {ok, LSocket} when is_port(LSocket) ->
4335            do_killing_multi_acceptors_inet(LSocket);
4336        {ok, LSocket} ->
4337            do_killing_multi_acceptors_socket(LSocket);
4338        {error, eaddrnotavail = Reason} ->
4339            ?SKIPT(listen_failed_str(Reason))
4340    end,
4341    ?P("done"),
4342    ok.
4343
4344do_killing_multi_acceptors_inet(LS) ->
4345    ?P("validate state - listen"),
4346    validate_acceptor_state(LS, [listen], []),
4347
4348    Parent = self(),
4349    F = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LS)} end,
4350    F2 = mktmofun(1000,Parent,LS),
4351    ?P("create first acceptor"),
4352    Pid = spawn(F),
4353    ?P("create second acceptor - with timeout"),
4354    Pid2 = spawn(F2),
4355
4356    ?P("sleep some"),
4357    receive after 100 -> ok
4358    end,
4359
4360    ?P("validate state - accepting"),
4361    validate_acceptor_state(LS, [accepting], []),
4362
4363    ?P("kill first acceptor"),
4364    exit(Pid, kill),
4365
4366    ?P("sleep some"),
4367    receive after 100 -> ok
4368    end,
4369
4370    ?P("validate state - still accepting"),
4371    validate_acceptor_state(LS, [accepting], []),
4372
4373    ?P("await second acceptor exit - timeout"),
4374    case ?EXPECT_ACCEPTS([{Pid2, {error,timeout}}], 1, 1000) of
4375	ok ->
4376	    ?P("second acceptor - expected result"),
4377	    ok;
4378	Any ->
4379	    ?P("second acceptor - failed:"
4380	       "~n      ~p", [Any]),
4381	    %% Check what Pid2 is doing
4382	    Pid2Info1 = process_info(Pid2),
4383	    Pid2Msgs1 = process_info(Pid2, messages),
4384	    %% Check if this is just a race...
4385	    ?SLEEP(?SECS(1)),
4386	    Pid2Info2 = process_info(Pid2),
4387	    Pid2Msgs2 = process_info(Pid2, messages),
4388	    ?P("second acceptor failed - check ~p"
4389	       "~n      Info 1: ~p"
4390	       "~n      Msgs 1: ~p"
4391	       "~n   After 1 sec sleep:"
4392	       "~n      Info 2: ~p"
4393	       "~n      Msgs 2: ~p",
4394	       [Pid2, Pid2Info1, Pid2Msgs1, Pid2Info2, Pid2Msgs2]),
4395	    ct:fail({unexpected_accepts, Any})
4396    end,
4397
4398    ?P("validate state - *not* accepting"),
4399    validate_acceptor_state(LS, [listen], [accepting]),
4400
4401    ?P("cleanup"),
4402    (catch gen_tcp:close(LS)),
4403    ok.
4404
4405do_killing_multi_acceptors_socket(LS) ->
4406    ?P("validate state - listening"),
4407    validate_acceptor_state(LS, 0, [listening], []),
4408
4409    Parent = self(),
4410    F = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LS)} end,
4411    F2 = mktmofun(1000,Parent,LS),
4412    ?P("create first acceptor"),
4413    Pid = spawn(F),
4414    ?P("create second acceptor - with timeout"),
4415    Pid2 = spawn(F2),
4416
4417    ?P("sleep some"),
4418    ct:sleep(100),
4419
4420    ?P("validate state - accepting"),
4421    validate_acceptor_state(LS, 2, [accepting], []),
4422
4423    ?P("kill first acceptor"),
4424    exit(Pid, kill),
4425    ?P("sleep some"),
4426    ct:sleep(100),
4427
4428    ?P("validate state - (still) accepting"),
4429    validate_acceptor_state(LS, 1, [accepting], []),
4430
4431    ?P("await second acceptor exit - timeout"),
4432    ok = ?EXPECT_ACCEPTS([{Pid2,{error,timeout}}],1,1000),
4433
4434    ?P("validate state - listening"),
4435    validate_acceptor_state(LS, 0, [listening], [accepting]),
4436
4437    ?P("cleanup"),
4438    (catch gen_tcp:close(LS)),
4439    ok.
4440
4441
4442%% Check that multi acceptors behaves as expected when killed (more).
4443killing_multi_acceptors2(Config) when is_list(Config) ->
4444    ?TC_TRY(killing_multi_acceptors2,
4445            fun() -> do_killing_multi_acceptors2(Config) end).
4446
4447do_killing_multi_acceptors2(Config) ->
4448    ?P("create listen socket"),
4449    case ?LISTEN(Config, 0,[]) of
4450        {ok, LSocket} when is_port(LSocket) ->
4451            do_killing_multi_acceptors2_inet(Config, LSocket);
4452        {ok, LSocket} ->
4453            do_killing_multi_acceptors2_socket(Config, LSocket);
4454        {error, eaddrnotavail = Reason} ->
4455            ?SKIPT(listen_failed_str(Reason))
4456    end,
4457    ?P("done"),
4458    ok.
4459
4460do_killing_multi_acceptors2_inet(Config, LS) ->
4461    ?P("validate state - listen"),
4462    validate_acceptor_state(LS, [listen], []),
4463
4464    Parent = self(),
4465    ?P("get port number for listen socket"),
4466    {ok, PortNo} = inet:port(LS),
4467
4468    F = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LS)} end,
4469    F2 = mktmofun(1000,Parent,LS),
4470
4471    ?P("create acceptor process 1"),
4472    Pid = spawn(F),
4473    ?P("create acceptor process 2"),
4474    Pid2 = spawn(F),
4475    ?P("wait some"),
4476    receive after 100 -> ok
4477    end,
4478
4479    ?P("validate state - accepting"),
4480    validate_acceptor_state(LS, [accepting], []),
4481
4482    ?P("kill acceptor 1"),
4483    exit(Pid,kill),
4484
4485    ?P("sleep some"),
4486    receive after 100 -> ok
4487    end,
4488
4489    ?P("validate state - (still) accepting"),
4490    {ok, L2} = prim_inet:getstatus(LS),
4491    true  = lists:member(accepting, L2),
4492
4493    ?P("kill acceptor 2"),
4494    exit(Pid2, kill),
4495
4496    ?P("sleep some"),
4497    receive after 100 -> ok
4498    end,
4499
4500    ?P("validate state - listening"),
4501    validate_acceptor_state(LS, [listen], [accepting]),
4502
4503    ?P("create acceptor 3"),
4504    Pid3 = spawn(F2),
4505
4506    ?P("wait some"),
4507    receive after 100 -> ok
4508    end,
4509
4510    ?P("validate state - accepting"),
4511    validate_acceptor_state(LS, [accepting], []),
4512
4513    ?P("connect to port ~p", [PortNo]),
4514    ?CONNECT(Config, "localhost", PortNo,[]),
4515
4516    ?P("await accept"),
4517    ok = ?EXPECT_ACCEPTS([{Pid3,{ok,CSock}}] when is_port(CSock),1,100),
4518
4519    ?P("validate state - listening"),
4520    validate_acceptor_state(LS, [listen], [accepting]),
4521
4522    ?P("cleanup"),
4523    (catch gen_tcp:close(LS)),
4524    ok.
4525
4526do_killing_multi_acceptors2_socket(Config, LS) ->
4527    ?P("validate state - listening"),
4528    validate_acceptor_state(LS, 0, [listening], []),
4529
4530    Parent = self(),
4531    ?P("get port number for listen socket"),
4532    {ok, PortNo} = inet:port(LS),
4533
4534    F = fun() -> Parent ! {accepted,self(),gen_tcp:accept(LS)} end,
4535    F2 = mktmofun(1000,Parent,LS),
4536
4537    ?P("create acceptor process 1"),
4538    Pid = spawn(F),
4539    ?P("create acceptor process 2"),
4540    Pid2 = spawn(F),
4541
4542    ?P("wait some"),
4543    ct:sleep(100),
4544
4545    ?P("validate state - accepting"),
4546    validate_acceptor_state(LS, 2, [accepting], []),
4547
4548    ?P("kill acceptor 1"),
4549    exit(Pid,kill),
4550
4551    ?P("sleep some"),
4552    ct:sleep(100),
4553
4554    ?P("validate state - (still) accepting"),
4555    validate_acceptor_state(LS, 1, [accepting], []),
4556
4557    ?P("kill acceptor 2"),
4558    exit(Pid2, kill),
4559
4560    ?P("sleep some"),
4561    receive after 100 -> ok
4562    end,
4563
4564    ?P("validate state - listening"),
4565    validate_acceptor_state(LS, 0, [listening], [accepting]),
4566
4567    ?P("create acceptor 3"),
4568    Pid3 = spawn(F2),
4569
4570    ?P("wait some"),
4571    ct:sleep(100),
4572
4573    ?P("validate state - accepting"),
4574    validate_acceptor_state(LS, 1, [accepting], []),
4575
4576    ?P("connect to port ~p", [PortNo]),
4577    ?CONNECT(Config, "localhost", PortNo,[]),
4578
4579    ?P("await accept"),
4580    ok = ?EXPECT_ACCEPTS([{Pid3,{ok, _CSock}}],1,100),
4581
4582    ?P("validate state - listening"),
4583    validate_acceptor_state(LS, 0, [listening], [accepting]),
4584
4585    ?P("cleanup"),
4586    (catch gen_tcp:close(LS)),
4587    ok.
4588
4589
4590%% Checks that multi-accept works when more than one accept can be
4591%% done at once (wb test of inet_driver).
4592several_accepts_in_one_go(Config) when is_list(Config) ->
4593    ?TC_TRY(several_accepts_in_one_go,
4594            fun() -> do_several_accepts_in_one_go(Config) end).
4595
4596do_several_accepts_in_one_go(Config) ->
4597    ?P("create listen socket"),
4598    NumActors = 8,
4599    LS = case ?LISTEN(Config, 0, [{backlog, NumActors}]) of
4600             {ok, LSock} ->
4601                 LSock;
4602             {error, eaddrnotavail = Reason} ->
4603                 ?SKIPT(listen_failed_str(Reason))
4604         end,
4605    Parent = self(),
4606    {ok, PortNo} = inet:port(LS),
4607    F1 = fun() ->
4608		 ?P("acceptor starting"),
4609		 Parent ! {accepted,self(),gen_tcp:accept(LS)}
4610         end,
4611    F2 = fun() ->
4612		 ?P("connector starting"),
4613		 Parent ! {connected,self(),?CONNECT(Config, "localhost",PortNo,[])}
4614         end,
4615    Ns = lists:seq(1, NumActors),
4616    ?P("start acceptors"),
4617    _  = [spawn(F1) || _ <- Ns],
4618    ?P("await accept timeouts"),
4619    ok = ?EXPECT_ACCEPTS([],1,500), % wait for tmo
4620    ?P("start connectors"),
4621    _  = [spawn(F2) || _ <- Ns],
4622    ?P("await accepts"),
4623    ok = ?EXPECT_ACCEPTS([{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}}],NumActors,15000),
4624    ?P("await connects"),
4625    ok = ?EXPECT_CONNECTS([{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}},{_,{ok,_}}],1000),
4626    ?P("done"),
4627    ok.
4628
4629flush(Msgs) ->
4630    erlang:yield(),
4631    receive Msg -> flush([Msg|Msgs])
4632    after     0 -> lists:reverse(Msgs)
4633    end.
4634
4635wait_until_accepting(Proc,0) ->
4636    exit({timeout_waiting_for_accepting,Proc});
4637wait_until_accepting(Proc,N) ->
4638    case process_info(Proc,current_function) of
4639        {current_function, {prim_inet, accept0, 3}} ->
4640            case process_info(Proc, status) of
4641                {status,waiting} ->
4642                    ok;
4643                _O1 ->
4644                    receive
4645                    after 5 ->
4646                            wait_until_accepting(Proc, N-1)
4647                    end
4648            end;
4649        {current_function, {gen, do_call, 4}} ->
4650            case process_info(Proc, status) of
4651                {status,waiting} ->
4652                    ok;
4653                _O1 ->
4654                    receive
4655                    after 5 ->
4656                            wait_until_accepting(Proc, N-1)
4657                    end
4658            end;
4659        _O2 ->
4660            receive
4661            after 5 ->
4662                    wait_until_accepting(Proc, N-1)
4663            end
4664    end.
4665
4666
4667%% Check that accept returns {error, system_limit}
4668%% (and not {error, enfile}) when running out of ports.
4669accept_system_limit(Config) when is_list(Config) ->
4670    Cond = fun() ->
4671		   case ?IS_SOCKET_BACKEND(Config) of
4672		       true ->
4673			   {skip, "Not complient with socket"};
4674		       false ->
4675			   ok
4676		   end
4677	   end,
4678    TC   = fun() -> do_accept_system_limit(Config) end,
4679    ?TC_TRY(accept_system_limit, Cond, TC).
4680
4681do_accept_system_limit(Config) ->
4682    ?P("create listen socket"),
4683    LS = case ?LISTEN(Config, 0, []) of
4684             {ok, LSocket} ->
4685                 LSocket;
4686             {error, eaddrnotavail = Reason} ->
4687                 ?SKIPT(listen_failed_str(Reason))
4688        end,
4689    {ok, {Addr, Port}} = inet:sockname(LS),
4690    ?P("listen socket \"bound\" to:"
4691       "~n      Address: ~p"
4692       "~n      Port:    ~p", [Addr, Port]),
4693    Me = self(),
4694    ?P("create connector"),
4695    Connector = spawn_link(fun() ->
4696                                   connector(Config, Port, Me)
4697                           end),
4698    ?P("sync with connector (~p)", [Connector]),
4699    receive {Connector, sync} -> Connector ! {self(), continue} end,
4700    ?P("begin accepting"),
4701    ok = acceptor(Connector, LS, false, []),
4702    ?P("stop connector (~p)", [Connector]),
4703    Connector ! stop,
4704    ?P("done"),
4705    ok.
4706
4707acceptor(Connector, LS, GotSL, A) ->
4708    case gen_tcp:accept(LS, 1000) of
4709        {ok, S} ->
4710            acceptor(Connector, LS, GotSL, [S|A]);
4711        {error, eaddrnotavail = Reason} ->
4712            ?SKIPE(accept_failed_str(Reason));
4713        {error, system_limit} ->
4714            ?P("acceptor: "
4715               "system limit => *almost* done (~w)", [length(A)]),
4716            acceptor(Connector, LS, true, A);
4717        {error, timeout} when GotSL ->
4718            ?P("acceptor: timeout (with system limit) => done (~w)",
4719               [length(A)]),
4720            ok;
4721        {error, timeout} ->
4722            ?P("acceptor: timeout *without* system limit => failure"
4723               "~n     Number of Accepted: ~w",
4724               [length(A)]),
4725            error
4726    end.
4727
4728connector(Config, AccPort, Tester) ->
4729    ?P("[connector] start"),
4730    ManyPorts = open_ports([]),
4731    ?P("[connector] length(ManyPorts): ~p", [length(ManyPorts)]),
4732    Tester ! {self(), sync},
4733    ?P("[connector] await continute from tester (~p)", [Tester]),
4734    receive {Tester, continue} -> timer:sleep(100) end,
4735    ?P("[connector] begin connecting"),
4736    ConnF =
4737        fun(Port) ->
4738                case (catch ?CONNECT(Config, {127,0,0,1}, AccPort)) of
4739                    {ok, Sock} ->
4740                        ?P("[connector] success: "
4741                           "~n      ~p", [Sock]),
4742                        Sock;
4743                    {error, eaddrnotavail = Reason} ->
4744                        ?SKIPE(connect_failed_str(Reason));
4745                    _Error ->
4746                        ?P("[connector] failure: "
4747                           "~n      ~p", [_Error]),
4748                        port_close(Port)
4749                end
4750        end,
4751    R = [ConnF(Port) || Port <- lists:sublist(ManyPorts, 10)],
4752    ?P("[connector] await stop"),
4753    receive stop -> ?P("[connector] stop (~w)", [length(R)]), R end.
4754
4755open_ports(L) ->
4756    case catch open_port({spawn_driver, "ram_file_drv"}, []) of
4757	Port when is_port(Port) ->
4758	    open_ports([Port|L]);
4759	{'EXIT', {system_limit, _}} ->
4760	    {L1, L2} = lists:split(5, L),
4761	    [port_close(Port) || Port <- L1],
4762	    L2
4763    end.
4764
4765
4766%% Check that active once and tcp_close messages behave as expected.
4767active_once_closed(Config) when is_list(Config) ->
4768    ?TC_TRY(active_once_closed, fun() -> do_active_once_closed(Config) end).
4769
4770do_active_once_closed(Config) ->
4771    ?P("stage 1"),
4772    (fun() ->
4773	     ?P("[stage1] begin setup"),
4774	     {Loop,A} = setup_closed_ao(Config),
4775	     ?P("[stage1] begin send"),
4776	     Loop({{error,closed},{error,econnaborted}},
4777                  fun() -> gen_tcp:send(A,"Hello") end),
4778	     ?P("[stage1] try set active:once => expect success"),
4779	     ok = inet:setopts(A, [{active,once}]),
4780	     ?P("[stage1] await socket closed"),
4781	     ok = receive {tcp_closed, A} -> ok after 1000 -> error end,
4782	     ?P("[stage1] try set active:once => expect failure (einval)"),
4783	     {error,einval} = inet:setopts(A,[{active,once}]),
4784	     ?P("[stage1] await socket closed - expect timeout"),
4785	     ok = receive {tcp_closed, A} -> error after 1000 -> ok end,
4786	     ?P("[stage1] done"),
4787	     ok
4788     end)(),
4789    ?P("stage 2"),
4790    (fun() ->
4791	     ?P("[stage2] begin setup"),
4792	     {Loop,A} = setup_closed_ao(Config),
4793	     ?P("[stage2] begin send"),
4794	     Loop({{error,closed},{error,econnaborted}},
4795                  fun() -> gen_tcp:send(A,"Hello") end),
4796	     ?P("[stage2] try set active:true => expect success"),
4797	     ok = inet:setopts(A,[{active,true}]),
4798	     ?P("[stage2] await socket closed"),
4799	     ok = receive {tcp_closed, A} -> ok after 1000 -> error end,
4800	     ?P("[stage2] try set active:true => expect failure (einval)"),
4801	     {error,einval} = inet:setopts(A,[{active,true}]),
4802	     ?P("[stage2] await socket closed - expect timeout"),
4803	     ok = receive {tcp_closed, A} -> error after 1000 -> ok end,
4804	     ?P("[stage2] done"),
4805	     ok
4806     end)(),
4807    ?P("stage 3"),
4808    (fun() ->
4809	     ?P("[stage3] begin setup"),
4810	     {Loop,A} = setup_closed_ao(Config),
4811	     ?P("[stage3] begin send"),
4812	     Loop({{error,closed},{error,econnaborted}},
4813                  fun() -> gen_tcp:send(A,"Hello") end),
4814	     ?P("[stage3] try set active:true => expect success"),
4815	     ok = inet:setopts(A,[{active,true}]),
4816	     ?P("[stage3] await socket closed"),
4817	     ok = receive {tcp_closed, A} -> ok after 1000 -> error end,
4818	     ?P("[stage3] try set active:once => expect failure (einval)"),
4819	     {error,einval} = inet:setopts(A,[{active,once}]),
4820	     ?P("[stage3] await socket closed - expect timeout"),
4821	     ok = receive {tcp_closed, A} -> error after 1000 -> ok end,
4822	     ?P("[stage3] done"),
4823	     ok
4824     end)(),
4825    ?P("stage 4"),
4826    (fun() ->
4827	     ?P("[stage4] begin setup"),
4828	     {Loop,A} = setup_closed_ao(Config),
4829	     ?P("[stage4] begin send"),
4830	     Loop({{error,closed},{error,econnaborted}},
4831			fun() -> gen_tcp:send(A,"Hello") end),
4832	     ?P("[stage1] try set active:once => expect success"),
4833	     ok = inet:setopts(A,[{active,once}]),
4834	     ?P("[stage4] await socket closed"),
4835	     ok = receive {tcp_closed, A} -> ok after 1000 -> error end,
4836	     ?P("[stage4] try set active:true => expect failure (einval)"),
4837	     {error,einval} = inet:setopts(A,[{active,true}]),
4838	     ?P("[stage4] await socket closed - expect timeout"),
4839	     ok = receive {tcp_closed, A} -> error after 1000 -> ok end,
4840	     ?P("[stage4] done"),
4841	     ok
4842     end)(),
4843    ?P("stage 5"),
4844    (fun() ->
4845	     ?P("[stage5] begin setup"),
4846	     {Loop,A} = setup_closed_ao(Config),
4847	     ?P("[stage5] begin send"),
4848	     Loop({{error,closed},{error,econnaborted}},
4849			fun() -> gen_tcp:send(A,"Hello") end),
4850	     ?P("[stage5] try set active:false => expect success"),
4851	     ok = inet:setopts(A,[{active,false}]),
4852	     ?P("[stage5] await socket closed => expect timeout"),
4853	     ok = receive {tcp_closed, A} -> error after 1000 -> ok end,
4854	     ?P("[stage5] try set active:once => expect success"),
4855	     ok = inet:setopts(A,[{active,once}]),
4856	     ?P("[stage5] await socket closed"),
4857	     ok = receive {tcp_closed, A} -> ok after 1000 -> error end,
4858	     ?P("[stage5] done"),
4859	     ok
4860     end)(),
4861    ?P("done"),
4862    ok.
4863
4864%% Check that active n and tcp_close messages behave as expected.
4865active_n_closed(Config) when is_list(Config) ->
4866    ?TC_TRY(active_n_closed, fun() -> do_active_n_closed(Config) end).
4867
4868do_active_n_closed(Config) ->
4869    ?P("create listen socket"),
4870    {ok, L} = ?LISTEN(Config, 0, [binary, {active, false}]),
4871
4872    P = self(),
4873
4874    {ok, Port} = inet:port(L),
4875
4876    ClientF =
4877        fun() ->
4878                ?P("[client] started"),
4879                Payload = <<0:50000/unit:8>>,
4880                Cnt = 10000,
4881                ?P("[client] send size"),
4882                P ! {size, Cnt * byte_size(Payload)},
4883                ?P("[client] try connect"),
4884                S = case ?CONNECT(Config, "localhost", Port,
4885                                  [binary, {active, false}]) of
4886                        {ok, CS} ->
4887                            ?P("[client] connected"),
4888                            P ! {continue, self()},
4889                            CS;
4890                        {error, eaddrnotavail = Reason} ->
4891                            ?SKIPE(connect_failed_str(Reason))
4892                    end,
4893                ?P("[client] send payload"),
4894                _ = [gen_tcp:send(S, Payload) || _ <- lists:seq(1, Cnt)],
4895                ?P("[client] close socket"),
4896                gen_tcp:close(S),
4897                ?P("[client] done"),
4898                exit(ok)
4899        end,
4900    ?P("create client process"),
4901    {Pid, MRef} = spawn_monitor(ClientF),
4902
4903    ?P("await size"),
4904    receive {size, SendSize} -> SendSize end,
4905    ?P("await continue or down"),
4906    receive
4907        {continue, Pid} ->
4908            ?P("got continue"),
4909            ok;
4910        {'DOWN', MRef, process, Pid, {skip, _} = SKIP} ->
4911            ?P("got *unexpected* skip"),
4912            gen_tcp:close(L),
4913            throw(SKIP);
4914        {'DOWN', MRef, process, Pid, ConnectRes} ->
4915            ?P("got *unexpected* crash: "
4916              "~n   ~p", [ConnectRes]),
4917            exit({unexpected, connect, ConnectRes})
4918    end,
4919    {ok, S} = gen_tcp:accept(L),
4920    inet:setopts(S, [{active, 10}]),
4921    ?P("start collecting data"),
4922    RecvSize = anc_await_closed_and_down(S, Pid, MRef),
4923
4924    ?P("close listen socket"),
4925    gen_tcp:close(L),
4926
4927    ?P("validate size"),
4928    if SendSize =:= RecvSize ->
4929            ?P("done"),
4930            ok;
4931       true ->
4932            ct:fail("Send and Recv size not equal: ~p ~p", [SendSize, RecvSize])
4933    end.
4934
4935
4936anc_await_closed_and_down(S, Pid, MRef) ->
4937    anc_await_closed_and_down(S, Pid, MRef, 0, false, false).
4938
4939anc_await_closed_and_down(_S, _Pid, _MRef, Size, true, true) ->
4940    Size;
4941anc_await_closed_and_down(S, Pid, MRef, Size, Closed, Down) ->
4942    receive
4943        {tcp, S, Bin} ->
4944            %% ?P("got a chunk (~w) of data", [byte_size(Bin)]),
4945            anc_await_closed_and_down(S, Pid, MRef,
4946                                      byte_size(Bin) + Size, Closed, Down);
4947        {tcp_closed, S} ->
4948            ?P("got closed -> we are done: ~w", [Size]),
4949            anc_await_closed_and_down(S, Pid, MRef, Size, true, Down);
4950        {tcp_passive, S} ->
4951            %% ?P("got passive -> active"),
4952            inet:setopts(S, [{active, 10}]),
4953            anc_await_closed_and_down(S, Pid, MRef, Size, Closed, true);
4954        {'DOWN', MRef, process, Pid, ok} ->
4955            ?P("Received expected down message regarding client"),
4956            anc_await_closed_and_down(S, Pid, MRef, Size, Closed, true);
4957
4958        {'DOWN', MRef, process, Pid, Reason} ->
4959            ?P("Received UNEXPECTED down message regarding client:"
4960               "~n   Reason:    ~p"
4961               "~n   Port Info: ~p",
4962               [Reason, (catch erlang:port_info(S))]),
4963            ct:fail({unexpected_client_down, Reason});
4964
4965       Msg ->
4966            ?P("ignore: ~p", [Msg]),
4967            anc_await_closed_and_down(S, Pid, MRef, Size, Closed, Down)
4968    end.
4969
4970%% Test the send_timeout socket option.
4971send_timeout(Config) when is_list(Config) ->
4972    ?TC_TRY(send_timeout, fun() -> do_send_timeout(Config) end).
4973
4974do_send_timeout(Config) ->
4975    ?P("begin"),
4976    Dir = filename:dirname(code:which(?MODULE)),
4977    ?P("create (slave) node"),
4978    {ok, RNode} = ?START_SLAVE_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
4979
4980    {TslTimeout, SndTimeout, BinData, SndBuf} =
4981	case ?IS_SOCKET_BACKEND(Config) of
4982	    true ->
4983		{100, 3000, binary:copy(<<$a:8>>, 10*1024), 5*1024};
4984	    false ->
4985		{1,   1000, binary:copy(<<$a:8>>, 1*1024),  16*1024}
4986	end,
4987
4988    %% Basic
4989    ?P("basic check wo autoclose"),
4990    send_timeout_basic(Config, BinData, SndBuf, TslTimeout, SndTimeout,
4991		       false, RNode),
4992    ?P("basic check w autoclose"),
4993    send_timeout_basic(Config, BinData, SndBuf, TslTimeout, SndTimeout,
4994		       true, RNode),
4995
4996    %% Check timeout length.
4997    ?P("spawn sink process (check timeout length)"),
4998    Self = self(),
4999    {Pid, Mon} = spawn_monitor(
5000                   fun() ->
5001                           {A, _} = setup_timeout_sink(Config,
5002						       RNode, SndTimeout,
5003						       true, SndBuf),
5004                           Send = fun() ->
5005                                          Res = gen_tcp:send(A, BinData),
5006                                          Self ! Res,
5007                                          Res
5008                                  end,
5009                           {{error, timeout}, _} =
5010			       timeout_sink_loop(Send, TslTimeout)
5011                   end),
5012    Diff = get_max_diff(),
5013    ?P("Max time for send: ~p", [Diff]),
5014    true = (Diff > (SndTimeout - 500)) and (Diff < (SndTimeout + 500)),
5015
5016    %% Wait for the process to die.
5017    ?P("await (timeout checker) process death"),
5018    receive {'DOWN', Mon, process, Pid, _} -> ok end,
5019
5020    %% Check that parallell writers do not hang forever
5021    ?P("check parallell writers wo autoclose"),
5022    send_timeout_para(Config, BinData, SndBuf, TslTimeout, SndTimeout,
5023		      false, RNode),
5024    ?P("check parallell writers w autoclose"),
5025    send_timeout_para(Config, BinData, SndBuf, TslTimeout, SndTimeout,
5026		      true, RNode),
5027
5028    ?P("stop (slave) node"),
5029    ?STOP_NODE(RNode),
5030
5031    ?P("done"),
5032    ok.
5033
5034send_timeout_basic(Config, BinData, SndBuf, TslTimeout, SndTimeout,
5035		   AutoClose, RNode) ->
5036    ?P("[basic] sink"),
5037    {A, Pid}              = setup_timeout_sink(Config, RNode, SndTimeout,
5038					       AutoClose, SndBuf),
5039    Send                  = fun() -> gen_tcp:send(A, BinData) end,
5040    {{error, timeout}, _} = timeout_sink_loop(Send, TslTimeout),
5041
5042    %% Check that the socket is not busy/closed...
5043    ?P("[basic] verify socket not busy/closed"),
5044    case gen_tcp:send(A, BinData) of
5045	{error, Reason} ->
5046	    ?P("[basic] (expected) send failure"),
5047	    after_send_timeout(AutoClose, Reason),
5048	    (catch gen_tcp:close(A)),
5049	    exit(Pid, kill),
5050	    ok;
5051	ok ->
5052            %% Note that there is no active reader on the other end,
5053            %% so a 'channel' has been filled, should remain filled.
5054	    ?P("[basic] UNEXPECTED send success"),
5055	    (catch gen_tcp:close(A)),
5056	    exit(Pid, kill),
5057	    ct:fail("Unexpected send success")
5058    end.
5059
5060send_timeout_para(Config, BinData, BufSz, TslTimeout, SndTimeout,
5061		  AutoClose, RNode) ->
5062    ?P("[para] sink -> entry with"
5063       "~n      size(BinData): ~p"
5064       "~n      BufSz:         ~p"
5065       "~n      SndTimeout:    ~p"
5066       "~n      AutoClose:     ~p",
5067       [byte_size(BinData), BufSz, SndTimeout, AutoClose]),
5068    {A, Pid} = setup_timeout_sink(Config, RNode, SndTimeout, AutoClose, BufSz),
5069    Self = self(),
5070    SenderFun = fun() ->
5071                        ?P("[para:sender] start"),
5072			Send = fun() -> gen_tcp:send(A, BinData) end,
5073			Self ! {self(), timeout_sink_loop(Send, TslTimeout)}
5074		end,
5075    ?P("[para] spawn process 1 with sender fun"),
5076    Snd1 = spawn_link(SenderFun),
5077    ?P("[para] spawn process 2 with sender fun"),
5078    Snd2 = spawn_link(SenderFun),
5079
5080    SockInfo    = fun() -> (catch inet:info(A)) end,
5081    SockTimeout = fun() ->
5082                          try inet:getopts(A, [send_timeout]) of
5083                              {ok, [V2]} ->
5084                                  V2;
5085                              {error, R2} ->
5086                                  ?F("ERROR: ~p", [R2]);
5087                              X2 ->
5088                                  ?F("UNKNOWN: ~p", [X2])
5089                          catch
5090                              C2:E2:S2 ->
5091                                  ?F("CATCHED: ~p, ~p, ~p", [C2, E2, S2])
5092                          end
5093                  end,
5094
5095    ?P("[para] await first sender timeout when"
5096       "~n   Sender 1: ~p"
5097       "~n   Sender 2: ~p", [Snd1, Snd2]),
5098    First =
5099        receive
5100            {Snd1, {{error, timeout}, N}} ->
5101                ?P("[para] timeout received from sender 1 (~p, ~p)", [Snd1, N]),
5102                1;
5103            {Snd2, {{error, timeout}, N}} ->
5104                ?P("[para] timeout received from sender 2 (~p, ~p)", [Snd2, N]),
5105                2;
5106
5107            {'EXIT', _Pid, {timetrap_timeout, _Timeout, _Stack}} ->
5108                %% The test case (timetrap) has timed out, which either means
5109                %% we are running on very slow hw or some system functions
5110                %% are slowing us down (this test case should never normally
5111                %% time out like this).
5112                ?P("Test case timetrap timeout - check for system events"),
5113                case kernel_test_global_sys_monitor:events(?SECS(5)) of
5114                    SysEvs when (SysEvs =/= []) ->
5115                        ?P("timetrap timeout with system events: "
5116                           "~n   System Events: ~p"
5117                           "~n   Sender 1 Info: ~p"
5118                           "~n   Sender 2 Info: ~p"
5119                           "~n   Socket Info:   ~p",
5120                           [SysEvs,
5121                            process_info(Snd1), process_info(Snd2),
5122                            SockInfo()]),
5123                        ?SKIPT(?F("TC system ~w events", [length(SysEvs)]));
5124                    {error, Reason} ->
5125                        ?P("TC timetrap timeout but failed get system events: "
5126                           "~n   Reason:        ~p"
5127                           "~n   Sender 1 Info: ~p"
5128                           "~n   Sender 2 Info: ~p"
5129                           "~n   Socket Info:   ~p",
5130                           [Reason,
5131                            process_info(Snd1), process_info(Snd2),
5132                            SockInfo()]),
5133                        exit({timetrap, {failed_get_sys_evs, Reason}});
5134                    [] ->
5135                        ?P("TC timetrap *without* system events: "
5136                           "~n   Sender 1 Info: ~p"
5137                           "~n   Sender 2 Info: ~p"
5138                           "~n   Socket Info:   ~p",
5139                           [process_info(Snd1), process_info(Snd2),
5140                            SockInfo()]),
5141                        exit(timetrap)
5142                end
5143
5144        after 20000 ->
5145                SockInfo1 = SockInfo(),
5146                SockTo1   = SockTimeout(),
5147                ?P("[para] UNEXPECTED timeout(1,~w) when:"
5148                   "~n   Sender 1 Info: ~p"
5149                   "~n   Sender 2 Info: ~p"
5150                   "~n   Socket Info:   ~p"
5151                   "~n   Send Timeout:  ~p"
5152                   "~n   Message Queue: ~p",
5153                   [AutoClose,
5154                    (catch process_info(Snd1)),
5155                    (catch process_info(Snd2)),
5156                    SockInfo1, SockTo1,
5157                    flush([])]),
5158                Snd1 ! {info_and_die, SockInfo, SockTimeout},
5159                Snd2 ! {info_and_die, SockInfo, SockTimeout},
5160                ct:sleep(?SECS(1)),
5161                exit({timeout, AutoClose})
5162        end,
5163
5164    Second = if (First =:= 1) -> 2; true -> 1 end,
5165    ?P("[para] await second sender ~w error", [Second]),
5166    receive
5167	{Snd1, {{error, Error_1}, N_1}} ->
5168            ?P("[para] error (~p) received from sender 1 (~p, ~p)",
5169               [Error_1, Snd1, N_1]),
5170            after_send_timeout(AutoClose, Error_1);
5171	{Snd2, {{error, Error_1}, N_1}} ->
5172            ?P("[para] error (~p) received from sender 2 (~p, ~p)",
5173               [Error_1, Snd2, N_1]),
5174            after_send_timeout(AutoClose, Error_1)
5175    after 10000 ->
5176            if (Second =:= 1) ->
5177                    SockInfo21 = SockInfo(),
5178                    SockTo21   = SockTimeout(),
5179                    ?P("[para] UNEXPECTED timeout(2, ~w):"
5180                       "~n   Sender 1 Info: ~p"
5181                       "~n   Socket Info:   ~p"
5182                       "~n   Send Timeout:  ~p"
5183                       "~n   Message Queue: ~p",
5184                       [AutoClose,
5185                        (catch process_info(Snd1)),
5186                        SockInfo21, SockTo21,
5187                        flush([])]),
5188                Snd1 ! {info_and_die, SockInfo, SockTimeout};
5189               true ->
5190                    SockInfo22 = SockInfo(),
5191                    SockTo22   = SockTimeout(),
5192                    ?P("[para] UNEXPECTED timeout(2, ~w):"
5193                       "~n   Sender 2 Info: ~p"
5194                       "~n   Socket Info:   ~p"
5195                       "~n   Send Timeout:  ~p"
5196                       "~n   Message Queue: ~p",
5197                       [AutoClose,
5198                        (catch process_info(Snd2)),
5199                        SockInfo22, SockTo22,
5200                        flush([])]),
5201                    Snd2 ! {info_and_die, SockInfo, SockTimeout}
5202            end,
5203            ct:sleep(?SECS(1)),
5204	    exit({timeout, AutoClose, Second})
5205    end,
5206
5207    ?P("[para] socket info: "
5208       "~n   ~p", [SockInfo()]),
5209    {error, Error_2} = gen_tcp:send(A, BinData),
5210    after_send_timeout(AutoClose, Error_2),
5211    ?P("[para] cleanup - await sender terminations"),
5212    st_await_sender_termination(Snd1, Snd2),
5213    ?P("[para] cleanup - close socket"),
5214    (catch gen_tcp:close(A)),
5215    ?P("[para] cleanup - kill sink"),
5216    exit(Pid, kill),
5217    ?P("[para] done"),
5218    ok.
5219
5220st_await_sender_termination(undefined, undefined) ->
5221    ok;
5222st_await_sender_termination(Sender1, Sender2) ->
5223    receive
5224        {'EXIT', Pid, Reason} when (Pid =:= Sender1) ->
5225            ?P("sender 1 (~p) terminated: "
5226               "~n   ~p", [Pid, Reason]),
5227            st_await_sender_termination(undefined, Sender2);
5228        {'EXIT', Pid, Reason} when (Pid =:= Sender2) ->
5229            ?P("sender 2 (~p) terminated: "
5230               "~n   ~p", [Pid, Reason]),
5231            st_await_sender_termination(Sender1, undefined)
5232    end.
5233
5234get_max_diff() ->
5235    receive
5236	ok ->
5237	    get_max_diff(0)
5238    after 10000 ->
5239	    exit(timeout)
5240    end.
5241
5242get_max_diff(Max) ->
5243    T1 = millis(),
5244    receive
5245	ok ->
5246	    Diff = millis() - T1,
5247	    if
5248		Diff > Max ->
5249		    ?P("new max send time: ~w", [Diff]),
5250		    get_max_diff(Diff);
5251		true ->
5252		    get_max_diff(Max)
5253	    end;
5254	{error,timeout} ->
5255	    Diff = millis() - T1,
5256	    if
5257		Diff > Max ->
5258		    ?P("timeout diff (> prev max send to): ~w", [Diff]),
5259		    Diff;
5260		true ->
5261		    Max
5262	    end
5263    after 10000 ->
5264              exit(timeout)
5265    end.
5266
5267after_send_timeout(AutoClose, Reason) ->
5268    case Reason of
5269        timeout              when AutoClose =:= false -> ok;
5270        {timeout, _RestData} when AutoClose =:= false -> ok;
5271        enotconn             when AutoClose =:= true  -> ok;
5272	closed               when AutoClose           -> ok;
5273        _ ->
5274            ?P("after_send_timeout -> "
5275               "~n      AutoClose: ~w"
5276               "~n      Reason:    ~p", [AutoClose, Reason]),
5277            exit({after_send_timeout, AutoClose, Reason})
5278    end.
5279
5280
5281%% Test the send_timeout socket option for active sockets.
5282send_timeout_active(Config) when is_list(Config) ->
5283    ?TC_TRY(send_timeout_active, fun() -> do_send_timeout_active(Config) end).
5284
5285do_send_timeout_active(Config) ->
5286    Dir = filename:dirname(code:which(?MODULE)),
5287    {ok, RNode} = ?START_SLAVE_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
5288    do_send_timeout_active(Config, false, RNode),
5289    do_send_timeout_active(Config, true, RNode),
5290    ?STOP_NODE(RNode),
5291    ok.
5292
5293do_send_timeout_active(Config, AutoClose, RNode) ->
5294    {A,C} = setup_active_timeout_sink(Config, RNode, 1, AutoClose),
5295    inet:setopts(A, [{active, once}]),
5296    Mad = spawn_link(RNode, fun() -> mad_sender(C) end),
5297    ListData = lists:duplicate(1000, $a),
5298    F = fun() ->
5299                ?P("[sink action] await data"),
5300		receive
5301		    {tcp, _Sock, _Data} ->
5302                        ?P("[sink action] active -> once"),
5303			inet:setopts(A, [{active, once}]),
5304                        ?P("[sink action] send payload"),
5305			Res = gen_tcp:send(A, ListData),
5306			Res;
5307		    Unexpected ->
5308			?P("[sink action] unexpected message: "
5309                           "~n      ~p", [Unexpected]),
5310			Unexpected
5311		end
5312	end,
5313    {{error, timeout}, _} = timeout_sink_loop(F, 1),
5314    unlink(Mad),
5315    exit(Mad, kill),
5316    flush(),
5317    ok.
5318
5319mad_sender(S) ->
5320    put(action,  nothing),
5321    put(sent,    0),
5322    put(elapsed, 0),
5323    mad_sender(S, 0).
5324
5325mad_sender(S, N) ->
5326    U = rand:uniform(1000000),
5327    put(action, send),
5328    Start   = erlang:monotonic_time(),
5329    Ret     = gen_tcp:send(S, integer_to_list(U)),
5330    Stop    = erlang:monotonic_time(),
5331    Elapsed = get(elapsed),
5332    put(elapsed, Elapsed + (Stop - Start)),
5333    put(action, sent),
5334    N2 = N + 1,
5335    put(sent,   N2),
5336    case Ret of
5337        ok ->
5338            mad_sender(S, N + 1);
5339        {error, timeout} = ERROR1 ->
5340            ?P("mad_sender -> send failed: timeout"
5341               "~n   Number of sends:     ~w"
5342               "~n   Elapsed (send) time: ~w msec",
5343               [N2,
5344                erlang:convert_time_unit(get(elapsed), native, millisecond)]),
5345            ERROR1;
5346        {error, {timeout, RestData}} = ERROR2 ->
5347            ?P("mad_sender -> "
5348               "send failed: timeout with ~w bytes of rest data"
5349               "~n   Number of sends:     ~w"
5350               "~n   Elapsed (send) time: ~w msec",
5351               [byte_size(RestData),
5352                N2,
5353                erlang:convert_time_unit(get(elapsed), native, millisecond)]),
5354            ERROR2;
5355        {error, Reason} = ERROR3 ->
5356            ?P("mad_sender -> send failed: "
5357               "~n   ~p"
5358               "~n   Number of sends:     ~w"
5359               "~n   Elapsed (send) time: ~w msec",
5360               [Reason,
5361                N2,
5362                erlang:convert_time_unit(get(elapsed), native, millisecond)]),
5363            ERROR3;
5364        ERROR4 ->
5365            ?P("mad_sender -> send failed: "
5366               "~n   ~p"
5367               "~n   Number of sends:     ~w"
5368               "~n   Elapsed (send) time: ~w msec",
5369               [ERROR4,
5370                N2,
5371                erlang:convert_time_unit(get(elapsed), native, millisecond)]),
5372            ERROR4
5373    end.
5374
5375flush() ->
5376    receive
5377	_X ->
5378	    flush()
5379    after 0 ->
5380	    ok
5381    end.
5382
5383setup_closed_ao(Config) ->
5384    Dir = filename:dirname(code:which(?MODULE)),
5385    ?P("[setup] start slave node"),
5386    R = case ?START_SLAVE_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir) of
5387            {ok, Slave} ->
5388                Slave;
5389            {error, Reason} ->
5390                ?SKIPT(?F("failed starting slave node: ~p", [Reason]))
5391        end,
5392    Host = get_hostname(node()),
5393    ?P("[setup] create listen socket"),
5394    L = case ?LISTEN(Config, 0, [{active,false},{packet,2}]) of
5395            {ok, LSock} ->
5396                LSock;
5397            {error, eaddrnotavail = LReason} ->
5398                (catch ?STOP_NODE(R)),
5399                ?SKIPT(listen_failed_str(LReason))
5400        end,
5401    Fun = fun(F) ->
5402                  receive
5403                      {From,X} when is_function(X) ->
5404                          From ! {self(),X()}, F(F);
5405                      die -> ok
5406                  end
5407          end,
5408    ?P("[setup] create remote runner"),
5409    Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]),
5410    {ok, Port} = inet:port(L),
5411    Remote = fun(Fu) ->
5412                     Pid ! {self(), Fu},
5413                     receive {Pid,X} -> X end
5414             end,
5415    Connect = fun() ->
5416                      ?CONNECT(Config, Host, Port,
5417                                      [{active, false}, {packet, 2}])
5418              end,
5419    ?P("[setup] create (remote) connection"),
5420    C = case Remote(Connect) of
5421            {ok, CSock} ->
5422                CSock;
5423            {error, eaddrnotavail = CReason} ->
5424                (catch ?STOP_NODE(R)),
5425                ?SKIPT(connect_failed_str(CReason))
5426        end,
5427    ?P("[setup] accept (local) connection"),
5428    A = case gen_tcp:accept(L) of
5429            {ok, ASock} ->
5430                ASock;
5431            {error, eaddrnotavail = AReason} ->
5432                (catch ?STOP_NODE(R)),
5433                ?SKIPT(accept_failed_str(AReason))
5434        end,
5435    ?P("[setup] send (local) and receive (remote) message"),
5436    gen_tcp:send(A,"Hello"),
5437    {ok, "Hello"} = Remote(fun() -> gen_tcp:recv(C,0) end),
5438    ?P("[setup] close (remote) connection"),
5439    ok =  Remote(fun() -> gen_tcp:close(C) end),
5440    Loop2 = fun(_,_,_,0) ->
5441		    {failure, timeout};
5442	       (L2,{MA,MB},F2,N) ->
5443		    case F2() of
5444			MA -> ?P("[setup] action result (MA): ~p", [MA] ), MA;
5445			MB -> ?P("[setup] action result (MB): ~p", [MB] ), MB;
5446			Other -> ?P("[setup] Loop2: ~p",[Other]),
5447				 receive after 1000 -> ok end,
5448				 L2(L2,{MA,MB},F2,N-1)
5449		    end
5450	    end,
5451    Loop = fun(Match2,F3) ->  Loop2(Loop2,Match2,F3,10) end,
5452    ?P("[setup] stop slave node"),
5453    ?STOP_NODE(R),
5454    ?P("[setup] done"),
5455    {Loop,A}.
5456
5457setup_timeout_sink(Config, RNode, Timeout, AutoClose, BufSz) ->
5458    Host    = get_hostname(node()),
5459    ?P("[sink] create listen socket"),
5460    {ok, L} = ?LISTEN(Config, 0, [{active,             false},
5461				  {packet,             4},
5462				  {sndbuf,             BufSz},
5463				  {send_timeout,       Timeout},
5464				  {send_timeout_close, AutoClose}]),
5465    Fun = fun(F) ->
5466		  receive
5467		      {From,X} when is_function(X) ->
5468			  From ! {self(),X()}, F(F);
5469		      die -> ok
5470		  end
5471	  end,
5472    ?P("[sink] start remote runner process (on ~p)", [RNode]),
5473    Pid =  rpc:call(RNode, erlang, spawn, [fun() -> Fun(Fun) end]),
5474    {ok, Port} = inet:port(L),
5475    Remote = fun(Fu) ->
5476		     Pid ! {self(), Fu},
5477		     receive {Pid,X} -> X
5478		     end
5479	     end,
5480    ?P("[sink] connect from remote node (~p)", [RNode]),
5481    {ok, C} = Remote(fun() ->
5482			     ?CONNECT(Config, Host,Port,
5483				      [{active, false},
5484				       {packet, 4},
5485				       {sndbuf, BufSz div 2}])
5486		     end),
5487    ?P("[sink] accept"),
5488    {ok, A} = gen_tcp:accept(L),
5489    ?P("[sink] accepted - send test message"),
5490    gen_tcp:send(A, "Hello"),
5491    ?P("[sink] message sent - "
5492       "recv 'check' message on remote node (~p)", [RNode]),
5493    {ok, "Hello"} = Remote(fun() -> gen_tcp:recv(C,0) end),
5494    ?P("[sink] cleanup - close listen socket"),
5495    (catch gen_tcp:close(L)),
5496    ?P("[sink] done with socket: "
5497       "~n   ~p", [A]),
5498    {A, Pid}.
5499
5500setup_active_timeout_sink(Config, RNode, Timeout, AutoClose) ->
5501    Host = get_hostname(node()),
5502    ListenOpts =  [binary,
5503		   {active,             false},
5504		   {packet,             0},
5505		   {nodelay,            true},
5506		   {keepalive,          true},
5507		   {send_timeout,       Timeout},
5508		   {send_timeout_close, AutoClose}],
5509    {ok, L} = ?LISTEN(Config, 0, ListenOpts),
5510    Fun = fun(F) ->
5511		  receive
5512		      {From,X} when is_function(X) ->
5513			  From ! {self(),X()},
5514			  F(F);
5515		      die -> ok
5516		  end
5517	  end,
5518    Pid = rpc:call(RNode, erlang, spawn, [fun() -> Fun(Fun) end]),
5519    {ok, Port} = inet:port(L),
5520    Remote = fun(Fu) ->
5521		     Pid ! {self(), Fu},
5522		     receive {Pid,X} -> X
5523		     end
5524	     end,
5525    {ok, C} = Remote(fun() ->
5526			     ?CONNECT(Config, Host, Port, [{active,false}])
5527		     end),
5528    {ok, A} = gen_tcp:accept(L),
5529    gen_tcp:send(A, "Hello"),
5530    {ok, "H"++_} = Remote(fun() -> gen_tcp:recv(C, 0) end),
5531    {A, C}.
5532
5533%% timeout_sink_loop(Action) ->
5534%%     timeout_sink_loop(Action, 1).
5535
5536timeout_sink_loop(Action, To) ->
5537    put(action,  nothing),
5538    put(sent,    0),
5539    put(elapsed, 0),
5540    timeout_sink_loop(Action, To, 0).
5541
5542timeout_sink_loop(Action, To, N) ->
5543    put(action, send),
5544    Start   = erlang:monotonic_time(),
5545    Ret     = Action(),
5546    Stop    = erlang:monotonic_time(),
5547    Elapsed = get(elapsed),
5548    put(elapsed, Elapsed + (Stop - Start)),
5549    put(action, sent),
5550    N2 = N + 1,
5551    put(sent,   N2),
5552    case Ret of
5553	ok ->
5554	    receive
5555                {info_and_die, SockInfo, SockTimeout} ->
5556                    ?P("[sink-loop] info and die: "
5557                       "~n   Socket Info:  ~p"
5558                       "~n   Send Timeout: ~p",
5559                       [SockInfo(), SockTimeout()]),
5560                    exit(normal)
5561            after To -> ok end,
5562	    timeout_sink_loop(Action, To, N+1);
5563	{error, {timeout, RestData}} ->
5564            ?P("[sink-loop] action result: "
5565               "~n   Number of actions: ~p"
5566               "~n   Elapsed time:      ~p msec"
5567               "~n   Result:            timeout with ~w of rest data",
5568               [N2,
5569                erlang:convert_time_unit(get(elapsed), native, millisecond),
5570                byte_size(RestData)]),
5571	    {{error, timeout}, N2};
5572	Other ->
5573            ?P("[sink-loop] action result: "
5574               "~n   Number of actions: ~p"
5575               "~n   Elapsed time:      ~p msec"
5576               "~n   Result:            ~p",
5577               [N2,
5578                erlang:convert_time_unit(get(elapsed), native, millisecond),
5579                Other]),
5580	    {Other, N2}
5581    end.
5582
5583has_superfluous_schedulers() ->
5584    case {erlang:system_info(schedulers),
5585	  erlang:system_info(logical_processors)} of
5586	{S, unknown} when S > 1 -> true;
5587	{S, P} when S > P -> true;
5588	_ -> false
5589    end.
5590
5591
5592%% Leaking message from inet_drv {inet_reply,P,ok}
5593%% when a socket sending resumes working after a send_timeout.
5594%% Should we even bother testing this if 'inet_backend = socket'?
5595otp_7731(Config) when is_list(Config) ->
5596    ?TC_TRY(otp_7731, fun() -> do_otp_7731(Config) end).
5597
5598do_otp_7731(Config) when is_list(Config) ->
5599    ?P("[ctrl] create server"),
5600    ServerPid = spawn_link(?MODULE, otp_7731_server, [Config, self()]),
5601    ?P("[ctrl] await listening port (number) from server"),
5602    receive {ServerPid, ready, PortNum} -> ok end,
5603
5604    ?P("[ctrl] connect to server on port ~w", [PortNum]),
5605    {ok, Socket} = ?CONNECT(Config, "localhost", PortNum,
5606                            [binary, {active, false}, {packet, raw},
5607                             {send_timeout, 1000}]),
5608
5609    ?P("[ctrl] send data"),
5610    otp_7731_send(Socket),
5611    ?P("[ctrl] sending complete - order server to recv"),
5612    ServerPid ! {self(), recv},
5613    ?P("[ctrl] await 'recv complete' from server"),
5614    receive {ServerPid, ok} -> ?P("[ctrl] received 'recv complete'"), ok end,
5615
5616    %% Now make sure inet_drv does not leak any internal messages.
5617    ?P("[ctrl] waiting for leaking messages..."),
5618    receive Msg ->
5619            ?P("[ctrl] got unexpected message: "
5620               "~n      ~p", [Msg]),
5621	    ct:fail({unexpected, Msg})
5622    after 1000 ->
5623	    ok
5624    end,
5625    ?P("[ctrl] no leaking messages - cleanup"),
5626    (catch gen_tcp:close(Socket)),
5627    ServerPid ! {self(), die},
5628    ?P("[ctrl] done."),
5629    ok.
5630
5631otp_7731_send(Socket) ->
5632    Bin = <<1:10000>>,
5633    ?P("[client] sending ~p bytes...", [byte_size(Bin)]),
5634    case gen_tcp:send(Socket, Bin) of
5635        ok ->
5636            otp_7731_send(Socket);
5637        {error, {timeout, RestData}} ->
5638            ?P("[client] send timeout with ~w bytes of rest data",
5639               [byte_size(RestData)]),
5640            ok;
5641        {error, timeout} ->
5642            ?P("[client] send timeout"),
5643            ok
5644    end.
5645
5646otp_7731_server(Config, Ctrl) ->
5647    ?P("[server] create listen socket"),
5648    {ok, LSocket} = ?LISTEN(Config, 0, [binary, {packet, raw},
5649                                       {active, false}]),
5650    {ok, {_, PortNum}} = inet:sockname(LSocket),
5651    ?P("[server] listening on port number ~p", [PortNum]),
5652    Ctrl ! {self(), ready, PortNum},
5653
5654    ?P("[server] accept"),
5655    {ok, CSocket} = gen_tcp:accept(LSocket),
5656    ?P("[server] accepted - close listen socket"),
5657    gen_tcp:close(LSocket),
5658
5659    ?P("[server] await recv order"),
5660    receive {Ctrl, recv} -> ok end,
5661
5662    ?P("[server] start receiving..."),
5663    otp_7731_recv(CSocket),
5664
5665    ?P("[server] announce recv done"),
5666    Ctrl ! {self(), ok},
5667
5668    ?P("[server] finished, (connection) closing..."),
5669    gen_tcp:close(CSocket),
5670    receive {Ctrl, die} -> ok end,
5671    ?P("[server] done"),
5672    exit(normal).
5673
5674
5675otp_7731_recv(Socket) ->
5676    case gen_tcp:recv(Socket, 0, 1000) of
5677        {ok, Bin} ->
5678            ?P("[server] received ~p bytes", [size(Bin)]),
5679            otp_7731_recv(Socket);
5680        {error, timeout} ->
5681            ?P("[server] receive timeout - done recv"),
5682            ok
5683    end.
5684
5685
5686%% OTP-7615: TCP-ports hanging in CLOSING state when sending large
5687%% buffer followed by a recv() that returns error due to closed
5688%% connection.
5689%% OTP-7615 Leaking closed ports.
5690zombie_sockets(Config) when is_list(Config) ->
5691    register(zombie_collector,self()),
5692    Calls = 10,
5693    ?P("create zombie server"),
5694    Server = spawn_link(?MODULE, zombie_server, [Config, self(), Calls]),
5695    {Server, ready, PortNum} = receive Msg -> Msg  end,
5696    ?P("Ports before = ~p",[lists:sort(erlang:ports())]),
5697    zombie_client_loop(Config, Calls, PortNum),
5698    Ports = lists:sort(zombie_collector(Calls, [])),
5699    Server ! terminate,
5700    ?P("Collected ports = ~p", [Ports]),
5701    [] = zombies_alive(Ports, 10),
5702    timer:sleep(1000),
5703    ?P("done"),
5704    ok.
5705
5706zombie_client_loop(_Config, 0, _) ->
5707    ?P("[zombie client] done"),
5708    ok;
5709zombie_client_loop(Config, N, PortNum) when is_integer(PortNum) ->
5710    ?P("[zombie client][~w] try connect", [N]),
5711    {ok, Socket} = ?CONNECT(Config, "localhost", PortNum,
5712                            [binary, {active, false}, {packet, raw}]),
5713    ?P("[zombie client] connected - now close ~p", [Socket]),
5714    gen_tcp:close(Socket), % to make server recv fail
5715    zombie_client_loop(Config, N-1, PortNum).
5716
5717
5718zombie_collector(0, Acc) ->
5719    ?P("[zombie collector] done: "
5720       "~n   ~p", [Acc]),
5721    Acc;
5722zombie_collector(N, Acc) ->
5723    receive
5724	{closed, Socket} ->
5725            ?P("[zombie collector] ~p closed", [Socket]),
5726	    zombie_collector(N-1, [Socket|Acc]);
5727	E ->
5728	    {unexpected, E, Acc}
5729    end.
5730
5731zombies_alive(Ports, WaitSec) ->
5732    Alive = lists:sort(erlang:ports()),
5733    ?P("[zombies alive][~w] Alive: ~p", [WaitSec, Alive]),
5734    Zombies = lists:filter(fun(P) -> lists:member(P, Alive) end, Ports),
5735    case Zombies of
5736	[] -> [];
5737	_ ->
5738	    case WaitSec of
5739		0 -> Zombies;
5740		_ -> timer:sleep(1000), % Wait some more for zombies to die
5741		     zombies_alive(Zombies, WaitSec-1)
5742	    end
5743    end.
5744
5745zombie_server(Config, Pid, Calls) ->
5746    ?P("[zombie server] try create listen socket with backlog: ~w", [Calls]),
5747    {ok, LSock} = ?LISTEN(Config, 0, [binary, {packet, raw},
5748                                      {active, false}, {backlog, Calls}]),
5749    {ok, {_, PortNum}} = inet:sockname(LSock),
5750    ?P("[zombie server] Listening on ~w with port number ~p", [LSock, PortNum]),
5751    BigBin = list_to_binary(lists:duplicate(100*1024, 77)),
5752    ?P("[zombie server] send ready"),
5753    Pid ! {self(), ready, PortNum},
5754    zombie_accept_loop(LSock, BigBin, Calls),
5755    ?P("[zombie server] await terminate"),
5756    terminate = receive Msg -> Msg end,
5757    ?P("[zombie server] terminating"),
5758    ok.
5759
5760zombie_accept_loop(_, _, 0) ->
5761    ?P("[zombie server] accept loop done"),
5762    ok;
5763zombie_accept_loop(Socket, BigBin, Calls) ->
5764    ?P("[zombie server][~w] try accept", [Calls]),
5765    case gen_tcp:accept(Socket) of
5766	{ok, NewSocket} ->
5767            ?P("[zombie server][~w] accepted ~p - create handler",
5768               [Calls, NewSocket]),
5769	    spawn_link(fun() -> zombie_server_handler(NewSocket, BigBin) end),
5770	    zombie_accept_loop(Socket, BigBin, Calls-1);
5771	E ->
5772	    E
5773    end.
5774
5775zombie_server_handler(Socket, Bin) ->
5776    ?P("[zombie server handler] got connection on ~p - attempt send", [Socket]),
5777    gen_tcp:send(Socket, Bin),
5778    ?P("[zombie server handler] Sent data, waiting for reply on ~p", [Socket]),
5779    case gen_tcp:recv(Socket, 4) of
5780        {error, closed} ->
5781            ?P("[zombie server handler] recv: closed (expected)"),
5782            ok;
5783        {error, econnaborted} -> % may be returned on Windows
5784            ?P("[zombie server handler] recv: econnaborted (expected)"),
5785            ok;
5786        {error, Reason} ->
5787            ?P("[zombie server handler] UNEXPECTED recv failure reason: ~p",
5788               [Reason]),
5789            exit({unexpected_recv_error_reason, Reason});
5790        {ok, _} ->
5791            ?P("[zombie server handler] UNEXPECTED recv success"),
5792            exit(unexpected_recv_success)
5793	  end,
5794    ?P("[zombie server handler] close socket ~p", [Socket]),
5795    gen_tcp:close(Socket),
5796    ?P("[zombie server handler] socket closed: inform collector"),
5797    zombie_collector ! {closed, Socket}.
5798
5799
5800%% Hanging send on windows when sending iolist with more than 16 binaries.
5801otp_7816(Config) when is_list(Config) ->
5802    ?TC_TRY(otp_7816, fun() -> do_otp_7816(Config) end).
5803
5804do_otp_7816(Config) ->
5805    Ctrl = self(),
5806    ?P("[ctrl] create server process..."),
5807    Server = spawn_link(fun() -> otp_7816_server(Config, Ctrl) end),
5808    ?P("[ctrl] await server process ready..."),
5809    receive {Server, ready, PortNum} -> ok end,
5810
5811    ?P("[ctrl] connect to server..."),
5812    {ok, Socket} = ?CONNECT(Config, "localhost", PortNum,
5813                            [binary, {active, false}, {packet, 4},
5814                             {send_timeout, 10}]),
5815
5816    %% We use the undocumented feature that sending can be resumed after
5817    %% a send_timeout without any data loss if the peer starts to receive data.
5818    %% Unless of course the 7816-bug is in affect, in which case the write event
5819    %% for the socket is lost on windows and not all data is sent.
5820
5821    ?P("[ctrl] begin sending..."),
5822
5823    [otp_7816_ctrl(Socket, 18, BinSize, Server) ||
5824	BinSize <- lists:seq(1000, 2000, 123)],
5825
5826    ?P("[ctrl] sending complete..."),
5827
5828    ok = gen_tcp:close(Socket),
5829    Server ! {self(), closed},
5830    {Server, closed} = receive M -> M end.
5831
5832
5833otp_7816_ctrl(Socket, BinNr, BinSize, Server) ->
5834    ?P("[ctrl] create payload (BinSz: ~w)...", [BinSize]),
5835    Data = lists:duplicate(BinNr, <<1:(BinSize*8)>>),
5836    ?P("[ctrl] socket info prior to start sending: "
5837       "~n      ~p", [inet:info(Socket)]),
5838    Ctrl   = self(),
5839    Client = spawn_link(fun() -> otp_7816_send_data(Ctrl, Socket, Data) end),
5840    SentBytes =
5841	receive
5842	    {Client, continue, Loops} ->
5843		?P("[ctrl] received continue from client: ~p", [Loops]),
5844		SB = Loops * BinNr * BinSize,
5845		Server ! {self(), recv, SB},
5846		SB
5847	end,
5848    ct:sleep(1000),
5849    ?P("[ctrl] socket info after sending ~w bytes: "
5850       "~n      ~p", [SentBytes, inet:info(Socket)]),
5851    ?P("[ctrl] await server result..."),
5852    ok = receive
5853	     {Server, SR} ->
5854		 ?P("[ctrl] server result: ~p", [SR]),
5855		 SR
5856	 end,
5857    ?P("[ctrl] await client termination..."),
5858    ok = receive
5859	     {'EXIT', Client, normal} ->
5860		 ?P("[ctrl] client normal exit"),
5861		 ok;
5862	     {'EXIT', Client, CR} ->
5863		 ?P("[ctrl] client unexpected exit reason: ~p", [CR]),
5864		 CR
5865	 end,
5866    ?P("[ctrl] done with BinSz: ~p", [BinSize]),
5867    ok.
5868
5869
5870otp_7816_send_data(Ctrl, Socket, Data) ->
5871    otp_7816_send_data(Ctrl, Socket, Data, 0).
5872
5873otp_7816_send_data(Ctrl, Socket, Data, Loops) ->
5874    ?P("[client] sending data (~w bytes, ~w)...", [iolist_size(Data), Loops]),
5875    case gen_tcp:send(Socket, Data) of
5876	ok ->
5877	    otp_7816_send_data(Ctrl, Socket, Data, Loops+1);
5878
5879	{error, timeout} when is_port(Socket) ->
5880	    %% For the 'classic' sockets, when the OS buffers are
5881	    %% full, the rest data are put into the (inet driver)
5882	    %% internal, for later sending. SO, it can be counted
5883	    %% as sent.
5884	    ?P("[client] send timeout when Loops: ~p (+1)", [Loops]),
5885	    Ctrl ! {self(), continue, Loops + 1},
5886	    exit(normal);
5887
5888	{error, timeout} ->
5889	    %% For inet_backend = 'socket' when we nothing of the
5890	    %% message was sent.
5891	    ?P("[client] send timeout when Loops: ~p", [Loops]),
5892	    Ctrl ! {self(), continue, Loops},
5893	    exit(normal);
5894
5895	{error, {timeout, RestData}} ->
5896	    %% A timeout means that **some** of the data was not sent,
5897	    %% currently there is no way to know how much.
5898	    %% NOTE THAT THIS MEANS THAT WE HAVE A PARTIAL PACKAGE
5899	    %% WRITTEN, INCLUDING A HEADER THAT INDUCATES A DATA
5900	    %% SIZE THAT IS **NOT** PRESENT!!
5901	    %% So for this trest case to work, we need to write the rest.
5902	    %% But we cannot do that without first setting the package to raw.
5903	    %%
5904	    ?P("[client] send timeout"
5905	       "~n      with ~w bytes of rest data"
5906	       "~n      when Loops: ~p", [byte_size(RestData), Loops]),
5907	    Ctrl ! {self(), continue, Loops + 1},
5908	    ?P("[client] packet to 'raw'..."),
5909	    ok = inet:setopts(Socket, [{packet, raw}, {send_timeout, 1000}]),
5910	    ?P("[client] send ~w bytes of rest data...",
5911	       [byte_size(RestData)]),
5912	    ok = gen_tcp:send(Socket, RestData),
5913	    ?P("[client] packet (back) to '4'..."),
5914	    ok = inet:setopts(Socket, [{packet, 4}, {send_timeout, 10}]),
5915	    ?P("[client] done"),
5916	    exit(normal)
5917
5918
5919    end.
5920
5921
5922otp_7816_server(Config, Ctrl) ->
5923    ?P("[server] create listening socket"),
5924    {ok, LSocket} = ?LISTEN(Config, 0, [binary, {packet, 4},
5925                                        {active, false}]),
5926    {ok, {_, PortNum}} = inet:sockname(LSocket),
5927    ?P("[server] listening on ~w with port number ~p", [LSocket, PortNum]),
5928    Ctrl ! {self(), ready, PortNum},
5929
5930    ?P("[server] accept connection..."),
5931    {ok, ASocket} = gen_tcp:accept(LSocket),
5932    ?P("[server] got connection..."),
5933    gen_tcp:close(LSocket),
5934
5935    otp_7816_server_loop(ASocket, Ctrl),
5936
5937    ?P("[server] terminating").
5938
5939
5940otp_7816_server_loop(Socket, Ctrl) ->
5941    ?P("[server] waiting for order..."),
5942    receive
5943	{Ctrl, recv, RecvBytes} ->
5944	    ?P("[server] start receiving (~w bytes)...", [RecvBytes]),
5945
5946	    ok = otp_7816_recv(Socket, RecvBytes),
5947
5948	    Ctrl ! {self(), ok},
5949	    otp_7816_server_loop(Socket, Ctrl);
5950
5951	{Ctrl, closed} ->
5952	    {error, closed} = gen_tcp:recv(Socket, 0, 1000),
5953	    Ctrl ! {self(), closed}
5954    end.
5955
5956otp_7816_recv(Socket, BytesLeft) ->
5957    otp_7816_recv(Socket, BytesLeft, 1).
5958
5959otp_7816_recv(_, 0, _) ->
5960    ?P("[server] got all data"),
5961    ok;
5962otp_7816_recv(Socket, BytesLeft, N) ->
5963    ?P("[server] try recv ~w (~p bytes left)", [N, BytesLeft]),
5964    case gen_tcp:recv(Socket, 0, 1000) of
5965	{ok, Bin} when (byte_size(Bin) =< BytesLeft) andalso
5966		       (byte_size(Bin) > 0) ->
5967	    ?P("[server] received ~p of ~p bytes",
5968	       [size(Bin), BytesLeft]),
5969	    otp_7816_recv(Socket, BytesLeft - byte_size(Bin), N+1);
5970	{ok, Bin} ->
5971	    ?P("[server] received unexpected data (~w): "
5972	       "~n   Expected:    ~p bytes"
5973	       "~n   Received:    ~p bytes"
5974	       "~n   Socket Info: ~p",
5975	       [N, BytesLeft, byte_size(Bin), inet:info(Socket)]),
5976	    {error, {unexpected_data, BytesLeft, byte_size(Bin)}};
5977	{error, timeout} ->
5978	    ?P("[server] got receive timeout when expecting more data:"
5979	       "~n      Socket Info: ~p", [inet:info(Socket)]),
5980	    {error, timeout}
5981    end.
5982
5983
5984%% ----------------------------------------------------------------------
5985
5986%% Receive a packet with a faulty packet header.
5987otp_8102(Config) when is_list(Config) ->
5988    {ok, LSocket} = ?LISTEN(Config, 0, []),
5989    {ok, {_, PortNum}} = inet:sockname(LSocket),
5990    ?P("Listening on ~w with port number ~p", [LSocket, PortNum]),
5991
5992    [otp_8102_do(Config, LSocket, PortNum, otp_8102_packet(Type,Size))
5993     || Size <- lists:seq(-10,-1),
5994	Type <- [4, {cdr,big}, {cdr,little}]],
5995
5996    gen_tcp:close(LSocket),
5997    ok.
5998
5999otp_8102_packet(4, Size) ->
6000    {<<Size:32/big>>, 4};
6001otp_8102_packet({cdr,big}, Size) ->
6002    {<<"GIOP",0,0,0,0,Size:32/big>>, cdr};
6003otp_8102_packet({cdr,little}, Size) ->
6004    {<<"GIOP",0,0,1,0,Size:32/little>>, cdr}.
6005
6006otp_8102_do(Config, LSocket, PortNum, {Bin,PType}) ->
6007
6008    ?P("Connect with packet option ~p ...",[PType]),
6009    {ok, RSocket} = ?CONNECT(Config, "localhost", PortNum, [binary,
6010                                                            {packet,PType},
6011                                                            {active,true}]),
6012    {ok, SSocket} = gen_tcp:accept(LSocket),
6013
6014    ?P("Got connection, sending ~p...",[Bin]),
6015
6016    ok = gen_tcp:send(SSocket, Bin),
6017
6018    ?P("Sending complete...",[]),
6019
6020    {tcp_error,RSocket,emsgsize} = receive M -> M end,
6021
6022    ?P("Got error msg, ok."),
6023    gen_tcp:close(SSocket),
6024    gen_tcp:close(RSocket).
6025
6026%% Verify packet_size handles long HTTP header lines.
6027otp_9389(Config) when is_list(Config) ->
6028    {ok, LS} = ?LISTEN(Config, 0, [{active,false}]),
6029    {ok, {_, PortNum}} = inet:sockname(LS),
6030    ?P("Listening on ~w with port number ~p", [LS, PortNum]),
6031    OrigLinkHdr = "/" ++ string:chars($S, 8192),
6032    _Server = spawn_link(
6033                fun() ->
6034                        {ok, S} = gen_tcp:accept(LS),
6035                        ok = inet:setopts(S, [{packet_size, 16384}]),
6036                        ok = otp_9389_loop(S, OrigLinkHdr),
6037                        ok = gen_tcp:close(S)
6038                end),
6039    {ok, S} = ?CONNECT(Config, "localhost", PortNum,
6040                                    [binary, {active, false}]),
6041    Req = "GET / HTTP/1.1\r\n"
6042        ++ "Host: localhost\r\n"
6043        ++ "Link: " ++ OrigLinkHdr ++ "\r\n\r\n",
6044    ok = gen_tcp:send(S, Req),
6045    ok = inet:setopts(S, [{packet, http}]),
6046    {ok, {http_response, {1,1}, 200, "OK"}} = gen_tcp:recv(S, 0),
6047    ok = inet:setopts(S, [{packet, httph}, {packet_size, 16384}]),
6048    {ok, {http_header, _, 'Content-Length', _, "0"}} = gen_tcp:recv(S, 0),
6049    {ok, {http_header, _, "Link", _, LinkHdr}} = gen_tcp:recv(S, 0),
6050    true = (LinkHdr == OrigLinkHdr),
6051    ok = gen_tcp:close(S),
6052    ok = gen_tcp:close(LS),
6053    ok.
6054
6055otp_9389_loop(S, OrigLinkHdr) ->
6056    ok = inet:setopts(S, [{active,once},{packet,http}]),
6057    receive
6058        {http, S, {http_request, 'GET', _, _}} ->
6059            ok = otp_9389_loop(S, OrigLinkHdr, undefined)
6060    after
6061        3000 ->
6062            error({timeout,request_line})
6063    end.
6064otp_9389_loop(S, OrigLinkHdr, ok) ->
6065    Resp = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n" ++
6066        "Link: " ++ OrigLinkHdr ++ "\r\n\r\n",
6067    ok = gen_tcp:send(S, Resp);
6068otp_9389_loop(S, OrigLinkHdr, State) ->
6069    ok = inet:setopts(S, [{active,once}, {packet,httph}]),
6070    receive
6071        {http, S, http_eoh} ->
6072            otp_9389_loop(S, OrigLinkHdr, ok);
6073        {http, S, {http_header, _, "Link", _, LinkHdr}} ->
6074            LinkHdr = OrigLinkHdr,
6075            otp_9389_loop(S, OrigLinkHdr, State);
6076        {http, S, {http_header, _, _Hdr, _, _Val}} ->
6077            otp_9389_loop(S, OrigLinkHdr, State);
6078        {http, S, {http_error, Err}} ->
6079            error({error, Err})
6080    after
6081        3000 ->
6082            error({timeout,header})
6083    end.
6084
6085wrapping_oct() ->
6086    [{timetrap, {minutes,20}}].
6087
6088%% Check that 64bit octet counters work.
6089wrapping_oct(Config) when is_list(Config) ->
6090    ?TC_TRY(wrapping_oct, fun() -> do_wrapping_oct(Config) end).
6091
6092%% {recbuf, 8192}, {sndbuf, 8192}
6093do_wrapping_oct(Config) ->
6094    ?P("[ctrl] create listen socket"),
6095    Ctrl = self(),
6096    {ok, LSock} = ?LISTEN(Config, 0, [{active,false},{mode,binary}]),
6097    {ok, LPort} = inet:port(LSock),
6098    ?P("[ctrl] spawn acceptor"),
6099    Acceptor = spawn_link(fun() -> oct_acceptor(Ctrl, LSock) end),
6100    ?P("[ctrl] spawn pump"),
6101    Pump     = spawn_link(fun() ->
6102                                  oct_datapump(Ctrl,
6103                                               Config, LPort, 16#10000FFFF)
6104                          end),
6105    ?P("[ctrl] await acceptor socket"),
6106    ASock = wc_await_socket("acceptor", Acceptor),
6107    ?P("[ctrl] await pump socket"),
6108    PSock = wc_await_socket("pump", Pump),
6109    ?P("[ctrl] await completion (from pump)"),
6110    Res = wc_await_completion(Acceptor, ASock, Pump, PSock),
6111    ?P("[ctrl] close listen socket"),
6112    gen_tcp:close(LSock),
6113    ?P("[ctrl] verify result"),
6114    ok = Res,
6115    ?P("[ctrl] done"),
6116    ok.
6117
6118wc_await_socket(Tag, Pid) ->
6119    receive
6120        {Pid, socket, AS} ->
6121            ?P("received ~s socket: "
6122               "~n      ~p", [Tag, AS]),
6123            AS
6124    end.
6125
6126wc_await_completion(Acceptor, ASock, Pump, PSock) ->
6127    wc_await_completion(Acceptor, ASock, Pump, PSock, 1, undefined).
6128
6129wc_await_completion(undefined = _Acceptor, _ASock,
6130                    undefined = _Pump,     _PSock,
6131                    Loops, Res) ->
6132    ?P("completed after ~w loops", [Loops]),
6133    Res;
6134wc_await_completion(Acceptor, ASock, Pump, PSock, Loops, CRes) ->
6135    receive
6136        {'EXIT', Pump, Res} ->
6137            ?P("[ctrl] Received pump exit: "
6138               "~n   Loops:  ~w"
6139               "~n   Reason: ~p", [Loops, Res]),
6140            wc_await_completion(Acceptor,  ASock,
6141                                undefined, PSock,
6142                                Loops + 1, Res);
6143        {'EXIT', Acceptor, Res} ->
6144            ?P("[ctrl] Received acceptor exit: "
6145               "~n   Loops:  ~w"
6146               "~n   Reason: ~p", [Loops, Res]),
6147            wc_await_completion(undefined, ASock,
6148                                Pump,      PSock,
6149                                Loops + 1, CRes)
6150
6151    after 10000 ->
6152            ASockInfo = wc_sock_info(ASock),
6153            AccInfo   = wc_proc_info(Acceptor),
6154            PSockInfo = wc_sock_info(PSock),
6155            PumpInfo  = wc_proc_info(Pump),
6156            ?P("Info ~w while waiting for clompletion: "
6157               "~n   Acceptor Socket Info: ~p"
6158               "~n   Acceptor Info:        ~p"
6159               "~n   Pump Socket Info:     ~p"
6160               "~n   Pump Info:            ~p",
6161               [Loops, ASockInfo, AccInfo, PSockInfo, PumpInfo]),
6162            wc_await_completion(Acceptor,  ASock,
6163                                Pump,      PSock,
6164                                Loops + 1, CRes)
6165    end.
6166
6167wc_sock_info(S) ->
6168    try inet:info(S)
6169    catch
6170        _:_:_ ->
6171            undefined
6172    end.
6173
6174wc_proc_info(P) when is_pid(P) ->
6175    try erlang:process_info(P)
6176    catch
6177        _:_:_ ->
6178            undefined
6179    end;
6180wc_proc_info(_) ->
6181    undefined.
6182
6183%% {recbuf, 16*1024}, {sndbuf, 16*1024}
6184oct_datapump(Ctrl, Config, Port, N) ->
6185    ?P("[pump] connect to listener"),
6186    {ok, CSock} = ?CONNECT(Config, "localhost", Port,
6187			   [{active, false}, {mode, binary}]),
6188    ?P("[pump] announce to ctrl"),
6189    Ctrl ! {self(), socket, CSock},
6190    {ok, [{sndbuf,SndBuf}]} = inet:getopts(CSock, [sndbuf]),
6191    ?P("[pump] connected - start 'pumping' with"
6192       "~n      SndBuf: ~w", [SndBuf]),
6193    put(action,  nothing),
6194    put(sent,    0),
6195    put(elapsed, 0),
6196    put(rem_bytes, N),
6197    oct_pump(CSock, N, binary:copy(<<$a:8>>,100000), 0, 0).
6198
6199oct_pump(S, N, _, _, _Sent) when N =< 0 ->
6200    ?P("[pump] done"),
6201    (catch gen_tcp:close(S)),
6202    exit(ok);
6203oct_pump(S, N, Bin, Last, Sent) ->
6204    put(action, send),
6205    Start   = erlang:monotonic_time(nanosecond),
6206    Res     = gen_tcp:send(S, Bin),
6207    Stop    = erlang:monotonic_time(nanosecond),
6208    Elapsed = get(elapsed),
6209    put(elapsed, Elapsed + (Stop - Start)),
6210    put(action,  sent),
6211    put(sent,    Sent+1),
6212    case Res of
6213	ok ->
6214	    case inet:getstat(S) of
6215		{ok, Stat} ->
6216		    {_, R} = lists:keyfind(send_oct, 1, Stat),
6217		    case (R < Last) of
6218			true ->
6219			    ?P("[pump] send counter error ~p < ~p", [R, Last]),
6220                            (catch gen_tcp:close(S)),
6221			    exit({error, {output_counter, R, Last, N}});
6222			false ->
6223                            put(rem_bytes, N - byte_size(Bin)),
6224			    oct_pump(S, N-byte_size(Bin), Bin, R, Sent+1)
6225		    end;
6226		{error, StatReason} ->
6227		    ?P("[pump] get stat failed:"
6228		       "~n      Reason:    ~p"
6229		       "~n   when"
6230		       "~n      Remaining: ~p"
6231		       "~n      Last:      ~p", [StatReason, N, Last]),
6232		    (catch gen_tcp:close(S)),
6233		    exit({error, {stat_failure, StatReason, N, Last}})
6234	    end;
6235	{error, SendReason} ->
6236	    ?P("[pump] send failed:"
6237	       "~n      Reason:    ~p"
6238	       "~n   when"
6239	       "~n      Remaining: ~p"
6240	       "~n      Last:      ~p", [SendReason, N, Last]),
6241	    (catch gen_tcp:close(S)),
6242	    exit({error, {send_failure, SendReason, N, Last}})
6243    end.
6244
6245
6246oct_acceptor(Ctrl, LSock) ->
6247    ?P("[acceptor] accept connection"),
6248    {ok, ASock} = gen_tcp:accept(LSock),
6249    ?P("[acceptor] announce to ctrl"),
6250    Ctrl ! {self(), socket, ASock},
6251    {ok, [{recbuf,RecBuf}]} = inet:getopts(ASock, [recbuf]),
6252    ?P("[acceptor] connection accepted - start receiving with: "
6253       "~n      RecBuf: ~w", [RecBuf]),
6254    put(action,  nothing),
6255    put(recv,    0),
6256    put(elapsed, 0),
6257    oct_aloop(ASock, inet:info(ASock), 0, 0).
6258
6259oct_aloop(S, LastInfo, Received, Times) ->
6260    put(action, recv),
6261    Start   = erlang:monotonic_time(),
6262    Res     = gen_tcp:recv(S, 0),
6263    Stop    = erlang:monotonic_time(),
6264    Elapsed = get(elapsed),
6265    put(elapsed, Elapsed + (Stop - Start)),
6266    put(action,  received),
6267    put(recv,    Times+1),
6268    case Res of
6269	{ok, _} ->
6270            #{counters := #{recv_oct := R} = _Stat} = Info = inet:info(S),
6271            case (R < Received) of
6272                true ->
6273                    ?P("[acceptor] recv counter error:"
6274                       "~n      Recv Cnt:  ~p"
6275                       "~n      Received:  ~p"
6276                       "~n      Times:     ~p"
6277                       "~n      Info:      ~p"
6278                       "~n      Last Info: ~p",
6279                       [R, Received, Times, Info, LastInfo]),
6280                    (catch gen_tcp:close(S)),
6281                    {error, {output_counter, R, Received, Times}};
6282                false ->
6283                    case Times rem 16#FFFFF of
6284                        0 ->
6285                            ?P("[acceptor] read: ~p"
6286                               "~n      Times: ~w"
6287                               "~n      Info:  ~p",
6288                               [R, Times, Info]);
6289                        _ ->
6290                            ok
6291                    end,
6292                    oct_aloop(S, Info, R, Times+1)
6293            end;
6294
6295	{error, RecvReason} ->
6296	    ?P("[acceptor] receive failed:"
6297	       "~n      Reason:   ~p"
6298	       "~n   when"
6299	       "~n      Received: ~p"
6300	       "~n      Times:    ~p", [RecvReason, Received, Times]),
6301	    (catch gen_tcp:close(S)),
6302            ct:sleep(1000), % Just give the 'pump' a chance to get there first
6303	    exit(closed)
6304    end.
6305
6306ok({ok,V}) -> V.
6307
6308get_hostname(Name) ->
6309    "@"++Host = lists:dropwhile(fun(C) -> C =/= $@ end, atom_to_list(Name)),
6310    Host.
6311
6312otp_13939(doc) ->
6313    ["Check that writing to a remotely closed socket doesn't block forever "
6314     "when exit_on_close is false."];
6315otp_13939(suite) ->
6316    [];
6317otp_13939(Config) when is_list(Config) ->
6318    {Pid, Ref} = spawn_opt(
6319        fun() ->
6320            {ok, Listener} = ?LISTEN(Config, 0, [{exit_on_close, false}]),
6321            {ok, Port} = inet:port(Listener),
6322
6323            spawn_link(
6324                fun() ->
6325                    {ok, Client} = ?CONNECT(Config, "localhost", Port,
6326                        [{active, false}]),
6327                    ok = gen_tcp:close(Client)
6328                end),
6329
6330            {ok, Accepted} = gen_tcp:accept(Listener),
6331
6332            ok = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>),
6333
6334            %% The bug surfaces when there's a delay between the send
6335            %% operations; inet:getstat is a red herring.
6336            timer:sleep(100),
6337
6338            {error, Code} = gen_tcp:send(Accepted, <<0:(10*1024*1024*8)>>),
6339            ct:pal("gen_tcp:send returned ~p~n", [Code])
6340        end, [link, monitor]),
6341
6342    receive
6343        {'DOWN', Ref, process, Pid, normal} ->
6344            ok
6345    after 1000 ->
6346        demonitor(Ref, [flush]),
6347        exit(Pid, normal),
6348        ct:fail("Server process blocked on send.")
6349    end.
6350
6351
6352%% No point in running this as the test case with inet_backend = socket
6353%% as it tests a bug in the inet driver that cannot reproduced with
6354%% inet_backend = socket.
6355otp_12242(Config) when is_list(Config) ->
6356    Cond = fun() ->
6357		   case os:type() of
6358		       {win32,_} ->
6359			   %% Even if we set sndbuf and recbuf to small sizes
6360			   %% Windows either happily accepts to send GBytes of
6361			   %% data in no time, so the second send below that
6362			   %% is supposed to time out just succedes, or the
6363			   %% first send that is supposed to fill the inet_drv
6364			   %% I/O queue and start waiting for when more data
6365			   %% can be sent instead sends all data but suffers
6366			   %% a send failure that closes the socket.
6367			   {skip, backpressure_broken_on_win32};
6368		       _ ->
6369			   case ?IS_SOCKET_BACKEND(Config) of
6370			       true ->
6371				   {skip, "Not complient with socket"};
6372			       false ->
6373				   ok
6374			   end
6375		   end
6376	   end,
6377    TC = fun() -> do_otp_12242(Config) end,
6378    ?TC_TRY(otp_12242, Cond, TC).
6379
6380do_otp_12242(Config) when is_list(Config) ->
6381    %% Find the IPv4 address of an up and running interface
6382    %% that is not loopback nor pointtopoint
6383    {ok, IFList} = inet:getifaddrs(),
6384    ?P("IFList "
6385       "~n      ~p", [IFList]),
6386    case
6387	lists:flatten(
6388	  [lists:filtermap(
6389	     fun ({addr, Addr}) when (tuple_size(Addr) =:= 4) ->
6390		     {true, Addr};
6391		 (_) ->
6392		     false
6393	     end, Opts)
6394	   || {_,Opts} <- IFList,
6395	      case lists:keyfind(flags, 1, Opts) of
6396		  {_,Flags} ->
6397		      lists:member(up, Flags)
6398			  andalso
6399			  lists:member(running, Flags)
6400			  andalso
6401			  not lists:member(loopback, Flags)
6402			  andalso
6403			  not lists:member(pointtopoint, Flags);
6404		  false ->
6405		      false
6406	      end])
6407    of
6408	[Addr|_] ->
6409	    otp_12242(Config, Addr);
6410	Other ->
6411	    ?SKIPT({no_external_address, Other})
6412    end.
6413
6414%%
6415otp_12242(Config, Addr) when (tuple_size(Addr) =:= 4) ->
6416    ct:timetrap(30000),
6417    ?P("Using address ~p", [Addr]),
6418    Bufsize  = 16 * 1024,
6419    Datasize = 128 * 1024 * 1024, % At least 1 s on GBit interface
6420    Blob     = binary:copy(<<$x>>, Datasize),
6421    LOpts =
6422        [{backlog,   4},
6423	 {reuseaddr, true},
6424	 {ip,        Addr},
6425         binary,
6426	 {active,    false},
6427         {recbuf,    Bufsize},
6428	 {sndbuf,    Bufsize},
6429	 {buffer,    Bufsize}],
6430    COpts =
6431        [binary,
6432	 {active,       false},
6433	 {ip,           Addr},
6434         {linger,       {true, 1}}, % 1 s
6435         {send_timeout, 500},
6436         {recbuf,       Bufsize},
6437	 {sndbuf,       Bufsize},
6438	 {buffer,       Bufsize}],
6439    Dir = filename:dirname(code:which(?MODULE)),
6440    {ok, ListenerNode} = ?START_SLAVE_NODE(?UNIQ_NODE_NAME, "-pa " ++ Dir),
6441    Tester = self(),
6442    ?P("create listener"),
6443    {Listener, ListenerMRef} =
6444        spawn_opt(
6445          ListenerNode,
6446          fun () ->
6447		  ?P("create listen socket"),
6448                  {ok,L}     = ?LISTEN(Config, 0, LOpts),
6449                  {ok,LPort} = inet:port(L),
6450		  ?P("inform tester about port number: ~w", [LPort]),
6451                  Tester ! {self(), port, LPort},
6452		  ?P("try accept"),
6453                  {ok, A}    = gen_tcp:accept(L),
6454		  ?P("accepted - close listen socket"),
6455                  ok         = gen_tcp:close(L),
6456		  ?P("await close order"),
6457                  receive
6458                      {Tester, stop} ->
6459			  ?P("close order received - close accepted socket"),
6460                          ok = gen_tcp:close(A)
6461                  end
6462          end, [link, monitor]),
6463    ?P("await listen port"),
6464    LPort = receive {Listener,port,P} -> P end,
6465    ?P("try connect to ~w", [LPort]),
6466    {ok,C} = ?CONNECT(Config, Addr, LPort, COpts, infinity),
6467    ?P("connected - get buffers"),
6468    {ok, ReadCOpts} = inet:getopts(C, [recbuf,sndbuf,buffer]),
6469    ?P("connected sockets buffers:"
6470       "~n      ~p", [ReadCOpts]),
6471
6472    otp_12242_2(C, Blob, Datasize),
6473
6474    ?P("send listener stop"),
6475    Listener ! {Tester, stop},
6476    ?P("await listener termination"),
6477    wait(ListenerMRef),
6478    ?P("stop listener node"),
6479    ?STOP_NODE(ListenerNode),
6480    ?P("done"),
6481    ok.
6482
6483
6484otp_12242_2(C, Blob, Datasize) ->
6485    %% Fill the buffers
6486    ?P("sending ~p bytes", [Datasize]),
6487    case gen_tcp:send(C, Blob) of
6488        ok ->
6489            ?P("sent ~p bytes", [Datasize]),
6490            otp_12242_3(C, Blob, Datasize);
6491        {error, {timeout, _RestData}} ->
6492            %% We filled the buffers and timed out;
6493            %% this is probably the socket backend - give up.
6494            ok;
6495        {error, timeout} ->
6496            %% The same as the previous clause
6497            ok
6498    end,
6499    _ = gen_tcp:close(C),
6500    ok.
6501
6502otp_12242_3(C, Blob, Datasize) ->
6503    %% Try to ensure that the close call is in progress
6504    %% before the owner proceeds with sending
6505    CloserMRef = otp_12242_closer(C),
6506
6507    ?P("await tref"),
6508    receive
6509        {tref,Tref} ->
6510	    ?P("tref received - now await trigger timeout"),
6511            receive {timeout,Tref,_} -> ok end,
6512            ?P("trigger timeout received - try send ~p bytes again",
6513	       [Datasize]),
6514            %% Now should the close be in progress...
6515            %% All buffers are full, remote end is not reading,
6516            %% and the send timeout is 1 s so this will timeout:
6517            {error, timeout} = gen_tcp:send(C, Blob),
6518            ?P("expected timeout - update send_timeout (to 10000)"),
6519            ok = inet:setopts(C, [{send_timeout, 10000}]),
6520            %% There is a hidden timeout here.  Port close is sampled
6521            %% every 5 s by prim_inet:send_recv_reply.
6522            %% Linger is 3 s so the Closer will finish this send:
6523            ?P("try send ~p bytes - expect error (closed)", [Datasize]),
6524            {error, closed} = gen_tcp:send(C, Blob),
6525            ?P("await closer termination"),
6526            normal = wait(CloserMRef),
6527            ok
6528    end.
6529
6530otp_12242_closer(C) ->
6531    Owner = self(),
6532    {_Closer, CloserMref} =
6533        spawn_opt(
6534          fun () ->
6535                  ?P("[closer] starting"),
6536                  Owner ! {tref, erlang:start_timer(50, Owner, closing)},
6537                  ?P("[closer] calling gen_tcp:close(C)"),
6538                  try gen_tcp:close(C) of
6539                      Result ->
6540                          ?P("[closer] gen_tcp:close(C) -> ~p", [Result]),
6541                          ok = Result
6542                  catch
6543                      Class:Reason:Stacktrace ->
6544                          ?P("[closer] catched gen_tcp:close(C):"
6545			     "~n      Error Class:  ~p"
6546			     "~n      Error:        ~p"
6547			     "~n      Stack trace:  ~p",
6548                            [Class, Reason, Stacktrace]),
6549                          erlang:raise(Class, Reason, Stacktrace)
6550                  end
6551          end, [link, monitor]),
6552    CloserMref.
6553
6554
6555wait(Mref) ->
6556    receive {'DOWN',Mref,_,_,Reason} -> Reason end.
6557
6558%% OTP-15536
6559%% Test that send error works correctly for delay_send
6560delay_send_error(Config) ->
6561    ?P("create listen socket"),
6562    {ok, L} =
6563        ?LISTEN(Config,
6564          0, [{reuseaddr, true}, {packet, 1}, {active, false}]),
6565    {ok,{{0,0,0,0},PortNum}}=inet:sockname(L),
6566
6567    delay_send_error(Config, L, PortNum, false),
6568    delay_send_error(Config, L, PortNum, true).
6569delay_send_error(Config, L, PortNum, Active) ->
6570    ?P("try connect - with delay_send:true active:~p",[Active]),
6571    {ok, C} =
6572        ?CONNECT(Config,
6573          "localhost", PortNum,
6574          [{packet, 1}, {active, Active}, {delay_send, true}]),
6575    ?P("try accept"),
6576    {ok, S} = gen_tcp:accept(L),
6577    %% Do a couple of sends first to see that it works
6578    ?P("send data"),
6579    ok = gen_tcp:send(C, "hello"),
6580    ?P("send data"),
6581    ok = gen_tcp:send(C, "hello"),
6582    ?P("send data"),
6583    ok = gen_tcp:send(C, "hello"),
6584    %% Close the receiver
6585    ?P("close receiver (accepted socket)"),
6586    ok = gen_tcp:shutdown(C, write),
6587    %%
6588    ?P("send data"),
6589    case gen_tcp:send(C, "hello") of
6590        ok ->
6591            ?P("send data"),
6592            case gen_tcp:send(C, "hello") of
6593                ok ->
6594                    delay_send_error2(C);
6595                {error, closed} ->
6596                    ?P("closed (expected)"),
6597                    ok
6598            end;
6599        {error, closed} ->
6600                    ?P("closed (expected)"),
6601            ok
6602    end,
6603    ok = gen_tcp:close(C).
6604
6605
6606delay_send_error2(Sock) ->
6607    delay_send_error2(Sock, 3).
6608
6609delay_send_error2(Sock, 0) ->
6610    gen_tcp:close(Sock),
6611    ct:fail("Unxpected send success");
6612delay_send_error2(Sock, N) ->
6613    %% Sleep in order for delay_send to have time to trigger
6614    %% This used to result in a double free
6615    timer:sleep(1000),
6616    case gen_tcp:send(Sock, "hello") of
6617        ok ->
6618            delay_send_error2(Sock, N-1);
6619        {error, closed} ->
6620            ?P("closed (expected, ~w)", [N]),
6621            ok;
6622        {error, Reason} ->
6623            ct:fail(?F("Unexpected send error: ~p", [Reason]))
6624    end.
6625
6626
6627
6628
6629%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6630
6631
6632-define(ACTIVE_N, 20).
6633
6634%% 30-second test for gen_tcp in {active, N} mode,
6635%% ensuring it does not get stuck.
6636%% Verifies that erl_check_io properly handles extra EPOLLIN signals.
6637bidirectional_traffic(Config) when is_list(Config) ->
6638    ?TC_TRY(bidirectional_traffic,
6639            fun() -> do_bidirectional_traffic(Config) end).
6640
6641do_bidirectional_traffic(Config) ->
6642    ?P("begin"),
6643    Workers = erlang:system_info(schedulers_online) * 2,
6644    ?P("Use ~w workers", [Workers]),
6645    Payload = crypto:strong_rand_bytes(32),
6646    {ok, LSock} = ?LISTEN(Config,
6647			  0,
6648			  [binary,
6649			   {packet, 0},
6650			   {active, false},
6651			   {reuseaddr, true}]),
6652    %% get all sockets to know failing ends
6653    ?P("listen socket created: "
6654       "~n      ~p", [LSock]),
6655    {ok, Port} = inet:port(LSock),
6656    ?P("listen socket port number ~w", [Port]),
6657    Control = self(),
6658    ?P("create ~w receivers", [Workers]),
6659    Receivers = [spawn_link(fun () ->
6660				    exchange(Config, LSock, Port, Payload, Control)
6661			    end) || _ <- lists:seq(1, Workers)],
6662    ?P("await the result"),
6663    Result =
6664	%% If any of the receivers report, we have an error
6665        receive
6666            {timeout, Socket, Total} ->
6667                ?P("timeout msg for ~p: ~w", [Socket, Total]),
6668                {fail, {timeout, Socket, Total}};
6669	    {error, Socket, Reason} ->
6670                ?P("error msg for ~p: ~p", [Socket, Reason]),
6671                {fail, {error, Socket, Reason}}
6672        after 30000 ->
6673                %% if it does not fail in 30 seconds, it most likely works
6674                ?P("timeout => success"),
6675                ok
6676        end,
6677    ?P("ensure all receivers terminated"),
6678    [begin unlink(Rec), exit(Rec, kill) end || Rec <- Receivers],
6679    ?P("close listen socket"),
6680    (catch gen_tcp:close(LSock)),
6681    ?P("done"),
6682    Result.
6683
6684
6685exchange(Config, LSock, Port, Payload, Control) ->
6686    %% spin up client
6687    _ClntRcv = spawn_link(
6688        fun () ->
6689                ?P("connect"),
6690                {ok, Client} =
6691                    ?CONNECT(Config,
6692			     "localhost",
6693			     Port,
6694			     [binary, {packet, 0}, {active, ?ACTIVE_N}]),
6695                ?P("connected: ~p", [Client]),
6696                send_recv_loop(Client, Payload, Control)
6697        end),
6698    ?P("accept"),
6699    {ok, Socket} = gen_tcp:accept(LSock),
6700    ?P("accepted: ~p", [Socket]),
6701    %% sending process
6702    send_recv_loop(Socket, Payload, Control).
6703
6704send_recv_loop(Socket, Payload, Control) ->
6705    %% {active, N} must be set to active > 12 to trigger the issue
6706    %% {active, 30} seems to trigger it quite often & reliably
6707    ?P("set (initial) active: ~p", [?ACTIVE_N]),
6708    inet:setopts(Socket, [{active, ?ACTIVE_N}]),
6709    ?P("spawn sender"),
6710    _Snd = spawn_link(
6711        fun Sender() ->
6712            case gen_tcp:send(Socket, Payload) of
6713                ok ->
6714                    Sender();
6715                {error, Reason} ->
6716                    ?P("Send failed: "
6717                       "~n      ~p", [Reason]),
6718                    exit({send_failed, Reason})
6719            end
6720        end),
6721    ?P("begin recv"),
6722    recv(Socket, 0, Control).
6723
6724recv(Socket, Total, Control) ->
6725    receive
6726        {tcp, Socket, Data} ->
6727            recv(Socket, Total + byte_size(Data), Control);
6728        {tcp_passive, Socket} ->
6729            inet:setopts(Socket, [{active, ?ACTIVE_N}]),
6730            recv(Socket, Total, Control);
6731        {tcp_closed, Socket} ->
6732            ?P("[recv] closed when total received: ~w"
6733               "~n      Socket Info: ~p",
6734	       [Total, (catch inet:info(Socket))]),
6735	    ok;
6736        Other ->
6737            ?P("[recv] received unexpected when total received: ~w"
6738               "~n      ~p"
6739               "~n      Socket:      ~p"
6740               "~n      Socket Info: ~p",
6741               [Total, Other, Socket, (catch inet:info(Socket))]),
6742            Control ! {error, Socket, Other}
6743    after 2000 ->
6744            %% no data received in 2 seconds => test failed
6745            ?P("[recv] received nothing when total received: ~w"
6746               "~n      Socket:      ~p"
6747               "~n      Socket Info: ~p",
6748               [Total, Socket, (catch inet:info(Socket))]),
6749            Control ! {timeout, Socket, Total}
6750    end.
6751
6752
6753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6754
6755%% This is the most basic of tests.
6756%% We create a listen socket, then spawns processes that create
6757%% monitors to it...
6758socket_monitor1(Config) when is_list(Config) ->
6759    ct:timetrap(?MINS(1)),
6760    ?TC_TRY(socket_monitor1,
6761            fun() -> do_socket_monitor1(Config) end).
6762
6763do_socket_monitor1(Config) ->
6764    ?P("begin"),
6765    Self         = self(),
6766    Type         = ?SOCKET_TYPE(Config),
6767    {ok, LSock1} = ?LISTEN(Config),
6768    F  = fun(S, Fun) -> spawn_monitor(fun() -> Fun(S, Self) end) end,
6769    F1 = fun(Socket, Parent) when is_pid(Parent) ->
6770		 ?P("[client] create monitor"),
6771		 MRef = inet:monitor(Socket),
6772		 Parent ! {self(), ready},
6773		 sm_await_socket_down(MRef, Socket, Type)
6774	 end,
6775    ?P("spawn client"),
6776    {Pid1, Mon1} = F(LSock1, F1),
6777    ?P("await client ready"),
6778    sm_await_client_ready(Pid1),
6779    ?P("close socket"),
6780    gen_tcp:close(LSock1),
6781    ?P("await client termination"),
6782    sm_await_down(Pid1, Mon1, ok),
6783    ?P("done"),
6784    ok.
6785
6786sm_await_socket_down(ExpMon, ExpSock, ExpType) ->
6787    sm_await_socket_down(ExpMon, ExpSock, ExpType, "client").
6788
6789sm_await_socket_down(ExpMon, ExpSock, ExpType, Name) ->
6790    receive
6791	{'DOWN', Mon, Type, Sock, Info} when (Type =:= ExpType) andalso
6792					     (Mon  =:= ExpMon)  andalso
6793					     (Sock =:= ExpSock) ->
6794	    ?P("[~s] received expected (socket) down message: "
6795	       "~n   Mon:  ~p"
6796	       "~n   Type: ~p"
6797	       "~n   Sock: ~p"
6798	       "~n   Info: ~p", [Name, Mon, Type, Sock, Info]),
6799	    exit(ok);
6800
6801	Any ->
6802	    ?P("[~s] received unexpected message: "
6803	       "~n   ~p", [Name, Any]),
6804	    exit({unexpected_message, Any})
6805    end.
6806
6807sm_await_client_ready(Pid) ->
6808    sm_await_client_ready(Pid, "client").
6809
6810sm_await_client_ready(Pid, Name) ->
6811    receive
6812	{Pid, ready} ->
6813	    ?P("received ~s ready", [Name])
6814    end.
6815
6816sm_await_down(Pid, Mon, ExpRes) ->
6817    receive
6818	{'DOWN', Mon, process, Pid, ExpRes} ->
6819	    ?P("received expected process down message from ~p", [Pid]),
6820	    ok;
6821	{'DOWN', Mon, process, Pid, UnexpRes} ->
6822	    ?P("received unexpected process down message from ~p: "
6823	       "~n   ~p", [Pid, UnexpRes]),
6824	    ct:fail({unexpected_down, UnexpRes})
6825    end.
6826
6827
6828%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6829
6830%% This is the most basic of tests.
6831%% We create "many" listen socket(s), then spawns processes that create
6832%% monitors to them...
6833socket_monitor1_manys(Config) when is_list(Config) ->
6834    ct:timetrap(?MINS(1)),
6835    ?TC_TRY(socket_monitor1_manys,
6836            fun() -> do_socket_monitor1_manys(Config) end).
6837
6838do_socket_monitor1_manys(Config) ->
6839    ?P("begin"),
6840    Self         = self(),
6841    Type         = ?SOCKET_TYPE(Config),
6842    ?P("[client] create socket(s)"),
6843    {ok, LSock1} = ?LISTEN(Config),
6844    {ok, LSock2} = ?LISTEN(Config),
6845    {ok, LSock3} = ?LISTEN(Config),
6846    {ok, LSock4} = ?LISTEN(Config),
6847    {ok, LSock5} = ?LISTEN(Config),
6848    F  = fun(S, Fun) -> spawn_monitor(fun() -> Fun(S, Self) end) end,
6849    F1 = fun(Sockets, Parent) when is_list(Sockets) andalso is_pid(Parent) ->
6850		 ?P("[client] create monitor(s)"),
6851		 Monitors = [{inet:monitor(Socket), Socket} ||
6852				Socket <- Sockets],
6853		 Parent ! {self(), ready},
6854		 sm_await_socket_down2(Monitors, Type)
6855	 end,
6856    ?P("spawn client"),
6857    {Pid1, Mon1} = F([LSock1, LSock2, LSock3, LSock4, LSock5], F1),
6858    ?P("await client ready"),
6859    sm_await_client_ready(Pid1),
6860    ?P("close socket(s)"),
6861    gen_tcp:close(LSock1),
6862    gen_tcp:close(LSock2),
6863    gen_tcp:close(LSock3),
6864    gen_tcp:close(LSock4),
6865    gen_tcp:close(LSock5),
6866    ?P("await client termination"),
6867    sm_await_down(Pid1, Mon1, ok),
6868    ?P("done"),
6869    ok.
6870
6871
6872sm_await_socket_down2(Monitors, ExpType) ->
6873    sm_await_socket_down2(Monitors, ExpType, "client").
6874
6875sm_await_socket_down2([], _ExpType, Name) ->
6876    ?P("[~s] all sockets down", [Name]),
6877    exit(ok);
6878sm_await_socket_down2(Mons, ExpType, Name) when is_list(Mons) ->
6879    ?P("[~s] await socket down", [Name]),
6880    receive
6881	{'DOWN', Mon, Type, Sock, Info} when (Type =:= ExpType) ->
6882	    ?P("[~s] received expected (socket) down message: "
6883	       "~n   Mon:  ~p"
6884	       "~n   Type: ~p"
6885	       "~n   Sock: ~p"
6886	       "~n   Info: ~p", [Name, Mon, Type, Sock, Info]),
6887	    case lists:keysearch(Mon, 1, Mons) of
6888		{value, {Mon, Sock}} ->
6889		    Mons2 = lists:keydelete(Mon, 1, Mons),
6890		    sm_await_socket_down2(Mons2, ExpType, Name);
6891		{value, Value} ->
6892		    ?P("[~s] Unexpected socket down: "
6893		       "~n   Value: ~p", [Name, Value]),
6894		    ct:fail({unexpected_monitor, Mon, Value});
6895		false ->
6896		    ct:fail({unknown_monitor, Mon})
6897	    end
6898    end.
6899
6900
6901
6902%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6903
6904%% This is the most basic of tests.
6905%% We create a listen socket, then spawn client process(es) that create
6906%% monitors to it...
6907socket_monitor1_manyc(Config) when is_list(Config) ->
6908    ct:timetrap(?MINS(1)),
6909    ?TC_TRY(socket_monitor1_manyc,
6910            fun() -> do_socket_monitor1_manyc(Config) end).
6911
6912do_socket_monitor1_manyc(Config) ->
6913    ?P("begin"),
6914    Self         = self(),
6915    Type         = ?SOCKET_TYPE(Config),
6916    {ok, LSock1} = ?LISTEN(Config),
6917    F  = fun(S, Fun, Name) ->
6918		 spawn_monitor(fun() -> Fun(S, Name, Self) end)
6919	 end,
6920    F1 = fun(Socket, Name, Parent) when is_list(Name) andalso is_pid(Parent) ->
6921		 ?P("[~s] monitor socket", [Name]),
6922		 MRef = inet:monitor(Socket),
6923		 Parent ! {self(), ready},
6924		 sm_await_socket_down(MRef, Socket, Type)
6925	 end,
6926    ?P("spawn client(s)"),
6927    {Pid1, Mon1} = F(LSock1, F1, "client1"),
6928    {Pid2, Mon2} = F(LSock1, F1, "client2"),
6929    {Pid3, Mon3} = F(LSock1, F1, "client3"),
6930    {Pid4, Mon4} = F(LSock1, F1, "client4"),
6931    {Pid5, Mon5} = F(LSock1, F1, "client5"),
6932    ?P("await client(s) ready"),
6933    sm_await_client_ready(Pid1, "client1"),
6934    sm_await_client_ready(Pid2, "client2"),
6935    sm_await_client_ready(Pid3, "client3"),
6936    sm_await_client_ready(Pid4, "client4"),
6937    sm_await_client_ready(Pid5, "client5"),
6938    ?P("close socket"),
6939    gen_tcp:close(LSock1),
6940    ?P("await client(s) termination"),
6941    sm_await_down(Pid1, Mon1, ok),
6942    sm_await_down(Pid2, Mon2, ok),
6943    sm_await_down(Pid3, Mon3, ok),
6944    sm_await_down(Pid4, Mon4, ok),
6945    sm_await_down(Pid5, Mon5, ok),
6946    ?P("done"),
6947    ok.
6948
6949
6950%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6951
6952%% This is the most basic of tests.
6953%% We create a listen socket, then spawns processes that create
6954%% monitors to it...
6955socket_monitor1_demon_after(Config) when is_list(Config) ->
6956    ct:timetrap(?MINS(1)),
6957    ?TC_TRY(socket_monitor1_demon_after,
6958            fun() -> do_socket_monitor1_demon_after(Config) end).
6959
6960do_socket_monitor1_demon_after(Config) ->
6961    ?P("begin"),
6962    Self         = self(),
6963    Type         = ?SOCKET_TYPE(Config),
6964    {ok, LSock1} = ?LISTEN(Config),
6965    F  = fun(S, Fun) -> spawn_monitor(fun() -> Fun(S, Self) end) end,
6966    F1 = fun(Socket, Parent) when is_pid(Parent) ->
6967		 ?P("[client] create monitor"),
6968		 MRef = inet:monitor(Socket),
6969		 ?P("[client] sleep some"),
6970		 ?SLEEP(?SECS(1)),
6971		 ?P("[client] cancel (socket) monitor"),
6972		 inet:cancel_monitor(MRef),
6973		 ?P("[client] announce ready"),
6974		 Parent ! {self(), ready},
6975		 sm_await_no_socket_down(MRef, Socket, Type)
6976	 end,
6977    ?P("spawn client"),
6978    {Pid1, Mon1} = F(LSock1, F1),
6979    ?P("await client ready"),
6980    sm_await_client_ready(Pid1),
6981    ?P("close socket"),
6982    gen_tcp:close(LSock1),
6983    ?P("await client termination"),
6984    sm_await_down(Pid1, Mon1, ok),
6985    ?P("done"),
6986    ok.
6987
6988
6989sm_await_no_socket_down(ExpMon, ExpSock, ExpType) ->
6990    sm_await_no_socket_down(ExpMon, ExpSock, ExpType, "client").
6991
6992sm_await_no_socket_down(ExpMon, ExpSock, ExpType, Name) ->
6993    receive
6994	{'DOWN', Mon, Type, Sock, Info} when (Type =:= ExpType) andalso
6995					     (Mon  =:= ExpMon)  andalso
6996					     (Sock =:= ExpSock) ->
6997	    ?P("[~s] received unexpected (socket) down message: "
6998	       "~n   Mon:  ~p"
6999	       "~n   Type: ~p"
7000	       "~n   Sock: ~p"
7001	       "~n   Info: ~p", [Name, Mon, Type, Sock, Info]),
7002	    exit({unexpected_down, Mon, Type, Sock, Info});
7003
7004	Any ->
7005	    ?P("[~s] received unexpected message: "
7006	       "~n   ~p", [Name, Any]),
7007	    exit({unexpected_message, Any})
7008
7009    after 1000 ->
7010	    ?P("[~s] expected message timeout", [Name]),
7011	    exit(ok)
7012    end.
7013
7014
7015%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7016
7017%% This is the most basic of tests.
7018%% Spawn a process that creates a (listen) socket, then spawns processes
7019%% that create monitors to it...
7020socket_monitor2(Config) when is_list(Config) ->
7021    ct:timetrap(?MINS(1)),
7022    ?TC_TRY(socket_monitor2,
7023            fun() -> do_socket_monitor2(Config) end).
7024
7025do_socket_monitor2(Config) ->
7026    ?P("begin"),
7027    Type         = ?SOCKET_TYPE(Config),
7028    Self         = self(),
7029    {OwnerPid, OwnerMon} =
7030	spawn_monitor(fun() ->
7031			      ?P("[owner] create (listen) socket"),
7032			      {ok, L} = ?LISTEN(Config),
7033			      ?P("[owner] send (listen) socket to ctrl"),
7034			      Self ! {socket, L},
7035			      ?P("[owner] ready"),
7036			      receive
7037				  {Self, die} ->
7038				      exit(normal)
7039			      end
7040		      end),
7041    LSock1 = receive
7042		 {socket, L} ->
7043		     ?P("received socket from owner"),
7044		     L;
7045		 {'DOWN', OwnerMon, process, OwnerPid, OwnerReason} ->
7046		     ?P("received unexpected owner termination: "
7047			"~n   ~p", [OwnerReason]),
7048		     ct:fail({unexpected_owner_termination, OwnerReason})
7049	     end,
7050    F  = fun(S, Fun) -> spawn_monitor(fun() -> Fun(S, Self) end) end,
7051    F1 = fun(Socket, Parent) when is_pid(Parent) ->
7052		 ?P("[client] create monitor"),
7053		 MRef = inet:monitor(Socket),
7054		 Parent ! {self(), ready},
7055		 sm_await_socket_down(MRef, Socket, Type)
7056	 end,
7057    ?P("spawn client"),
7058    {Pid1, Mon1} = F(LSock1, F1),
7059    ?P("spawn client"),
7060    sm_await_client_ready(Pid1),
7061    ?P("kill owner"),
7062    exit(OwnerPid, kill),
7063    ?P("await owner termination"),
7064    sm_await_down(OwnerPid, OwnerMon, killed),
7065    ?P("await client termination"),
7066    sm_await_down(Pid1, Mon1, ok),
7067    ?P("done"),
7068    ok.
7069
7070
7071%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7072
7073%% This is the most basic of tests.
7074%% Spawn a process that creates "many" (listen) socket(s), then spawns
7075%% a process that create monitors to them...
7076
7077socket_monitor2_manys(Config) when is_list(Config) ->
7078    ct:timetrap(?MINS(1)),
7079    ?TC_TRY(socket_monitor2_manys,
7080            fun() -> do_socket_monitor2_manys(Config) end).
7081
7082do_socket_monitor2_manys(Config) ->
7083    ?P("begin"),
7084    Type         = ?SOCKET_TYPE(Config),
7085    Self         = self(),
7086    ?P("spawn owner"),
7087    {OwnerPid, OwnerMon} =
7088	spawn_monitor(fun() ->
7089			      ?P("[owner] create (listen) socket(s)"),
7090			      {ok, L1} = ?LISTEN(Config),
7091			      {ok, L2} = ?LISTEN(Config),
7092			      {ok, L3} = ?LISTEN(Config),
7093			      {ok, L4} = ?LISTEN(Config),
7094			      {ok, L5} = ?LISTEN(Config),
7095			      ?P("[owner] send (listen) socket(s) to ctrl"),
7096			      Self ! {socket, [L1, L2, L3, L4, L5]},
7097			      ?P("[owner] ready"),
7098			      receive
7099				  {Self, die} ->
7100				      exit(normal)
7101			      end
7102		      end),
7103    ?P("await sockets (from owner)"),
7104    LSocks = receive
7105		 {socket, Socks} ->
7106		     ?P("received socket(s) from owner"),
7107		     Socks;
7108		 {'DOWN', OwnerMon, process, OwnerPid, OwnerReason} ->
7109		     ?P("received unexpected owner termination: "
7110			"~n   ~p", [OwnerReason]),
7111		     ct:fail({unexpected_owner_termination, OwnerReason})
7112	     end,
7113    F  = fun(S, Fun) -> spawn_monitor(fun() -> Fun(S, Self) end) end,
7114    F1 = fun(Sockets, Parent) when is_list(Sockets) andalso is_pid(Parent) ->
7115		 ?P("[client] create monitor(s)"),
7116		 Monitors = [{inet:monitor(Socket), Socket} ||
7117				Socket <- Sockets],
7118		 ?P("[client] announce ready"),
7119		 Parent ! {self(), ready},
7120		 sm_await_socket_down2(Monitors, Type)
7121	 end,
7122    ?P("spawn client"),
7123    {Pid1, Mon1} = F(LSocks, F1),
7124    ?P("await client ready"),
7125    sm_await_client_ready(Pid1),
7126    ?P("kill owner"),
7127    exit(OwnerPid, kill),
7128    ?P("await owner (~p) termination", [OwnerPid]),
7129    sm_await_down(OwnerPid, OwnerMon, killed),
7130    ?P("await client termination"),
7131    sm_await_down(Pid1, Mon1, ok),
7132    ?P("done"),
7133    ok.
7134
7135
7136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7137
7138%% This is the most basic of tests.
7139%% Spawn a process that creates a (listen) socket, then spawns (client)
7140%% processes that create monitors to it...
7141socket_monitor2_manyc(Config) when is_list(Config) ->
7142    ct:timetrap(?MINS(1)),
7143    ?TC_TRY(socket_monitor2_manyc,
7144            fun() -> do_socket_monitor2_manyc(Config) end).
7145
7146do_socket_monitor2_manyc(Config) ->
7147    ?P("begin"),
7148    Type         = ?SOCKET_TYPE(Config),
7149    Self         = self(),
7150    {OwnerPid, OwnerMon} =
7151	spawn_monitor(fun() ->
7152			      {ok, L} = ?LISTEN(Config),
7153			      Self ! {socket, L},
7154			      receive
7155				  {Self, die} ->
7156				      exit(normal)
7157			      end
7158		      end),
7159    LSock1 = receive
7160		 {socket, L} ->
7161		     ?P("received socket from owner"),
7162		     L;
7163		 {'DOWN', OwnerMon, process, OwnerPid, OwnerReason} ->
7164		     ?P("received unexpected owner termination: "
7165			"~n   ~p", [OwnerReason]),
7166		     ct:fail({unexpected_owner_termination, OwnerReason})
7167	     end,
7168    F  = fun(S, Fun, Name) ->
7169		 spawn_monitor(fun() -> Fun(S, Name, Self) end)
7170	 end,
7171    F1 = fun(Socket, Name, Parent) when is_list(Name) andalso is_pid(Parent) ->
7172		 ?P("[~s] create monitor", [Name]),
7173		 MRef = inet:monitor(Socket),
7174		 Parent ! {self(), ready},
7175		 sm_await_socket_down(MRef, Socket, Type, Name)
7176	 end,
7177    ?P("spawn client(s)"),
7178    {Pid1, Mon1} = F(LSock1, F1, "client1"),
7179    {Pid2, Mon2} = F(LSock1, F1, "client2"),
7180    {Pid3, Mon3} = F(LSock1, F1, "client3"),
7181    {Pid4, Mon4} = F(LSock1, F1, "client4"),
7182    {Pid5, Mon5} = F(LSock1, F1, "client5"),
7183    ?P("await client(s) ready"),
7184    sm_await_client_ready(Pid1, "client1"),
7185    sm_await_client_ready(Pid2, "client2"),
7186    sm_await_client_ready(Pid3, "client3"),
7187    sm_await_client_ready(Pid4, "client4"),
7188    sm_await_client_ready(Pid5, "client5"),
7189    ?P("kill owner"),
7190    exit(OwnerPid, kill),
7191    ?P("await owner termination"),
7192    sm_await_down(OwnerPid, OwnerMon, killed),
7193    ?P("await client(s) termination"),
7194    sm_await_down(Pid1, Mon1, ok),
7195    sm_await_down(Pid2, Mon2, ok),
7196    sm_await_down(Pid3, Mon3, ok),
7197    sm_await_down(Pid4, Mon4, ok),
7198    sm_await_down(Pid5, Mon5, ok),
7199    ?P("done"),
7200    ok.
7201
7202
7203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7204
7205%% This is the most basic of tests.
7206%% Spawn a process that creates a (listen) socket, then spawns (client)
7207%% processes that create monitors to it...
7208otp_17492(Config) when is_list(Config) ->
7209    ct:timetrap(?MINS(1)),
7210    ?TC_TRY(otp_17492, fun() -> do_otp_17492(Config) end).
7211
7212do_otp_17492(Config) ->
7213    ?P("begin"),
7214
7215    Self = self(),
7216
7217    ?P("try create listen socket"),
7218    {ok, L} = ?LISTEN(Config, 0, []),
7219
7220    ?P("try get (created) listen socket info"),
7221    try inet:info(L) of
7222	#{owner := Owner} = Info when is_pid(Owner) andalso (Owner =:= Self) ->
7223	    ?P("(created) Listen socket info: ~p", [Info]);
7224	OBadInfo ->
7225	    ?P("(created) listen socket info: ~p", [OBadInfo]),
7226	    (catch gen_tcp:close(L)),
7227	    ct:fail({invalid_created_info, OBadInfo})
7228    catch
7229	OC:OE:OS ->
7230	    ?P("Failed get (created) listen socket info: "
7231	       "~n   Class: ~p"
7232	       "~n   Error: ~p"
7233	       "~n   Stack: ~p", [OC, OE, OS]),
7234	    (catch gen_tcp:close(L)),
7235	    ct:fail({unexpected_created_info_result, {OC, OE, OS}})
7236    end,
7237
7238    ?P("try close (listen) socket"),
7239    ok = gen_tcp:close(L),
7240
7241    ?P("try get (closed) listen socket info"),
7242    try inet:info(L) of
7243	#{states := [closed]} = CInfo when is_port(L) ->
7244	    ?P("(closed) listen socket info: "
7245	       "~n   ~p", [CInfo]);
7246	#{rstates := [closed], wstates := [closed]} = CInfo ->
7247	    ?P("(closed) listen socket info: "
7248	       "~n   ~p", [CInfo]);
7249	CBadInfo ->
7250	    ?P("(closed) listen socket info: ~p", [CBadInfo]),
7251	    ct:fail({invalid_closed_info, CBadInfo})
7252    catch
7253	CC:CE:CS ->
7254	    ?P("Failed get (closed) listen socket info: "
7255	       "~n   Class: ~p"
7256	       "~n   Error: ~p"
7257	       "~n   Stack: ~p", [CC, CE, CS]),
7258	    (catch gen_tcp:close(L)),
7259	    ct:fail({unexpected_closed_info_result, {CC, CE, CS}})
7260    end,
7261
7262    ?P("done"),
7263    ok.
7264
7265
7266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7267
7268pi(Item) ->
7269    {Item, Val} = process_info(self(), Item),
7270    Val.
7271
7272
7273%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7274
7275send_failed_str(Reason) ->
7276    ?F("Send failed: ~w", [Reason]).
7277
7278connect_failed_str(Reason) ->
7279    ?F("Connect failed: ~w", [Reason]).
7280
7281listen_failed_str(Reason) ->
7282    ?F("Listen failed: ~w", [Reason]).
7283
7284accept_failed_str(Reason) ->
7285    ?F("Accept failed: ~w", [Reason]).
7286
7287port_failed_str(Reason) ->
7288    ?F("Port failed: ~w", [Reason]).
7289