Esempio n. 1
0
static gboolean
kms_webrtc_session_configure_connection (KmsWebrtcSession * self,
    KmsSdpSession * sess, SdpMediaConfig * neg_mconf,
    SdpMediaConfig * remote_mconf, gboolean offerer)
{
  GstSDPMedia *neg_media = kms_sdp_media_config_get_sdp_media (neg_mconf);
  const gchar *neg_proto_str = gst_sdp_media_get_proto (neg_media);
  GstSDPMedia *remote_media = kms_sdp_media_config_get_sdp_media (remote_mconf);
  const gchar *remote_proto_str = gst_sdp_media_get_proto (remote_media);

  if (g_strcmp0 (neg_proto_str, remote_proto_str) != 0) {
    GST_WARNING_OBJECT (self,
        "Negotiated proto ('%s') not matching with remote proto ('%s')",
        neg_proto_str, remote_proto_str);
    return FALSE;
  }

  if (g_strcmp0 (neg_proto_str, "DTLS/SCTP") != 0) {
    return FALSE;
  }

  kms_webrtc_session_add_connection (self, sess, neg_mconf, offerer);

  return TRUE;
}
Esempio n. 2
0
static const gchar *
kms_ice_nice_agent_sdp_media_add_ice_candidate (KmsWebrtcSession * self,
    SdpMediaConfig * mconf, NiceAgent * agent, NiceCandidate * cand)
{
  char *media_stream_id;
  GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  const gchar *mid;

  media_stream_id = kms_webrtc_session_get_stream_id (self, mconf);
  if (media_stream_id == NULL) {
    return NULL;
  }

  if (atoi (media_stream_id) != cand->stream_id) {
    return NULL;
  }

  sdp_media_add_ice_candidate (media, agent, cand);

  mid = kms_sdp_media_config_get_mid (mconf);
  if (mid == NULL) {
    return "";
  }

  return mid;
}
Esempio n. 3
0
static gboolean
kms_webrtc_session_add_connection (KmsWebrtcSession * self,
    KmsSdpSession * sess, SdpMediaConfig * mconf, gboolean offerer)
{
  KmsBaseRtpSession *base_rtp_sess = KMS_BASE_RTP_SESSION (sess);
  gboolean connected, active;
  KmsIRtpConnection *conn;

  conn = kms_base_rtp_session_get_connection (base_rtp_sess, mconf);
  if (conn == NULL) {
    GST_ERROR_OBJECT (self, "No connection created");
    return FALSE;
  }

  g_object_get (conn, "added", &connected, NULL);
  if (connected) {
    GST_DEBUG_OBJECT (self, "Conn already added");
    return TRUE;
  }

  active =
      sdp_utils_media_is_active (kms_sdp_media_config_get_sdp_media (mconf),
      offerer);

  kms_i_rtp_connection_add (conn, GST_BIN (self), active);
  kms_i_rtp_connection_sink_sync_state_with_parent (conn);
  kms_i_rtp_connection_src_sync_state_with_parent (conn);

  return TRUE;
}
Esempio n. 4
0
void
kms_webrtc_session_remote_sdp_add_ice_candidate (KmsWebrtcSession *
    self, KmsIceCandidate * candidate, guint8 index)
{
  KmsSdpSession *sdp_sess = KMS_SDP_SESSION (self);
  SdpMessageContext *remote_sdp_ctx = sdp_sess->remote_sdp_ctx;
  GSList *medias;
  SdpMediaConfig *mconf;

  if (remote_sdp_ctx == NULL) {
    GST_INFO_OBJECT (self, "Cannot update remote SDP until it is set.");
    return;
  }

  medias = kms_sdp_message_context_get_medias (remote_sdp_ctx);
  mconf = g_slist_nth_data (medias, index);
  if (mconf == NULL) {
    GST_WARNING_OBJECT (self,
        "Media not found in remote SDP for index %" G_GUINT16_FORMAT, index);
  } else {
    GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);

    sdp_media_add_ice_candidate (media, self->agent, candidate);
  }
}
Esempio n. 5
0
static KmsIRtpConnection *
kms_webrtc_session_create_connection (KmsBaseRtpSession * base_rtp_sess,
    SdpMediaConfig * mconf, const gchar * name, guint16 min_port,
    guint16 max_port)
{
  KmsWebrtcSession *self = KMS_WEBRTC_SESSION (base_rtp_sess);
  GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  KmsWebRtcBaseConnection *conn;

  self->min_port = min_port;
  self->max_port = max_port;

  if (g_strcmp0 (gst_sdp_media_get_proto (media), "DTLS/SCTP") == 0) {
    GST_DEBUG_OBJECT (self, "Create SCTP connection");
    conn =
        KMS_WEBRTC_BASE_CONNECTION (kms_webrtc_sctp_connection_new
        (self->agent, self->context, name, min_port, max_port));
  } else {
    GST_DEBUG_OBJECT (self, "Create RTP connection");
    conn =
        KMS_WEBRTC_BASE_CONNECTION (kms_webrtc_connection_new
        (self->agent, self->context, name));
  }

  return KMS_I_RTP_CONNECTION (conn);
}
Esempio n. 6
0
gint
kms_sdp_media_config_get_abs_send_time_id (SdpMediaConfig * mconf)
{
  GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  guint a;

  for (a = 0;; a++) {
    const gchar *attr;
    gchar **tokens;

    attr = gst_sdp_media_get_attribute_val_n (media, EXT_MAP, a);
    if (attr == NULL) {
      break;
    }

    tokens = g_strsplit (attr, " ", 0);
    if (g_strcmp0 (RTP_HDR_EXT_ABS_SEND_TIME_URI, tokens[1]) == 0) {
      gint ret = atoi (tokens[0]);

      g_strfreev (tokens);
      return ret;
    }

    g_strfreev (tokens);
  }

  return -1;
}
Esempio n. 7
0
static gboolean
kms_base_rtp_session_configure_connection (KmsBaseRtpSession * self,
    SdpMediaConfig * neg_mconf, SdpMediaConfig * remote_mconf, gboolean offerer)
{
  GstSDPMedia *neg_media = kms_sdp_media_config_get_sdp_media (neg_mconf);
  const gchar *neg_proto_str = gst_sdp_media_get_proto (neg_media);
  const gchar *neg_media_str = gst_sdp_media_get_media (neg_media);

  GstSDPMedia *remote_media = kms_sdp_media_config_get_sdp_media (remote_mconf);
  const gchar *remote_proto_str = gst_sdp_media_get_proto (remote_media);
  const gchar *remote_media_str = gst_sdp_media_get_media (remote_media);
  gboolean active;

  if (g_strcmp0 (neg_proto_str, remote_proto_str) != 0) {
    GST_WARNING_OBJECT (self,
        "Negotiated proto ('%s') not matching with remote proto ('%s')",
        neg_proto_str, remote_proto_str);
    return FALSE;
  }

  if (!kms_utils_contains_proto (neg_proto_str, "RTP")) {
    GST_DEBUG_OBJECT (self, "'%s' protocol does not need RTP connection",
        neg_proto_str);
    /* It cannot be managed here but could be managed by the child class */
    return FALSE;
  }

  if (g_strcmp0 (neg_media_str, remote_media_str) != 0) {
    GST_WARNING_OBJECT (self,
        "Negotiated media ('%s') not matching with remote media ('%s')",
        neg_media_str, remote_media_str);
    return FALSE;
  }

  if (kms_base_rtp_session_process_remote_ssrc (self, remote_media,
          neg_mconf) == NULL) {
    return TRUE;                /* It cannot be managed here but could be managed by the child class */
  }

  active = sdp_utils_media_is_active (neg_media, offerer);

  return kms_base_rtp_session_add_connection_for_session (self, neg_mconf,
      active);
}
Esempio n. 8
0
static void
kms_rtp_endpoint_start_transport_send (KmsBaseSdpEndpoint *
    base_sdp_endpoint, gboolean offerer)
{
  KmsRtpEndpoint *self = KMS_RTP_ENDPOINT (base_sdp_endpoint);
  SdpMessageContext *remote_ctx =
      kms_base_sdp_endpoint_get_remote_sdp_ctx (base_sdp_endpoint);
  const GstSDPMessage *sdp =
      kms_sdp_message_context_get_sdp_message (remote_ctx);
  const GSList *item = kms_sdp_message_context_get_medias (remote_ctx);
  const GstSDPConnection *msg_conn = gst_sdp_message_get_connection (sdp);

  /* Chain up */
  KMS_BASE_SDP_ENDPOINT_CLASS (parent_class)->start_transport_send
      (base_sdp_endpoint, offerer);

  for (; item != NULL; item = g_slist_next (item)) {
    SdpMediaConfig *mconf = item->data;
    GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
    const GstSDPConnection *media_con;
    KmsRtpBaseConnection *conn;
    guint port;

    if (media->port == 0) {
      continue;
    }

    if (gst_sdp_media_connections_len (media) != 0) {
      media_con = gst_sdp_media_get_connection (media, 0);
    } else {
      media_con = msg_conn;
    }

    if (media_con == NULL || media_con->address == NULL
        || media_con->address[0] == '\0') {
      const gchar *media_str = gst_sdp_media_get_media (media);

      GST_WARNING_OBJECT (self, "Missing connection information for '%s'",
          media_str);
      continue;
    }

    conn = kms_rtp_endpoint_media_get_connection (self, mconf);
    if (conn == NULL) {
      continue;
    }

    port = gst_sdp_media_get_port (media);
    kms_rtp_base_connection_set_remote_info (conn,
        media_con->address, port, port + 1);
    /* TODO: get rtcp port from attr if it exists */
  }
}
Esempio n. 9
0
/* Configure media SDP begin */
static gboolean
kms_rtp_endpoint_configure_media (KmsBaseSdpEndpoint * base_sdp_endpoint,
    SdpMediaConfig * mconf)
{
  KmsRtpEndpoint *self = KMS_RTP_ENDPOINT (base_sdp_endpoint);
  KmsBaseRtpEndpoint *base_rtp = KMS_BASE_RTP_ENDPOINT (self);
  GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  guint conn_len, c;
  guint attr_len, a;
  KmsRtpBaseConnection *conn;
  gboolean ret = TRUE;

  /* Chain up */
  ret = KMS_BASE_SDP_ENDPOINT_CLASS
      (kms_rtp_endpoint_parent_class)->configure_media (base_sdp_endpoint,
      mconf);
  if (ret == FALSE) {
    return FALSE;
  }

  conn_len = gst_sdp_media_connections_len (media);
  for (c = 0; c < conn_len; c++) {
    gst_sdp_media_remove_connection (media, c);
  }

  conn =
      KMS_RTP_BASE_CONNECTION (kms_base_rtp_endpoint_get_connection (base_rtp,
          mconf));
  if (conn == NULL) {
    return TRUE;
  }

  media->port = kms_rtp_base_connection_get_rtp_port (conn);

  attr_len = gst_sdp_media_attributes_len (media);
  for (a = 0; a < attr_len; a++) {
    const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, a);

    if (g_strcmp0 (attr->key, "rtcp") == 0) {
      gst_sdp_media_remove_attribute (media, a);
      /* TODO: complete rtcp attr with addr and rtcp port */
    }
  }

  return TRUE;
}
Esempio n. 10
0
static void
gst_media_add_remote_candidates (SdpMediaConfig * mconf,
    KmsWebRtcBaseConnection * conn,
    const gchar * msg_ufrag, const gchar * msg_pwd)
{
  const GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  KmsIceBaseAgent *agent = conn->agent;
  gchar *stream_id = conn->stream_id;
  const gchar *ufrag, *pwd;
  guint len, i;

  ufrag = gst_sdp_media_get_attribute_val (media, SDP_ICE_UFRAG_ATTR);
  pwd = gst_sdp_media_get_attribute_val (media, SDP_ICE_PWD_ATTR);

  if (!kms_ice_base_agent_set_remote_credentials (agent, stream_id, ufrag, pwd)) {
    GST_WARNING ("Cannot set remote media credentials (%s, %s).", ufrag, pwd);
    if (!kms_ice_base_agent_set_remote_credentials (agent, stream_id, msg_ufrag,
            msg_pwd)) {
      GST_WARNING ("Cannot set remote message credentials (%s, %s).", ufrag,
          pwd);
      return;
    } else {
      GST_DEBUG ("Set remote message credentials OK (%s, %s).", ufrag, pwd);
    }
  } else {
    GST_DEBUG ("Set remote media credentials OK (%s, %s).", ufrag, pwd);
  }

  len = gst_sdp_media_attributes_len (media);
  for (i = 0; i < len; i++) {
    const GstSDPAttribute *attr;
    KmsIceCandidate *candidate;
    gint idx = kms_sdp_media_config_get_id (mconf);
    const gchar *mid = kms_sdp_media_config_get_mid (mconf);

    attr = gst_sdp_media_get_attribute (media, i);
    if (g_strcmp0 (SDP_CANDIDATE_ATTR, attr->key) != 0) {
      continue;
    }

    candidate = kms_ice_candidate_new (attr->value, mid, idx);
    kms_ice_base_agent_add_ice_candidate (agent, candidate, stream_id);
    g_object_unref (candidate);
  }
}
Esempio n. 11
0
gboolean
kms_webrtc_session_set_crypto_info (KmsWebrtcSession * self,
    SdpMediaConfig * mconf)
{
  GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  gchar *fingerprint;

  /* Crypto info */
  fingerprint = kms_webrtc_session_generate_fingerprint_sdp_attr (self, mconf);
  if (fingerprint == NULL) {
    return FALSE;
  }

  gst_sdp_media_add_attribute (media, "fingerprint", fingerprint);
  g_free (fingerprint);

  return TRUE;
}
Esempio n. 12
0
gboolean
kms_webrtc_session_set_ice_credentials (KmsWebrtcSession * self,
    SdpMediaConfig * mconf)
{
  GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  KmsWebRtcBaseConnection *conn;
  gchar *ufrag, *pwd;

  conn = kms_webrtc_session_get_connection (self, mconf);
  if (conn == NULL) {
    return FALSE;
  }

  kms_ice_base_agent_get_local_credentials (self->agent, conn->stream_id,
      &ufrag, &pwd);
  gst_sdp_media_add_attribute (media, SDP_ICE_UFRAG_ATTR, ufrag);
  g_free (ufrag);
  gst_sdp_media_add_attribute (media, SDP_ICE_PWD_ATTR, pwd);
  g_free (pwd);

  return TRUE;
}
Esempio n. 13
0
static gboolean
kms_webrtc_session_sdp_media_add_default_info (KmsWebrtcSession * self,
    SdpMediaConfig * mconf, gboolean use_ipv6)
{
  GstSDPMedia *media = kms_sdp_media_config_get_sdp_media (mconf);
  KmsIceBaseAgent *agent = self->agent;
  char *stream_id;
  KmsIceCandidate *rtp_default_candidate, *rtcp_default_candidate;
  gchar *rtp_addr;
  gchar *rtcp_addr;
  const gchar *rtp_addr_type, *rtcp_addr_type;
  gboolean rtp_is_ipv6, rtcp_is_ipv6;
  guint rtp_port, rtcp_port;
  guint conn_len, c;
  gchar *str;
  guint attr_len, i;

  stream_id = kms_webrtc_session_get_stream_id (self, mconf);
  if (stream_id == NULL) {
    return FALSE;
  }

  rtp_default_candidate =
      kms_ice_base_agent_get_default_local_candidate (agent, stream_id,
      NICE_COMPONENT_TYPE_RTP);

  if (kms_sdp_media_config_is_rtcp_mux (mconf) ||
      kms_sdp_media_config_get_group (mconf) != NULL) {
    rtcp_default_candidate =
        kms_ice_base_agent_get_default_local_candidate (agent, stream_id,
        NICE_COMPONENT_TYPE_RTP);
  } else {
    rtcp_default_candidate =
        kms_ice_base_agent_get_default_local_candidate (agent, stream_id,
        NICE_COMPONENT_TYPE_RTCP);
  }

  if (rtcp_default_candidate == NULL || rtcp_default_candidate == NULL) {
    GST_WARNING_OBJECT (self,
        "Error getting ICE candidates. Network can be unavailable.");
    return FALSE;
  }

  rtp_addr = kms_ice_candidate_get_address (rtp_default_candidate);
  rtp_port = kms_ice_candidate_get_port (rtp_default_candidate);
  rtp_is_ipv6 =
      kms_ice_candidate_get_ip_version (rtp_default_candidate) == IP_VERSION_6;

  rtcp_addr = kms_ice_candidate_get_address (rtcp_default_candidate);
  rtcp_port = kms_ice_candidate_get_port (rtcp_default_candidate);
  rtcp_is_ipv6 =
      kms_ice_candidate_get_ip_version (rtcp_default_candidate) == IP_VERSION_6;

  rtp_addr_type = rtp_is_ipv6 ? "IP6" : "IP4";
  rtcp_addr_type = rtcp_is_ipv6 ? "IP6" : "IP4";

  if (use_ipv6 != rtp_is_ipv6) {
    GST_WARNING_OBJECT (self, "No valid rtp address type: %s", rtp_addr_type);
    return FALSE;
  }

  media->port = rtp_port;
  conn_len = gst_sdp_media_connections_len (media);
  for (c = 0; c < conn_len; c++) {
    gst_sdp_media_remove_connection (media, c);
  }
  gst_sdp_media_add_connection (media, "IN", rtp_addr_type, rtp_addr, 0, 0);

  attr_len = gst_sdp_media_attributes_len (media);
  for (i = 0; i < attr_len; i++) {
    const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i);

    if (g_strcmp0 (attr->key, "rtcp") == 0) {
      str =
          g_strdup_printf ("%d IN %s %s", rtcp_port, rtcp_addr_type, rtcp_addr);
      gst_sdp_attribute_clear ((GstSDPAttribute *) attr);
      gst_sdp_attribute_set ((GstSDPAttribute *) attr, "rtcp", str);
      g_free (str);
    }
  }

  g_free (rtp_addr);
  g_free (rtcp_addr);

  g_object_unref (rtp_default_candidate);
  g_object_unref (rtcp_default_candidate);

  return TRUE;
}