mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	Merge "res_pjsip: Add "webrtc" configuration option"
This commit is contained in:
		| @@ -1010,6 +1010,18 @@ | ||||
| 						underlying transport. Note that enabling bundle will also enable the rtcp_mux option. | ||||
| 					</para></description> | ||||
| 				</configOption> | ||||
| 				<configOption name="webrtc" default="no"> | ||||
| 					<synopsis>Defaults and enables some options that are relevant to WebRTC</synopsis> | ||||
| 					<description><para> | ||||
| 						When set to "yes" this also enables the following values that are needed in | ||||
| 						order for basic WebRTC support to work: rtcp_mux, use_avpf, ice_support, and | ||||
| 						use_received_transport. The following configuration settings also get defaulted | ||||
| 						as follows:</para> | ||||
| 						<para>media_encryption=dtls</para> | ||||
| 						<para>dtls_verify=fingerprint</para> | ||||
| 						<para>dtls_setup=actpass</para> | ||||
| 					</description> | ||||
| 				</configOption> | ||||
| 			</configObject> | ||||
| 			<configObject name="auth"> | ||||
| 				<synopsis>Authentication type</synopsis> | ||||
| @@ -4244,6 +4256,18 @@ void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size) | ||||
| 	dest[chars_to_copy] = '\0'; | ||||
| } | ||||
|  | ||||
| int ast_copy_pj_str2(char **dest, const pj_str_t *src) | ||||
| { | ||||
| 	int res = ast_asprintf(dest, "%.*s", (int)pj_strlen(src), pj_strbuf(src)); | ||||
|  | ||||
| 	if (res < 0) { | ||||
| 		*dest = NULL; | ||||
| 	} | ||||
|  | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
|  | ||||
| int ast_sip_is_content_type(pjsip_media_type *content_type, char *type, char *subtype) | ||||
| { | ||||
| 	pjsip_media_type compare; | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| 	global: | ||||
| 		LINKER_SYMBOL_PREFIXast_sip_*; | ||||
| 		LINKER_SYMBOL_PREFIXast_copy_pj_str; | ||||
| 		LINKER_SYMBOL_PREFIXast_copy_pj_str2; | ||||
| 		LINKER_SYMBOL_PREFIXast_pjsip_rdata_get_endpoint; | ||||
| 	local: | ||||
| 		*; | ||||
|   | ||||
| @@ -1363,8 +1363,30 @@ static int sip_endpoint_apply_handler(const struct ast_sorcery *sorcery, void *o | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (endpoint->media.bundle) { | ||||
| 		endpoint->media.rtcp_mux = 1; | ||||
| 	endpoint->media.rtcp_mux |= endpoint->media.bundle; | ||||
|  | ||||
| 	/* | ||||
| 	 * If webrtc has been enabled then enable those attributes, and default | ||||
| 	 * some, that are needed in order for webrtc to work. | ||||
| 	 */ | ||||
| 	endpoint->media.bundle |= endpoint->media.webrtc; | ||||
| 	endpoint->media.rtcp_mux |= endpoint->media.webrtc; | ||||
| 	endpoint->media.rtp.use_avpf |= endpoint->media.webrtc; | ||||
| 	endpoint->media.rtp.ice_support |= endpoint->media.webrtc; | ||||
| 	endpoint->media.rtp.use_received_transport |= endpoint->media.webrtc; | ||||
|  | ||||
| 	if (endpoint->media.webrtc) { | ||||
| 		endpoint->media.rtp.encryption = AST_SIP_MEDIA_ENCRYPT_DTLS; | ||||
| 		endpoint->media.rtp.dtls_cfg.enabled = 1; | ||||
| 		endpoint->media.rtp.dtls_cfg.default_setup = AST_RTP_DTLS_SETUP_ACTPASS; | ||||
| 		endpoint->media.rtp.dtls_cfg.verify = AST_RTP_DTLS_VERIFY_FINGERPRINT; | ||||
|  | ||||
| 		if (ast_strlen_zero(endpoint->media.rtp.dtls_cfg.certfile) || | ||||
| 			(ast_strlen_zero(endpoint->media.rtp.dtls_cfg.cafile))) { | ||||
| 			ast_log(LOG_ERROR, "WebRTC can't be enabled on endpoint '%s' - a DTLS cert " | ||||
| 				"or ca file has not been specified", ast_sorcery_object_get_id(endpoint)); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| @@ -1990,6 +2012,7 @@ int ast_res_pjsip_initialize_configuration(void) | ||||
| 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_audio_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_audio_streams)); | ||||
| 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "max_video_streams", "1", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, media.max_video_streams)); | ||||
| 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "bundle", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.bundle)); | ||||
| 	ast_sorcery_object_field_register(sip_sorcery, "endpoint", "webrtc", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.webrtc)); | ||||
|  | ||||
| 	if (ast_sip_initialize_sorcery_transport()) { | ||||
| 		ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n"); | ||||
|   | ||||
| @@ -1025,6 +1025,65 @@ static void process_ssrc_attributes(struct ast_sip_session *session, struct ast_ | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void process_msid_attribute(struct ast_sip_session *session, | ||||
| 	struct ast_sip_session_media *session_media, pjmedia_sdp_media *media) | ||||
| { | ||||
| 	pjmedia_sdp_attr *attr; | ||||
|  | ||||
| 	if (!session->endpoint->media.webrtc) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	attr = pjmedia_sdp_media_find_attr2(media, "msid", NULL); | ||||
| 	if (attr) { | ||||
| 		ast_free(session_media->msid); | ||||
| 		ast_copy_pj_str2(&session_media->msid, &attr->value); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void add_msid_to_stream(struct ast_sip_session *session, | ||||
| 	struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media) | ||||
| { | ||||
| 	pj_str_t stmp; | ||||
| 	pjmedia_sdp_attr *attr; | ||||
|  | ||||
| 	if (!session->endpoint->media.webrtc) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (ast_strlen_zero(session_media->msid)) { | ||||
| 		char uuid1[AST_UUID_STR_LEN], uuid2[AST_UUID_STR_LEN]; | ||||
|  | ||||
| 		if (ast_asprintf(&session_media->msid, "{%s} {%s}", | ||||
| 			ast_uuid_generate_str(uuid1, sizeof(uuid1)), | ||||
| 			ast_uuid_generate_str(uuid2, sizeof(uuid2))) < 0) { | ||||
| 			session_media->msid = NULL; | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	attr = pjmedia_sdp_attr_create(pool, "msid", pj_cstr(&stmp, session_media->msid)); | ||||
| 	pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr); | ||||
| } | ||||
|  | ||||
| static void add_rtcp_fb_to_stream(struct ast_sip_session *session, | ||||
| 	struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media) | ||||
| { | ||||
| 	pj_str_t stmp; | ||||
| 	pjmedia_sdp_attr *attr; | ||||
|  | ||||
| 	if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) { | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	 * For now just automatically add it the stream even though it hasn't | ||||
| 	 * necessarily been negotiated. | ||||
| 	 */ | ||||
| 	attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* ccm fir")); | ||||
| 	pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr); | ||||
| } | ||||
|  | ||||
| /*! \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 pjmedia_sdp_session *sdp, | ||||
| @@ -1068,7 +1127,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, | ||||
| 	} | ||||
|  | ||||
| 	process_ssrc_attributes(session, session_media, stream); | ||||
|  | ||||
| 	process_msid_attribute(session, session_media, stream); | ||||
| 	session_media_transport = ast_sip_session_media_get_transport(session, session_media); | ||||
|  | ||||
| 	if (session_media_transport == session_media || !session_media->bundled) { | ||||
| @@ -1527,6 +1586,8 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as | ||||
| 	} | ||||
|  | ||||
| 	add_ssrc_to_stream(session, session_media, pool, media); | ||||
| 	add_msid_to_stream(session, session_media, pool, media); | ||||
| 	add_rtcp_fb_to_stream(session, session_media, pool, media); | ||||
|  | ||||
| 	/* Add the media stream to the SDP */ | ||||
| 	sdp->media[sdp->media_count++] = media; | ||||
|   | ||||
| @@ -395,6 +395,7 @@ static void session_media_dtor(void *obj) | ||||
| 	} | ||||
|  | ||||
| 	ast_free(session_media->mid); | ||||
| 	ast_free(session_media->msid); | ||||
| } | ||||
|  | ||||
| struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_session *session, | ||||
| @@ -3573,15 +3574,17 @@ static int add_bundle_groups(struct ast_sip_session *session, pj_pool_t *pool, p | ||||
| 	int index, mid_id; | ||||
| 	struct sip_session_media_bundle_group *bundle_group; | ||||
|  | ||||
| 	if (session->endpoint->media.webrtc) { | ||||
| 		attr = pjmedia_sdp_attr_create(pool, "msid-semantic", pj_cstr(&stmp, "WMS *")); | ||||
| 		pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr); | ||||
| 	} | ||||
|  | ||||
| 	if (!session->endpoint->media.bundle) { | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	memset(bundle_groups, 0, sizeof(bundle_groups)); | ||||
|  | ||||
| 	attr = pjmedia_sdp_attr_create(pool, "msid-semantic", pj_cstr(&stmp, "WMS *")); | ||||
| 	pjmedia_sdp_attr_add(&answer->attr_count, answer->attr, attr); | ||||
|  | ||||
| 	/* Build the bundle group layout so we can then add it to the SDP */ | ||||
| 	for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) { | ||||
| 		struct ast_sip_session_media *session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user