mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
sctp: Take some socket configurations from Firefox's datachannel code
- Do not send ABORTs for unexpected packets are as response to INIT - Enable interleaving of messages of different streams - Configure 1MB send and receive buffer for the socket - Enable SCTP_SEND_FAILED_EVENT and SCTP_PARTIAL_DELIVERY_EVENT events - Set SCTP_REUSE_PORT configuration - Set SCTP_EXPLICIT_EOR and the corresponding send flag. We probably want to split packets to a maximum size later and only set the flag on the last packet. Firefox uses 0x4000 as maximum size here. - Enable SCTP_ENABLE_CHANGE_ASSOC_REQ - Disable PMTUD and set an maximum initial MTU of 1200
This commit is contained in:
parent
c497370254
commit
26a6b17593
1 changed files with 81 additions and 5 deletions
|
@ -183,6 +183,16 @@ gst_sctp_association_init (GstSctpAssociation * self)
|
|||
/* Explicit Congestion Notification */
|
||||
usrsctp_sysctl_set_sctp_ecn_enable (0);
|
||||
|
||||
/* Do not send ABORTs in response to INITs (1).
|
||||
* Do not send ABORTs for received Out of the Blue packets (2).
|
||||
*/
|
||||
usrsctp_sysctl_set_sctp_blackhole (2);
|
||||
|
||||
/* Enable interleaving messages for different streams (incoming)
|
||||
* See: https://tools.ietf.org/html/rfc6458#section-8.1.20
|
||||
*/
|
||||
usrsctp_sysctl_set_sctp_default_frag_interleave (2);
|
||||
|
||||
usrsctp_sysctl_set_sctp_nr_outgoing_streams_default
|
||||
(DEFAULT_NUMBER_OF_SCTP_STREAMS);
|
||||
}
|
||||
|
@ -449,11 +459,15 @@ gst_sctp_association_send_data (GstSctpAssociation * self, const guint8 * buf,
|
|||
remote_addr = get_sctp_socket_address (self, self->remote_port);
|
||||
g_mutex_unlock (&self->association_mutex);
|
||||
|
||||
/* TODO: We probably want to split too large chunks into multiple packets
|
||||
* and only set the SCTP_EOR flag on the last one. Firefox is using 0x4000
|
||||
* as the maximum packet size
|
||||
*/
|
||||
memset (&spa, 0, sizeof (spa));
|
||||
|
||||
spa.sendv_sndinfo.snd_ppid = g_htonl (ppid);
|
||||
spa.sendv_sndinfo.snd_sid = stream_id;
|
||||
spa.sendv_sndinfo.snd_flags = ordered ? 0 : SCTP_UNORDERED;
|
||||
spa.sendv_sndinfo.snd_flags = SCTP_EOR | (ordered ? 0 : SCTP_UNORDERED);
|
||||
spa.sendv_sndinfo.snd_context = 0;
|
||||
spa.sendv_sndinfo.snd_assoc_id = 0;
|
||||
spa.sendv_flags = SCTP_SEND_SNDINFO_VALID;
|
||||
|
@ -532,15 +546,17 @@ create_sctp_socket (GstSctpAssociation * self)
|
|||
struct linger l;
|
||||
struct sctp_event event;
|
||||
struct sctp_assoc_value stream_reset;
|
||||
int buf_size = 1024 * 1024;
|
||||
int value = 1;
|
||||
guint16 event_types[] = {
|
||||
SCTP_ASSOC_CHANGE,
|
||||
SCTP_PEER_ADDR_CHANGE,
|
||||
SCTP_REMOTE_ERROR,
|
||||
SCTP_SEND_FAILED,
|
||||
SCTP_SEND_FAILED_EVENT,
|
||||
SCTP_SHUTDOWN_EVENT,
|
||||
SCTP_ADAPTATION_INDICATION,
|
||||
/*SCTP_PARTIAL_DELIVERY_EVENT, */
|
||||
SCTP_PARTIAL_DELIVERY_EVENT,
|
||||
/*SCTP_AUTHENTICATION_EVENT, */
|
||||
SCTP_STREAM_RESET_EVENT,
|
||||
/*SCTP_SENDER_DRY_EVENT, */
|
||||
|
@ -559,6 +575,19 @@ create_sctp_socket (GstSctpAssociation * self)
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (usrsctp_setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
|
||||
(const void *) &buf_size, sizeof (buf_size)) < 0) {
|
||||
GST_ERROR_OBJECT (self, "Could not change receive buffer size: (%u) %s",
|
||||
errno, g_strerror (errno));
|
||||
goto error;
|
||||
}
|
||||
if (usrsctp_setsockopt (sock, SOL_SOCKET, SO_SNDBUF,
|
||||
(const void *) &buf_size, sizeof (buf_size)) < 0) {
|
||||
GST_ERROR_OBJECT (self, "Could not change send buffer size: (%u) %s",
|
||||
errno, g_strerror (errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Properly return errors */
|
||||
if (usrsctp_set_non_blocking (sock, 1) < 0) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
|
@ -577,19 +606,34 @@ create_sctp_socket (GstSctpAssociation * self)
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (usrsctp_setsockopt (sock, IPPROTO_SCTP, SCTP_REUSE_PORT, &value,
|
||||
sizeof (int))) {
|
||||
GST_DEBUG_OBJECT (self, "Could not set SCTP_REUSE_PORT: (%u) %s", errno,
|
||||
g_strerror (errno));
|
||||
}
|
||||
|
||||
if (usrsctp_setsockopt (sock, IPPROTO_SCTP, SCTP_NODELAY, &value,
|
||||
sizeof (int))) {
|
||||
GST_ERROR_OBJECT (self, "Could not set SCTP_NODELAY: (%u) %s", errno,
|
||||
GST_DEBUG_OBJECT (self, "Could not set SCTP_NODELAY: (%u) %s", errno,
|
||||
g_strerror (errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (usrsctp_setsockopt (sock, IPPROTO_SCTP, SCTP_EXPLICIT_EOR, &value,
|
||||
sizeof (int))) {
|
||||
GST_ERROR_OBJECT (self, "Could not set SCTP_EXPLICIT_EOR: (%u) %s", errno,
|
||||
g_strerror (errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
memset (&stream_reset, 0, sizeof (stream_reset));
|
||||
stream_reset.assoc_id = SCTP_ALL_ASSOC;
|
||||
stream_reset.assoc_value = 1;
|
||||
stream_reset.assoc_value =
|
||||
SCTP_ENABLE_RESET_STREAM_REQ | SCTP_ENABLE_CHANGE_ASSOC_REQ;
|
||||
if (usrsctp_setsockopt (sock, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET,
|
||||
&stream_reset, sizeof (stream_reset))) {
|
||||
GST_ERROR_OBJECT (self, "Could not set SCTP_ENABLE_STREAM_RESET: (%u) %s",
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Could not set SCTP_ENABLE_STREAM_RESET | SCTP_ENABLE_CHANGE_ASSOC_REQ: (%u) %s",
|
||||
errno, g_strerror (errno));
|
||||
goto error;
|
||||
}
|
||||
|
@ -634,6 +678,8 @@ static gboolean
|
|||
client_role_connect (GstSctpAssociation * self)
|
||||
{
|
||||
struct sockaddr_conn local_addr, remote_addr;
|
||||
struct sctp_paddrparams paddrparams;
|
||||
socklen_t opt_len;
|
||||
gint ret;
|
||||
|
||||
g_mutex_lock (&self->association_mutex);
|
||||
|
@ -658,6 +704,36 @@ client_role_connect (GstSctpAssociation * self)
|
|||
g_strerror (errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
memset (&paddrparams, 0, sizeof (struct sctp_paddrparams));
|
||||
memcpy (&paddrparams.spp_address, &remote_addr,
|
||||
sizeof (struct sockaddr_conn));
|
||||
opt_len = (socklen_t) sizeof (struct sctp_paddrparams);
|
||||
ret =
|
||||
usrsctp_getsockopt (self->sctp_ass_sock, IPPROTO_SCTP,
|
||||
SCTP_PEER_ADDR_PARAMS, &paddrparams, &opt_len);
|
||||
if (ret < 0) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"usrsctp_getsockopt(SCTP_PEER_ADDR_PARAMS) error: (%u) %s", errno,
|
||||
g_strerror (errno));
|
||||
} else {
|
||||
/* draft-ietf-rtcweb-data-channel-13 section 5: max initial MTU IPV4 1200, IPV6 1280 */
|
||||
paddrparams.spp_pathmtu = 1200;
|
||||
paddrparams.spp_flags &= ~SPP_PMTUD_ENABLE;
|
||||
paddrparams.spp_flags |= SPP_PMTUD_DISABLE;
|
||||
opt_len = (socklen_t) sizeof (struct sctp_paddrparams);
|
||||
ret = usrsctp_setsockopt (self->sctp_ass_sock, IPPROTO_SCTP,
|
||||
SCTP_PEER_ADDR_PARAMS, &paddrparams, opt_len);
|
||||
if (ret < 0) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"usrsctp_setsockopt(SCTP_PEER_ADDR_PARAMS) error: (%u) %s", errno,
|
||||
g_strerror (errno));
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (self, "PMTUD disabled, MTU set to %u",
|
||||
paddrparams.spp_pathmtu);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
return FALSE;
|
||||
|
|
Loading…
Reference in a new issue