[asterisk-commits] kmoore: branch kmoore/pjsip_dtls r394606 - /team/kmoore/pjsip_dtls/res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 17 15:07:53 CDT 2013


Author: kmoore
Date: Wed Jul 17 15:07:52 2013
New Revision: 394606

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=394606
Log:
Finish DTLS support and fix bugs

Add support in SDES SRTP and DTLS SRTP for varying tag lengths.

Fix a segfault where certain SDP lines were handled improperly.

Fix up and refactor remainder of DTLS support.

Modified:
    team/kmoore/pjsip_dtls/res/res_sip_sdp_rtp.c

Modified: team/kmoore/pjsip_dtls/res/res_sip_sdp_rtp.c
URL: http://svnview.digium.com/svn/asterisk/team/kmoore/pjsip_dtls/res/res_sip_sdp_rtp.c?view=diff&rev=394606&r1=394605&r2=394606
==============================================================================
--- team/kmoore/pjsip_dtls/res/res_sip_sdp_rtp.c (original)
+++ team/kmoore/pjsip_dtls/res/res_sip_sdp_rtp.c Wed Jul 17 15:07:52 2013
@@ -555,6 +555,7 @@
 		return -1;
 	}
 
+	session->dtls_cfg.suite = ((session->endpoint->srtp_tag_32) ? AST_AES_CM_128_HMAC_SHA1_32 : AST_AES_CM_128_HMAC_SHA1_80);
 	if (dtls->set_configuration(session_media->rtp, &session->dtls_cfg)) {
 		ast_log(LOG_ERROR, "Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
 			session_media->rtp);
@@ -575,7 +576,13 @@
 
 	for (i = 0; i < stream->attr_count; i++) {
 		pjmedia_sdp_attr *attr = stream->attr[i];
-		pj_str_t *value = pj_strtrim(&attr->value);
+		pj_str_t *value;
+
+		if (!attr->value.ptr) {
+			continue;
+		}
+
+		value = pj_strtrim(&attr->value);
 
 		if (!pj_strcmp2(&attr->name, "setup")) {
 			RAII_VAR(char *, setup_type, ast_strndup(value->ptr, value->slen), ast_free);
@@ -666,40 +673,11 @@
 	return -1;
 }
 
-/*! \brief Function which negotiates an incoming media stream */
-static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
-					 const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
-{
-	char host[NI_MAXHOST];
-	RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
-	enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
-	enum ast_sip_session_media_encryption incoming_encryption;
-
-	/* If no type formats have been configured reject this stream */
-	if (!ast_format_cap_has_type(session->endpoint->codecs, media_type)) {
-		return 0;
-	}
-
-	/* Ensure incoming transport is compatible with the endpoint's configuration */
-	incoming_encryption = check_endpoint_media_transport(session->endpoint, stream);
-	if (incoming_encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) {
-		return -1;
-	}
-
-	ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
-
-	/* Ensure that the address provided is valid */
-	if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
-		/* The provided host was actually invalid so we error out this negotiation */
-		return -1;
-	}
-
-	/* Using the connection information create an appropriate RTP instance */
-	if (!session_media->rtp && create_rtp(session, session_media, ast_sockaddr_is_ipv6(addrs))) {
-		return -1;
-	}
-
-	switch (incoming_encryption) {
+static int setup_media_encryption(struct ast_sip_session *session,
+	struct ast_sip_session_media *session_media,
+	const struct pjmedia_sdp_media *stream)
+{
+	switch (session->endpoint->media_encryption) {
 	case AST_SIP_MEDIA_ENCRYPT_SDES:
 		if (setup_sdes_srtp(session_media, stream)) {
 			return -1;
@@ -714,9 +692,46 @@
 		}
 		break;
 	case AST_SIP_MEDIA_TRANSPORT_INVALID:
-		/* Already handled above, fallthrough */
 	case AST_SIP_MEDIA_ENCRYPT_NONE:
 		break;
+	}
+
+	return 0;
+}
+
+/*! \brief Function which negotiates an incoming media stream */
+static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
+					 const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
+{
+	char host[NI_MAXHOST];
+	RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free_ptr);
+	enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
+
+	/* If no type formats have been configured reject this stream */
+	if (!ast_format_cap_has_type(session->endpoint->codecs, media_type)) {
+		return 0;
+	}
+
+	/* Ensure incoming transport is compatible with the endpoint's configuration */
+	if (check_endpoint_media_transport(session->endpoint, stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
+		return -1;
+	}
+
+	ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
+
+	/* Ensure that the address provided is valid */
+	if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
+		/* The provided host was actually invalid so we error out this negotiation */
+		return -1;
+	}
+
+	/* Using the connection information create an appropriate RTP instance */
+	if (!session_media->rtp && create_rtp(session, session_media, ast_sockaddr_is_ipv6(addrs))) {
+		return -1;
+	}
+
+	if (setup_media_encryption(session, session_media, stream)) {
+		return -1;
 	}
 
 	return set_caps(session, session_media, stream);
@@ -729,31 +744,89 @@
 	pj_str_t stmp;
 	pjmedia_sdp_attr *attr;
 	const char *crypto_attribute;
-
-	if (session->endpoint->media_encryption == AST_SIP_MEDIA_ENCRYPT_DTLS) {
+	struct ast_rtp_engine_dtls *dtls;
+
+	switch (session->endpoint->media_encryption) {
+	case AST_SIP_MEDIA_ENCRYPT_NONE:
+	case AST_SIP_MEDIA_TRANSPORT_INVALID:
+		break;
+	case AST_SIP_MEDIA_ENCRYPT_SDES:
+		if (!session_media->srtp) {
+			session_media->srtp = ast_sdp_srtp_alloc();
+			if (!session_media->srtp) {
+				return -1;
+			}
+		}
+
+		crypto_attribute = ast_sdp_srtp_get_attrib(session_media->srtp,
+			0 /* DTLS running? No */,
+			session->endpoint->srtp_tag_32 /* 32 byte tag length? */);
+		if (!crypto_attribute) {
+			/* No crypto attribute to add, bad news */
+			return -1;
+		}
+
+		attr = pjmedia_sdp_attr_create(pool, "crypto", pj_cstr(&stmp, crypto_attribute));
+		media->attr[media->attr_count++] = attr;
+		break;
+	case AST_SIP_MEDIA_ENCRYPT_DTLS:
 		if (setup_dtls_srtp(session, session_media)) {
 			return -1;
 		}
-		return 0;
-	}
-
-	if (!session_media->srtp && session->endpoint->media_encryption == AST_SIP_MEDIA_ENCRYPT_SDES) {
-		session_media->srtp = ast_sdp_srtp_alloc();
-		if (!session_media->srtp) {
+
+		dtls = ast_rtp_instance_get_dtls(session_media->rtp);
+		if (!dtls) {
 			return -1;
 		}
-	}
-
-	crypto_attribute = ast_sdp_srtp_get_attrib(session_media->srtp,
-		session->endpoint->media_encryption == AST_SIP_MEDIA_ENCRYPT_DTLS /* DTLS running? */,
-		0 /* don't prefer 32byte tag length */);
-	if (!crypto_attribute) {
-		/* No crypto attribute to add */
-		return -1;
-	}
-
-	attr = pjmedia_sdp_attr_create(pool, "crypto", pj_cstr(&stmp, crypto_attribute));
-	media->attr[media->attr_count++] = attr;
+
+		switch (dtls->get_connection(session_media->rtp)) {
+		case AST_RTP_DTLS_CONNECTION_NEW:
+			attr = pjmedia_sdp_attr_create(pool, "connection", pj_cstr(&stmp, "new"));
+			media->attr[media->attr_count++] = attr;
+			break;
+		case AST_RTP_DTLS_CONNECTION_EXISTING:
+			attr = pjmedia_sdp_attr_create(pool, "connection", pj_cstr(&stmp, "existing"));
+			media->attr[media->attr_count++] = attr;
+			break;
+		default:
+			break;
+		}
+
+		switch (dtls->get_setup(session_media->rtp)) {
+		case AST_RTP_DTLS_SETUP_ACTIVE:
+			attr = pjmedia_sdp_attr_create(pool, "setup", pj_cstr(&stmp, "active"));
+			media->attr[media->attr_count++] = attr;
+			break;
+		case AST_RTP_DTLS_SETUP_PASSIVE:
+			attr = pjmedia_sdp_attr_create(pool, "setup", pj_cstr(&stmp, "passive"));
+			media->attr[media->attr_count++] = attr;
+			break;
+		case AST_RTP_DTLS_SETUP_ACTPASS:
+			attr = pjmedia_sdp_attr_create(pool, "setup", pj_cstr(&stmp, "actpass"));
+			media->attr[media->attr_count++] = attr;
+			break;
+		case AST_RTP_DTLS_SETUP_HOLDCONN:
+			attr = pjmedia_sdp_attr_create(pool, "setup", pj_cstr(&stmp, "holdconn"));
+			media->attr[media->attr_count++] = attr;
+			break;
+		default:
+			break;
+		}
+
+		if ((crypto_attribute = dtls->get_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1))) {
+			RAII_VAR(struct ast_str *, fingerprint, ast_str_create(64), ast_free);
+			if (!fingerprint) {
+				return -1;
+			}
+
+			ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
+
+			attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
+			media->attr[media->attr_count++] = attr;
+		}
+		break;
+	}
+
 	return 0;
 }
 
@@ -777,7 +850,6 @@
 	struct ast_format format;
 	RAII_VAR(struct ast_format_cap *, caps, NULL, ast_format_cap_destroy);
 	enum ast_format_type media_type = stream_to_media_type(session_media->stream_type);
-	int crypto_res;
 
 	int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
 		!ast_format_cap_is_empty(session->direct_media_cap);
@@ -799,11 +871,14 @@
 		return -1;
 	}
 
-	crypto_res = add_crypto_to_stream(session, session_media, pool, media);
+	if (add_crypto_to_stream(session, session_media, pool, media)) {
+		return -1;
+	}
 
 	media->desc.media = pj_str(session_media->stream_type);
 	media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
-		!crypto_res, session_media->rtp, session->endpoint->use_avpf));
+		session->endpoint->media_encryption == AST_SIP_MEDIA_ENCRYPT_SDES,
+		session_media->rtp, session->endpoint->use_avpf));
 
 	/* Add connection level details */
 	if (direct_media_enabled) {
@@ -928,8 +1003,17 @@
 		return 1;
 	}
 
+	/* Ensure incoming transport is compatible with the endpoint's configuration */
+	if (check_endpoint_media_transport(session->endpoint, remote_stream) == AST_SIP_MEDIA_TRANSPORT_INVALID) {
+		return -1;
+	}
+
 	/* Create an RTP instance if need be */
 	if (!session_media->rtp && create_rtp(session, session_media, session->endpoint->rtp_ipv6)) {
+		return -1;
+	}
+
+	if (setup_media_encryption(session, session_media, remote_stream)) {
 		return -1;
 	}
 




More information about the asterisk-commits mailing list