From 831b12497613a33ae578c529569402118c392ac9 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Wed, 12 Jun 2019 15:00:38 +0200 Subject: [PATCH] webrtcbin: Support data channel SDP offers from Chrome When negotiating a data channel, Chrome as recent as 75 still uses SDP based on version 05 of the SCTP SDP draft, for example: m=application 9 DTLS/SCTP 5000 a=sctpmap:5000 webrtc-datachannel 1024 Implement support for parsing SCTP port out of SDP message with sctpmap attribute. Fixes data channel negotiation with Chrome browser. --- ext/webrtc/gstwebrtcbin.c | 7 ------ ext/webrtc/webrtcsdp.c | 55 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/ext/webrtc/gstwebrtcbin.c b/ext/webrtc/gstwebrtcbin.c index 337384c..923af6b 100644 --- a/ext/webrtc/gstwebrtcbin.c +++ b/ext/webrtc/gstwebrtcbin.c @@ -2794,13 +2794,6 @@ _create_answer_task (GstWebRTCBin * webrtc, const GstStructure * options) "for webrtc-datachannel"); goto rejected; } - if (g_strcmp0 (gst_sdp_media_get_format (offer_media, 0), - "webrtc-datachannel") != 0) { - GST_WARNING_OBJECT (webrtc, - "format field of data channel m= line " - "is not \'webrtc-datachannel\'"); - goto rejected; - } sctp_port = _get_sctp_port_from_media (offer_media); if (sctp_port == -1) { GST_WARNING_OBJECT (webrtc, "media does not contain a sctp port"); diff --git a/ext/webrtc/webrtcsdp.c b/ext/webrtc/webrtcsdp.c index 56ecc79..42d650f 100644 --- a/ext/webrtc/webrtcsdp.c +++ b/ext/webrtc/webrtcsdp.c @@ -712,21 +712,56 @@ _generate_ice_credentials (gchar ** ufrag, gchar ** password) int _get_sctp_port_from_media (const GstSDPMedia * media) { - int sctpmap = -1, i; + int i; + const gchar *format; + gchar *endptr; - for (i = 0; i < gst_sdp_media_attributes_len (media); i++) { - const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i); + if (gst_sdp_media_formats_len (media) != 1) { + /* only exactly one format is supported */ + return -1; + } - if (g_strcmp0 (attr->key, "sctp-port") == 0) { - return atoi (attr->value); - } else if (g_strcmp0 (attr->key, "sctpmap") == 0) { - sctpmap = atoi (attr->value); + format = gst_sdp_media_get_format (media, 0); + + if (g_strcmp0 (format, "webrtc-datachannel") == 0) { + /* draft-ietf-mmusic-sctp-sdp-21, e.g. Firefox 63 and later */ + + for (i = 0; i < gst_sdp_media_attributes_len (media); i++) { + const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i); + + if (g_strcmp0 (attr->key, "sctp-port") == 0) { + gint64 port = g_ascii_strtoll (attr->value, &endptr, 10); + if (endptr == attr->value) { + /* conversion error */ + return -1; + } + return port; + } + } + } else { + /* draft-ietf-mmusic-sctp-sdp-05, e.g. Chrome as recent as 75 */ + gint64 port = g_ascii_strtoll (format, &endptr, 10); + if (endptr == format) { + /* conversion error */ + return -1; + } + + for (i = 0; i < gst_sdp_media_attributes_len (media); i++) { + const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i); + + if (g_strcmp0 (attr->key, "sctpmap") == 0 && atoi (attr->value) == port) { + /* a=sctpmap:5000 webrtc-datachannel 256 */ + gchar **parts = g_strsplit (attr->value, " ", 3); + if (!parts[1] || g_strcmp0 (parts[1], "webrtc-datachannel") != 0) { + port = -1; + } + g_strfreev (parts); + return port; + } } } - if (sctpmap >= 0) - GST_LOG ("no sctp-port attribute in media"); - return sctpmap; + return -1; } guint64 -- 2.7.4