1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
-module(sctp).
%%
%% A small example demonstrating the establishment of an SCTP
%% association with gen_sctp.
%%
-export([assoc/0,
dbg/0]).
-include_lib("kernel/include/inet_sctp.hrl").
-define(ADDR, {127,0,0,1}).
-define(SERVER_PORT, 3868).
-define(CONNECT_TIMEOUT, 2000).
-define(REQUEST, <<0:64>>).
-define(REPLY, <<1:64>>).
-record(server, {client,
socket,
assoc}).
-record(client, {socket,
assoc}).
%% assoc/0
%%
%% Return on a successfully established association, raise an
%% exception otherwise.
assoc() ->
{_, MRef} = spawn_monitor(fun server/0),
receive {'DOWN', MRef, process, _, Info} -> Info end.
%% dbg/0
dbg() ->
dbg:tracer(),
dbg:p(all,c),
dbg:tpl(?MODULE, [{'_',[],[{exception_trace}]}]),
dbg:tp(gen_sctp, [{'_',[],[{exception_trace}]}]),
ok.
%% server/0
server() ->
{ok, Sock} = gen_sctp:open([binary,
{reuseaddr, true},
{active, true},
{ip, ?ADDR},
{port, ?SERVER_PORT}]),
ok = gen_sctp:listen(Sock, true),
{_Pid, MRef} = spawn_monitor(fun client/0),
s(#server{client = MRef, socket = Sock}),
gen_sctp:close(Sock).
%% s/1
s(#server{} = S) ->
s(s(receive T -> T end, S));
s(T) ->
T.
%% s/2
s({sctp, Sock, _RA, _RP, {[], #sctp_assoc_change{state = comm_up,
assoc_id = Id}}},
#server{socket = Sock, assoc = undefined}
= S) ->
S#server{assoc = Id};
s({sctp, Sock, _RA, _RP, {[#sctp_sndrcvinfo{assoc_id = AId,
stream = SId}],
?REQUEST}},
#server{socket = Sock, assoc = AId}
= S) ->
ok = gen_sctp:send(Sock, AId, SId, ?REPLY),
S;
s({'DOWN', MRef, process, _, normal} = T, #server{client = MRef}) ->
T.
%% client/0
client() ->
{ok, Sock} = gen_sctp:open([binary,
{reuseaddr, true},
{active, true},
{ip, ?ADDR},
{port, 0}]),
ok = gen_sctp:connect_init(Sock, ?ADDR, ?SERVER_PORT, []),
c(#client{socket = Sock}),
gen_sctp:close(Sock).
%% c/1
c(#client{} = S) ->
c(c(receive T -> T end, S));
c(T) ->
T.
c({sctp, Sock, _RA, _RP, {[], #sctp_assoc_change{state = comm_up,
assoc_id = Id}}},
#client{socket = Sock, assoc = undefined}
= S) ->
ok = gen_sctp:send(Sock, Id, 0, ?REQUEST),
S#client{assoc = Id};
c({sctp, Sock, _RA, _RP, {[#sctp_sndrcvinfo{assoc_id = AId}], ?REPLY}},
#client{socket = Sock, assoc = AId}) ->
ok.
|