/*! \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; }
static int container_test1_helper(struct ast_format_cap *cap1, struct ast_format_cap *cap2, struct ast_test *test) { int res = AST_TEST_PASS; struct ast_format_cap *cap_joint = NULL; struct ast_format tmpformat; if (ast_format_attr_reg_interface(&test_interface)) { ast_test_status_update(test, "test_interface failed to register.\n"); ast_format_cap_destroy(cap1); ast_format_cap_destroy(cap2); return AST_TEST_FAIL; } ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_G722, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_H263, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)); ast_format_cap_add(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, AST_FORMAT_ATTR_END)); /* Test is compatible */ if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || !ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 1.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Test things that are not compatible */ if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX, 0)) || ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_SPEEX16, 0)) || ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_H261, 0))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 2.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Test compatiblity with format with attributes. */ if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 3.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } if (!ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 4.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } if (ast_format_cap_iscompatible(cap1, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, /* 48khz was not compatible, so this should fail iscompatible check */ AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap1 failed to properly detect compatibility test 5.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets start testing the functions that compare ast_format_cap objects. * Genreate the cap2 object to contain some similar formats as cap1 * and some different formats as well. */ ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_H261, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)); ast_format_cap_add(cap2, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_12KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_32KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, AST_FORMAT_ATTR_END)); /* find joint formats between cap1 and cap2 */ cap_joint = ast_format_cap_joint(cap1, cap2); if (!cap_joint) { ast_test_status_update(test, "failed to create joint capabilities correctly.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* determine if cap_joint is what we think it should be */ if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* make sure joint cap does not have formats that should not be there */ if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_SIREN7, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_TESTLAW, 1, TEST_ATTR_KEY_STRING, "testing caps hooray", TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_8KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_16KHZ, TEST_ATTR_KEY_SAMP_RATE, TEST_ATTR_VAL_SAMP_48KHZ, AST_FORMAT_ATTR_END))) { ast_test_status_update(test, "ast cap_joint failed to properly detect compatibility test 1.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets test removing a capability */ if (ast_format_cap_remove(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { ast_test_status_update(test, "ast_format_cap_remove failed. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets make sure what we just removed does not still exist */ if (ast_format_cap_iscompatible(cap_joint, &tmpformat)) { ast_test_status_update(test, "ast_format_cap_remove failed 2. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets test removing a capability by id.*/ if (ast_format_cap_remove_byid(cap_joint, AST_FORMAT_GSM)) { ast_test_status_update(test, "ast_format_cap_remove failed 3. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* Lets make sure what we just removed does not still exist */ if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0))) { ast_test_status_update(test, "ast_format_cap_remove failed 4. \n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* lets test getting joint formats by type */ ast_format_cap_destroy(cap_joint); if (!(cap_joint = ast_format_cap_get_type(cap1, AST_FORMAT_TYPE_VIDEO))) { ast_test_status_update(test, "ast_format_cap_get_type failed.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* lets make sure our joint capability structure has what we expect */ if (!ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H264, 0)) || !ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_H263, 0))) { ast_test_status_update(test, "get_type failed 2.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* now make sure joint does not have anything but video */ if (ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ALAW, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_ULAW, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_GSM, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_JPEG, 0)) || ast_format_cap_iscompatible(cap_joint, ast_format_set(&tmpformat, AST_FORMAT_T140, 0))) { ast_test_status_update(test, "get_type failed 3.\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* now lets remove everythign from cap_joint */ ast_format_cap_remove_all(cap_joint); if (!ast_format_cap_is_empty(cap_joint)) { ast_test_status_update(test, "failed to remove all\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* now lets add all by type */ ast_format_cap_add_all_by_type(cap_joint, AST_FORMAT_TYPE_AUDIO); if (ast_format_cap_is_empty(cap_joint)) { ast_test_status_update(test, "failed to add all by type AUDIO\n"); res = AST_TEST_FAIL; } ast_format_cap_iter_start(cap_joint); while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { if (AST_FORMAT_GET_TYPE(tmpformat.id) != AST_FORMAT_TYPE_AUDIO) { ast_test_status_update(test, "failed to add all by type AUDIO\n"); res = AST_TEST_FAIL; ast_format_cap_iter_end(cap_joint); goto test3_cleanup; } } ast_format_cap_iter_end(cap_joint); /* test append */ ast_format_cap_append(cap_joint, cap1); ast_format_cap_iter_start(cap1); while (!(ast_format_cap_iter_next(cap1, &tmpformat))) { if (!ast_format_cap_iscompatible(cap_joint, &tmpformat)) { ast_test_status_update(test, "failed to append format capabilities.\n"); res = AST_TEST_FAIL; ast_format_cap_iter_end(cap1); goto test3_cleanup; } } ast_format_cap_iter_end(cap1); /* test copy */ cap1 = ast_format_cap_destroy(cap1); cap1 = ast_format_cap_dup(cap_joint); if (!ast_format_cap_identical(cap_joint, cap1)) { ast_test_status_update(test, "failed to copy capabilities\n"); res = AST_TEST_FAIL; goto test3_cleanup; } /* test remove by type */ ast_format_cap_remove_bytype(cap_joint, AST_FORMAT_TYPE_AUDIO); if (ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_AUDIO)) { ast_test_status_update(test, "failed to remove all by type audio\n"); res = AST_TEST_FAIL; goto test3_cleanup; } if (!ast_format_cap_has_type(cap_joint, AST_FORMAT_TYPE_TEXT)) { /* it should still have text */ ast_test_status_update(test, "failed to remove all by type audio\n"); res = AST_TEST_FAIL; goto test3_cleanup; } ast_format_cap_iter_start(cap_joint); while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { if (AST_FORMAT_GET_TYPE(tmpformat.id) == AST_FORMAT_TYPE_AUDIO) { ast_test_status_update(test, "failed to remove all by type audio\n"); res = AST_TEST_FAIL; ast_format_cap_iter_end(cap_joint); goto test3_cleanup; } } ast_format_cap_iter_end(cap_joint); /* test add all */ ast_format_cap_remove_all(cap_joint); ast_format_cap_add_all(cap_joint); { int video = 0, audio = 0, text = 0, image = 0; ast_format_cap_iter_start(cap_joint); while (!(ast_format_cap_iter_next(cap_joint, &tmpformat))) { switch (AST_FORMAT_GET_TYPE(tmpformat.id)) { case AST_FORMAT_TYPE_AUDIO: audio++; break; case AST_FORMAT_TYPE_VIDEO: video++; break; case AST_FORMAT_TYPE_TEXT: text++; break; case AST_FORMAT_TYPE_IMAGE: image++; break; } } ast_format_cap_iter_end(cap_joint); if (!video || !audio || !text || !image) { ast_test_status_update(test, "failed to add all\n"); res = AST_TEST_FAIL; goto test3_cleanup; } } /* test copy2 */ ast_format_cap_copy(cap2, cap_joint); if (!ast_format_cap_identical(cap2, cap_joint)) { ast_test_status_update(test, "ast_format_cap_copy failed\n"); res = AST_TEST_FAIL; goto test3_cleanup; } test3_cleanup: ast_format_cap_destroy(cap1); ast_format_cap_destroy(cap2); ast_format_cap_destroy(cap_joint); /* unregister interface */ if (ast_format_attr_unreg_interface(&test_interface)) { ast_test_status_update(test, "test_interface failed to unregister.\n"); res = AST_TEST_FAIL; } return res; }