This module provides functions for communicating with
sockets using the SCTP protocol. The implementation assumes that
the OS kernel supports SCTP
During development, this implementation was tested on:
During OTP adaptation it was tested on:
This module was written for one-to-many style sockets
(type
Record definitions for this module can be found using:
-include_lib("kernel/include/inet_sctp.hrl").
These record definitions use the "new" spelling 'adaptation', not the deprecated 'adaption', regardless of which spelling the underlying C API uses.
One of the
Abnormally terminates the association specified by
Closes the socket and all associations on it. The unsent
data is flushed as in
Same as
Establishes a new association for socket
Using a value of
#sctp_assoc_change{ state = atom(), error = atom(), outbound_streams = integer(), inbound_streams = integer(), assoc_id = assoc_id() }
The number of outbound and inbound streams can be set by
giving an
connect(Socket, Ip, Port>, [{sctp_initmsg,#sctp_initmsg{num_ostreams=OutStreams, max_instreams=MaxInStreams}}])
All options
The returned
Association is successfully established. This
indicates a successful completion of
The association cannot be established
(
Other states do not normally occur in the output from
Field
Same as
Initiates a new association for socket
The fundamental difference between this API
and
The parameters are as described in
The timer associated with
Assigns a new controlling process
Gracefully terminates the association specified by
Translates an SCTP error number from, for example,
Sets up a socket to listen on the IP address and port number it is bound to.
For type
For type
Creates an SCTP socket and binds it to the local addresses
specified by all
Other options:
Sets up the socket for IPv6.
Sets up the socket for IPv4. This is the default.
A default set of socket
Branches off an existing association
The existing association argument
Receives the
The
Possible SCTP events:
#sctp_paddr_change{ addr = {ip_address(),port()}, state = atom(), error = integer(), assoc_id = assoc_id() }
Indicates change of the status of the IP address of the peer
specified by
In case of an error (for example,
#sctp_send_failed{ flags = true | false, error = integer(), info = #sctp_sndrcvinfo{}, assoc_id = assoc_id() data = binary() }
The sender can receive this event if a send operation fails.
A Boolean specifying if the data has been transmitted over the wire.
Provides extended diagnostics, use
The original
The whole original data chunk attempted to be sent.
In the current implementation of the Erlang/SCTP binding,
this event is internally converted into an
#sctp_adaptation_event{ adaptation_ind = integer(), assoc_id = assoc_id() }
Delivered when a peer sends an adaptation layer indication
parameter (configured through option
#sctp_pdapi_event{ indication = sctp_partial_delivery_aborted, assoc_id = assoc_id() }
A partial delivery failure. In the current implementation of
the Erlang/SCTP binding, this event is internally converted
into an
Sends the
Sends a
The set of admissible SCTP socket options is by construction
orthogonal to the sets of TCP, UDP, and generic
Determines the type of data returned from
If
If
Notice that this can cause the message queue to overflow, as there is no way to throttle the sender in this case (no flow control).
If
If
Sets the Type-Of-Service field on the IP datagrams that are sent, to the specified value. This effectively determines a prioritization policy for the outbound packets. The acceptable values are system-dependent.
A protocol-independent equivalent of
Defaults to
Defaults to
The size, in bytes, of the OS kernel send buffer for this socket.
Sending errors would occur for datagrams larger than
The size, in bytes, of the OS kernel receive buffer for this socket.
Sending errors would occur for datagrams larger than
Overrides which callback module is used. Defaults to
#sctp_rtoinfo{ assoc_id = assoc_id(), initial = integer(), max = integer(), min = integer() }
Determines retransmission time-out parameters, in milliseconds,
for the association(s) specified by
#sctp_assocparams{ assoc_id = assoc_id(), asocmaxrxt = integer(), number_peer_destinations = integer(), peer_rwnd = integer(), local_rwnd = integer(), cookie_life = integer() }
Determines association parameters for the association(s) specified by
#sctp_initmsg{ num_ostreams = integer(), max_instreams = integer(), max_attempts = integer(), max_init_timeo = integer() }
Determines the default parameters that this socket tries
to negotiate with its peer while establishing an association with it.
Is to be set after
Determines the time, in seconds, after which an idle association is
automatically closed.
Turns on|off the Nagle algorithm for merging small packets into larger ones. This improves throughput at the expense of latency.
If
Turns on|off automatic mapping of IPv4 addresses into IPv6 ones
(if the socket address family is
Determines the maximum chunk size if message fragmentation is used.
If
#sctp_prim{ assoc_id = assoc_id(), addr = {IP, Port} } IP = ip_address() Port = port_number()
For the association specified by
#sctp_setpeerprim{ assoc_id = assoc_id(), addr = {IP, Port} } IP = ip_address() Port = port_number()
When set, informs the peer to use
#sctp_setadaptation{ adaptation_ind = integer() }
When set, requests that the local endpoint uses the value specified
by
#sctp_paddrparams{ assoc_id = assoc_id(), address = {IP, Port}, hbinterval = integer(), pathmaxrxt = integer(), pathmtu = integer(), sackdelay = integer(), flags = list() } IP = ip_address() Port = port_number()
Determines various per-address parameters for
the association specified by
Heartbeat interval, in milliseconds
Maximum number of retransmissions before this address is considered unreachable (and an alternative address is selected)
Fixed Path MTU, if automatic discovery is disabled (see
Delay, in milliseconds, for SAC messages (if the delay is
enabled, see
The following flags are available:
#sctp_sndrcvinfo{ stream = integer(), ssn = integer(), flags = list(), ppid = integer(), context = integer(), timetolive = integer(), tsn = integer(), cumtsn = integer(), assoc_id = assoc_id() }
The following fields typically must be specified by the sender:
Stream number (0-base) within the association to send the messages through;
The following flags are recognised:
Other fields are rarely used. For complete information, see
#sctp_event_subscribe{ data_io_event = true | false, association_event = true | false, address_event = true | false, send_failure_event = true | false, peer_error_event = true | false, shutdown_event = true | false, partial_delivery_event = true | false, adaptation_layer_event = true | false }
This option determines which
#sctp_assoc_value{ assoc_id = assoc_id(), assoc_value = integer() }
Rarely used. Determines the ACK time
(specified by
#sctp_status{ assoc_id = assoc_id(), state = atom(), rwnd = integer(), unackdata = integer(), penddata = integer(), instrms = integer(), outstrms = integer(), fragmentation_point = integer(), primary = #sctp_paddrinfo{} }
This option is read-only. It determines the status of
the SCTP association specified by
Semantics of the other fields:
#sctp_paddrinfo{ assoc_id = assoc_id(), address = {IP, Port}, state = inactive | active | unconfirmed, cwnd = integer(), srtt = integer(), rto = integer(), mtu = integer() } IP = ip_address() Port = port_number()
This option is read-only. It determines the parameters specific to
the peer address specified by
Example of an Erlang SCTP server that receives SCTP messages and prints them on the standard output:
-module(sctp_server). -export([server/0,server/1,server/2]). -include_lib("kernel/include/inet.hrl"). -include_lib("kernel/include/inet_sctp.hrl"). server() -> server(any, 2006). server([Host,Port]) when is_list(Host), is_list(Port) -> {ok, #hostent{h_addr_list = [IP|_]}} = inet:gethostbyname(Host), io:format("~w -> ~w~n", [Host, IP]), server([IP, list_to_integer(Port)]). server(IP, Port) when is_tuple(IP) orelse IP == any orelse IP == loopback, is_integer(Port) -> {ok,S} = gen_sctp:open(Port, [{recbuf,65536}, {ip,IP}]), io:format("Listening on ~w:~w. ~w~n", [IP,Port,S]), ok = gen_sctp:listen(S, true), server_loop(S). server_loop(S) -> case gen_sctp:recv(S) of {error, Error} -> io:format("SCTP RECV ERROR: ~p~n", [Error]); Data -> io:format("Received: ~p~n", [Data]) end, server_loop(S).
Example of an Erlang SCTP client interacting with the above server.
Notice that in this example the client creates an association with
the server with 5 outbound streams. Therefore, sending of
-module(sctp_client). -export([client/0, client/1, client/2]). -include_lib("kernel/include/inet.hrl"). -include_lib("kernel/include/inet_sctp.hrl"). client() -> client([localhost]). client([Host]) -> client(Host, 2006); client([Host, Port]) when is_list(Host), is_list(Port) -> client(Host,list_to_integer(Port)), init:stop(). client(Host, Port) when is_integer(Port) -> {ok,S} = gen_sctp:open(), {ok,Assoc} = gen_sctp:connect (S, Host, Port, [{sctp_initmsg,#sctp_initmsg{num_ostreams=5}}]), io:format("Connection Successful, Assoc=~p~n", [Assoc]), io:write(gen_sctp:send(S, Assoc, 0, <<"Test 0">>)), io:nl(), timer:sleep(10000), io:write(gen_sctp:send(S, Assoc, 5, <<"Test 5">>)), io:nl(), timer:sleep(10000), io:write(gen_sctp:abort(S, Assoc)), io:nl(), timer:sleep(1000), gen_sctp:close(S).
A simple Erlang SCTP client that uses the
-module(ex3). -export([client/4]). -include_lib("kernel/include/inet.hrl"). -include_lib("kernel/include/inet_sctp.hrl"). client(Peer1, Port1, Peer2, Port2) when is_tuple(Peer1), is_integer(Port1), is_tuple(Peer2), is_integer(Port2) -> {ok,S} = gen_sctp:open(), SctpInitMsgOpt = {sctp_initmsg,#sctp_initmsg{num_ostreams=5}}, ActiveOpt = {active, true}, Opts = [SctpInitMsgOpt, ActiveOpt], ok = gen_sctp:connect(S, Peer1, Port1, Opts), ok = gen_sctp:connect(S, Peer2, Port2, Opts), io:format("Connections initiated~n", []), client_loop(S, Peer1, Port1, undefined, Peer2, Port2, undefined). client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) -> receive {sctp, S, Peer1, Port1, {_Anc, SAC}} when is_record(SAC, sctp_assoc_change), AssocId1 == undefined -> io:format("Association 1 connect result: ~p. AssocId: ~p~n", [SAC#sctp_assoc_change.state, SAC#sctp_assoc_change.assoc_id]), client_loop(S, Peer1, Port1, SAC#sctp_assoc_change.assoc_id, Peer2, Port2, AssocId2); {sctp, S, Peer2, Port2, {_Anc, SAC}} when is_record(SAC, sctp_assoc_change), AssocId2 == undefined -> io:format("Association 2 connect result: ~p. AssocId: ~p~n", [SAC#sctp_assoc_change.state, SAC#sctp_assoc_change.assoc_id]), client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, SAC#sctp_assoc_change.assoc_id); {sctp, S, Peer1, Port1, Data} -> io:format("Association 1: received ~p~n", [Data]), client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2); {sctp, S, Peer2, Port2, Data} -> io:format("Association 2: received ~p~n", [Data]), client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2); Other -> io:format("Other ~p~n", [Other]), client_loop(S, Peer1, Port1, AssocId1, Peer2, Port2, AssocId2) after 5000 -> ok end.