static int replace_network_address(struct sdp_chopper *chop, struct network_address *address, struct packet_stream *ps, struct sdp_ng_flags *flags) { char buf[64]; int len; struct packet_stream *sink = packet_stream_sink(ps); if (is_addr_unspecified(&address->parsed) && !(sink && is_trickle_ice_address(&sink->advertised_endpoint))) return 0; if (copy_up_to(chop, &address->address_type)) return -1; if (flags->media_address.s && is_addr_unspecified(&flags->parsed_media_address)) __parse_address(&flags->parsed_media_address, NULL, NULL, &flags->media_address); if (!is_addr_unspecified(&flags->parsed_media_address)) { if (IN6_IS_ADDR_V4MAPPED(&flags->parsed_media_address)) len = sprintf(buf, "IP4 " IPF, IPP(flags->parsed_media_address.s6_addr32[3])); else { memcpy(buf, "IP6 ", 4); inet_ntop(AF_INET6, &flags->parsed_media_address, buf + 4, sizeof(buf)-4); len = strlen(buf); } } else call_stream_address(buf, ps, SAF_NG, &len); chopper_append_dup(chop, buf, len); if (skip_over(chop, &address->address)) return -1; return 0; }
static int replace_network_address(struct sdp_chopper *chop, struct network_address *address, struct packet_stream *ps, struct sdp_ng_flags *flags) { char buf[64]; int len; struct packet_stream *sink = packet_stream_sink(ps); if (is_addr_unspecified(&address->parsed) && !(sink && is_trickle_ice_address(&sink->advertised_endpoint))) return 0; if (copy_up_to(chop, &address->address_type)) return -1; if (flags->media_address.s && is_addr_unspecified(&flags->parsed_media_address)) __parse_address(&flags->parsed_media_address, NULL, NULL, &flags->media_address); if (!is_addr_unspecified(&flags->parsed_media_address)) len = sprintf(buf, "%s %s", flags->parsed_media_address.family->rfc_name, sockaddr_print_buf(&flags->parsed_media_address)); else call_stream_address46(buf, ps, SAF_NG, &len, NULL); chopper_append_dup(chop, buf, len); if (skip_over(chop, &address->address)) return -1; return 0; }
static void __sdp_ice(struct stream_params *sp, struct sdp_media *media) { struct sdp_attribute *attr; struct attribute_candidate *ac; struct ice_candidate *cand; GQueue *q; GList *ql; attr = attr_get_by_id_m_s(media, ATTR_ICE_UFRAG); if (!attr) return; sp->ice_ufrag = attr->value; SP_SET(sp, ICE); q = attr_list_get_by_id(&media->attributes, ATTR_CANDIDATE); if (!q) goto no_cand; for (ql = q->head; ql; ql = ql->next) { attr = ql->data; ac = &attr->u.candidate; if (!ac->parsed) continue; cand = g_slice_alloc(sizeof(*cand)); *cand = ac->cand_parsed; g_queue_push_tail(&sp->ice_candidates, cand); } no_cand: if ((attr = attr_get_by_id(&media->attributes, ATTR_ICE_OPTIONS))) { if (str_str(&attr->value, "trickle") >= 0) SP_SET(sp, TRICKLE_ICE); } else if (is_trickle_ice_address(&sp->rtp_endpoint)) SP_SET(sp, TRICKLE_ICE); if (attr_get_by_id(&media->attributes, ATTR_ICE_LITE)) SP_SET(sp, ICE_LITE); attr = attr_get_by_id_m_s(media, ATTR_ICE_PWD); if (attr) sp->ice_pwd = attr->value; }
/* XXX split this function up */ int sdp_streams(const GQueue *sessions, GQueue *streams, struct sdp_ng_flags *flags) { struct sdp_session *session; struct sdp_media *media; struct stream_params *sp; GList *l, *k; const char *errstr; int num; struct sdp_attribute *attr; num = 0; for (l = sessions->head; l; l = l->next) { session = l->data; for (k = session->media_streams.head; k; k = k->next) { media = k->data; sp = g_slice_alloc0(sizeof(*sp)); sp->index = ++num; errstr = "No address info found for stream"; if (fill_endpoint(&sp->rtp_endpoint, media, flags, NULL, media->port_num)) goto error; sp->consecutive_ports = media->port_count; sp->protocol = transport_protocol(&media->transport); sp->type = media->media_type; memcpy(sp->direction, flags->direction, sizeof(sp->direction)); sp->desired_family = flags->address_family; bf_set_clear(&sp->sp_flags, SP_FLAG_ASYMMETRIC, flags->asymmetric); bf_set_clear(&sp->sp_flags, SP_FLAG_STRICT_SOURCE, flags->strict_source); bf_set_clear(&sp->sp_flags, SP_FLAG_MEDIA_HANDOVER, flags->media_handover); errstr = "Invalid RTP payload types"; if (__rtp_payload_types(sp, media)) goto error; /* a=crypto */ attr = attr_get_by_id(&media->attributes, ATTR_CRYPTO); if (attr) { sp->crypto.crypto_suite = attr->u.crypto.crypto_suite; sp->crypto.mki_len = attr->u.crypto.mki_len; if (sp->crypto.mki_len) { sp->crypto.mki = malloc(sp->crypto.mki_len); memcpy(sp->crypto.mki, attr->u.crypto.mki, sp->crypto.mki_len); } sp->sdes_tag = attr->u.crypto.tag; assert(sizeof(sp->crypto.master_key) >= attr->u.crypto.master_key.len); assert(sizeof(sp->crypto.master_salt) >= attr->u.crypto.salt.len); memcpy(sp->crypto.master_key, attr->u.crypto.master_key.s, attr->u.crypto.master_key.len); memcpy(sp->crypto.master_salt, attr->u.crypto.salt.s, attr->u.crypto.salt.len); sp->crypto.session_params.unencrypted_srtp = attr->u.crypto.unencrypted_srtp; sp->crypto.session_params.unencrypted_srtcp = attr->u.crypto.unencrypted_srtcp; sp->crypto.session_params.unauthenticated_srtp = attr->u.crypto.unauthenticated_srtp; } /* a=sendrecv/sendonly/recvonly/inactive */ SP_SET(sp, SEND); SP_SET(sp, RECV); if (attr_get_by_id_m_s(media, ATTR_RECVONLY)) SP_CLEAR(sp, SEND); else if (attr_get_by_id_m_s(media, ATTR_SENDONLY)) SP_CLEAR(sp, RECV); else if (attr_get_by_id_m_s(media, ATTR_INACTIVE)) { SP_CLEAR(sp, RECV); SP_CLEAR(sp, SEND); } /* a=setup */ attr = attr_get_by_id_m_s(media, ATTR_SETUP); if (attr) { if (attr->u.setup.value == SETUP_ACTPASS || attr->u.setup.value == SETUP_ACTIVE) SP_SET(sp, SETUP_ACTIVE); if (attr->u.setup.value == SETUP_ACTPASS || attr->u.setup.value == SETUP_PASSIVE) SP_SET(sp, SETUP_PASSIVE); } /* a=fingerprint */ attr = attr_get_by_id_m_s(media, ATTR_FINGERPRINT); if (attr && attr->u.fingerprint.hash_func) { sp->fingerprint.hash_func = attr->u.fingerprint.hash_func; memcpy(sp->fingerprint.digest, attr->u.fingerprint.fingerprint, sp->fingerprint.hash_func->num_bytes); } __sdp_ice(sp, media); /* determine RTCP endpoint */ if (attr_get_by_id(&media->attributes, ATTR_RTCP_MUX)) { SP_SET(sp, RTCP_MUX); goto next; } if (media->port_count != 1) goto next; attr = attr_get_by_id(&media->attributes, ATTR_RTCP); if (!attr) { SP_SET(sp, IMPLICIT_RTCP); goto next; } if (attr->u.rtcp.port_num == sp->rtp_endpoint.port && !is_trickle_ice_address(&sp->rtp_endpoint)) { SP_SET(sp, RTCP_MUX); goto next; } errstr = "Invalid RTCP attribute"; if (fill_endpoint(&sp->rtcp_endpoint, media, flags, &attr->u.rtcp.address, attr->u.rtcp.port_num)) goto error; next: g_queue_push_tail(streams, sp); } } return 0; error: ilog(LOG_WARNING, "Failed to extract streams from SDP: %s", errstr); if (sp) g_slice_free1(sizeof(*sp), sp); return -1; }