/*! \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->media.codecs, media_type)) {
		return 0;
	}

	/* Ensure incoming transport is compatible with the endpoint's configuration */
	if (!session->endpoint->media.rtp.use_received_transport &&
		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 (session->endpoint->media.rtp.use_received_transport) {
		pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport);
	}

	if (setup_media_encryption(session, session_media, stream)) {
		return -1;
	}

	if (set_caps(session, session_media, stream)) {
		return -1;
	}

	if (media_type == AST_FORMAT_TYPE_AUDIO) {
		apply_packetization(session, session_media, stream);
	}

	return 1;
}
Beispiel #2
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);
	enum ast_media_type media_type = stream_to_media_type(session_media->stream_type);
	enum ast_sip_session_media_encryption encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
	int res;

	/* If port is 0, ignore this media stream */
	if (!stream->desc.port) {
		ast_debug(3, "Media stream '%s' is already declined\n", session_media->stream_type);
		return 0;
	}

	/* If no type formats have been configured reject this stream */
	if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
		ast_debug(3, "Endpoint has no codecs for media type '%s', declining stream\n", session_media->stream_type);
		return 0;
	}

	/* Ensure incoming transport is compatible with the endpoint's configuration */
	if (!session->endpoint->media.rtp.use_received_transport) {
		encryption = check_endpoint_media_transport(session->endpoint, stream);

		if (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;
	}

	res = setup_media_encryption(session, session_media, sdp, stream);
	if (res) {
		if (!session->endpoint->media.rtp.encryption_optimistic) {
			/* If optimistic encryption is disabled and crypto should have been enabled
			 * but was not this session must fail.
			 */
			return -1;
		}
		/* There is no encryption, sad. */
		session_media->encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
 	}

	/* If we've been explicitly configured to use the received transport OR if
	 * encryption is on and crypto is present use the received transport.
	 * This is done in case of optimistic because it may come in as RTP/AVP or RTP/SAVP depending
	 * on the configuration of the remote endpoint (optimistic themselves or mandatory).
	 */
	if ((session->endpoint->media.rtp.use_received_transport) ||
		((encryption == AST_SIP_MEDIA_ENCRYPT_SDES) && !res)) {
		pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport);
 	}

	if (set_caps(session, session_media, stream)) {
		return 0;
	}
	return 1;
}