Add new parsing API, for stream and candidates
authorYouness Alaoui <youness.alaoui@collabora.co.uk>
Tue, 5 Feb 2013 23:21:39 +0000 (18:21 -0500)
committerYouness Alaoui <youness.alaoui@collabora.co.uk>
Tue, 5 Feb 2013 23:21:39 +0000 (18:21 -0500)
agent/agent.c
agent/agent.h
docs/reference/libnice/libnice-sections.txt
nice/libnice.sym

index a25bc9a..b481ff6 100644 (file)
@@ -2225,26 +2225,12 @@ nice_agent_get_local_credentials (
   return ret;
 }
 
-NICEAPI_EXPORT int
-nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint component_id, const GSList *candidates)
+static int
+_set_remote_candidates_locked (NiceAgent *agent, Stream *stream,
+    Component *component, const GSList *candidates)
 {
-  const GSList *i; 
+  const GSList *i;
   int added = 0;
-  Stream *stream;
-  Component *component;
-
-  nice_debug ("Agent %p: set_remote_candidates %d %d", agent, stream_id, component_id);
-
-  agent_lock();
-
-  if (!agent_find_component (agent, stream_id, component_id,
-          &stream, &component)) {
-    g_warning ("Could not find component %u in stream %u", component_id,
-        stream_id);
-    added = -1;
-    goto done;
-  }
-
 
   if (agent->reliable && component->tcp == NULL) {
     nice_debug ("Agent %p: not setting remote candidate for s%d:%d because "
@@ -2259,8 +2245,8 @@ nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint compo
    if (nice_address_is_valid (&d->addr) == TRUE) {
      gboolean res =
          priv_add_remote_candidate (agent,
-             stream_id,
-             component_id,
+             stream->id,
+             component->id,
              d->type,
              &d->addr,
              &d->base_addr,
@@ -2283,11 +2269,38 @@ nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint compo
  }
 
  done:
- agent_unlock();
  return added;
 }
 
 
+NICEAPI_EXPORT int
+nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint component_id, const GSList *candidates)
+{
+  int added = 0;
+  Stream *stream;
+  Component *component;
+
+  nice_debug ("Agent %p: set_remote_candidates %d %d", agent, stream_id, component_id);
+
+  agent_lock();
+
+  if (!agent_find_component (agent, stream_id, component_id,
+          &stream, &component)) {
+    g_warning ("Could not find component %u in stream %u", component_id,
+        stream_id);
+    added = -1;
+    goto done;
+  }
+
+  added = _set_remote_candidates_locked (agent, stream, component, candidates);
+
+ done:
+  agent_unlock();
+
+  return added;
+}
+
+
 static gint
 _nice_agent_recv (
   NiceAgent *agent,
@@ -3052,6 +3065,77 @@ nice_agent_get_stream_name (NiceAgent *agent, guint stream_id)
   return name;
 }
 
+static NiceCandidate *
+_get_default_local_candidate_locked (NiceAgent *agent,
+    Stream *stream,  Component *component)
+{
+  GSList *i;
+  NiceCandidate *default_candidate = NULL;
+  NiceCandidate *default_rtp_candidate = NULL;
+
+  if (component->id != NICE_COMPONENT_TYPE_RTP) {
+    Component *rtp_component;
+
+    if (!agent_find_component (agent, stream->id, NICE_COMPONENT_TYPE_RTP,
+            NULL, &rtp_component))
+      goto done;
+
+    default_rtp_candidate = _get_default_local_candidate_locked (agent, stream,
+        rtp_component);
+    if (default_rtp_candidate == NULL)
+      goto done;
+  }
+
+
+  for (i = component->local_candidates; i; i = i->next) {
+    NiceCandidate *local_candidate = i->data;
+
+    /* Only check for ipv4 candidates */
+    if (nice_address_ip_version (&local_candidate->addr) != 4)
+      continue;
+    if (component->id == NICE_COMPONENT_TYPE_RTP) {
+      if (default_candidate == NULL ||
+          local_candidate->priority < default_candidate->priority) {
+        default_candidate = local_candidate;
+      }
+    } else if (strncmp (local_candidate->foundation,
+            default_rtp_candidate->foundation,
+            NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
+      default_candidate = local_candidate;
+      break;
+    }
+  }
+
+ done:
+  return default_candidate;
+}
+
+NICEAPI_EXPORT NiceCandidate *
+nice_agent_get_default_local_candidate (NiceAgent *agent,
+    guint stream_id,  guint component_id)
+{
+  Stream *stream = NULL;
+  Component *component = NULL;
+  NiceCandidate *default_candidate = NULL;
+
+  agent_lock ();
+
+  /* step: check if the component exists*/
+  if (!agent_find_component (agent, stream_id, component_id,
+          &stream, &component))
+    goto done;
+
+  default_candidate = _get_default_local_candidate_locked (agent, stream,
+      component);
+  if (default_candidate)
+    default_candidate = nice_candidate_copy (default_candidate);
+
+ done:
+  agent_unlock ();
+
+  return default_candidate;
+}
+
 static const gchar *
 _cand_type_to_sdp (NiceCandidateType type) {
   switch(type) {
@@ -3067,17 +3151,34 @@ _cand_type_to_sdp (NiceCandidateType type) {
   }
 }
 
+static void
+_generate_candidate_sdp (NiceAgent *agent,
+    NiceCandidate *candidate, GString *sdp)
+{
+  gchar ip4[INET6_ADDRSTRLEN];
 
-NICEAPI_EXPORT gchar *
-nice_agent_generate_local_sdp (NiceAgent *agent)
+  nice_address_to_string (&candidate->addr, ip4);
+  g_string_append_printf (sdp, "a=candidate:%.*s %d %s %d %s %d",
+      NICE_CANDIDATE_MAX_FOUNDATION, candidate->foundation,
+      candidate->component_id,
+      candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "???",
+      candidate->priority, ip4, nice_address_get_port (&candidate->addr));
+  g_string_append_printf (sdp, " typ %s", _cand_type_to_sdp (candidate->type));
+  if (nice_address_is_valid (&candidate->base_addr) &&
+      !nice_address_equal (&candidate->addr, &candidate->base_addr)) {
+    nice_address_to_string (&candidate->base_addr, ip4);
+    g_string_append_printf (sdp, " raddr %s rport %d", ip4,
+        nice_address_get_port (&candidate->base_addr));
+  }
+}
+
+static void
+_generate_stream_sdp (NiceAgent *agent, Stream *stream,
+    GString *sdp, gboolean include_non_ice)
 {
-  GString * sdp = g_string_new (NULL);
-  GSList *i, *j, *k;
+  GSList *i, *j;
 
-  agent_lock();
-  for (i = agent->streams; i; i = i->next) {
-    Stream *stream = i->data;
-    NiceCandidate *default_candidate = NULL;
+  if (include_non_ice) {
     NiceAddress rtp, rtcp;
     gchar ip4[INET6_ADDRSTRLEN];
 
@@ -3087,31 +3188,20 @@ nice_agent_generate_local_sdp (NiceAgent *agent)
     nice_address_set_ipv4 (&rtcp, 0);
 
     /* Find default candidates */
-    for (j = stream->components; j; j = j->next) {
-      Component *component = j->data;
-
-      for (k = component->local_candidates; k; k = k->next) {
-        NiceCandidate *local_candidate = k->data;
-
-        if (local_candidate->component_id > 2)
-          continue;
-
-        /* Only check for ipv4 candidates */
-        if (nice_address_ip_version (&local_candidate->addr) != 4)
-          continue;
-        if (component->id == NICE_COMPONENT_TYPE_RTP) {
-          if (default_candidate == NULL ||
-              local_candidate->priority < default_candidate->priority) {
-            default_candidate = local_candidate;
-            rtp = local_candidate->addr;
-          }
-        } else if (component->id == NICE_COMPONENT_TYPE_RTCP &&
-            default_candidate != NULL &&
-            strncmp (local_candidate->foundation, default_candidate->foundation,
-                NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
-          rtcp = local_candidate->addr;
-          break;
-        }
+    for (i = stream->components; i; i = i->next) {
+      Component *component = i->data;
+      NiceCandidate *default_candidate;
+
+      if (component->id == NICE_COMPONENT_TYPE_RTP) {
+        default_candidate = _get_default_local_candidate_locked (agent, stream,
+            component);
+        if (default_candidate)
+          rtp = default_candidate->addr;
+      } else if (component->id == NICE_COMPONENT_TYPE_RTCP) {
+        default_candidate = _get_default_local_candidate_locked (agent, stream,
+            component);
+        if (default_candidate)
+          rtcp = default_candidate->addr;
       }
     }
 
@@ -3122,31 +3212,78 @@ nice_agent_generate_local_sdp (NiceAgent *agent)
     if (nice_address_get_port (&rtcp) != 0)
       g_string_append_printf (sdp, "a=rtcp:%d\n",
           nice_address_get_port (&rtcp));
-    g_string_append_printf (sdp, "a=ice-ufrag:%s\n", stream->local_ufrag);
-    g_string_append_printf (sdp, "a=ice-pwd:%s\n", stream->local_password);
+  }
 
-    for (j = stream->components; j; j = j->next) {
-      Component *component = j->data;
+  g_string_append_printf (sdp, "a=ice-ufrag:%s\n", stream->local_ufrag);
+  g_string_append_printf (sdp, "a=ice-pwd:%s\n", stream->local_password);
 
-      for (k = component->local_candidates; k; k = k->next) {
-        NiceCandidate *cand = k->data;
-
-        nice_address_to_string (&cand->addr, ip4);
-        g_string_append_printf (sdp, "a=candidate:%.*s %d %s %d %s %d",
-            NICE_CANDIDATE_MAX_FOUNDATION, cand->foundation, cand->component_id,
-            cand->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "???",
-            cand->priority, ip4, nice_address_get_port (&cand->addr));
-        g_string_append_printf (sdp, " typ %s", _cand_type_to_sdp (cand->type));
-        if (nice_address_is_valid (&cand->base_addr) &&
-            !nice_address_equal (&cand->addr, &cand->base_addr)) {
-          nice_address_to_string (&cand->base_addr, ip4);
-          g_string_append_printf (sdp, " raddr %s rport %d", ip4,
-              nice_address_get_port (&cand->base_addr));
-        }
-        g_string_append (sdp, "\n");
-      }
+  for (i = stream->components; i; i = i->next) {
+    Component *component = i->data;
+
+    for (j = component->local_candidates; j; j = j->next) {
+      NiceCandidate *candidate = j->data;
+
+      _generate_candidate_sdp (agent, candidate, sdp);
+      g_string_append (sdp, "\n");
     }
   }
+}
+
+NICEAPI_EXPORT gchar *
+nice_agent_generate_local_sdp (NiceAgent *agent)
+{
+  GString * sdp = g_string_new (NULL);
+  GSList *i;
+
+  agent_lock();
+
+  for (i = agent->streams; i; i = i->next) {
+    Stream *stream = i->data;
+
+    _generate_stream_sdp (agent, stream, sdp, TRUE);
+  }
+
+  agent_unlock();
+
+  return g_string_free (sdp, FALSE);
+}
+
+NICEAPI_EXPORT gchar *
+nice_agent_generate_local_stream_sdp (NiceAgent *agent, guint stream_id,
+    gboolean include_non_ice)
+{
+  GString *sdp = NULL;
+  gchar *ret = NULL;
+  Stream *stream;
+
+  agent_lock();
+
+  stream = agent_find_stream (agent, stream_id);
+  if (stream == NULL)
+    goto done;
+
+  sdp = g_string_new (NULL);
+  _generate_stream_sdp (agent, stream, sdp, include_non_ice);
+  ret = g_string_free (sdp, FALSE);
+
+ done:
+  agent_unlock();
+
+  return ret;
+}
+
+NICEAPI_EXPORT gchar *
+nice_agent_generate_local_candidate_sdp (NiceAgent *agent,
+    NiceCandidate *candidate)
+{
+  GString *sdp = NULL;
+
+  g_return_val_if_fail(candidate, NULL);
+
+  agent_lock();
+
+  sdp = g_string_new (NULL);
+  _generate_candidate_sdp (agent, candidate, sdp);
 
   agent_unlock();
 
@@ -3193,137 +3330,93 @@ nice_agent_parse_remote_sdp (NiceAgent *agent, const gchar *sdp)
       }
       g_free (name);
     } else if (g_str_has_prefix (sdp_lines[i], "a=ice-ufrag:")) {
-      const gchar *ufrag = sdp_lines[i] + 12;
-
       if (current_stream == NULL) {
         ret = -1;
         goto done;
       }
-      g_strlcpy (current_stream->remote_ufrag, ufrag, NICE_STREAM_MAX_UFRAG);
+      g_strlcpy (current_stream->remote_ufrag, sdp_lines[i] + 12,
+          NICE_STREAM_MAX_UFRAG);
     } else if (g_str_has_prefix (sdp_lines[i], "a=ice-pwd:")) {
-      const gchar *pwd = sdp_lines[i] + 10;
-
       if (current_stream == NULL) {
         ret = -1;
         goto done;
       }
-      g_strlcpy (current_stream->remote_password, pwd, NICE_STREAM_MAX_PWD);
+      g_strlcpy (current_stream->remote_password, sdp_lines[i] + 10,
+          NICE_STREAM_MAX_PWD);
     } else if (g_str_has_prefix (sdp_lines[i], "a=candidate:")) {
-      const gchar *candidate = sdp_lines[i] + 12;
-      int ntype = -1;
-      gchar **tokens = NULL;
-      const gchar *foundation = NULL;
-      guint component_id;
-      const gchar *transport = NULL;
-      guint32 priority;
-      const gchar *addr = NULL;
-      guint16 port;
-      const gchar *type = NULL;
-      const gchar *raddr = NULL;
-      guint16 rport;
-      static const gchar *type_names[] = {"host", "srflx", "prflx", "relay"};
-      guint j;
+      NiceCandidate *candidate = NULL;
+      Component *component = NULL;
+      GSList *cands = NULL;
+      gint added;
 
       if (current_stream == NULL) {
         ret = -1;
         goto done;
       }
-
-      tokens = g_strsplit (candidate, " ", 0);
-      for (j = 0; tokens && tokens[j]; j++) {
-        switch (j) {
-          case 0:
-            foundation = tokens[j];
-            break;
-          case 1:
-            component_id = (guint) g_ascii_strtoull (tokens[j], NULL, 10);
-            break;
-          case 2:
-            transport = tokens[j];
-            break;
-          case 3:
-            priority = (guint32) g_ascii_strtoull (tokens[j], NULL, 10);
-            break;
-          case 4:
-            addr = tokens[j];
-            break;
-          case 5:
-            port = (guint16) g_ascii_strtoull (tokens[j], NULL, 10);
-            break;
-          default:
-            if (tokens[j + 1] == NULL) {
-              g_strfreev(tokens);
-              ret = -1;
-              goto done;
-            }
-            if (g_strcmp0 (tokens[j], "typ") == 0) {
-              type = tokens[j + 1];
-            } else if (g_strcmp0 (tokens[j], "raddr") == 0) {
-              raddr = tokens[j + 1];
-            } else if (g_strcmp0 (tokens[j], "rport") == 0) {
-              rport = (guint16) g_ascii_strtoull (tokens[j + 1], NULL, 10);
-            }
-            j++;
-            break;
-        }
-      }
-      if (type == NULL) {
-        g_strfreev(tokens);
+      candidate = nice_agent_parse_remote_candidate_sdp (agent,
+          current_stream->id, sdp_lines[i]);
+      if (candidate == NULL) {
         ret = -1;
         goto done;
       }
 
-      ntype = -1;
-      for (j = 0; j < G_N_ELEMENTS (type_names); j++) {
-        if (g_strcmp0 (type, type_names[j]) == 0) {
-          ntype = j;
-          break;
-        }
-      }
-      if (ntype == -1) {
-        g_strfreev(tokens);
+      if (!agent_find_component (agent, candidate->stream_id,
+              candidate->component_id, NULL, &component)) {
+        nice_candidate_free (candidate);
         ret = -1;
         goto done;
       }
+      cands = g_slist_prepend (cands, candidate);
+      added = _set_remote_candidates_locked (agent, current_stream,
+          component, cands);
+      g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);
+      if (added > 0)
+        ret++;
+    }
+  }
 
-      if (g_strcmp0 (transport, "UDP") == 0) {
-        NiceCandidate *cand = NULL;
-        GSList *cands = NULL;
-        gint added;
-
-        cand = nice_candidate_new(ntype);
-        cand->component_id = component_id;
-        cand->stream_id = current_stream->id;
-        cand->transport = NICE_CANDIDATE_TRANSPORT_UDP;
-        g_strlcpy(cand->foundation, foundation, NICE_CANDIDATE_MAX_FOUNDATION);
-        cand->priority = priority;
-
-        if (!nice_address_set_from_string (&cand->addr, addr)) {
-          nice_candidate_free (cand);
-          g_strfreev(tokens);
-          ret = -1;
-          goto done;
-        }
-        nice_address_set_port (&cand->addr, port);
-
-        if (raddr && rport) {
-          if (!nice_address_set_from_string (&cand->base_addr, raddr)) {
-            nice_candidate_free (cand);
-            g_strfreev(tokens);
-            ret = -1;
-            goto done;
-          }
-          nice_address_set_port (&cand->base_addr, rport);
-        }
+ done:
+  if (sdp_lines)
+    g_strfreev(sdp_lines);
 
-        cands = g_slist_prepend (cands, cand);
-        added = nice_agent_set_remote_candidates (agent, current_stream->id,
-            component_id, cands);
-        g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);
-        if (added > 0)
-          ret++;
+  agent_unlock();
+
+  return ret;
+}
+
+NICEAPI_EXPORT GSList *
+nice_agent_parse_remote_stream_sdp (NiceAgent *agent, guint stream_id,
+    const gchar *sdp, gchar **ufrag, gchar **pwd)
+{
+  Stream *stream = NULL;
+  gchar **sdp_lines = NULL;
+  GSList *candidates = NULL;
+  gint i;
+
+  agent_lock();
+
+  stream = agent_find_stream (agent, stream_id);
+  if (stream == NULL) {
+    goto done;
+  }
+
+  sdp_lines = g_strsplit (sdp, "\n", 0);
+  for (i = 0; sdp_lines && sdp_lines[i]; i++) {
+    if (ufrag && g_str_has_prefix (sdp_lines[i], "a=ice-ufrag:")) {
+      *ufrag = g_strdup (sdp_lines[i] + 12);
+    } else if (pwd && g_str_has_prefix (sdp_lines[i], "a=ice-pwd:")) {
+      *pwd = g_strdup (sdp_lines[i] + 10);
+    } else if (g_str_has_prefix (sdp_lines[i], "a=candidate:")) {
+      NiceCandidate *candidate = NULL;
+
+      candidate = nice_agent_parse_remote_candidate_sdp (agent, stream->id,
+          sdp_lines[i]);
+      if (candidate == NULL) {
+        g_slist_free_full(candidates, (GDestroyNotify)&nice_candidate_free);
+        candidates = NULL;
+        break;
       }
-      g_strfreev(tokens);
+      candidates = g_slist_prepend (candidates, candidate);
     }
   }
 
@@ -3333,5 +3426,108 @@ nice_agent_parse_remote_sdp (NiceAgent *agent, const gchar *sdp)
 
   agent_unlock();
 
-  return ret;
+  return candidates;
+}
+
+NICEAPI_EXPORT NiceCandidate *
+nice_agent_parse_remote_candidate_sdp (NiceAgent *agent, guint stream_id,
+    const gchar *sdp)
+{
+  NiceCandidate *candidate = NULL;
+  int ntype = -1;
+  gchar **tokens = NULL;
+  const gchar *foundation = NULL;
+  guint component_id;
+  const gchar *transport = NULL;
+  guint32 priority;
+  const gchar *addr = NULL;
+  guint16 port;
+  const gchar *type = NULL;
+  const gchar *raddr = NULL;
+  guint16 rport;
+  static const gchar *type_names[] = {"host", "srflx", "prflx", "relay"};
+  guint i;
+
+  if (!g_str_has_prefix (sdp, "a=candidate:"))
+    goto done;
+
+  tokens = g_strsplit (sdp + 12, " ", 0);
+  for (i = 0; tokens && tokens[i]; i++) {
+    switch (i) {
+      case 0:
+        foundation = tokens[i];
+        break;
+      case 1:
+        component_id = (guint) g_ascii_strtoull (tokens[i], NULL, 10);
+        break;
+      case 2:
+        transport = tokens[i];
+        break;
+      case 3:
+        priority = (guint32) g_ascii_strtoull (tokens[i], NULL, 10);
+        break;
+      case 4:
+        addr = tokens[i];
+        break;
+      case 5:
+        port = (guint16) g_ascii_strtoull (tokens[i], NULL, 10);
+        break;
+      default:
+        if (tokens[i + 1] == NULL)
+          goto done;
+
+        if (g_strcmp0 (tokens[i], "typ") == 0) {
+          type = tokens[i + 1];
+        } else if (g_strcmp0 (tokens[i], "raddr") == 0) {
+          raddr = tokens[i + 1];
+        } else if (g_strcmp0 (tokens[i], "rport") == 0) {
+          rport = (guint16) g_ascii_strtoull (tokens[i + 1], NULL, 10);
+        }
+        i++;
+        break;
+    }
+  }
+  if (type == NULL)
+    goto done;
+
+  ntype = -1;
+  for (i = 0; i < G_N_ELEMENTS (type_names); i++) {
+    if (g_strcmp0 (type, type_names[i]) == 0) {
+      ntype = i;
+      break;
+    }
+  }
+  if (ntype == -1)
+    goto done;
+
+  if (g_strcmp0 (transport, "UDP") == 0) {
+    candidate = nice_candidate_new(ntype);
+    candidate->component_id = component_id;
+    candidate->stream_id = stream_id;
+    candidate->transport = NICE_CANDIDATE_TRANSPORT_UDP;
+    g_strlcpy(candidate->foundation, foundation, NICE_CANDIDATE_MAX_FOUNDATION);
+    candidate->priority = priority;
+
+    if (!nice_address_set_from_string (&candidate->addr, addr)) {
+      nice_candidate_free (candidate);
+      candidate = NULL;
+      goto done;
+    }
+    nice_address_set_port (&candidate->addr, port);
+
+    if (raddr && rport) {
+      if (!nice_address_set_from_string (&candidate->base_addr, raddr)) {
+        nice_candidate_free (candidate);
+        candidate = NULL;
+        goto done;
+      }
+      nice_address_set_port (&candidate->base_addr, rport);
+    }
+  }
+
+ done:
+  if (tokens)
+    g_strfreev(tokens);
+
+  return candidate;
 }
index 082d598..0655744 100644 (file)
@@ -824,10 +824,38 @@ const gchar *nice_agent_get_stream_name (
     guint stream_id);
 
 /**
+ * nice_agent_get_default_local_candidate:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * This helper function will return the recommended default candidate to be
+ * used for non-ICE compatible clients. This will usually be the candidate
+ * with the lowest priority, since it will be the longest path but the one with
+ * the most chances of success.
+ * <note>
+     <para>
+     This function is only useful in order to manually generate the
+     local SDP
+     </para>
+ * </note>
+ *
+ * Returns: The candidate to be used as the default candidate, or %NULL in case
+ * of error. Must be freed with nice_candidate_free() once done.
+ *
+ */
+NiceCandidate *
+nice_agent_get_default_local_candidate (
+    NiceAgent *agent,
+    guint stream_id,
+    guint component_id);
+
+/**
  * nice_agent_generate_local_sdp:
  * @agent: The #NiceAgent Object
  *
- * Generate an SDP string containing the local candidates and credentials.
+ * Generate an SDP string containing the local candidates and credentials for
+ * all streams and components in the agent.
  *
  <note>
    <para>
@@ -842,12 +870,15 @@ const gchar *nice_agent_get_stream_name (
    </para>
    <para>
      The default candidate in the SDP will be selected based on the lowest
-     priority candidate.
+     priority candidate for the first component.
    </para>
  </note>
  *
  * <para>See also: nice_agent_set_stream_name() </para>
  * <para>See also: nice_agent_parse_remote_sdp() </para>
+ * <para>See also: nice_agent_generate_local_stream_sdp() </para>
+ * <para>See also: nice_agent_generate_local_candidate_sdp() </para>
+ * <para>See also: nice_agent_get_default_local_candidate() </para>
  *
  * Returns: A string representing the local SDP. Must be freed with g_free()
  * once done.
@@ -859,6 +890,69 @@ nice_agent_generate_local_sdp (
   NiceAgent *agent);
 
 /**
+ * nice_agent_generate_local_stream_sdp:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @include_non_ice: Whether or not to include non ICE specific lines
+ * (m=, c= and a=rtcp: lines)
+ *
+ * Generate an SDP string containing the local candidates and credentials
+ * for a stream.
+ *
+ <note>
+   <para>
+     The SDP will not contain any codec lines and the 'm' line will not list
+     any payload types.
+   </para>
+   <para>
+    It is highly recommended to set the name of the stream prior to calling this
+    function. Unnamed streams will show up as '-' in the 'm' line.
+   </para>
+   <para>
+     The default candidate in the SDP will be selected based on the lowest
+     priority candidate.
+   </para>
+ </note>
+ *
+ * <para>See also: nice_agent_set_stream_name() </para>
+ * <para>See also: nice_agent_parse_remote_stream_sdp() </para>
+ * <para>See also: nice_agent_generate_local_sdp() </para>
+ * <para>See also: nice_agent_generate_local_candidate_sdp() </para>
+ * <para>See also: nice_agent_get_default_local_candidate() </para>
+ *
+ * Returns: A string representing the local SDP for the stream. Must be freed
+ * with g_free() once done.
+ *
+ * Since: 0.1.4
+ **/
+gchar *
+nice_agent_generate_local_stream_sdp (
+    NiceAgent *agent,
+    guint stream_id,
+    gboolean include_non_ice);
+
+/**
+ * nice_agent_generate_local_candidate_sdp:
+ * @agent: The #NiceAgent Object
+ * @candidate: The candidate to generate
+ *
+ * Generate an SDP string representing a local candidate.
+ *
+ * <para>See also: nice_agent_parse_remote_candidate_sdp() </para>
+ * <para>See also: nice_agent_generate_local_sdp() </para>
+ * <para>See also: nice_agent_generate_local_stream_sdp() </para>
+ *
+ * Returns: A string representing the SDP for the candidate. Must be freed
+ * with g_free() once done.
+ *
+ * Since: 0.1.4
+ **/
+gchar *
+nice_agent_generate_local_candidate_sdp (
+    NiceAgent *agent,
+    NiceCandidate *candidate);
+
+/**
  * nice_agent_parse_remote_sdp:
  * @agent: The #NiceAgent Object
  * @sdp: The remote SDP to parse
@@ -877,6 +971,8 @@ nice_agent_generate_local_sdp (
  *
  * <para>See also: nice_agent_set_stream_name() </para>
  * <para>See also: nice_agent_generate_local_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_stream_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_candidate_sdp() </para>
  *
  * Returns: The number of candidates added, negative on errors
  *
@@ -888,6 +984,59 @@ nice_agent_parse_remote_sdp (
     const gchar *sdp);
 
 
+/**
+ * nice_agent_parse_remote_stream_sdp:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream to parse
+ * @sdp: The remote SDP to parse
+ * @ufrag: Pointer to store the ice ufrag if non %NULL. Must be freed with
+ * g_free() after use
+ * @pwd: Pointer to store the ice password if non %NULL. Must be freed with
+ * g_free() after use
+ *
+ * Parse an SDP string representing a single stream and extracts candidates
+ * and credentials from it.
+ *
+ * <para>See also: nice_agent_generate_local_stream_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_candidate_sdp() </para>
+ *
+ * Returns: A #GSList of candidates parsed from the SDP, or %NULL in case of
+ * errors
+ *
+ * Since: 0.1.4
+ **/
+GSList *
+nice_agent_parse_remote_stream_sdp (
+    NiceAgent *agent,
+    guint stream_id,
+    const gchar *sdp,
+    gchar **ufrag,
+    gchar **pwd);
+
+
+/**
+ * nice_agent_parse_remote_candidate_sdp:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream the candidate belongs to
+ * @sdp: The remote SDP to parse
+ *
+ * Parse an SDP string and extracts the candidate from it.
+ *
+ * <para>See also: nice_agent_generate_local_candidate_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_stream_sdp() </para>
+ *
+ * Returns: The parsed candidate or %NULL if there was an error.
+ *
+ * Since: 0.1.4
+ **/
+NiceCandidate *
+nice_agent_parse_remote_candidate_sdp (
+    NiceAgent *agent,
+    guint stream_id,
+    const gchar *sdp);
+
 G_END_DECLS
 
 #endif /* _AGENT_H */
index 043e8d8..8da7505 100644 (file)
@@ -30,8 +30,13 @@ nice_agent_set_software
 nice_agent_restart
 nice_agent_set_stream_name
 nice_agent_get_stream_name
+nice_agent_get_default_local_candidate
 nice_agent_generate_local_sdp
+nice_agent_generate_local_stream_sdp
+nice_agent_generate_local_canidate_sdp
 nice_agent_parse_remote_sdp
+nice_agent_parse_remote_stream_sdp
+nice_agent_parse_remote_candidate_sdp
 <SUBSECTION Standard>
 NICE_AGENT
 NICE_IS_AGENT
index ebbf570..d1a51ab 100644 (file)
@@ -18,7 +18,10 @@ nice_agent_add_local_address
 nice_agent_add_stream
 nice_agent_attach_recv
 nice_agent_gather_candidates
+nice_agent_generate_local_candidate_sdp
 nice_agent_generate_local_sdp
+nice_agent_generate_local_stream_sdp
+nice_agent_get_default_local_candidate
 nice_agent_get_local_candidates
 nice_agent_get_local_credentials
 nice_agent_get_remote_candidates
@@ -27,7 +30,9 @@ nice_agent_get_stream_name
 nice_agent_get_type
 nice_agent_new
 nice_agent_new_reliable
+nice_agent_parse_remote_candidate_sdp
 nice_agent_parse_remote_sdp
+nice_agent_parse_remote_stream_sdp
 nice_agent_remove_stream
 nice_agent_restart
 nice_agent_send