From bfb350ecc30d44e64ed75512690a0e4fbbb6bc2a Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Tue, 20 Sep 2011 09:27:02 +0200
Subject: erts,kernel: Rename operations common to TCP and SCTP
---
lib/kernel/src/inet_int.hrl | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 6f1688c6a2..9154e90e1f 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -83,15 +83,17 @@
-define(INET_REQ_IFSET, 23).
-define(INET_REQ_SUBSCRIBE, 24).
-define(INET_REQ_GETIFADDRS, 25).
+-define(INET_REQ_ACCEPT, 26).
+-define(INET_REQ_LISTEN, 27).
%% TCP requests
--define(TCP_REQ_ACCEPT, 40).
--define(TCP_REQ_LISTEN, 41).
+%%-define(TCP_REQ_ACCEPT, 40). MOVED
+%%-define(TCP_REQ_LISTEN, 41). MERGED
-define(TCP_REQ_RECV, 42).
-define(TCP_REQ_UNRECV, 43).
-define(TCP_REQ_SHUTDOWN, 44).
%% UDP and SCTP requests
-define(PACKET_REQ_RECV, 60).
--define(SCTP_REQ_LISTEN, 61).
+%%-define(SCTP_REQ_LISTEN, 61). MERGED
-define(SCTP_REQ_BINDX, 62). %% Multi-home SCTP bind
%% subscribe codes, INET_REQ_SUBSCRIBE
--
cgit v1.2.3
From faea8584311fcb5365c585280e5e9b2364ed121e Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Fri, 2 Sep 2011 10:38:39 +0200
Subject: erts,kernel: Add type stream sockets to SCTP
---
lib/kernel/doc/src/gen_sctp.xml | 16 ++++++++++------
lib/kernel/src/gen_sctp.erl | 14 ++++++++++++--
lib/kernel/src/inet.erl | 27 ++++++++++++++++-----------
lib/kernel/src/inet6_sctp.erl | 6 +++---
lib/kernel/src/inet6_tcp.erl | 8 ++++----
lib/kernel/src/inet6_udp.erl | 6 +++---
lib/kernel/src/inet_int.hrl | 3 ++-
lib/kernel/src/inet_sctp.erl | 6 +++---
lib/kernel/src/inet_tcp.erl | 8 ++++----
lib/kernel/src/inet_udp.erl | 4 ++--
10 files changed, 59 insertions(+), 39 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index 688cd0f78f..b9f23674f0 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -254,15 +254,19 @@
-
+
+
Set up a socket to listen.
Sets up a socket to listen on the IP address and port number
- it is bound to. IsServer must be true
- or false.
- In the contrast to TCP, in SCTP there is no listening queue length.
- If IsServer is true the socket accepts new associations, i.e.
- it will become an SCTP server socket.
+ it is bound to.
+ For type seqpacket sockets (the default)
+ IsServer must be true or false.
+ In the contrast to TCP, in SCTP there is no listening queue length.
+ If IsServer is true the socket accepts new associations, i.e.
+ it will become an SCTP server socket.
+ For type stream sockets Backlog defines
+ the backlog queue length just like in TCP.
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 6cebb7ab97..3351796481 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -109,9 +109,11 @@ open() ->
| {ifaddr,IP}
| inet:address_family()
| {port,Port}
+ | {type,SockType}
| option(),
IP :: inet:ip_address() | any | loopback,
Port :: inet:port_number(),
+ SockType :: seqpacket | stream,
Socket :: sctp_socket().
open(Opts) when is_list(Opts) ->
@@ -134,9 +136,11 @@ open(X) ->
| {ifaddr,IP}
| inet:address_family()
| {port,Port}
+ | {type,SockType}
| option(),
IP :: inet:ip_address() | any | loopback,
Port :: inet:port_number(),
+ SockType :: seqpacket | stream,
Socket :: sctp_socket().
open(Port, Opts) when is_integer(Port), is_list(Opts) ->
@@ -161,12 +165,18 @@ close(S) ->
-spec listen(Socket, IsServer) -> ok | {error, Reason} when
Socket :: sctp_socket(),
IsServer :: boolean(),
+ Reason :: term();
+ (Socket, Backlog) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ Backlog :: integer(),
Reason :: term().
-listen(S, Flag) when is_port(S), is_boolean(Flag) ->
+listen(S, Backlog)
+ when is_port(S), is_boolean(Backlog);
+ is_port(S), is_integer(Backlog) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
- Mod:listen(S, Flag);
+ Mod:listen(S, Backlog);
Error -> Error
end;
listen(S, Flag) ->
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 48a6f3db65..22056e6974 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -36,7 +36,7 @@
-export([i/0, i/1, i/2]).
--export([getll/1, getfd/1, open/7, fdopen/5]).
+-export([getll/1, getfd/1, open/8, fdopen/6]).
-export([tcp_controlling_process/2, udp_controlling_process/2,
tcp_close/1, udp_close/1]).
@@ -115,7 +115,8 @@
'mtu' | 'netmask' | 'flags' |'hwaddr'.
-type address_family() :: 'inet' | 'inet6'.
--type protocol_option() :: 'tcp' | 'udp' | 'sctp'.
+-type socket_protocol() :: 'tcp' | 'udp' | 'sctp'.
+-type socket_type() :: 'stream' | 'dgram' | 'seqpacket'.
-type stat_option() ::
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
@@ -748,6 +749,8 @@ sctp_opt([Opt|Opts], Mod, R, As) ->
sctp_opt(Opts, Mod, R#sctp_opts{port=P}, As);
Error -> Error
end;
+ {type,Type} when Type =:= seqpacket; Type =:= stream ->
+ sctp_opt(Opts, Mod, R#sctp_opts{type=Type}, As);
binary -> sctp_opt (Opts, Mod, R, As, mode, binary);
list -> sctp_opt (Opts, Mod, R, As, mode, list);
{sctp_module,_} -> sctp_opt (Opts, Mod, R, As); % Done with
@@ -996,13 +999,14 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
Addr :: ip_address(),
Port :: port_number(),
Opts :: [socket_setopt()],
- Protocol :: protocol_option(),
- Family :: 'inet' | 'inet6',
+ Protocol :: socket_protocol(),
+ Family :: address_family(),
+ Type :: socket_type(),
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
-open(Fd, Addr, Port, Opts, Protocol, Family, Module) when Fd < 0 ->
- case prim_inet:open(Protocol, Family) of
+open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 ->
+ case prim_inet:open(Protocol, Family, Type) of
{ok,S} ->
case prim_inet:setopts(S, Opts) of
ok ->
@@ -1029,18 +1033,19 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Module) when Fd < 0 ->
Error ->
Error
end;
-open(Fd, _Addr, _Port, Opts, Protocol, Family, Module) ->
- fdopen(Fd, Opts, Protocol, Family, Module).
+open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) ->
+ fdopen(Fd, Opts, Protocol, Family, Type, Module).
-spec fdopen(Fd :: non_neg_integer(),
Opts :: [socket_setopt()],
- Protocol :: protocol_option(),
+ Protocol :: socket_protocol(),
Family :: address_family(),
+ Type :: socket_type(),
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
-fdopen(Fd, Opts, Protocol, Family, Module) ->
- case prim_inet:fdopen(Protocol, Fd, Family) of
+fdopen(Fd, Opts, Protocol, Family, Type, Module) ->
+ case prim_inet:fdopen(Protocol, Family, Type, Fd) of
{ok, S} ->
case prim_inet:setopts(S, Opts) of
ok ->
diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl
index 5bf3fca647..f034535ba0 100644
--- a/lib/kernel/src/inet6_sctp.erl
+++ b/lib/kernel/src/inet6_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -54,8 +54,8 @@ translate_ip(IP) ->
open(Opts) ->
case inet:sctp_options(Opts, ?MODULE) of
- {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,opts=SOs}} ->
- inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, ?MODULE);
+ {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,type=Type,opts=SOs}} ->
+ inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, Type, ?MODULE);
Error -> Error
end.
diff --git a/lib/kernel/src/inet6_tcp.erl b/lib/kernel/src/inet6_tcp.erl
index cc45f6c7f6..c714b2bee0 100644
--- a/lib/kernel/src/inet6_tcp.erl
+++ b/lib/kernel/src/inet6_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -93,7 +93,7 @@ do_connect(Addr = {A,B,C,D,E,F,G,H}, Port, Opts, Time) when
port=BPort,
opts=SockOpts}}
when ?ip6(Ab,Bb,Cb,Db,Eb,Fb,Gb,Hb), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,stream,?MODULE) of
{ok, S} ->
case prim_inet:connect(S, Addr, Port, Time) of
ok -> {ok,S};
@@ -115,7 +115,7 @@ listen(Port, Opts) ->
port=BPort,
opts=SockOpts}=R}
when ?ip6(A,B,C,D,E,F,G,H), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet6,stream,?MODULE) of
{ok, S} ->
case prim_inet:listen(S, R#listen_opts.backlog) of
ok -> {ok, S};
@@ -149,5 +149,5 @@ accept(L,Timeout) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, tcp, inet6, ?MODULE).
+ inet:fdopen(Fd, Opts, tcp, inet6, stream, ?MODULE).
diff --git a/lib/kernel/src/inet6_udp.erl b/lib/kernel/src/inet6_udp.erl
index e81d417151..ca43c94211 100644
--- a/lib/kernel/src/inet6_udp.erl
+++ b/lib/kernel/src/inet6_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -45,7 +45,7 @@ open(Port, Opts) ->
port=BPort,
opts=SockOpts}}
when ?ip6(A,B,C,D,E,F,G,H), ?port(BPort) ->
- inet:open(Fd,BAddr,BPort,SockOpts,udp,inet6,?MODULE);
+ inet:open(Fd,BAddr,BPort,SockOpts,udp,inet6,dgram,?MODULE);
{ok, _} -> exit(badarg)
end.
@@ -84,4 +84,4 @@ controlling_process(Socket, NewOwner) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, udp, inet6, ?MODULE).
+ inet:fdopen(Fd, Opts, udp, inet6, dgram, ?MODULE).
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 9154e90e1f..735347b4b1 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -29,7 +29,7 @@
-define(INET_AF_ANY, 3). % Fake for ANY in any address family
-define(INET_AF_LOOPBACK, 4). % Fake for LOOPBACK in any address family
-%% type codes (gettype, INET_REQ_GETTYPE)
+%% type codes to open and gettype - INET_REQ_GETTYPE
-define(INET_TYPE_STREAM, 1).
-define(INET_TYPE_DGRAM, 2).
-define(INET_TYPE_SEQPACKET, 3).
@@ -401,6 +401,7 @@
ifaddr,
port = 0,
fd = -1,
+ type = seqpacket,
opts = [{mode, binary},
{buffer, ?SCTP_DEF_BUFSZ},
{sndbuf, ?SCTP_DEF_BUFSZ},
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index de74b573bd..e670dcfdad 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -53,8 +53,8 @@ translate_ip(IP) ->
open(Opts) ->
case inet:sctp_options(Opts, ?MODULE) of
- {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,opts=SOs}} ->
- inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, ?MODULE);
+ {ok,#sctp_opts{fd=Fd,ifaddr=Addr,port=Port,type=Type,opts=SOs}} ->
+ inet:open(Fd, Addr, Port, SOs, sctp, ?FAMILY, Type, ?MODULE);
Error -> Error
end.
diff --git a/lib/kernel/src/inet_tcp.erl b/lib/kernel/src/inet_tcp.erl
index 6dadccd6a9..4c2db16ce3 100644
--- a/lib/kernel/src/inet_tcp.erl
+++ b/lib/kernel/src/inet_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -95,7 +95,7 @@ do_connect({A,B,C,D}, Port, Opts, Time) when ?ip(A,B,C,D), ?port(Port) ->
port=BPort,
opts=SockOpts}}
when ?ip(Ab,Bb,Cb,Db), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,stream,?MODULE) of
{ok, S} ->
case prim_inet:connect(S, {A,B,C,D}, Port, Time) of
ok -> {ok,S};
@@ -117,7 +117,7 @@ listen(Port, Opts) ->
port=BPort,
opts=SockOpts}=R}
when ?ip(A,B,C,D), ?port(BPort) ->
- case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,?MODULE) of
+ case inet:open(Fd,BAddr,BPort,SockOpts,tcp,inet,stream,?MODULE) of
{ok, S} ->
case prim_inet:listen(S, R#listen_opts.backlog) of
ok -> {ok, S};
@@ -150,4 +150,4 @@ accept(L,Timeout) ->
%% Create a port/socket from a file descriptor
%%
fdopen(Fd, Opts) ->
- inet:fdopen(Fd, Opts, tcp, inet, ?MODULE).
+ inet:fdopen(Fd, Opts, tcp, inet, stream, ?MODULE).
diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl
index 60bd96f332..80d930fe10 100644
--- a/lib/kernel/src/inet_udp.erl
+++ b/lib/kernel/src/inet_udp.erl
@@ -52,7 +52,7 @@ open(Port, Opts) ->
ifaddr=BAddr={A,B,C,D},
port=BPort,
opts=SockOpts}} when ?ip(A,B,C,D), ?port(BPort) ->
- inet:open(Fd,BAddr,BPort,SockOpts,udp,inet,?MODULE);
+ inet:open(Fd,BAddr,BPort,SockOpts,udp,inet,dgram,?MODULE);
{ok, _} -> exit(badarg)
end.
@@ -93,7 +93,7 @@ controlling_process(Socket, NewOwner) ->
fdopen(Fd, Opts) ->
inet:fdopen(Fd,
optuniquify([{recbuf, ?RECBUF} | Opts]),
- udp, inet, ?MODULE).
+ udp, inet, dgram, ?MODULE).
%% Remove all duplicate options from an option list.
--
cgit v1.2.3
From 3b81d47f7f4415661d4371989637374567e2ab2a Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Fri, 2 Sep 2011 10:37:08 +0200
Subject: kernel: Add tests for SCTP stream sockets
Also fix tests for new prim_inet:open function.
---
lib/kernel/test/erl_boot_server_SUITE.erl | 2 +-
lib/kernel/test/gen_sctp_SUITE.erl | 100 ++++++++++++++++++++++++++++--
2 files changed, 97 insertions(+), 5 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/erl_boot_server_SUITE.erl b/lib/kernel/test/erl_boot_server_SUITE.erl
index cea3715ce4..bb64c01058 100644
--- a/lib/kernel/test/erl_boot_server_SUITE.erl
+++ b/lib/kernel/test/erl_boot_server_SUITE.erl
@@ -346,7 +346,7 @@ good_hosts(_Config) ->
[GoodHost1, GoodHost2, GoodHost3].
open_udp() ->
- ?line {ok, S} = prim_inet:open(udp, inet),
+ ?line {ok, S} = prim_inet:open(udp, inet, dgram),
?line ok = prim_inet:setopts(S, [{mode,list},{active,true},
{deliver,term},{broadcast,true}]),
?line {ok,_} = prim_inet:bind(S, {0,0,0,0}, 0),
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 1b534a5fc4..1cf3d659d4 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -30,14 +30,15 @@
-export(
[basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
- xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1]).
+ xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
+ basic_stream/1, xfer_stream_min/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, api_open_close, api_listen, api_connect_init,
- api_opts, xfer_min, xfer_active, def_sndrcvinfo,
- implicit_inet6].
+ api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
+ basic_stream, xfer_stream_min].
groups() ->
[].
@@ -96,7 +97,7 @@ xfer_min(Config) when is_list(Config) ->
?line Stream = 0,
?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
?line Loopback = {127,0,0,1},
- ?line {ok,Sb} = gen_sctp:open(),
+ ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
?line {ok,Pb} = inet:port(Sb),
?line ok = gen_sctp:listen(Sb, true),
@@ -654,6 +655,97 @@ implicit_inet6(S1, Addr) ->
end,
?line ok = gen_sctp:close(S2).
+basic_stream(doc) ->
+ "Hello world stream socket";
+basic_stream(suite) ->
+ [];
+basic_stream(Config) when is_list(Config) ->
+ ?line {ok,S} = gen_sctp:open([{type,stream}]),
+ ?line ok = gen_sctp:listen(S, true),
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:listen(S, 10) end),
+ ?line ok = gen_sctp:close(S),
+ ok.
+
+xfer_stream_min(doc) ->
+ "Minimal data transfer";
+xfer_stream_min(suite) ->
+ [];
+xfer_stream_min(Config) when is_list(Config) ->
+ ?line Stream = 0,
+ ?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
+ ?line Loopback = {127,0,0,1},
+ ?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
+ ?line {ok,Pb} = inet:port(Sb),
+ ?line ok = gen_sctp:listen(Sb, true),
+
+ ?line {ok,Sa} = gen_sctp:open([{type,stream}]),
+ ?line {ok,Pa} = inet:port(Sa),
+ ?line {ok,#sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId}} =
+ gen_sctp:connect(Sa, Loopback, Pb, []),
+ ?line {ok,{Loopback,
+ Pa,[],
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=SbAssocId}}} =
+ gen_sctp:recv(Sb, infinity),
+ ?line SaOutboundStreams = SbInboundStreams,
+ ?line SbOutboundStreams = SaInboundStreams,
+ ?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
+ ?line case gen_sctp:recv(Sb, infinity) of
+ {ok,{Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data}} -> ok;
+ {ok,{Loopback,
+ Pa,[],
+ #sctp_paddr_change{addr = {Loopback,_},
+ state = addr_available,
+ error = 0,
+ assoc_id = SbAssocId}}} ->
+ {ok,{Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data}} = gen_sctp:recv(Sb, infinity)
+ end,
+ ?line ok =
+ do_from_other_process(
+ fun () -> gen_sctp:send(Sb, SbAssocId, 0, Data) end),
+ ?line {ok,{Loopback,
+ Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data}} =
+ gen_sctp:recv(Sa, infinity),
+ %%
+ ?line ok = gen_sctp:close(Sa),
+ ?line {ok,{Loopback,
+ Pa,[],
+ #sctp_shutdown_event{assoc_id=SbAssocId}}} =
+ gen_sctp:recv(Sb, infinity),
+ ?line {ok,{Loopback,
+ Pa,[],
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}}} =
+ gen_sctp:recv(Sb, infinity),
+ ?line ok = gen_sctp:close(Sb),
+
+ ?line receive
+ Msg -> test_server:fail({received,Msg})
+ after 17 -> ok
+ end,
+ ok.
+
do_from_other_process(Fun) ->
--
cgit v1.2.3
From 1cc7485467b1b4e9efd15259b58e1182d2e9723c Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Fri, 2 Sep 2011 10:29:58 +0200
Subject: erts,kernel: Implement gen_sctp:peeloff/2
---
lib/kernel/src/gen_sctp.erl | 18 +++++++++++++++++-
lib/kernel/src/inet.erl | 16 ++++++++++++----
lib/kernel/src/inet6_sctp.erl | 11 ++++++++++-
lib/kernel/src/inet_int.hrl | 3 ++-
lib/kernel/src/inet_sctp.erl | 11 ++++++++++-
5 files changed, 51 insertions(+), 8 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index 3351796481..77ca26b845 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -27,7 +27,8 @@
-include("inet_sctp.hrl").
-export([open/0,open/1,open/2,close/1]).
--export([listen/2,connect/4,connect/5,connect_init/4,connect_init/5]).
+-export([listen/2,peeloff/2]).
+-export([connect/4,connect/5,connect_init/4,connect_init/5]).
-export([eof/2,abort/2]).
-export([send/3,send/4,recv/1,recv/2]).
-export([error_string/1]).
@@ -182,6 +183,21 @@ listen(S, Backlog)
listen(S, Flag) ->
erlang:error(badarg, [S,Flag]).
+-spec peeloff(Socket, Assoc) -> {ok, NewSocket} | {error, Reason} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{} | assoc_id(),
+ NewSocket :: sctp_socket(),
+ Reason :: term().
+
+peeloff(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
+ peeloff(S, AssocId);
+peeloff(S, AssocId) when is_port(S), is_integer(AssocId) ->
+ case inet_db:lookup_socket(S) of
+ {ok,Mod} ->
+ Mod:peeloff(S, AssocId);
+ Error -> Error
+ end.
+
-spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, inet:posix()} when
Socket :: sctp_socket(),
Addr :: inet:ip_address() | inet:hostname(),
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 22056e6974..b60c68e3a1 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1061,18 +1061,24 @@ fdopen(Fd, Opts, Protocol, Family, Type, Module) ->
%% socket stat
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-i() -> i(tcp), i(udp).
+i() -> i(tcp), i(udp), i(sctp).
i(Proto) -> i(Proto, [port, module, recv, sent, owner,
- local_address, foreign_address, state]).
+ local_address, foreign_address, state, type]).
i(tcp, Fs) ->
ii(tcp_sockets(), Fs, tcp);
i(udp, Fs) ->
- ii(udp_sockets(), Fs, udp).
+ ii(udp_sockets(), Fs, udp);
+i(sctp, Fs) ->
+ ii(sctp_sockets(), Fs, sctp).
ii(Ss, Fs, Proto) ->
- LLs = [h_line(Fs) | info_lines(Ss, Fs, Proto)],
+ LLs =
+ case info_lines(Ss, Fs, Proto) of
+ [] -> [];
+ InfoLines -> [h_line(Fs) | InfoLines]
+ end,
Maxs = foldl(
fun(Line,Max0) -> smax(Max0,Line) end,
duplicate(length(Fs),0),LLs),
@@ -1140,6 +1146,7 @@ info(S, F, Proto) ->
case prim_inet:gettype(S) of
{ok,{_,stream}} -> "STREAM";
{ok,{_,dgram}} -> "DGRAM";
+ {ok,{_,seqpacket}} -> "SEQPACKET";
_ -> " "
end;
fd ->
@@ -1191,6 +1198,7 @@ fmt_port(N, Proto) ->
%% Return a list of all tcp sockets
tcp_sockets() -> port_list("tcp_inet").
udp_sockets() -> port_list("udp_inet").
+sctp_sockets() -> port_list("sctp_inet").
%% Return all ports having the name 'Name'
port_list(Name) ->
diff --git a/lib/kernel/src/inet6_sctp.erl b/lib/kernel/src/inet6_sctp.erl
index f034535ba0..c47483bbdd 100644
--- a/lib/kernel/src/inet6_sctp.erl
+++ b/lib/kernel/src/inet6_sctp.erl
@@ -32,7 +32,8 @@
-define(FAMILY, inet6).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
+-export([open/1,close/1,listen/2,peeloff/2,connect/5]).
+-export([sendmsg/3,send/4,recv/2]).
@@ -65,6 +66,14 @@ close(S) ->
listen(S, Flag) ->
prim_inet:listen(S, Flag).
+peeloff(S, AssocId) ->
+ case prim_inet:peeloff(S, AssocId) of
+ {ok, NewS}=Result ->
+ inet_db:register_socket(NewS, ?MODULE),
+ Result;
+ Error -> Error
+ end.
+
connect(S, Addr, Port, Opts, Timer) ->
inet_sctp:connect(S, Addr, Port, Opts, Timer).
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 735347b4b1..f8984b13fe 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -95,6 +95,7 @@
-define(PACKET_REQ_RECV, 60).
%%-define(SCTP_REQ_LISTEN, 61). MERGED
-define(SCTP_REQ_BINDX, 62). %% Multi-home SCTP bind
+-define(SCTP_REQ_PEELOFF, 63).
%% subscribe codes, INET_REQ_SUBSCRIBE
-define(INET_SUBS_EMPTY_OUT_Q, 1).
@@ -102,7 +103,7 @@
%% reply codes for *_REQ_*
-define(INET_REP_ERROR, 0).
-define(INET_REP_OK, 1).
--define(INET_REP_SCTP, 2).
+-define(INET_REP, 2).
%% INET, TCP and UDP options:
-define(INET_OPT_REUSEADDR, 0).
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index e670dcfdad..8482dd1b12 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_sctp.erl
@@ -31,7 +31,8 @@
-define(FAMILY, inet).
-export([getserv/1,getaddr/1,getaddr/2,translate_ip/1]).
--export([open/1,close/1,listen/2,connect/5,sendmsg/3,send/4,recv/2]).
+-export([open/1,close/1,listen/2,peeloff/2,connect/5]).
+-export([sendmsg/3,send/4,recv/2]).
@@ -64,6 +65,14 @@ close(S) ->
listen(S, Flag) ->
prim_inet:listen(S, Flag).
+peeloff(S, AssocId) ->
+ case prim_inet:peeloff(S, AssocId) of
+ {ok, NewS}=Result ->
+ inet_db:register_socket(NewS, ?MODULE),
+ Result;
+ Error -> Error
+ end.
+
%% A non-blocking connect is implemented when the initial call is to
%% gen_sctp:connect_init which passes the value nowait as the Timer
connect(S, Addr, Port, Opts, Timer) ->
--
cgit v1.2.3
From 5895bb8d7bde52972f74f6b51748230982f762f7 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Fri, 2 Sep 2011 16:18:13 +0200
Subject: kernel: Add tests for gen_sctp:peeloff/2
---
lib/kernel/test/gen_sctp_SUITE.erl | 200 ++++++++++++++++++++++++++++++++++++-
1 file changed, 197 insertions(+), 3 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 1cf3d659d4..f422ffe442 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -31,14 +31,14 @@
[basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
- basic_stream/1, xfer_stream_min/1]).
+ basic_stream/1, xfer_stream_min/1, peeloff/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, api_open_close, api_listen, api_connect_init,
api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
- basic_stream, xfer_stream_min].
+ basic_stream, xfer_stream_min, peeloff].
groups() ->
[].
@@ -418,7 +418,11 @@ setopt(S, Opt, Val) ->
inet:setopts(S, [{Opt,Val}]).
ok({ok,X}) ->
- io:format("OK: ~p~n", [X]),
+ io:format("OK[~w]: ~p~n", [self(),X]),
+ X.
+
+log(X) ->
+ io:format("LOG[~w]: ~p~n", [self(),X]),
X.
flush() ->
@@ -773,3 +777,193 @@ do_from_other_process(Fun) ->
{'DOWN',Mref,_,_,Reason} ->
erlang:exit(Reason)
end.
+
+
+
+peeloff(doc) ->
+ "Peel off an SCTP stream socket";
+peeloff(suite) ->
+ [];
+peeloff(Config) when is_list(Config) ->
+ ?line Addr = {127,0,0,1},
+ ?line Stream = 0,
+ ?line Timeout = 333,
+ ?line S1 = socket_start(Addr, Timeout),
+ ?line P1 = socket_call(S1, port),
+ ?line Socket1 = socket_call(S1, socket),
+ ?line ok = socket_call(S1, {listen,true}),
+ ?line S2 = socket_start(Addr, Timeout),
+ ?line P2 = socket_call(S2, port),
+ ?line Socket2 = socket_call(S2, socket),
+ %%
+ ?line H_a = socket_req(S1, recv_assoc),
+ ?line {S2Ai,Sa,Sb} = socket_call(S2, {connect,Addr,P1,[]}),
+ ?line {S1Ai,Sb,Sa,Addr,P2} = socket_resp(H_a),
+ %%
+ ?line H_b = socket_req(S1, recv),
+ ?line ok = socket_call(S2, {send,S2Ai,Stream,<<"Data H_b">>}),
+ ?line {Addr,P2,S1Ai,Stream,<<"Data H_b">>} = socket_resp(H_b),
+ ?line H_c = socket_req(S1, {recv,Socket2}),
+ ?line ok =
+ socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Data H_c">>}),
+ ?line {Addr,P1,S2Ai,Stream,<<"Data H_c">>} = socket_resp(H_c),
+ %%
+ ?line S3 = socket_peeloff(Socket1, S1Ai, Timeout),
+ ?line P3 = socket_call(S3, port),
+ ?line Socket3 = socket_call(S3, socket),
+ ?line S3Ai = S1Ai,
+ %%
+ ?line H_d = socket_req(S2, recv),
+ ?line ok = socket_call(S3, {send,S3Ai,Stream,<<"Data H_d">>}),
+ ?line {Addr,P3,S2Ai,Stream,<<"Data H_d">>} = socket_resp(H_d),
+ ?line ok = socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Data S2">>}),
+ ?line {Addr,P2,S3Ai,Stream,<<"Data S2">>} = socket_call(S2, {recv,Socket3}),
+ %%
+ ?line inet:i(sctp),
+ ?line ok = socket_stop(S1),
+ ?line ok = socket_stop(S2),
+ ?line {Addr,P2,[],#sctp_shutdown_event{assoc_id=S1Ai}} =
+ ok(socket_stop(S3)),
+ ok.
+
+%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% socket gen_server ultra light
+
+socket_peeloff(Socket, AssocId, Timeout) ->
+ Starter =
+ fun () ->
+ {ok,NewSocket} =
+ gen_sctp:peeloff(Socket, AssocId),
+ NewSocket
+ end,
+ socket_starter(Starter, Timeout).
+
+socket_start(Addr, Timeout) ->
+ Starter =
+ fun () ->
+ {ok,Socket} =
+ gen_sctp:open([{type,seqpacket},{ifaddr,Addr}]),
+ Socket
+ end,
+ socket_starter(Starter, Timeout).
+
+socket_starter(Starter, Timeout) ->
+ Parent = self(),
+ Owner =
+ spawn_link(
+ fun () ->
+ socket_starter(Starter(), Timeout, Parent)
+ end),
+ io:format("Started socket ~w.~n", [Owner]),
+ Owner.
+
+socket_starter(Socket, Timeout, Parent) ->
+ try
+ Handler = socket_handler(Socket, Timeout),
+ socket_loop(Socket, Timeout, Parent, Handler)
+ catch
+ Class:Reason ->
+ Stacktrace = erlang:get_stacktrace(),
+ io:format(?MODULE_STRING":socket exception ~w:~w at~n"
+ "~p.~n", [Class,Reason,Stacktrace]),
+ erlang:raise(Class, Reason, Stacktrace)
+ end.
+
+socket_loop(Socket, Timeout, Parent, Handler) ->
+ receive
+ {Parent,Ref} -> % socket_stop()
+ Result =
+ case log(gen_sctp:recv(Socket, Timeout)) of
+ {error,timeout} -> ok;
+ R -> R
+ end,
+ ok = gen_sctp:close(Socket),
+ Parent ! {self(),Ref, Result};
+ {Parent,Ref,Msg} ->
+ Parent ! {self(),Ref,Handler(Msg)},
+ socket_loop(Socket, Timeout, Parent, Handler)
+ end.
+
+socket_handler(Socket, Timeout) ->
+ fun ({listen,Listen}) ->
+ gen_sctp:listen(Socket, Listen);
+ (port) ->
+ ok(inet:port(Socket));
+ (socket) ->
+ Socket;
+ (recv_assoc) ->
+ {AssocAddr,AssocPort,[],
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=Os,
+ inbound_streams=Is,
+ assoc_id=AssocId}} =
+ ok(gen_sctp:recv(Socket, infinity)),
+ case log(gen_sctp:recv(Socket, Timeout)) of
+ {ok,AssocAddr,AssocPort,[],
+ #sctp_paddr_change{addr = {AssocAddr,AssocPort},
+ state = addr_available,
+ error = 0,
+ assoc_id = AssocId}} -> ok;
+ {error,timeout} -> ok
+ end,
+ {AssocId,Os,Is,AssocAddr,AssocPort};
+ ({connect,ConAddr,ConPort,ConOpts}) ->
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=Os,
+ inbound_streams=Is,
+ assoc_id=AssocId} =
+ ok(gen_sctp:connect(Socket, ConAddr, ConPort, ConOpts)),
+ case log(gen_sctp:recv(Socket, Timeout)) of
+ {ok,ConAddr,ConPort,[],
+ #sctp_paddr_change{addr = {ConAddr,ConPort},
+ state = addr_available,
+ error = 0,
+ assoc_id = AssocId}} -> ok;
+ {error,timeout} -> ok
+ end,
+ {AssocId,Os,Is};
+ ({send,AssocId,Stream,Data}) ->
+ gen_sctp:send(Socket, AssocId, Stream, Data);
+ ({send,S,AssocId,Stream,Data}) ->
+ gen_sctp:send(S, AssocId, Stream, Data);
+ (recv) ->
+ {Addr,Port,
+ [#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}],Data} =
+ ok(gen_sctp:recv(Socket, infinity)),
+ {Addr,Port,AssocId,Stream,Data};
+ ({recv,S}) ->
+ {Addr,Port,
+ [#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}],Data} =
+ ok(gen_sctp:recv(S, infinity)),
+ {Addr,Port,AssocId,Stream,Data}
+ end.
+
+socket_stop(Handler) ->
+ Mref = erlang:monitor(process, Handler),
+ Handler ! {self(),Mref},
+ receive
+ {Handler,Mref,Result} ->
+ receive {'DOWN',Mref,_,_,_} -> Result end;
+ {'DOWN',Mref,_,_,Error} ->
+ exit(Error)
+ end.
+
+socket_call(Handler, Request) ->
+ socket_resp(socket_req(Handler, Request)).
+
+socket_req(Handler, Request) ->
+ Mref = erlang:monitor(process, Handler),
+ Handler ! {self(),Mref,Request},
+ {Handler,Mref}.
+
+socket_resp({Handler,Mref}) ->
+ receive
+ {'DOWN',Mref,_,_,Error} ->
+ exit(Error);
+ {Handler,Mref,Reply} ->
+ erlang:demonitor(Mref),
+ receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end,
+ Reply
+ end.
--
cgit v1.2.3
From 6dd80f3e9a556dc94ae59280f532e153e463b798 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Fri, 9 Sep 2011 17:40:29 +0200
Subject: erts,kernel: Bugfix - collect fragmented SCTP messages on recv
---
lib/kernel/test/gen_sctp_SUITE.erl | 53 +++++++++++++++++++++++++++++++++++---
1 file changed, 50 insertions(+), 3 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index f422ffe442..9d12c629de 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -31,14 +31,14 @@
[basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
- basic_stream/1, xfer_stream_min/1, peeloff/1]).
+ basic_stream/1, xfer_stream_min/1, peeloff/1, buffers/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, api_open_close, api_listen, api_connect_init,
api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
- basic_stream, xfer_stream_min, peeloff].
+ basic_stream, xfer_stream_min, peeloff, buffers].
groups() ->
[].
@@ -826,6 +826,49 @@ peeloff(Config) when is_list(Config) ->
ok(socket_stop(S3)),
ok.
+
+
+buffers(doc) ->
+ ["Check sndbuf and recbuf behaviour"];
+buffers(suite) ->
+ [];
+buffers(Config) when is_list(Config) ->
+ ?line Limit = 8192,
+ ?line Data = mk_data(Limit),
+ ?line Addr = {127,0,0,1},
+ ?line Stream = 1,
+ ?line Timeout = 333,
+ ?line S1 = socket_start(Addr, Timeout),
+ ?line P1 = socket_call(S1, port),
+ ?line ok = socket_call(S1, {listen,true}),
+ ?line S2 = socket_start(Addr, Timeout),
+ ?line P2 = socket_call(S2, port),
+ %%
+ ?line H_a = socket_req(S1, recv_assoc),
+ ?line {S2Ai,Sa,Sb} = socket_call(S2, {connect,Addr,P1,[]}),
+ ?line {S1Ai,Sb,Sa,Addr,P2} = socket_resp(H_a),
+ %%
+ ?line ok = socket_call(S1, {setopts,[{recbuf,Limit}]}),
+ ?line case socket_call(S1, {getopts,[recbuf]}) of
+ {ok,[{recbuf,RB1}]} when RB1 >= Limit -> ok
+ end,
+ ?line H_b = socket_req(S1, recv),
+ ?line ok = socket_call(S2, {send,S2Ai,Stream,Data}),
+ ?line {Addr,P2,S1Ai,Stream,Data} = socket_resp(H_b),
+ %%
+ ?line ok = socket_stop(S1),
+ ?line {Addr,P1,[],#sctp_shutdown_event{assoc_id=S2Ai}} =
+ ok(socket_stop(S2)),
+ ok.
+
+mk_data(Words) ->
+ mk_data(0, Words, <<>>).
+%%
+mk_data(Words, Words, Bin) ->
+ Bin;
+mk_data(N, Words, Bin) ->
+ mk_data(N+1, Words, <>).
+
%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% socket gen_server ultra light
@@ -937,7 +980,11 @@ socket_handler(Socket, Timeout) ->
{Addr,Port,
[#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}],Data} =
ok(gen_sctp:recv(S, infinity)),
- {Addr,Port,AssocId,Stream,Data}
+ {Addr,Port,AssocId,Stream,Data};
+ ({setopts,Opts}) ->
+ inet:setopts(Socket, Opts);
+ ({getopts,Optnames}) ->
+ inet:getopts(Socket, Optnames)
end.
socket_stop(Handler) ->
--
cgit v1.2.3
From 2831667add272eab3915bcecd9b8f3c89aad78f3 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Tue, 20 Sep 2011 15:56:59 +0000
Subject: kernel: Bugfix - SCTP connect with sndrcvinfo in assoc_change event
On some platforms (FreeBSD) the #sctp_assoc_change{state=comm_up}
event arriving during gen_sctp:connect/4,5 contains ancillary
data #sctp_sndrcvinfo{}. That was not expected by the code.
---
lib/kernel/src/inet_sctp.erl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/src/inet_sctp.erl b/lib/kernel/src/inet_sctp.erl
index 8482dd1b12..2d799d79fa 100644
--- a/lib/kernel/src/inet_sctp.erl
+++ b/lib/kernel/src/inet_sctp.erl
@@ -111,7 +111,7 @@ connect(S, Addr, Port, Opts, Timer) ->
connect_get_assoc(S, Addr, Port, false, Timer) ->
case recv(S, inet:timeout(Timer)) of
- {ok, {Addr, Port, [], #sctp_assoc_change{state=St}=Ev}} ->
+ {ok, {Addr, Port, _, #sctp_assoc_change{state=St}=Ev}} ->
if St =:= comm_up ->
%% Yes, successfully connected, return the whole
%% sctp_assoc_change event (containing, in particular,
@@ -132,7 +132,7 @@ connect_get_assoc(S, Addr, Port, false, Timer) ->
connect_get_assoc(S, Addr, Port, Active, Timer) ->
Timeout = inet:timeout(Timer),
receive
- {sctp,S,Addr,Port,{[],#sctp_assoc_change{state=St}=Ev}} ->
+ {sctp,S,Addr,Port,{_,#sctp_assoc_change{state=St}=Ev}} ->
case Active of
once ->
prim_inet:setopt(S, active, once);
--
cgit v1.2.3
From 4ef92bf4416c988a459a361e71e402c286e889b5 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Tue, 20 Sep 2011 16:01:29 +0000
Subject: kernel: Fix SCTP tests for the FreeBSD protocol stack
---
lib/kernel/test/gen_sctp_SUITE.erl | 506 ++++++++++++++++++++++++-------------
1 file changed, 337 insertions(+), 169 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 9d12c629de..8011c22ce5 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -109,29 +109,44 @@ xfer_min(Config) when is_list(Config) ->
inbound_streams=SaInboundStreams,
assoc_id=SaAssocId}=SaAssocChange} =
gen_sctp:connect(Sa, Loopback, Pb, []),
- ?line {ok,{Loopback,
- Pa,[],
+ ?line {SbAssocId,SaOutboundStreams,SaInboundStreams} =
+ case recv_event(ok(gen_sctp:recv(Sb, infinity))) of
+ {Loopback,Pa,
#sctp_assoc_change{state=comm_up,
error=0,
outbound_streams=SbOutboundStreams,
inbound_streams=SbInboundStreams,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
- ?line SaOutboundStreams = SbInboundStreams,
- ?line SbOutboundStreams = SaInboundStreams,
+ assoc_id=AssocId}} ->
+ {AssocId,SbInboundStreams,SbOutboundStreams};
+ {Loopback,Pa,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=AssocId}} ->
+ {Loopback,Pa,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=AssocId}} =
+ ?line recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ {AssocId,SbInboundStreams,SbOutboundStreams}
+ end,
+
?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
- ?line case gen_sctp:recv(Sb, infinity) of
- {ok,{Loopback,
- Pa,
- [#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data}} -> ok;
- {ok,{Loopback,
- Pa,[],
+ ?line case ok(gen_sctp:recv(Sb, infinity)) of
+ {Loopback,
+ Pa,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SbAssocId}],
+ Data} -> ok;
+ Event1 ->
+ {Loopback,Pa,
#sctp_paddr_change{addr = {Loopback,_},
state = addr_available,
error = 0,
- assoc_id = SbAssocId}}} ->
+ assoc_id = SbAssocId}} =
+ recv_event(Event1),
{ok,{Loopback,
Pa,
[#sctp_sndrcvinfo{stream=Stream,
@@ -139,30 +154,40 @@ xfer_min(Config) when is_list(Config) ->
Data}} = gen_sctp:recv(Sb, infinity)
end,
?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
- ?line {ok,{Loopback,
- Pb,
+ ?line case ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
- Data}} =
- gen_sctp:recv(Sa, infinity),
+ Data} ->
+ ok;
+ Event2 ->
+ {Loopback,Pb,
+ #sctp_paddr_change{addr={_,Pb},
+ state=addr_confirmed,
+ error=0,
+ assoc_id=SaAssocId}} =
+ ?line recv_event(Event2),
+ ?line {Loopback,
+ Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ ok(gen_sctp:recv(Sa, infinity))
+ end,
%%
?line ok = gen_sctp:eof(Sa, SaAssocChange),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_shutdown_event{assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
- ?line {ok,{Loopback,
- Pb,[],
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SaAssocId}}} =
- gen_sctp:recv(Sa, infinity),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
+ ?line {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} =
+ recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ ?line {Loopback,Pb,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(ok(gen_sctp:recv(Sa, infinity))),
+ ?line {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
+ recv_event(ok(gen_sctp:recv(Sb, infinity))),
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
@@ -187,32 +212,51 @@ xfer_active(Config) when is_list(Config) ->
?line {ok,Sa} = gen_sctp:open([{active,true}]),
?line {ok,Pa} = inet:port(Sa),
- ?line {ok,#sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SaOutboundStreams,
- inbound_streams=SaInboundStreams,
- assoc_id=SaAssocId}=SaAssocChange} =
- gen_sctp:connect(Sa, Loopback, Pb, []),
+ ?line ok = gen_sctp:connect_init(Sa, Loopback, Pb, []),
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId} = SaAssocChange =
+ recv_assoc_change(Sa, Loopback, Pb, Timeout),
?line io:format("Sa=~p, Pa=~p, Sb=~p, Pb=~p, SaAssocId=~p, "
"SaOutboundStreams=~p, SaInboundStreams=~p~n",
[Sa,Pa,Sb,Pb,SaAssocId,
SaOutboundStreams,SaInboundStreams]),
- ?line SbAssocId =
- receive
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SbOutboundStreams,
- inbound_streams=SbInboundStreams,
- assoc_id=SBAI}}} ->
- ?line SaOutboundStreams = SbInboundStreams,
- ?line SaInboundStreams = SbOutboundStreams,
- SBAI
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
- end,
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SbOutboundStreams,
+ inbound_streams=SbInboundStreams,
+ assoc_id=SbAssocId} =
+ recv_assoc_change(Sb, Loopback, Pa, Timeout),
+ ?line SbOutboundStreams = SaInboundStreams,
+ ?line SbInboundStreams = SaOutboundStreams,
?line io:format("SbAssocId=~p~n", [SbAssocId]),
+
+ ?line case recv_paddr_change(Sa, Loopback, Pb, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId} -> ok;
+ timeout -> ok
+ end,
+ ?line case recv_paddr_change(Sb, Loopback, Pa, 314) of
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=SbAssocId} -> ok;
+ #sctp_paddr_change{state=addr_available,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=SbAssocId} -> ok;
+ timeout -> ok
+ end,
+ ?line [] = flush(),
+
?line ok =
do_from_other_process(
fun () -> gen_sctp:send(Sa, SaAssocId, 0, Data) end),
@@ -220,19 +264,7 @@ xfer_active(Config) when is_list(Config) ->
{sctp,Sb,Loopback,Pa,
{[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SbAssocId}],
- Data}} -> ok;
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_paddr_change{addr = {Loopback,_},
- state = addr_available,
- error = 0,
- assoc_id = SbAssocId}}} ->
- ?line receive
- {sctp,Sb,Loopback,Pa,
- {[#sctp_sndrcvinfo{stream=Stream,
- assoc_id=SbAssocId}],
- Data}} -> ok
- end
+ Data}} -> ok
after Timeout ->
?line test_server:fail({unexpected,flush()})
end,
@@ -247,23 +279,19 @@ xfer_active(Config) when is_list(Config) ->
end,
%%
?line ok = gen_sctp:abort(Sa, SaAssocChange),
- ?line receive
- {sctp,Sb,Loopback,Pa,
- {[],
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SbAssocId}}} -> ok
- after Timeout ->
+ ?line case recv_assoc_change(Sb, Loopback, Pa, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SbAssocId} -> ok;
+ timeout ->
?line test_server:fail({unexpected,flush()})
end,
?line ok = gen_sctp:close(Sb),
- ?line receive
- {sctp,Sa,Loopback,Pb,
- {[],
- #sctp_assoc_change{state=comm_lost,
- assoc_id=SaAssocId}}} -> ok
- after Timeout ->
- ?line test_server:fail({unexpected,flush()})
- end,
+ ?line case recv_assoc_change(Sa, Loopback, Pb, Timeout) of
+ #sctp_assoc_change{state=comm_lost,
+ assoc_id=SaAssocId} -> ok;
+ timeout ->
+ ?line test_server:fail({unexpected,flush()})
+ end,
?line receive
{sctp_error,Sa,enotconn} -> ok % Solaris
after 17 -> ok %% Only happens on Solaris
@@ -276,6 +304,30 @@ xfer_active(Config) when is_list(Config) ->
end,
ok.
+recv_assoc_change(S, Addr, Port, Timeout) ->
+ receive
+ {sctp,S,Addr,Port,{[], #sctp_assoc_change{}=AssocChange}} ->
+ AssocChange;
+ {sctp,S,Addr,Port,
+ {[#sctp_sndrcvinfo{assoc_id=AssocId}],
+ #sctp_assoc_change{assoc_id=AssocId}=AssocChange}} ->
+ AssocChange
+ after Timeout ->
+ timeout
+ end.
+
+recv_paddr_change(S, Addr, Port, Timeout) ->
+ receive
+ {sctp,S,Addr,Port,{[], #sctp_paddr_change{}=PaddrChange}} ->
+ PaddrChange;
+ {sctp,S,Addr,Port,
+ {[#sctp_sndrcvinfo{assoc_id=AssocId}],
+ #sctp_paddr_change{assoc_id=AssocId}=PaddrChange}} ->
+ PaddrChange
+ after Timeout ->
+ timeout
+ end.
+
def_sndrcvinfo(doc) ->
"Test that #sctp_sndrcvinfo{} parameters set on a socket "
"are used by gen_sctp:send/4";
@@ -312,20 +364,33 @@ def_sndrcvinfo(Config) when is_list(Config) ->
assoc_id=S2AssocId} = S2AssocChange =
ok(gen_sctp:connect(S2, Loopback, P1, [])),
?LOGVAR(S2AssocChange),
- ?line case ok(gen_sctp:recv(S1)) of
- {Loopback, P2,[],
+ ?line case recv_event(ok(gen_sctp:recv(S1))) of
+ {Loopback,P2,
#sctp_assoc_change{
+ state=comm_up,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId);
+ {Loopback,P2,
+ #sctp_paddr_change{
+ state=addr_confirmed,
+ error=0,
+ assoc_id=S1AssocId}} ->
+ ?LOGVAR(S1AssocId),
+ {Loopback,P2,
+ #sctp_assoc_change{
state=comm_up,
error=0,
- assoc_id=S1AssocId}} ->
- ?LOGVAR(S1AssocId)
+ assoc_id=S1AssocId}} =
+ recv_event(ok(gen_sctp:recv(S1)))
end,
+
?line #sctp_sndrcvinfo{
- ppid=17, context=0, timetolive=0, assoc_id=S1AssocId} =
+ ppid=17, context=0, timetolive=0} = %, assoc_id=S1AssocId} =
getopt(
S1, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S1AssocId}),
?line #sctp_sndrcvinfo{
- ppid=0, context=0, timetolive=0, assoc_id=S2AssocId} =
+ ppid=0, context=0, timetolive=0} = %, assoc_id=S2AssocId} =
getopt(
S2, sctp_default_send_param, #sctp_sndrcvinfo{assoc_id=S2AssocId}),
%%
@@ -335,7 +400,19 @@ def_sndrcvinfo(Config) when is_list(Config) ->
{Loopback,P1,
[#sctp_sndrcvinfo{
stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
- <<"1: ",Data/binary>>} -> ok
+ <<"1: ",Data/binary>>} -> ok;
+ Event1 ->
+ ?line {Loopback,P1,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,P1},
+ error=0,
+ assoc_id=S2AssocId}} =
+ recv_event(Event1),
+ ?line {Loopback,P1,
+ [#sctp_sndrcvinfo{
+ stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
+ <<"1: ",Data/binary>>} =
+ ok(gen_sctp:recv(S2))
end,
%%
?line ok =
@@ -368,10 +445,12 @@ def_sndrcvinfo(Config) when is_list(Config) ->
[#sctp_sndrcvinfo{
stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
<<"3: ",Data/binary>>} -> ok;
- {Loopback,P2,[],
- #sctp_paddr_change{
- addr={Loopback,_}, state=addr_available,
- error=0, assoc_id=S1AssocId}} ->
+ Event2 ->
+ {Loopback,P2,
+ #sctp_paddr_change{
+ addr={Loopback,_}, state=addr_available,
+ error=0, assoc_id=S1AssocId}} =
+ recv_event(Event2),
?line case ok(gen_sctp:recv(S1)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
@@ -525,7 +604,10 @@ api_listen(Config) when is_list(Config) ->
#sctp_assoc_change{
state=comm_lost}}} =
gen_sctp:recv(Sa, infinity);
- {error,#sctp_assoc_change{state=cant_assoc}} -> ok
+ {error,#sctp_assoc_change{state=cant_assoc}} ->
+ ok%;
+ %% {error,{Localhost,Pb,_,#sctp_assoc_change{state=cant_assoc}}} ->
+ %% ok
end,
?line ok = gen_sctp:listen(Sb, true),
?line {ok,#sctp_assoc_change{state=comm_up,
@@ -557,29 +639,41 @@ api_connect_init(Config) when is_list(Config) ->
?line {ok,Sa} = gen_sctp:open(),
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
{error,econnrefused} ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{state=comm_lost}}} =
- gen_sctp:recv(Sa, infinity);
+ ?line {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} =
+ recv_event(ok(gen_sctp:recv(Sa, infinity)));
ok ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{state=cant_assoc}}} =
- gen_sctp:recv(Sa, infinity)
+ ?line {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} =
+ recv_event(ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:listen(Sb, true),
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
ok ->
- ?line {ok,{Localhost,
- Pb,[],
- #sctp_assoc_change{
- state = comm_up}}} =
- gen_sctp:recv(Sa, infinity)
+ ?line {Localhost,Pb,#sctp_assoc_change{state=comm_up}} =
+ recv_event(ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
ok.
+recv_event({Addr,Port,[],#sctp_assoc_change{}=AssocChange}) ->
+ {Addr,Port,AssocChange};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_assoc_change{assoc_id=Assoc}=AssocChange}) ->
+ {Addr,Port,AssocChange};
+recv_event({Addr,Port,[],#sctp_paddr_change{}=PaddrChange}) ->
+ {Addr,Port,PaddrChange};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_paddr_change{assoc_id=Assoc}=PaddrChange}) ->
+ {Addr,Port,PaddrChange};
+recv_event({Addr,Port,[],#sctp_shutdown_event{}=ShutdownEvent}) ->
+ {Addr,Port,ShutdownEvent};
+recv_event({Addr,Port,
+ [#sctp_sndrcvinfo{assoc_id=Assoc}],
+ #sctp_shutdown_event{assoc_id=Assoc}=ShutdownEvent}) ->
+ {Addr,Port,ShutdownEvent}.
+
api_opts(doc) ->
"Test socket options";
api_opts(suite) ->
@@ -645,9 +739,14 @@ implicit_inet6(S1, Addr) ->
?line P2 = ok(inet:port(S2)),
?line #sctp_assoc_change{state=comm_up} =
ok(gen_sctp:connect(S2, Addr, P1, [])),
- ?line case ok(gen_sctp:recv(S1)) of
- {Addr,P2,[],#sctp_assoc_change{state=comm_up}} ->
- ok
+ ?line case recv_event(ok(gen_sctp:recv(S1))) of
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} ->
+ ok;
+ {Addr,P2,#sctp_paddr_change{state=addr_confirmed,
+ addr={Addr,P2},
+ error=0}} ->
+ {Addr,P2,#sctp_assoc_change{state=comm_up}} =
+ recv_event(ok(gen_sctp:recv(S1)))
end,
?line case ok(inet:sockname(S1)) of
{Addr,P1} -> ok;
@@ -692,14 +791,29 @@ xfer_stream_min(Config) when is_list(Config) ->
inbound_streams=SaInboundStreams,
assoc_id=SaAssocId}} =
gen_sctp:connect(Sa, Loopback, Pb, []),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SbOutboundStreams,
- inbound_streams=SbInboundStreams,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
+ ?line {SbOutboundStreams,SbInboundStreams,SbAssocId} =
+ case recv_event(ok(gen_sctp:recv(Sb, infinity))) of
+ {Loopback,Pa,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=OS,
+ inbound_streams=IS,
+ assoc_id=AI}} ->
+ {OS,IS,AI};
+ {Loopback,Pa,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={Loopback,Pa},
+ error=0,
+ assoc_id=AI}} ->
+ {Loopback,Pa,
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=OS,
+ inbound_streams=IS,
+ assoc_id=AI}} =
+ recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ {OS,IS,AI}
+ end,
?line SaOutboundStreams = SbInboundStreams,
?line SbOutboundStreams = SaInboundStreams,
?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
@@ -724,24 +838,33 @@ xfer_stream_min(Config) when is_list(Config) ->
?line ok =
do_from_other_process(
fun () -> gen_sctp:send(Sb, SbAssocId, 0, Data) end),
- ?line {ok,{Loopback,
- Pb,
+ ?line case ok(gen_sctp:recv(Sa, infinity)) of
+ {Loopback,Pb,
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
- Data}} =
- gen_sctp:recv(Sa, infinity),
- %%
+ Data} -> ok;
+ Event1 ->
+ ?line {Loopback,Pb,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,Pb},
+ error=0,
+ assoc_id=SaAssocId}} =
+ recv_event(Event1),
+ ?line {Loopback,Pb,
+ [#sctp_sndrcvinfo{stream=Stream,
+ assoc_id=SaAssocId}],
+ Data} =
+ ok(gen_sctp:recv(Sa, infinity))
+ end,
?line ok = gen_sctp:close(Sa),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_shutdown_event{assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
- ?line {ok,{Loopback,
- Pa,[],
- #sctp_assoc_change{state=shutdown_comp,
- error=0,
- assoc_id=SbAssocId}}} =
- gen_sctp:recv(Sb, infinity),
+ ?line {Loopback,Pa,
+ #sctp_shutdown_event{assoc_id=SbAssocId}} =
+ recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ ?line {Loopback,Pa,
+ #sctp_assoc_change{state=shutdown_comp,
+ error=0,
+ assoc_id=SbAssocId}} =
+ recv_event(ok(gen_sctp:recv(Sb, infinity))),
?line ok = gen_sctp:close(Sb),
?line receive
@@ -822,8 +945,8 @@ peeloff(Config) when is_list(Config) ->
?line inet:i(sctp),
?line ok = socket_stop(S1),
?line ok = socket_stop(S2),
- ?line {Addr,P2,[],#sctp_shutdown_event{assoc_id=S1Ai}} =
- ok(socket_stop(S3)),
+ ?line {Addr,P2,#sctp_shutdown_event{assoc_id=S1Ai}} =
+ recv_event(ok(socket_stop(S3))),
ok.
@@ -857,8 +980,8 @@ buffers(Config) when is_list(Config) ->
?line {Addr,P2,S1Ai,Stream,Data} = socket_resp(H_b),
%%
?line ok = socket_stop(S1),
- ?line {Addr,P1,[],#sctp_shutdown_event{assoc_id=S2Ai}} =
- ok(socket_stop(S2)),
+ ?line {Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}} =
+ recv_event(ok(socket_stop(S2))),
ok.
mk_data(Words) ->
@@ -935,38 +1058,83 @@ socket_handler(Socket, Timeout) ->
(socket) ->
Socket;
(recv_assoc) ->
- {AssocAddr,AssocPort,[],
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=Os,
- inbound_streams=Is,
- assoc_id=AssocId}} =
- ok(gen_sctp:recv(Socket, infinity)),
- case log(gen_sctp:recv(Socket, Timeout)) of
- {ok,AssocAddr,AssocPort,[],
- #sctp_paddr_change{addr = {AssocAddr,AssocPort},
- state = addr_available,
- error = 0,
- assoc_id = AssocId}} -> ok;
- {error,timeout} -> ok
- end,
- {AssocId,Os,Is,AssocAddr,AssocPort};
+ case recv_event(ok(gen_sctp:recv(Socket, Timeout))) of
+ {AssocAddr,AssocPort,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,AssocPort},
+ error=0,
+ assoc_id=AssocId}} ->
+ {AssocAddr,AssocPort,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=Os,
+ inbound_streams=Is,
+ assoc_id=AssocId}} =
+ recv_event(ok(gen_sctp:recv(Socket, infinity))),
+ {AssocId,Os,Is,AssocAddr,AssocPort};
+ {AssocAddr,AssocPort,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=Os,
+ inbound_streams=Is,
+ assoc_id=AssocId}} ->
+ {AssocId,Os,Is,AssocAddr,AssocPort}
+ end;
+ %% {AssocAddr,AssocPort,[],
+ %% #sctp_assoc_change{state=comm_up,
+ %% error=0,
+ %% outbound_streams=Os,
+ %% inbound_streams=Is,
+ %% assoc_id=AssocId}} =
+ %% ok(gen_sctp:recv(Socket, infinity)),
+ %% case log(gen_sctp:recv(Socket, Timeout)) of
+ %% {ok,AssocAddr,AssocPort,[],
+ %% #sctp_paddr_change{addr = {AssocAddr,AssocPort},
+ %% state = addr_available,
+ %% error = 0,
+ %% assoc_id = AssocId}} -> ok;
+ %% {error,timeout} -> ok
+ %% end,
+ %% {AssocId,Os,Is,AssocAddr,AssocPort};
({connect,ConAddr,ConPort,ConOpts}) ->
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=Os,
- inbound_streams=Is,
- assoc_id=AssocId} =
- ok(gen_sctp:connect(Socket, ConAddr, ConPort, ConOpts)),
- case log(gen_sctp:recv(Socket, Timeout)) of
- {ok,ConAddr,ConPort,[],
- #sctp_paddr_change{addr = {ConAddr,ConPort},
- state = addr_available,
- error = 0,
- assoc_id = AssocId}} -> ok;
- {error,timeout} -> ok
- end,
- {AssocId,Os,Is};
+ ok = gen_sctp:connect_init(Socket, ConAddr, ConPort, ConOpts),
+ case recv_event(ok(gen_sctp:recv(Socket, Timeout))) of
+ {ConAddr,ConPort,
+ #sctp_paddr_change{state=addr_confirmed,
+ addr={_,ConPort},
+ error=0,
+ assoc_id=AssocId}} ->
+ {ConAddr,ConPort,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=Os,
+ inbound_streams=Is,
+ assoc_id=AssocId}} =
+ recv_event(ok(gen_sctp:recv(Socket, infinity))),
+ {AssocId,Os,Is};
+ {ConAddr,ConPort,
+ #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=Os,
+ inbound_streams=Is,
+ assoc_id=AssocId}} ->
+ {AssocId,Os,Is}
+ end;
+ %% #sctp_assoc_change{state=comm_up,
+ %% error=0,
+ %% outbound_streams=Os,
+ %% inbound_streams=Is,
+ %% assoc_id=AssocId} =
+ %% ok(gen_sctp:connect(Socket, ConAddr, ConPort, ConOpts)),
+ %% case log(gen_sctp:recv(Socket, Timeout)) of
+ %% {ok,ConAddr,ConPort,[],
+ %% #sctp_paddr_change{addr = {ConAddr,ConPort},
+ %% state = addr_available,
+ %% error = 0,
+ %% assoc_id = AssocId}} -> ok;
+ %% {error,timeout} -> ok
+ %% end,
+ %% {AssocId,Os,Is};
({send,AssocId,Stream,Data}) ->
gen_sctp:send(Socket, AssocId, Stream, Data);
({send,S,AssocId,Stream,Data}) ->
--
cgit v1.2.3
From c501ca26c01d222af4b05b1732059a7a9684b1c3 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Thu, 22 Sep 2011 11:11:57 +0200
Subject: kernel: Rewrite SCTP test socket handler
The socket handler needs more flexibility regarding which events
are expected to be received.
---
lib/kernel/test/gen_sctp_SUITE.erl | 603 ++++++++++++++++++++++---------------
1 file changed, 360 insertions(+), 243 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 8011c22ce5..07434df8da 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -110,7 +110,7 @@ xfer_min(Config) when is_list(Config) ->
assoc_id=SaAssocId}=SaAssocChange} =
gen_sctp:connect(Sa, Loopback, Pb, []),
?line {SbAssocId,SaOutboundStreams,SaInboundStreams} =
- case recv_event(ok(gen_sctp:recv(Sb, infinity))) of
+ case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
{Loopback,Pa,
#sctp_assoc_change{state=comm_up,
error=0,
@@ -129,12 +129,12 @@ xfer_min(Config) when is_list(Config) ->
outbound_streams=SbOutboundStreams,
inbound_streams=SbInboundStreams,
assoc_id=AssocId}} =
- ?line recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ ?line recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
{AssocId,SbInboundStreams,SbOutboundStreams}
end,
?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
- ?line case ok(gen_sctp:recv(Sb, infinity)) of
+ ?line case log_ok(gen_sctp:recv(Sb, infinity)) of
{Loopback,
Pa,
[#sctp_sndrcvinfo{stream=Stream,
@@ -154,7 +154,7 @@ xfer_min(Config) when is_list(Config) ->
Data}} = gen_sctp:recv(Sb, infinity)
end,
?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
- ?line case ok(gen_sctp:recv(Sa, infinity)) of
+ ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
{Loopback,Pb,
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
@@ -172,22 +172,22 @@ xfer_min(Config) when is_list(Config) ->
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
Data} =
- ok(gen_sctp:recv(Sa, infinity))
+ log_ok(gen_sctp:recv(Sa, infinity))
end,
%%
?line ok = gen_sctp:eof(Sa, SaAssocChange),
?line {Loopback,Pa,#sctp_shutdown_event{assoc_id=SbAssocId}} =
- recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
?line {Loopback,Pb,
#sctp_assoc_change{state=shutdown_comp,
error=0,
assoc_id=SaAssocId}} =
- recv_event(ok(gen_sctp:recv(Sa, infinity))),
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity))),
?line {Loopback,Pa,
#sctp_assoc_change{state=shutdown_comp,
error=0,
assoc_id=SbAssocId}} =
- recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
@@ -338,11 +338,11 @@ def_sndrcvinfo(Config) when is_list(Config) ->
?line Data = <<"What goes up, must come down.">>,
%%
?line S1 =
- ok(gen_sctp:open(
+ log_ok(gen_sctp:open(
0, [{sctp_default_send_param,#sctp_sndrcvinfo{ppid=17}}])),
?LOGVAR(S1),
?line P1 =
- ok(inet:port(S1)),
+ log_ok(inet:port(S1)),
?LOGVAR(P1),
?line #sctp_sndrcvinfo{ppid=17, context=0, timetolive=0, assoc_id=0} =
getopt(S1, sctp_default_send_param),
@@ -350,10 +350,10 @@ def_sndrcvinfo(Config) when is_list(Config) ->
gen_sctp:listen(S1, true),
%%
?line S2 =
- ok(gen_sctp:open()),
+ log_ok(gen_sctp:open()),
?LOGVAR(S2),
?line P2 =
- ok(inet:port(S2)),
+ log_ok(inet:port(S2)),
?LOGVAR(P2),
?line #sctp_sndrcvinfo{ppid=0, context=0, timetolive=0, assoc_id=0} =
getopt(S2, sctp_default_send_param),
@@ -362,9 +362,9 @@ def_sndrcvinfo(Config) when is_list(Config) ->
state=comm_up,
error=0,
assoc_id=S2AssocId} = S2AssocChange =
- ok(gen_sctp:connect(S2, Loopback, P1, [])),
+ log_ok(gen_sctp:connect(S2, Loopback, P1, [])),
?LOGVAR(S2AssocChange),
- ?line case recv_event(ok(gen_sctp:recv(S1))) of
+ ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
{Loopback,P2,
#sctp_assoc_change{
state=comm_up,
@@ -382,7 +382,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
state=comm_up,
error=0,
assoc_id=S1AssocId}} =
- recv_event(ok(gen_sctp:recv(S1)))
+ recv_event(log_ok(gen_sctp:recv(S1)))
end,
?line #sctp_sndrcvinfo{
@@ -396,7 +396,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
%%
?line ok =
gen_sctp:send(S1, S1AssocId, 1, <<"1: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S2)) of
+ ?line case log_ok(gen_sctp:recv(S2)) of
{Loopback,P1,
[#sctp_sndrcvinfo{
stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
@@ -412,7 +412,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
[#sctp_sndrcvinfo{
stream=1, ppid=17, context=0, assoc_id=S2AssocId}],
<<"1: ",Data/binary>>} =
- ok(gen_sctp:recv(S2))
+ log_ok(gen_sctp:recv(S2))
end,
%%
?line ok =
@@ -432,7 +432,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
%%
?line ok =
gen_sctp:send(S1, S1AssocId, 0, <<"2: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S2)) of
+ ?line case log_ok(gen_sctp:recv(S2)) of
{Loopback,P1,
[#sctp_sndrcvinfo{
stream=0, ppid=19, context=0, assoc_id=S2AssocId}],
@@ -440,7 +440,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
end,
?line ok =
gen_sctp:send(S2, S2AssocChange, 1, <<"3: ",Data/binary>>),
- ?line case ok(gen_sctp:recv(S1)) of
+ ?line case log_ok(gen_sctp:recv(S1)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=1, ppid=0, context=0, assoc_id=S1AssocId}],
@@ -451,7 +451,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
addr={Loopback,_}, state=addr_available,
error=0, assoc_id=S1AssocId}} =
recv_event(Event2),
- ?line case ok(gen_sctp:recv(S1)) of
+ ?line case log_ok(gen_sctp:recv(S1)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=1, ppid=0, context=0,
@@ -467,7 +467,7 @@ def_sndrcvinfo(Config) when is_list(Config) ->
#sctp_sndrcvinfo{stream=0, ppid=20, assoc_id=S2AssocId},
<<"4: ",Data/binary>>)
end),
- ?line case ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of
+ ?line case log_ok(do_from_other_process(fun() -> gen_sctp:recv(S1) end)) of
{Loopback,P2,
[#sctp_sndrcvinfo{
stream=0, ppid=20, context=0, assoc_id=S1AssocId}],
@@ -496,9 +496,9 @@ getopt(S, Opt, Param) ->
setopt(S, Opt, Val) ->
inet:setopts(S, [{Opt,Val}]).
-ok({ok,X}) ->
- io:format("OK[~w]: ~p~n", [self(),X]),
- X.
+log_ok(X) -> log(ok(X)).
+
+ok({ok,X}) -> X.
log(X) ->
io:format("LOG[~w]: ~p~n", [self(),X]),
@@ -640,16 +640,16 @@ api_connect_init(Config) when is_list(Config) ->
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
{error,econnrefused} ->
?line {Localhost,Pb,#sctp_assoc_change{state=comm_lost}} =
- recv_event(ok(gen_sctp:recv(Sa, infinity)));
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)));
ok ->
?line {Localhost,Pb,#sctp_assoc_change{state=cant_assoc}} =
- recv_event(ok(gen_sctp:recv(Sa, infinity)))
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:listen(Sb, true),
?line case gen_sctp:connect_init(Sa, localhost, Pb, []) of
ok ->
?line {Localhost,Pb,#sctp_assoc_change{state=comm_up}} =
- recv_event(ok(gen_sctp:recv(Sa, infinity)))
+ recv_event(log_ok(gen_sctp:recv(Sa, infinity)))
end,
?line ok = gen_sctp:close(Sa),
?line ok = gen_sctp:close(Sb),
@@ -699,7 +699,7 @@ api_opts(Config) when is_list(Config) ->
end.
implicit_inet6(Config) when is_list(Config) ->
- ?line Hostname = ok(inet:gethostname()),
+ ?line Hostname = log_ok(inet:gethostname()),
?line
case gen_sctp:open(0, [inet6]) of
{ok,S1} ->
@@ -712,16 +712,16 @@ implicit_inet6(Config) when is_list(Config) ->
?line ok = gen_sctp:close(S1),
%%
?line Localhost =
- ok(inet:getaddr("localhost", inet6)),
+ log_ok(inet:getaddr("localhost", inet6)),
?line io:format("~s ~p~n", ["localhost",Localhost]),
?line S2 =
- ok(gen_sctp:open(0, [{ip,Localhost}])),
+ log_ok(gen_sctp:open(0, [{ip,Localhost}])),
?line implicit_inet6(S2, Localhost),
?line ok = gen_sctp:close(S2),
%%
?line io:format("~s ~p~n", [Hostname,Host]),
?line S3 =
- ok(gen_sctp:open(0, [{ifaddr,Host}])),
+ log_ok(gen_sctp:open(0, [{ifaddr,Host}])),
?line implicit_inet6(S3, Host),
?line ok = gen_sctp:close(S1);
{error,eafnosupport} ->
@@ -734,25 +734,25 @@ implicit_inet6(Config) when is_list(Config) ->
implicit_inet6(S1, Addr) ->
?line ok = gen_sctp:listen(S1, true),
- ?line P1 = ok(inet:port(S1)),
- ?line S2 = ok(gen_sctp:open(0, [inet6])),
- ?line P2 = ok(inet:port(S2)),
+ ?line P1 = log_ok(inet:port(S1)),
+ ?line S2 = log_ok(gen_sctp:open(0, [inet6])),
+ ?line P2 = log_ok(inet:port(S2)),
?line #sctp_assoc_change{state=comm_up} =
- ok(gen_sctp:connect(S2, Addr, P1, [])),
- ?line case recv_event(ok(gen_sctp:recv(S1))) of
+ log_ok(gen_sctp:connect(S2, Addr, P1, [])),
+ ?line case recv_event(log_ok(gen_sctp:recv(S1))) of
{Addr,P2,#sctp_assoc_change{state=comm_up}} ->
ok;
{Addr,P2,#sctp_paddr_change{state=addr_confirmed,
addr={Addr,P2},
error=0}} ->
{Addr,P2,#sctp_assoc_change{state=comm_up}} =
- recv_event(ok(gen_sctp:recv(S1)))
+ recv_event(log_ok(gen_sctp:recv(S1)))
end,
- ?line case ok(inet:sockname(S1)) of
+ ?line case log_ok(inet:sockname(S1)) of
{Addr,P1} -> ok;
{{0,0,0,0,0,0,0,0},P1} -> ok
end,
- ?line case ok(inet:sockname(S2)) of
+ ?line case log_ok(inet:sockname(S2)) of
{Addr,P2} -> ok;
{{0,0,0,0,0,0,0,0},P2} -> ok
end,
@@ -792,7 +792,7 @@ xfer_stream_min(Config) when is_list(Config) ->
assoc_id=SaAssocId}} =
gen_sctp:connect(Sa, Loopback, Pb, []),
?line {SbOutboundStreams,SbInboundStreams,SbAssocId} =
- case recv_event(ok(gen_sctp:recv(Sb, infinity))) of
+ case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
{Loopback,Pa,
#sctp_assoc_change{state=comm_up,
error=0,
@@ -811,7 +811,7 @@ xfer_stream_min(Config) when is_list(Config) ->
outbound_streams=OS,
inbound_streams=IS,
assoc_id=AI}} =
- recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
{OS,IS,AI}
end,
?line SaOutboundStreams = SbInboundStreams,
@@ -838,7 +838,7 @@ xfer_stream_min(Config) when is_list(Config) ->
?line ok =
do_from_other_process(
fun () -> gen_sctp:send(Sb, SbAssocId, 0, Data) end),
- ?line case ok(gen_sctp:recv(Sa, infinity)) of
+ ?line case log_ok(gen_sctp:recv(Sa, infinity)) of
{Loopback,Pb,
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
@@ -854,17 +854,17 @@ xfer_stream_min(Config) when is_list(Config) ->
[#sctp_sndrcvinfo{stream=Stream,
assoc_id=SaAssocId}],
Data} =
- ok(gen_sctp:recv(Sa, infinity))
+ log_ok(gen_sctp:recv(Sa, infinity))
end,
?line ok = gen_sctp:close(Sa),
?line {Loopback,Pa,
#sctp_shutdown_event{assoc_id=SbAssocId}} =
- recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
?line {Loopback,Pa,
#sctp_assoc_change{state=shutdown_comp,
error=0,
assoc_id=SbAssocId}} =
- recv_event(ok(gen_sctp:recv(Sb, infinity))),
+ recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
?line ok = gen_sctp:close(Sb),
?line receive
@@ -911,42 +911,97 @@ peeloff(Config) when is_list(Config) ->
?line Addr = {127,0,0,1},
?line Stream = 0,
?line Timeout = 333,
- ?line S1 = socket_start(Addr, Timeout),
- ?line P1 = socket_call(S1, port),
- ?line Socket1 = socket_call(S1, socket),
- ?line ok = socket_call(S1, {listen,true}),
- ?line S2 = socket_start(Addr, Timeout),
- ?line P2 = socket_call(S2, port),
- ?line Socket2 = socket_call(S2, socket),
+ ?line S1 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line ?LOGVAR(S1),
+ ?line P1 = socket_call(S1, get_port),
+ ?line ?LOGVAR(P1),
+ ?line Socket1 = socket_call(S1, get_socket),
+ ?line ?LOGVAR(Socket1),
+ ?line socket_call(S1, {listen,true}),
+ ?line S2 = socket_open([{ifaddr,Addr}], Timeout),
+ ?line ?LOGVAR(S2),
+ ?line P2 = socket_call(S2, get_port),
+ ?line ?LOGVAR(P2),
+ ?line Socket2 = socket_call(S2, get_socket),
+ ?line ?LOGVAR(Socket2),
%%
- ?line H_a = socket_req(S1, recv_assoc),
- ?line {S2Ai,Sa,Sb} = socket_call(S2, {connect,Addr,P1,[]}),
- ?line {S1Ai,Sb,Sa,Addr,P2} = socket_resp(H_a),
+ ?line socket_call(S2, {connect_init,Addr,P1,[]}),
+ ?line S2Ai =
+ receive
+ {S2,{Addr,P1,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line ?LOGVAR(S2Ai),
+ ?line S1Ai =
+ receive
+ {S1,{Addr,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line ?LOGVAR(S1Ai),
%%
- ?line H_b = socket_req(S1, recv),
- ?line ok = socket_call(S2, {send,S2Ai,Stream,<<"Data H_b">>}),
- ?line {Addr,P2,S1Ai,Stream,<<"Data H_b">>} = socket_resp(H_b),
- ?line H_c = socket_req(S1, {recv,Socket2}),
- ?line ok =
- socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Data H_c">>}),
- ?line {Addr,P1,S2Ai,Stream,<<"Data H_c">>} = socket_resp(H_c),
+ ?line socket_call(S2, {send,S2Ai,Stream,<<"Number one">>}),
+ ?line
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,<<"Number one">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line socket_call(S2, {send,Socket1,S1Ai,Stream,<<"Number two">>}),
+ ?line
+ receive
+ {S2,{Addr,P1,S2Ai,Stream,<<"Number two">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
%%
?line S3 = socket_peeloff(Socket1, S1Ai, Timeout),
- ?line P3 = socket_call(S3, port),
- ?line Socket3 = socket_call(S3, socket),
+ ?line ?LOGVAR(S3),
+ ?line P3 = socket_call(S3, get_port),
+ ?line ?LOGVAR(P3),
?line S3Ai = S1Ai,
+ ?line ?LOGVAR(S3Ai),
%%
- ?line H_d = socket_req(S2, recv),
- ?line ok = socket_call(S3, {send,S3Ai,Stream,<<"Data H_d">>}),
- ?line {Addr,P3,S2Ai,Stream,<<"Data H_d">>} = socket_resp(H_d),
- ?line ok = socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Data S2">>}),
- ?line {Addr,P2,S3Ai,Stream,<<"Data S2">>} = socket_call(S2, {recv,Socket3}),
+ ?line socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}),
+ ?line
+ receive
+ {S2,{Addr,P3,S2Ai,Stream,<<"Number three">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
+ ?line socket_call(S3, {send,Socket2,S2Ai,Stream,<<"Number four">>}),
+ ?line
+ receive
+ {S3,{Addr,P2,S3Ai,Stream,<<"Number four">>}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2,S3])
+ end,
%%
?line inet:i(sctp),
- ?line ok = socket_stop(S1),
- ?line ok = socket_stop(S2),
- ?line {Addr,P2,#sctp_shutdown_event{assoc_id=S1Ai}} =
- recv_event(ok(socket_stop(S3))),
+ ?line socket_close_verbose(S1),
+ ?line socket_close_verbose(S2),
+ ?line
+ receive
+ {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ ?line
+ receive
+ {S3,{Addr,P2,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S3Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S3])
+ end,
+ ?line socket_close_verbose(S3),
+ ?line [] = flush(),
ok.
@@ -960,28 +1015,65 @@ buffers(Config) when is_list(Config) ->
?line Data = mk_data(Limit),
?line Addr = {127,0,0,1},
?line Stream = 1,
- ?line Timeout = 333,
- ?line S1 = socket_start(Addr, Timeout),
- ?line P1 = socket_call(S1, port),
+ ?line Timeout = 1333,
+ ?line S1 = socket_open([{ip,Addr}], Timeout),
+ ?line ?LOGVAR(S1),
+ ?line P1 = socket_call(S1, get_port),
+ ?line ?LOGVAR(P1),
?line ok = socket_call(S1, {listen,true}),
- ?line S2 = socket_start(Addr, Timeout),
- ?line P2 = socket_call(S2, port),
+ ?line S2 = socket_open([{ip,Addr}], Timeout),
+ ?line ?LOGVAR(S2),
+ ?line P2 = socket_call(S2, get_port),
+ ?line ?LOGVAR(P2),
%%
- ?line H_a = socket_req(S1, recv_assoc),
- ?line {S2Ai,Sa,Sb} = socket_call(S2, {connect,Addr,P1,[]}),
- ?line {S1Ai,Sb,Sa,Addr,P2} = socket_resp(H_a),
+ ?line socket_call(S2, {connect_init,Addr,P1,[]}),
+ ?line S2Ai =
+ receive
+ {S2,{Addr,P1,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId2}}} -> AssocId2
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
+ ?line S1Ai =
+ receive
+ {S1,{Addr,P2,
+ #sctp_assoc_change{
+ state=comm_up,
+ assoc_id=AssocId1}}} -> AssocId1
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
%%
- ?line ok = socket_call(S1, {setopts,[{recbuf,Limit}]}),
+ ?line socket_call(S1, {setopts,[{recbuf,Limit}]}),
?line case socket_call(S1, {getopts,[recbuf]}) of
- {ok,[{recbuf,RB1}]} when RB1 >= Limit -> ok
+ [{recbuf,RB1}] when RB1 >= Limit -> ok
end,
- ?line H_b = socket_req(S1, recv),
- ?line ok = socket_call(S2, {send,S2Ai,Stream,Data}),
- ?line {Addr,P2,S1Ai,Stream,Data} = socket_resp(H_b),
+ ?line socket_call(S2, {send,S2Ai,Stream,Data}),
+ ?line
+ receive
+ {S1,{Addr,P2,S1Ai,Stream,Data}} -> ok
+ after Timeout ->
+ socket_bailout([S1,S2])
+ end,
%%
- ?line ok = socket_stop(S1),
- ?line {Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}} =
- recv_event(ok(socket_stop(S2))),
+ ?line socket_close_verbose(S1),
+ ?line
+ receive
+ {S2,{Addr,P1,#sctp_shutdown_event{assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ ?line
+ receive
+ {S2,{Addr,P1,#sctp_assoc_change{state=shutdown_comp,
+ assoc_id=S2Ai}}} -> ok
+ after Timeout ->
+ socket_bailout([S2])
+ end,
+ ?line socket_close_verbose(S2),
+ ?line [] = flush(),
ok.
mk_data(Words) ->
@@ -995,38 +1087,101 @@ mk_data(N, Words, Bin) ->
%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% socket gen_server ultra light
+socket_open(SocketOpts, Timeout) ->
+ Opts = [{type,seqpacket},{active,once},binary|SocketOpts],
+ Starter =
+ fun () ->
+ {ok,Socket} =
+ gen_sctp:open(Opts),
+ Socket
+ end,
+ s_start(Starter, Timeout).
+
socket_peeloff(Socket, AssocId, Timeout) ->
+ Opts = [{active,once},binary],
Starter =
fun () ->
{ok,NewSocket} =
gen_sctp:peeloff(Socket, AssocId),
+ ok = inet:setopts(NewSocket, Opts),
NewSocket
end,
- socket_starter(Starter, Timeout).
+ s_start(Starter, Timeout).
+
+socket_close_verbose(S) ->
+ History = socket_history(socket_close(S)),
+ io:format("socket_close ~p:~n ~p.~n", [S,History]),
+ History.
+
+socket_close(S) ->
+ s_req(S, close).
+
+socket_call(S, Request) ->
+ s_req(S, {Request}).
+
+%% socket_get(S, Key) ->
+%% s_req(S, {get,Key}).
+
+socket_bailout([S|Ss]) ->
+ History = socket_history(socket_close(S)),
+ io:format("bailout ~p:~n ~p.~n", [S,History]),
+ socket_bailout(Ss);
+socket_bailout([]) ->
+ io:format("flush: ~p.~n", [flush()]),
+ test_server:fail(socket_bailout).
+
+socket_history({State,Flush}) ->
+ {lists:keysort(
+ 2,
+ lists:flatten(
+ [[{Key,Val} || Val <- Vals]
+ || {Key,Vals} <- gb_trees:to_list(State)])),
+ Flush}.
+
+s_handler(Socket) ->
+ fun ({listen,Listen}) ->
+ ok = gen_sctp:listen(Socket, Listen);
+ (get_port) ->
+ ok(inet:port(Socket));
+ (get_socket) ->
+ Socket;
+ ({connect_init,ConAddr,ConPort,ConOpts}) ->
+ ok = gen_sctp:connect_init(Socket, ConAddr, ConPort, ConOpts);
+ ({send,AssocId,Stream,Data}) ->
+ ok = gen_sctp:send(Socket, AssocId, Stream, Data);
+ ({send,OtherSocket,AssocId,Stream,Data}) ->
+ ok = gen_sctp:send(OtherSocket, AssocId, Stream, Data);
+ ({setopts,Opts}) ->
+ ok = inet:setopts(Socket, Opts);
+ ({getopts,Optnames}) ->
+ ok(inet:getopts(Socket, Optnames))
+ end.
-socket_start(Addr, Timeout) ->
- Starter =
- fun () ->
- {ok,Socket} =
- gen_sctp:open([{type,seqpacket},{ifaddr,Addr}]),
- Socket
- end,
- socket_starter(Starter, Timeout).
+s_req(S, Req) ->
+ Mref = erlang:monitor(process, S),
+ S ! {self(),Mref,Req},
+ receive
+ {'DOWN',Mref,_,_,Error} ->
+ exit(Error);
+ {S,Mref,Reply} ->
+ erlang:demonitor(Mref),
+ receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end,
+ Reply
+ end.
-socket_starter(Starter, Timeout) ->
+s_start(Starter, Timeout) ->
Parent = self(),
Owner =
spawn_link(
fun () ->
- socket_starter(Starter(), Timeout, Parent)
+ s_start(Starter(), Timeout, Parent)
end),
- io:format("Started socket ~w.~n", [Owner]),
Owner.
-socket_starter(Socket, Timeout, Parent) ->
+s_start(Socket, Timeout, Parent) ->
+ Handler = s_handler(Socket),
try
- Handler = socket_handler(Socket, Timeout),
- socket_loop(Socket, Timeout, Parent, Handler)
+ s_loop(Socket, Timeout, Parent, Handler, gb_trees:empty())
catch
Class:Reason ->
Stacktrace = erlang:get_stacktrace(),
@@ -1035,150 +1190,112 @@ socket_starter(Socket, Timeout, Parent) ->
erlang:raise(Class, Reason, Stacktrace)
end.
-socket_loop(Socket, Timeout, Parent, Handler) ->
+s_loop(Socket, Timeout, Parent, Handler, State) ->
receive
- {Parent,Ref} -> % socket_stop()
- Result =
- case log(gen_sctp:recv(Socket, Timeout)) of
- {error,timeout} -> ok;
- R -> R
- end,
+ {Parent,Ref,close} -> % socket_close()
+ erlang:send_after(Timeout, self(), {Parent,Ref,exit}),
+ s_loop(Socket, Timeout, Parent, Handler, State);
+ {Parent,Ref,exit} ->
ok = gen_sctp:close(Socket),
- Parent ! {self(),Ref, Result};
- {Parent,Ref,Msg} ->
- Parent ! {self(),Ref,Handler(Msg)},
- socket_loop(Socket, Timeout, Parent, Handler)
+ Key = exit,
+ Val = {now(),Socket},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),Ref,{NewState,flush()}};
+ {Parent,Ref,{Msg}} ->
+ Result = Handler(Msg),
+ Key = req,
+ Val = {now(),{Msg,Result}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),Ref,Result},
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ %% {Parent,Ref,{get,Key}} ->
+ %% Parent ! {self(),Ref,gb_get(Key, State)},
+ %% s_loop(Socket, Timeout, Parent, Handler, State);
+ {sctp,Socket,Addr,Port,
+ {[#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}=SRI],Data}}
+ when not is_tuple(Data) ->
+ case gb_get({assoc_change,AssocId}, State) of
+ [{_,{Addr,Port,
+ #sctp_assoc_change{
+ state=comm_up,
+ inbound_streams=Is}}}|_]
+ when 0 =< Stream, Stream < Is-> ok;
+ [] -> ok
+ end,
+ Key = {msg,AssocId,Stream},
+ Val = {now(),{Addr,Port,SRI,Data}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),{Addr,Port,AssocId,Stream,Data}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_assoc_change{assoc_id=AssocId,state=St}=SAC}} ->
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ Key = {assoc_change,AssocId},
+ Val = {now(),{Addr,Port,SAC}},
+ case {gb_get(Key, State),St} of
+ {[],_} -> ok;
+ {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],_}
+ when St =:= comm_lost; St =:= shutdown_comp -> ok
+ end,
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(),{Addr,Port,SAC}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_paddr_change{assoc_id=AssocId,
+ addr={_,Port},
+ state=St}=SPC}} ->
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ case {gb_get({assoc_change,AssocId}, State),St} of
+ {[],_} when St =:= addr_confirmed -> ok
+ end,
+ Key = {paddr_change,AssocId},
+ Val = {now(),{Addr,Port,SPC}},
+ NewState = gb_push(Key, Val, State),
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ {sctp,Socket,Addr,Port,
+ {SRI,#sctp_shutdown_event{assoc_id=AssocId}=SSE}} ->
+ case SRI of
+ [#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
+ [] -> ok
+ end,
+ case gb_get({assoc_change,AssocId}, State) of
+ [{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_] -> ok;
+ [] -> ok
+ end,
+ Key = {shutdown_event,AssocId},
+ Val = {now(),{Addr,Port}},
+ NewState = gb_push(Key, Val, State),
+ Parent ! {self(), {Addr,Port,SSE}},
+ again(Socket),
+ s_loop(Socket, Timeout, Parent, Handler, NewState);
+ Unexpected ->
+ erlang:error({unexpected,Unexpected})
end.
-socket_handler(Socket, Timeout) ->
- fun ({listen,Listen}) ->
- gen_sctp:listen(Socket, Listen);
- (port) ->
- ok(inet:port(Socket));
- (socket) ->
- Socket;
- (recv_assoc) ->
- case recv_event(ok(gen_sctp:recv(Socket, Timeout))) of
- {AssocAddr,AssocPort,
- #sctp_paddr_change{state=addr_confirmed,
- addr={_,AssocPort},
- error=0,
- assoc_id=AssocId}} ->
- {AssocAddr,AssocPort,
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=Os,
- inbound_streams=Is,
- assoc_id=AssocId}} =
- recv_event(ok(gen_sctp:recv(Socket, infinity))),
- {AssocId,Os,Is,AssocAddr,AssocPort};
- {AssocAddr,AssocPort,
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=Os,
- inbound_streams=Is,
- assoc_id=AssocId}} ->
- {AssocId,Os,Is,AssocAddr,AssocPort}
- end;
- %% {AssocAddr,AssocPort,[],
- %% #sctp_assoc_change{state=comm_up,
- %% error=0,
- %% outbound_streams=Os,
- %% inbound_streams=Is,
- %% assoc_id=AssocId}} =
- %% ok(gen_sctp:recv(Socket, infinity)),
- %% case log(gen_sctp:recv(Socket, Timeout)) of
- %% {ok,AssocAddr,AssocPort,[],
- %% #sctp_paddr_change{addr = {AssocAddr,AssocPort},
- %% state = addr_available,
- %% error = 0,
- %% assoc_id = AssocId}} -> ok;
- %% {error,timeout} -> ok
- %% end,
- %% {AssocId,Os,Is,AssocAddr,AssocPort};
- ({connect,ConAddr,ConPort,ConOpts}) ->
- ok = gen_sctp:connect_init(Socket, ConAddr, ConPort, ConOpts),
- case recv_event(ok(gen_sctp:recv(Socket, Timeout))) of
- {ConAddr,ConPort,
- #sctp_paddr_change{state=addr_confirmed,
- addr={_,ConPort},
- error=0,
- assoc_id=AssocId}} ->
- {ConAddr,ConPort,
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=Os,
- inbound_streams=Is,
- assoc_id=AssocId}} =
- recv_event(ok(gen_sctp:recv(Socket, infinity))),
- {AssocId,Os,Is};
- {ConAddr,ConPort,
- #sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=Os,
- inbound_streams=Is,
- assoc_id=AssocId}} ->
- {AssocId,Os,Is}
- end;
- %% #sctp_assoc_change{state=comm_up,
- %% error=0,
- %% outbound_streams=Os,
- %% inbound_streams=Is,
- %% assoc_id=AssocId} =
- %% ok(gen_sctp:connect(Socket, ConAddr, ConPort, ConOpts)),
- %% case log(gen_sctp:recv(Socket, Timeout)) of
- %% {ok,ConAddr,ConPort,[],
- %% #sctp_paddr_change{addr = {ConAddr,ConPort},
- %% state = addr_available,
- %% error = 0,
- %% assoc_id = AssocId}} -> ok;
- %% {error,timeout} -> ok
- %% end,
- %% {AssocId,Os,Is};
- ({send,AssocId,Stream,Data}) ->
- gen_sctp:send(Socket, AssocId, Stream, Data);
- ({send,S,AssocId,Stream,Data}) ->
- gen_sctp:send(S, AssocId, Stream, Data);
- (recv) ->
- {Addr,Port,
- [#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}],Data} =
- ok(gen_sctp:recv(Socket, infinity)),
- {Addr,Port,AssocId,Stream,Data};
- ({recv,S}) ->
- {Addr,Port,
- [#sctp_sndrcvinfo{stream=Stream,assoc_id=AssocId}],Data} =
- ok(gen_sctp:recv(S, infinity)),
- {Addr,Port,AssocId,Stream,Data};
- ({setopts,Opts}) ->
- inet:setopts(Socket, Opts);
- ({getopts,Optnames}) ->
- inet:getopts(Socket, Optnames)
- end.
+again(Socket) ->
+ inet:setopts(Socket, [{active,once}]).
-socket_stop(Handler) ->
- Mref = erlang:monitor(process, Handler),
- Handler ! {self(),Mref},
- receive
- {Handler,Mref,Result} ->
- receive {'DOWN',Mref,_,_,_} -> Result end;
- {'DOWN',Mref,_,_,Error} ->
- exit(Error)
+gb_push(Key, Val, GBT) ->
+ case gb_trees:lookup(Key, GBT) of
+ none ->
+ gb_trees:insert(Key, [Val], GBT);
+ {value,V} ->
+ gb_trees:update(Key, [Val|V], GBT)
end.
-socket_call(Handler, Request) ->
- socket_resp(socket_req(Handler, Request)).
-
-socket_req(Handler, Request) ->
- Mref = erlang:monitor(process, Handler),
- Handler ! {self(),Mref,Request},
- {Handler,Mref}.
-
-socket_resp({Handler,Mref}) ->
- receive
- {'DOWN',Mref,_,_,Error} ->
- exit(Error);
- {Handler,Mref,Reply} ->
- erlang:demonitor(Mref),
- receive {'DOWN',Mref,_,_,_} -> ok after 0 -> ok end,
- Reply
+gb_get(Key, GBT) ->
+ case gb_trees:lookup(Key, GBT) of
+ none ->
+ [];
+ {value,V} ->
+ V
end.
--
cgit v1.2.3
From 3be53d45e394dab127563d7a8d6da109cd9bc108 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Wed, 28 Sep 2011 10:19:17 +0200
Subject: kernel: Adjust SCTP tests to Solaris quirks
---
lib/kernel/test/gen_sctp_SUITE.erl | 94 +++++++++++++++++++++++++-------------
1 file changed, 63 insertions(+), 31 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 07434df8da..301f69ce09 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -250,9 +250,10 @@ xfer_active(Config) when is_list(Config) ->
error=0,
assoc_id=SbAssocId} -> ok;
#sctp_paddr_change{state=addr_available,
- addr={Loopback,Pa},
+ addr={Loopback,P},
error=0,
- assoc_id=SbAssocId} -> ok;
+ assoc_id=SbAssocId} ->
+ ?line match_unless_solaris(Pa, P);
timeout -> ok
end,
?line [] = flush(),
@@ -266,7 +267,7 @@ xfer_active(Config) when is_list(Config) ->
assoc_id=SbAssocId}],
Data}} -> ok
after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line test_server:fail({timeout,flush()})
end,
?line ok = gen_sctp:send(Sb, SbAssocId, 0, Data),
?line receive
@@ -275,7 +276,7 @@ xfer_active(Config) when is_list(Config) ->
assoc_id=SaAssocId}],
Data}} -> ok
after Timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line test_server:fail({timeout,flush()})
end,
%%
?line ok = gen_sctp:abort(Sa, SaAssocChange),
@@ -283,19 +284,20 @@ xfer_active(Config) when is_list(Config) ->
#sctp_assoc_change{state=comm_lost,
assoc_id=SbAssocId} -> ok;
timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line test_server:fail({timeout,flush()})
end,
?line ok = gen_sctp:close(Sb),
?line case recv_assoc_change(Sa, Loopback, Pb, Timeout) of
#sctp_assoc_change{state=comm_lost,
assoc_id=SaAssocId} -> ok;
timeout ->
- ?line test_server:fail({unexpected,flush()})
+ ?line io:format("timeout waiting for comm_lost on Sa~n"),
+ ?line match_unless_solaris(ok, {timeout,flush()})
end,
?line receive
- {sctp_error,Sa,enotconn} -> ok % Solaris
- after 17 -> ok %% Only happens on Solaris
- end,
+ {sctp_error,Sa,enotconn} -> ok % Solaris
+ after 17 -> ok
+ end,
?line ok = gen_sctp:close(Sa),
%%
?line receive
@@ -780,17 +782,28 @@ xfer_stream_min(Config) when is_list(Config) ->
?line Data = <<"The quick brown fox jumps over a lazy dog 0123456789">>,
?line Loopback = {127,0,0,1},
?line {ok,Sb} = gen_sctp:open([{type,seqpacket}]),
+ ?line ?LOGVAR(Sb),
?line {ok,Pb} = inet:port(Sb),
+ ?line ?LOGVAR(Pb),
?line ok = gen_sctp:listen(Sb, true),
?line {ok,Sa} = gen_sctp:open([{type,stream}]),
+ ?line ?LOGVAR(Sa),
?line {ok,Pa} = inet:port(Sa),
- ?line {ok,#sctp_assoc_change{state=comm_up,
- error=0,
- outbound_streams=SaOutboundStreams,
- inbound_streams=SaInboundStreams,
- assoc_id=SaAssocId}} =
- gen_sctp:connect(Sa, Loopback, Pb, []),
+ ?line ?LOGVAR(Pa),
+ ?line #sctp_assoc_change{state=comm_up,
+ error=0,
+ outbound_streams=SaOutboundStreams,
+ inbound_streams=SaInboundStreams,
+ assoc_id=SaAssocId_X} =
+ log_ok(gen_sctp:connect(Sa, Loopback, Pb, [])),
+ ?line ?LOGVAR(SaAssocId_X),
+ ?line [{_,#sctp_paddrinfo{assoc_id=SaAssocId,state=active}}] =
+ log_ok(inet:getopts(Sa, [{sctp_get_peer_addr_info,
+ #sctp_paddrinfo{address={Loopback,Pb}}}])),
+ ?line ?LOGVAR(SaAssocId),
+ ?line match_unless_solaris(SaAssocId_X, SaAssocId),
+
?line {SbOutboundStreams,SbInboundStreams,SbAssocId} =
case recv_event(log_ok(gen_sctp:recv(Sb, infinity))) of
{Loopback,Pa,
@@ -814,8 +827,11 @@ xfer_stream_min(Config) when is_list(Config) ->
recv_event(log_ok(gen_sctp:recv(Sb, infinity))),
{OS,IS,AI}
end,
+ ?line ?LOGVAR(SbAssocId),
?line SaOutboundStreams = SbInboundStreams,
+ ?line ?LOGVAR(SaOutboundStreams),
?line SbOutboundStreams = SaInboundStreams,
+ ?line ?LOGVAR(SbOutboundStreams),
?line ok = gen_sctp:send(Sa, SaAssocId, 0, Data),
?line case gen_sctp:recv(Sb, infinity) of
{ok,{Loopback,
@@ -966,7 +982,11 @@ peeloff(Config) when is_list(Config) ->
?line ?LOGVAR(S3),
?line P3 = socket_call(S3, get_port),
?line ?LOGVAR(P3),
- ?line S3Ai = S1Ai,
+ ?line [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] =
+ socket_call(S3,
+ {getopts,[{sctp_get_peer_addr_info,
+ #sctp_paddrinfo{address={Addr,P2}}}]}),
+ %%?line S3Ai = S1Ai,
?line ?LOGVAR(S3Ai),
%%
?line socket_call(S3, {send,S3Ai,Stream,<<"Number three">>}),
@@ -989,7 +1009,8 @@ peeloff(Config) when is_list(Config) ->
?line socket_close_verbose(S2),
?line
receive
- {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai}}} -> ok
+ {S3,{Addr,P2,#sctp_shutdown_event{assoc_id=S3Ai_X}}} ->
+ ?line match_unless_solaris(S3Ai, S3Ai_X)
after Timeout ->
socket_bailout([S3])
end,
@@ -1011,11 +1032,10 @@ buffers(doc) ->
buffers(suite) ->
[];
buffers(Config) when is_list(Config) ->
- ?line Limit = 8192,
- ?line Data = mk_data(Limit),
+ ?line Limit = 4096,
?line Addr = {127,0,0,1},
?line Stream = 1,
- ?line Timeout = 1333,
+ ?line Timeout = 3333,
?line S1 = socket_open([{ip,Addr}], Timeout),
?line ?LOGVAR(S1),
?line P1 = socket_call(S1, get_port),
@@ -1047,9 +1067,12 @@ buffers(Config) when is_list(Config) ->
end,
%%
?line socket_call(S1, {setopts,[{recbuf,Limit}]}),
- ?line case socket_call(S1, {getopts,[recbuf]}) of
- [{recbuf,RB1}] when RB1 >= Limit -> ok
- end,
+ ?line Recbuf =
+ case socket_call(S1, {getopts,[recbuf]}) of
+ [{recbuf,RB1}] when RB1 >= Limit -> RB1
+ end,
+ ?line Data = mk_data(Recbuf+Limit),
+ ?line socket_call(S2, {setopts,[{sndbuf,Recbuf+Limit}]}),
?line socket_call(S2, {send,S2Ai,Stream,Data}),
?line
receive
@@ -1076,13 +1099,13 @@ buffers(Config) when is_list(Config) ->
?line [] = flush(),
ok.
-mk_data(Words) ->
- mk_data(0, Words, <<>>).
+mk_data(Bytes) ->
+ mk_data(0, Bytes, <<>>).
%%
-mk_data(Words, Words, Bin) ->
- Bin;
-mk_data(N, Words, Bin) ->
- mk_data(N+1, Words, <>).
+mk_data(N, Bytes, Bin) when N < Bytes ->
+ mk_data(N+4, Bytes, <>);
+mk_data(_, _, Bin) ->
+ Bin.
%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% socket gen_server ultra light
@@ -1247,14 +1270,17 @@ s_loop(Socket, Timeout, Parent, Handler, State) ->
s_loop(Socket, Timeout, Parent, Handler, NewState);
{sctp,Socket,Addr,Port,
{SRI,#sctp_paddr_change{assoc_id=AssocId,
- addr={_,Port},
+ addr={_,P},
state=St}=SPC}} ->
+ match_unless_solaris(Port, P),
case SRI of
[#sctp_sndrcvinfo{assoc_id=AssocId,stream=0}] -> ok;
[] -> ok
end,
case {gb_get({assoc_change,AssocId}, State),St} of
- {[],_} when St =:= addr_confirmed -> ok
+ {[{_,{Addr,Port,#sctp_assoc_change{state=comm_up}}}|_],
+ addr_available} -> ok;
+ {[],addr_confirmed} -> ok
end,
Key = {paddr_change,AssocId},
Val = {now(),{Addr,Port,SPC}},
@@ -1299,3 +1325,9 @@ gb_get(Key, GBT) ->
{value,V} ->
V
end.
+
+match_unless_solaris(A, B) ->
+ case os:type() of
+ {unix,sunos} -> B;
+ _ -> A = B
+ end.
--
cgit v1.2.3
From 4f8e3e94357cd4730c9e3135f2bafd9b6d4fd13e Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Wed, 28 Sep 2011 11:48:08 +0200
Subject: erts,kernel: Return eprotonosupport when SCTP is not supported
It is better that gen_sctp:open/0-2 returns the informative Posix
return code {error,eprotonosupport} than previously {error,badarg}
when SCTP is not supported since it is so platform dependent.
---
lib/kernel/test/gen_sctp_SUITE.erl | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 301f69ce09..d0b0bdf4d4 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -44,17 +44,12 @@ groups() ->
[].
init_per_suite(Config) ->
- try gen_sctp:open() of
+ case gen_sctp:open() of
{ok,Socket} ->
gen_sctp:close(Socket),
[];
- _ ->
- []
- catch
- error:badarg ->
- {skip,"SCTP not supported on this machine"};
- _:_ ->
- Config
+ {error,eprotonosupport} ->
+ {skip,"SCTP not supported on this machine"}
end.
end_per_suite(_Conifig) ->
--
cgit v1.2.3
From 3d4c4eaf917e92c52c6533e17c98aeab81125f3b Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Tue, 18 Oct 2011 16:27:00 +0200
Subject: kernel: Adjust SCTP test to SuSE quirk
inet:port/1 on peeled off socket returns 0. Bug? Who's?
---
lib/kernel/test/gen_sctp_SUITE.erl | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index d0b0bdf4d4..300152ddce 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -43,7 +43,7 @@ all() ->
groups() ->
[].
-init_per_suite(Config) ->
+init_per_suite(_Config) ->
case gen_sctp:open() of
{ok,Socket} ->
gen_sctp:close(Socket),
@@ -52,7 +52,7 @@ init_per_suite(Config) ->
{skip,"SCTP not supported on this machine"}
end.
-end_per_suite(_Conifig) ->
+end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
@@ -975,8 +975,9 @@ peeloff(Config) when is_list(Config) ->
%%
?line S3 = socket_peeloff(Socket1, S1Ai, Timeout),
?line ?LOGVAR(S3),
- ?line P3 = socket_call(S3, get_port),
- ?line ?LOGVAR(P3),
+ ?line P3_X = socket_call(S3, get_port),
+ ?line ?LOGVAR(P3_X),
+ ?line P3 = case P3_X of 0 -> P1; _ -> P3_X end,
?line [{_,#sctp_paddrinfo{assoc_id=S3Ai,state=active}}] =
socket_call(S3,
{getopts,[{sctp_get_peer_addr_info,
--
cgit v1.2.3
From d6d9371d50e7e9ad8708e914b72fa755ce5a5385 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen
Date: Fri, 21 Oct 2011 17:51:34 +0200
Subject: kernel: Documented gen_sctp:peeloff/2
---
lib/kernel/doc/src/gen_sctp.xml | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
(limited to 'lib/kernel')
diff --git a/lib/kernel/doc/src/gen_sctp.xml b/lib/kernel/doc/src/gen_sctp.xml
index b9f23674f0..418bfae4b8 100644
--- a/lib/kernel/doc/src/gen_sctp.xml
+++ b/lib/kernel/doc/src/gen_sctp.xml
@@ -45,7 +45,15 @@
SUSE Linux Enterprise Server 10 (x86_64) kernel 2.6.16.27-0.6-smp,
with lksctp-tools-1.0.6, briefly on Solaris 10, and later on
SUSE Linux Enterprise Server 10 Service Pack 1 (x86_64)
- kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7.
+ kernel 2.6.16.54-0.2.3-smp with lksctp-tools-1.0.7,
+ and later also on FreeBSD 8.2.
+
+
+ This module was written for one-to-many style sockets
+ (type seqpacket). With the addition of
+ peeloff/2, one-to-one style
+ sockets (type stream) were introduced.
+
Record definitions for the gen_sctp module can be found using:
-include_lib("kernel/include/inet_sctp.hrl").
These record definitions use the "new" spelling 'adaptation',
@@ -299,11 +307,39 @@
is used. In particular, the socket is opened in
binary and
passive mode,
+ with SockType seqpacket,
and with reasonably large
kernel and driver
buffers.
+
+
+
+ Peel off a type stream socket from a type seqpacket one
+
+
+
+ Branch off an existing association Assoc
+ in a socket Socket of type seqpacket
+ (one-to-may style) into
+ a new socket NewSocket of type stream
+ (one-to-one style).
+
+
+ The existing association argument Assoc
+ can be either a
+
+ #sctp_assoc_change{}
+
+ record as returned from e.g
+ recv/*,
+ connect/* or
+ from a listening socket in active mode. Or it can be just
+ the field assoc_id integer from such a record.
+
+
+
--
cgit v1.2.3