/*! \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; }
/*! \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; }