예제 #1
0
파일: sdp.c 프로젝트: jungle0755/rtpengine
static int replace_consecutive_port_count(struct sdp_chopper *chop, struct sdp_media *media,
		struct packet_stream *ps, GList *j)
{
	int cons;
	struct packet_stream *ps_n;

	if (media->port_count == 1 || !ps->sfd)
		return 0;

	for (cons = 1; cons < media->port_count; cons++) {
		j = j->next;
		if (!j)
			goto warn;
		ps_n = j->data;
		if (ps_n->sfd->fd.localport != ps->sfd->fd.localport + cons * 2) {
warn:
			ilog(LOG_WARN, "Failed to handle consecutive ports");
			break;
		}
	}

	chopper_append_printf(chop, "/%i", cons);

	return 0;
}
예제 #2
0
파일: sdp.c 프로젝트: jungle0755/rtpengine
static int insert_ice_address(struct sdp_chopper *chop, struct packet_stream *ps, struct interface_address *ifa) {
	char buf[64];
	int len;

	call_stream_address46(buf, ps, SAF_ICE, &len, ifa);
	chopper_append_dup(chop, buf, len);
	chopper_append_printf(chop, " %hu", ps->sfd->fd.localport);

	return 0;
}
예제 #3
0
파일: sdp.c 프로젝트: gnufreex/rtpengine
static int insert_ice_address(struct sdp_chopper *chop, struct stream_fd *sfd) {
	char buf[64];
	int len;

	call_stream_address46(buf, sfd->stream, SAF_ICE, &len, sfd->local_intf);
	chopper_append_dup(chop, buf, len);
	chopper_append_printf(chop, " %u", sfd->socket.local.port);

	return 0;
}
예제 #4
0
파일: sdp.c 프로젝트: gnufreex/rtpengine
static void insert_candidates(struct sdp_chopper *chop, struct packet_stream *rtp, struct packet_stream *rtcp,
		struct sdp_ng_flags *flags, struct sdp_media *sdp_media)
{
	const struct local_intf *ifa;
	struct call_media *media;
	struct ice_agent *ag;
	unsigned int type_pref, local_pref;
	enum ice_candidate_type cand_type;
	struct ice_candidate *cand;

	media = rtp->media;

	cand_type = ICT_HOST;
	if (flags->ice_force_relay)
		cand_type = ICT_RELAY;
	if (MEDIA_ISSET(media, PASSTHRU))
		new_priority(sdp_media, cand_type, &type_pref, &local_pref);
	else {
		type_pref = ice_type_preference(cand_type);
		local_pref = -1;
	}

	ag = media->ice_agent;

	if (ag && AGENT_ISSET(ag, COMPLETED)) {
		ifa = rtp->selected_sfd->local_intf;
		insert_candidate(chop, rtp->selected_sfd, type_pref, ifa->unique_id, cand_type);
		if (rtcp) /* rtcp-mux only possible in answer */
			insert_candidate(chop, rtcp->selected_sfd, type_pref, ifa->unique_id, cand_type);

		if (flags->opmode == OP_OFFER && AGENT_ISSET(ag, CONTROLLING)) {
			GQueue rc;
			GList *l;
			chopper_append_c(chop, "a=remote-candidates:");
			ice_remote_candidates(&rc, ag);
			for (l = rc.head; l; l = l->next) {
				if (l != rc.head)
					chopper_append_c(chop, " ");
				cand = l->data;
				chopper_append_printf(chop, "%lu %s %u", cand->component_id,
						sockaddr_print_buf(&cand->endpoint.address), cand->endpoint.port);
			}
			chopper_append_c(chop, "\r\n");
			g_queue_clear(&rc);
		}
		return;
	}

	insert_sfd_candidates(chop, rtp, type_pref, local_pref, cand_type);

	if (rtcp) /* rtcp-mux only possible in answer */
		insert_sfd_candidates(chop, rtcp, type_pref, local_pref, cand_type);
}
예제 #5
0
파일: sdp.c 프로젝트: gnufreex/rtpengine
static int insert_raddr_rport(struct sdp_chopper *chop, struct packet_stream *ps, const struct local_intf *ifa) {
        char buf[64];
        int len;

	chopper_append_c(chop, " raddr ");
	call_stream_address46(buf, ps, SAF_ICE, &len, ifa);
	chopper_append_dup(chop, buf, len);
	chopper_append_c(chop, " rport ");
	chopper_append_printf(chop, "%u", ps->selected_sfd->socket.local.port);

	return 0;
}
예제 #6
0
파일: sdp.c 프로젝트: jungle0755/rtpengine
static void insert_crypto(struct call_media *media, struct sdp_chopper *chop) {
	char b64_buf[((SRTP_MAX_MASTER_KEY_LEN + SRTP_MAX_MASTER_SALT_LEN) / 3 + 1) * 4 + 4];
	char *p;
	int state = 0, save = 0, i;
	struct crypto_params *cp = &media->sdes_out.params;
	unsigned long long ull;

	if (!cp->crypto_suite || !MEDIA_ISSET(media, SDES) || MEDIA_ISSET(media, PASSTHRU))
		return;

	p = b64_buf;
	p += g_base64_encode_step((unsigned char *) cp->master_key,
			cp->crypto_suite->master_key_len, 0,
			p, &state, &save);
	p += g_base64_encode_step((unsigned char *) cp->master_salt,
			cp->crypto_suite->master_salt_len, 0,
			p, &state, &save);
	p += g_base64_encode_close(0, p, &state, &save);

	chopper_append_c(chop, "a=crypto:");
	chopper_append_printf(chop, "%u ", media->sdes_out.tag);
	chopper_append_c(chop, cp->crypto_suite->name);
	chopper_append_c(chop, " inline:");
	chopper_append_dup(chop, b64_buf, p - b64_buf);
	if (cp->mki_len) {
		ull = 0;
		for (i = 0; i < cp->mki_len && i < sizeof(ull); i++)
			ull |= cp->mki[cp->mki_len - i - 1] << (i * 8);
		chopper_append_printf(chop, "|%llu:%u", ull, cp->mki_len);
	}
	if (cp->session_params.unencrypted_srtp)
		chopper_append_c(chop, " UNENCRYPTED_SRTP");
	if (cp->session_params.unencrypted_srtcp)
		chopper_append_c(chop, " UNENCRYPTED_SRTCP");
	if (cp->session_params.unauthenticated_srtp)
		chopper_append_c(chop, " UNAUTHENTICATED_SRTP");
	chopper_append_c(chop, "\r\n");
}
예제 #7
0
파일: sdp.c 프로젝트: jungle0755/rtpengine
static void insert_candidate(struct sdp_chopper *chop, struct packet_stream *ps, unsigned int component,
		unsigned int type_pref, unsigned int local_pref, enum ice_candidate_type type,
		struct interface_address *ifa)
{
	unsigned long priority;

	priority = ice_priority_pref(type_pref, local_pref, component);
	chopper_append_c(chop, "a=candidate:");
	chopper_append_str(chop, &ifa->ice_foundation);
	chopper_append_printf(chop, " %u UDP %lu ", component, priority);
	insert_ice_address(chop, ps, ifa);
	chopper_append_c(chop, " typ ");
	chopper_append_c(chop, ice_candidate_type_str(type));
	/* raddr and rport are required for non-host candidates: rfc5245 section-15.1 */
	if(type != ICT_HOST)
		insert_raddr_rport(chop, ps, ifa);
	chopper_append_c(chop, "\r\n");
}
예제 #8
0
파일: sdp.c 프로젝트: jungle0755/rtpengine
static int replace_media_port(struct sdp_chopper *chop, struct sdp_media *media, struct packet_stream *ps) {
	str *port = &media->port;
	unsigned int p;

	if (!media->port_num)
		return 0;

	if (copy_up_to(chop, port))
		return -1;

	p = ps->sfd ? ps->sfd->fd.localport : 0;
	chopper_append_printf(chop, "%u", p);

	if (skip_over(chop, port))
		return -1;

	return 0;
}
예제 #9
0
파일: sdp.c 프로젝트: gnufreex/rtpengine
static void insert_candidate(struct sdp_chopper *chop, struct stream_fd *sfd,
		unsigned int type_pref, unsigned int local_pref, enum ice_candidate_type type)
{
	unsigned long priority;
	struct packet_stream *ps = sfd->stream;
	const struct local_intf *ifa = sfd->local_intf;

	if (local_pref == -1)
		local_pref = ifa->unique_id;

	priority = ice_priority_pref(type_pref, local_pref, ps->component);
	chopper_append_c(chop, "a=candidate:");
	chopper_append_str(chop, &ifa->ice_foundation);
	chopper_append_printf(chop, " %u UDP %lu ", ps->component, priority);
	insert_ice_address(chop, sfd);
	chopper_append_c(chop, " typ ");
	chopper_append_c(chop, ice_candidate_type_str(type));
	/* raddr and rport are required for non-host candidates: rfc5245 section-15.1 */
	if(type != ICT_HOST)
		insert_raddr_rport(chop, ps, ifa);
	chopper_append_c(chop, "\r\n");
}
예제 #10
0
파일: sdp.c 프로젝트: jungle0755/rtpengine
/* called with call->master_lock held in W */
int sdp_replace(struct sdp_chopper *chop, GQueue *sessions, struct call_monologue *monologue,
		struct sdp_ng_flags *flags)
{
	struct sdp_session *session;
	struct sdp_media *sdp_media;
	GList *l, *k, *m, *j;
	int media_index, sess_conn;
	struct call_media *call_media;
	struct packet_stream *ps, *ps_rtcp;

	m = monologue->medias.head;

	for (l = sessions->head; l; l = l->next) {
		session = l->data;
		if (!m)
			goto error;
		call_media = m->data;
		if (call_media->index != 1)
			goto error;
		j = call_media->streams.head;
		if (!j)
			goto error;
		ps = j->data;

		sess_conn = 0;
		if (flags->replace_sess_conn)
			sess_conn = 1;
		else {
			for (k = session->media_streams.head; k; k = k->next) {
				sdp_media = k->data;
				if (!sdp_media->connection.parsed) {
					sess_conn = 1;
					break;
				}
			}
		}

		if (session->origin.parsed && flags->replace_origin &&
		    !flags->ice_force_relay) {
			if (replace_network_address(chop, &session->origin.address, ps, flags))
				goto error;
		}
		if (session->connection.parsed && sess_conn &&
		    !flags->ice_force_relay) {
			if (replace_network_address(chop, &session->connection.address, ps, flags))
				goto error;
		}

		if (!MEDIA_ISSET(call_media, PASSTHRU)) {
			if (process_session_attributes(chop, &session->attributes, flags))
				goto error;
		}

		media_index = 1;

		for (k = session->media_streams.head; k; k = k->next) {
			sdp_media = k->data;
			if (!m)
				goto error;
			call_media = m->data;
			if (call_media->index != media_index)
				goto error;
			j = call_media->streams.head;
			if (!j)
				goto error;
			ps = j->data;

			if (!flags->ice_force_relay) {
			        if (replace_media_port(chop, sdp_media, ps))
				        goto error;
			        if (replace_consecutive_port_count(chop, sdp_media, ps, j))
				        goto error;
				if (replace_transport_protocol(chop, sdp_media, call_media))
				        goto error;

				if (sdp_media->connection.parsed) {
				        if (replace_network_address(chop, &sdp_media->connection.address, ps, flags))
					        goto error;
				}
			}

			if (process_media_attributes(chop, sdp_media, flags, call_media))
				goto error;

			copy_up_to_end_of(chop, &sdp_media->s);

			ps_rtcp = NULL;
			if (ps->rtcp_sibling) {
				ps_rtcp = ps->rtcp_sibling;
				j = j->next;
				if (!j)
					goto error;
				assert(j->data == ps_rtcp);
			}

			if (!sdp_media->port_num || !ps->sfd)
				goto next;

			if (MEDIA_ARESET2(call_media, SEND, RECV))
				chopper_append_c(chop, "a=sendrecv\r\n");
			else if (MEDIA_ISSET(call_media, SEND))
				chopper_append_c(chop, "a=sendonly\r\n");
			else if (MEDIA_ISSET(call_media, RECV))
				chopper_append_c(chop, "a=recvonly\r\n");
			else
				chopper_append_c(chop, "a=inactive\r\n");

			if (call_media->protocol && call_media->protocol->rtp) {
				if (MEDIA_ISSET(call_media, RTCP_MUX) && flags->opmode == OP_ANSWER) {
					chopper_append_c(chop, "a=rtcp:");
					chopper_append_printf(chop, "%hu", ps->sfd->fd.localport);
					chopper_append_c(chop, "\r\na=rtcp-mux\r\n");
					ps_rtcp = NULL;
				}
				else if (ps_rtcp && !flags->ice_force_relay) {
					chopper_append_c(chop, "a=rtcp:");
					chopper_append_printf(chop, "%hu", ps_rtcp->sfd->fd.localport);
					if (!MEDIA_ISSET(call_media, RTCP_MUX))
						chopper_append_c(chop, "\r\n");
					else
						chopper_append_c(chop, "\r\na=rtcp-mux\r\n");
				}
			}
			else
				ps_rtcp = NULL;

			insert_crypto(call_media, chop);
			insert_dtls(call_media, chop);

			if (MEDIA_ISSET(call_media, ICE) && call_media->ice_agent) {
				chopper_append_c(chop, "a=ice-ufrag:");
				chopper_append_str(chop, &call_media->ice_agent->ufrag[1]);
				chopper_append_c(chop, "\r\na=ice-pwd:");
				chopper_append_str(chop, &call_media->ice_agent->pwd[1]);
				chopper_append_c(chop, "\r\n");
			}

			if (!flags->ice_remove)
				insert_candidates(chop, ps, ps_rtcp, flags, sdp_media);

next:
			media_index++;
			m = m->next;
		}
	}

	copy_remainder(chop);
	return 0;

error:
	ilog(LOG_ERROR, "Error rewriting SDP");
	return -1;
}
예제 #11
0
파일: sdp.c 프로젝트: jungle0755/rtpengine
static void insert_candidates(struct sdp_chopper *chop, struct packet_stream *rtp, struct packet_stream *rtcp,
		struct sdp_ng_flags *flags, struct sdp_media *sdp_media)
{
	GList *l;
	struct interface_address *ifa;
	unsigned int pref;
	struct call_media *media;
	struct local_interface *lif;
	struct ice_agent *ag;
	unsigned int type_pref, local_pref;
	enum ice_candidate_type cand_type;
	struct ice_candidate *cand;

	media = rtp->media;

	cand_type = ICT_HOST;
	if (flags->ice_force_relay)
		cand_type = ICT_RELAY;
	if (MEDIA_ISSET(media, PASSTHRU))
		new_priority(sdp_media, cand_type, &type_pref, &local_pref);
	else {
		type_pref = ice_type_preference(cand_type);
		local_pref = -1;
	}

	ag = media->ice_agent;
	lif = ag ? ag->local_interface : media->interface;

	if (ag && AGENT_ISSET(ag, COMPLETED)) {
		ifa = g_atomic_pointer_get(&media->local_address);
		insert_candidate(chop, rtp, 1, type_pref, ifa->preference, cand_type, ifa);
		if (rtcp) /* rtcp-mux only possible in answer */
			insert_candidate(chop, rtcp, 2, type_pref, ifa->preference, cand_type, ifa);

		if (flags->opmode == OP_OFFER && AGENT_ISSET(ag, CONTROLLING)) {
			GQueue rc;
			GList *l;
			chopper_append_c(chop, "a=remote-candidates:");
			ice_remote_candidates(&rc, ag);
			for (l = rc.head; l; l = l->next) {
				if (l != rc.head)
					chopper_append_c(chop, " ");
				cand = l->data;
				chopper_append_printf(chop, "%lu %s %u", cand->component_id,
						smart_ntop_buf(&cand->endpoint.ip46), cand->endpoint.port);
			}
			chopper_append_c(chop, "\r\n");
			g_queue_clear(&rc);
		}
		return;
	}

	for (l = lif->list.head; l; l = l->next) {
		ifa = l->data;
		pref = (local_pref == -1) ? ifa->preference : local_pref;

		insert_candidate(chop, rtp, 1, type_pref, pref, cand_type, ifa);

		if (rtcp) /* rtcp-mux only possible in answer */
			insert_candidate(chop, rtcp, 2, type_pref, pref, cand_type, ifa);

		if (local_pref != -1)
			local_pref++;
	}
}