summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Waters <matthew@centricular.com>2020-08-20 12:58:30 +1000
committerMatthew Waters <matthew@centricular.com>2020-08-20 13:01:17 +1000
commit9011539940b34f07ceccf04dd6bb89bbad316cb5 (patch)
treec964a995d098af1aa67febab025bdf911bd58817
parent8e9f8c7f2c7be7e05a4992a31eeea294313c33aa (diff)
downloadgstreamer-plugins-bad-9011539940b34f07ceccf04dd6bb89bbad316cb5.tar.gz
webrtc/ice: resolve .local candidates internally
Requires the system's DNS resolver to support mdns resolution. Fixes interoperablity with recent versions of chrome/firefox that produce .local address in for local candidates. Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1139
-rw-r--r--ext/webrtc/gstwebrtcice.c95
1 files changed, 93 insertions, 2 deletions
diff --git a/ext/webrtc/gstwebrtcice.c b/ext/webrtc/gstwebrtcice.c
index 23a490baa..20556fb7f 100644
--- a/ext/webrtc/gstwebrtcice.c
+++ b/ext/webrtc/gstwebrtcice.c
@@ -611,6 +611,47 @@ _candidate_type_to_string (NiceCandidateType type)
}
#endif
+/* parse the address for possible resolution */
+static gboolean
+get_candidate_address (const gchar * candidate, gchar ** prefix,
+ gchar ** address, gchar ** postfix)
+{
+ char **tokens = NULL;
+
+ if (!g_str_has_prefix (candidate, "a=candidate:")) {
+ GST_ERROR ("candidate \"%s\" does not start with \"a=candidate:\"",
+ candidate);
+ goto failure;
+ }
+
+ if (!(tokens = g_strsplit (candidate, " ", 6))) {
+ GST_ERROR ("candidate \"%s\" could not be tokenized", candidate);
+ goto failure;
+ }
+
+ if (g_strv_length (tokens) < 6) {
+ GST_ERROR ("candidate \"%s\" tokenization resulted in not enough tokens",
+ candidate);
+ goto failure;
+ }
+
+ if (address)
+ *address = g_strdup (tokens[4]);
+ tokens[4] = NULL;
+ if (prefix)
+ *prefix = g_strjoinv (" ", tokens);
+ if (postfix)
+ *postfix = g_strdup (tokens[5]);
+
+ g_strfreev (tokens);
+ return TRUE;
+
+failure:
+ if (tokens)
+ g_strfreev (tokens);
+ return FALSE;
+}
+
/* must start with "a=candidate:" */
void
gst_webrtc_ice_add_candidate (GstWebRTCICE * ice, GstWebRTCICEStream * stream,
@@ -627,8 +668,58 @@ gst_webrtc_ice_add_candidate (GstWebRTCICE * ice, GstWebRTCICEStream * stream,
nice_agent_parse_remote_candidate_sdp (ice->priv->nice_agent,
item->nice_stream_id, candidate);
if (!cand) {
- GST_WARNING_OBJECT (ice, "Could not parse candidate \'%s\'", candidate);
- return;
+ /* might be a .local candidate */
+ char *prefix = NULL, *address = NULL, *postfix = NULL;
+ char *new_addr, *new_candidate;
+ char *new_candv[4] = { NULL, };
+
+ if (!get_candidate_address (candidate, &prefix, &address, &postfix)) {
+ GST_WARNING_OBJECT (ice, "Failed to retrieve address from candidate %s",
+ candidate);
+ goto fail;
+ }
+
+ if (!g_str_has_suffix (address, ".local")) {
+ GST_WARNING_OBJECT (ice, "candidate address \'%s\' does not end "
+ "with \'.local\'", address);
+ goto fail;
+ }
+
+ /* FIXME: async */
+ if (!(new_addr = _resolve_host (ice, address))) {
+ GST_WARNING_OBJECT (ice, "Failed to resolve %s", address);
+ goto fail;
+ }
+
+ new_candv[0] = prefix;
+ new_candv[1] = new_addr;
+ new_candv[2] = postfix;
+ new_candv[3] = NULL;
+ new_candidate = g_strjoinv (" ", new_candv);
+
+ GST_DEBUG_OBJECT (ice, "resolved to candidate %s", new_candidate);
+
+ cand =
+ nice_agent_parse_remote_candidate_sdp (ice->priv->nice_agent,
+ item->nice_stream_id, new_candidate);
+ g_free (new_candidate);
+ if (!cand) {
+ GST_WARNING_OBJECT (ice, "Could not parse candidate \'%s\'",
+ new_candidate);
+ goto fail;
+ }
+
+ g_free (prefix);
+ g_free (new_addr);
+ g_free (postfix);
+
+ if (0) {
+ fail:
+ g_free (prefix);
+ g_free (address);
+ g_free (postfix);
+ return;
+ }
}
candidates = g_slist_append (candidates, cand);