Asterisk - The Open Source Telephony Project GIT-master-0bf3178
Functions | Variables
res_pjsip_sdp_rtp.c File Reference

SIP SDP media stream handling. More...

#include "asterisk.h"
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjmedia.h>
#include <pjlib.h>
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/netsock2.h"
#include "asterisk/channel.h"
#include "asterisk/causes.h"
#include "asterisk/sched.h"
#include "asterisk/acl.h"
#include "asterisk/sdp_srtp.h"
#include "asterisk/dsp.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stream.h"
#include "asterisk/logger_category.h"
#include "asterisk/format_cache.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "asterisk/res_pjsip_session_caps.h"
Include dependency graph for res_pjsip_sdp_rtp.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_crypto_to_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
 
static void add_extmap_to_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
 
static void add_ice_to_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media, unsigned int include_candidates)
 Function which adds ICE attributes to a media stream. More...
 
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, struct ast_stream *stream)
 
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)
 
static void add_ssrc_to_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
 Function which adds ssrc attributes to a media stream. More...
 
static int apply_cap_to_bundled (struct ast_sip_session_media *session_media, struct ast_sip_session_media *session_media_transport, struct ast_stream *asterisk_stream, struct ast_format_cap *joint)
 
static void apply_dtls_attrib (struct ast_sip_session_media *session_media, pjmedia_sdp_attr *attr)
 
static int apply_negotiated_sdp_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local, const struct pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void change_outgoing_sdp_stream_media_address (pjsip_tx_data *tdata, struct pjmedia_sdp_media *stream, struct ast_sip_transport *transport)
 Function which updates the media stream with external media address, if applicable. More...
 
static enum ast_sip_session_media_encryption check_endpoint_media_transport (struct ast_sip_endpoint *endpoint, const struct pjmedia_sdp_media *stream)
 Checks whether the encryption offered in SDP is compatible with the endpoint's configuration. More...
 
static void check_ice_support (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_stream)
 Function which checks for ice attributes in an audio stream. More...
 
static int create_outgoing_sdp_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
 Function which creates an outgoing stream. More...
 
static int create_rtp (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp)
 Internal function which creates an RTP instance. More...
 
static void enable_rtcp (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_media)
 Enable RTCP on an RTP session. More...
 
static void enable_rtp_extension (struct ast_sip_session *session, struct ast_sip_session_media *session_media, enum ast_rtp_extension extension, enum ast_rtp_extension_direction direction, const pjmedia_sdp_session *sdp)
 Enable an RTP extension on an RTP session. More...
 
static pjmedia_sdp_attr * generate_fmtp_attr (pj_pool_t *pool, struct ast_format *format, int rtp_code)
 
static pjmedia_sdp_attr * generate_rtpmap_attr (struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool, int rtp_code, int asterisk_format, struct ast_format *format, int code)
 
static pjmedia_sdp_attr * generate_rtpmap_attr2 (struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool, int rtp_code, int asterisk_format, struct ast_format *format, int code, int sample_rate)
 
static void get_codecs (struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs, struct ast_sip_session_media *session_media, struct ast_format_cap *astformats)
 
static enum ast_sip_session_media_encryption get_media_encryption_type (pj_str_t transport, const struct pjmedia_sdp_media *stream, unsigned int *optimistic)
 figure out media transport encryption type from the media transport string More...
 
static int load_module (void)
 Load the module. More...
 
static struct ast_framemedia_session_rtcp_read_callback (struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 
static struct ast_framemedia_session_rtp_read_callback (struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 
static int media_session_rtp_write_callback (struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
 
static int media_stream_has_crypto (const struct pjmedia_sdp_media *stream)
 figure out if media stream has crypto lines for sdes More...
 
static int negotiate_incoming_sdp_stream (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp, int index, struct ast_stream *asterisk_stream)
 Function which negotiates an incoming media stream. More...
 
static int parse_dtls_attrib (struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
 
static void process_extmap_attributes (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_stream)
 Function which processes extmap attributes in a stream. More...
 
static void process_ice_attributes (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
 Function which processes ICE attributes in an audio stream. More...
 
static void process_ice_auth_attrb (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
 
static void process_ssrc_attributes (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_stream)
 Function which processes ssrc attributes in a stream. More...
 
static int rtp_check_timeout (const void *data)
 Check whether RTP is being received or not. More...
 
static int send_keepalive (const void *data)
 
static int set_caps (struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_sip_session_media *session_media_transport, const struct pjmedia_sdp_media *stream, int is_offer, struct ast_stream *asterisk_stream)
 
static void set_ice_components (struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 
static struct ast_format_capset_incoming_call_offer_cap (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream)
 
static void set_session_media_remotely_held (struct ast_sip_session_media *session_media, const struct ast_sip_session *session, const pjmedia_sdp_media *media, const struct ast_stream *stream, const struct ast_sockaddr *addrs)
 
static int setup_dtls_srtp (struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 
static int setup_media_encryption (struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
 
static int setup_sdes_srtp (struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream)
 
static int setup_srtp (struct ast_sip_session_media *session_media)
 
static void stream_destroy (struct ast_sip_session_media *session_media)
 Function which destroys the RTP instance when session ends. More...
 
static void stream_stop (struct ast_sip_session_media *session_media)
 Function which stops the RTP instance. More...
 
static int unload_module (void)
 Unloads the sdp RTP/AVP module from Asterisk. More...
 
static int video_info_incoming_request (struct ast_sip_session *session, struct pjsip_rx_data *rdata)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP SDP RTP/AVP stream handler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_pjsip,res_pjsip_session", }
 
static struct ast_sockaddr address_rtp
 Address for RTP. More...
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_sip_session_sdp_handler audio_sdp_handler
 SDP handler for 'audio' media stream. More...
 
static struct ast_sched_contextsched
 Scheduler for RTCP purposes. More...
 
static const char STR_AUDIO [] = "audio"
 
static const char STR_VIDEO [] = "video"
 
static struct ast_sip_session_supplement video_info_supplement
 
static struct ast_sip_session_sdp_handler video_sdp_handler
 SDP handler for 'video' media stream. More...
 

Detailed Description

SIP SDP media stream handling.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file res_pjsip_sdp_rtp.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2549 of file res_pjsip_sdp_rtp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2549 of file res_pjsip_sdp_rtp.c.

◆ add_crypto_to_stream()

static int add_crypto_to_stream ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
pj_pool_t *  pool,
pjmedia_sdp_media *  media 
)
static

Definition at line 1648 of file res_pjsip_sdp_rtp.c.

1651{
1652 pj_str_t stmp;
1653 pjmedia_sdp_attr *attr;
1654 enum ast_rtp_dtls_hash hash;
1655 const char *crypto_attribute;
1656 struct ast_rtp_engine_dtls *dtls;
1657 struct ast_sdp_srtp *tmp;
1658 static const pj_str_t STR_NEW = { "new", 3 };
1659 static const pj_str_t STR_EXISTING = { "existing", 8 };
1660 static const pj_str_t STR_ACTIVE = { "active", 6 };
1661 static const pj_str_t STR_PASSIVE = { "passive", 7 };
1662 static const pj_str_t STR_ACTPASS = { "actpass", 7 };
1663 static const pj_str_t STR_HOLDCONN = { "holdconn", 8 };
1664 static const pj_str_t STR_MEDSECREQ = { "requested", 9 };
1665 enum ast_rtp_dtls_setup setup;
1666
1667 switch (session_media->encryption) {
1670 break;
1672 if (!session_media->srtp) {
1673 session_media->srtp = ast_sdp_srtp_alloc();
1674 if (!session_media->srtp) {
1675 return -1;
1676 }
1677 }
1678
1679 tmp = session_media->srtp;
1680
1681 do {
1682 crypto_attribute = ast_sdp_srtp_get_attrib(tmp,
1683 0 /* DTLS running? No */,
1684 session->endpoint->media.rtp.srtp_tag_32 /* 32 byte tag length? */);
1685 if (!crypto_attribute) {
1686 /* No crypto attribute to add, bad news */
1687 return -1;
1688 }
1689
1690 attr = pjmedia_sdp_attr_create(pool, "crypto",
1691 pj_cstr(&stmp, crypto_attribute));
1692 media->attr[media->attr_count++] = attr;
1693 } while ((tmp = AST_LIST_NEXT(tmp, sdp_srtp_list)));
1694
1695 if (session->endpoint->security_negotiation == AST_SIP_SECURITY_NEG_MEDIASEC) {
1696 attr = pjmedia_sdp_attr_create(pool, "3ge2ae", &STR_MEDSECREQ);
1697 media->attr[media->attr_count++] = attr;
1698 }
1699
1700 break;
1702 if (setup_dtls_srtp(session, session_media)) {
1703 return -1;
1704 }
1705
1706 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1707 if (!dtls) {
1708 return -1;
1709 }
1710
1711 switch (dtls->get_connection(session_media->rtp)) {
1713 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_NEW);
1714 media->attr[media->attr_count++] = attr;
1715 break;
1717 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_EXISTING);
1718 media->attr[media->attr_count++] = attr;
1719 break;
1720 default:
1721 break;
1722 }
1723
1724 /* If this is an answer we need to use our current state, if it's an offer we need to use
1725 * the configured value.
1726 */
1727 if (session->inv_session->neg
1728 && pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
1729 setup = dtls->get_setup(session_media->rtp);
1730 } else {
1731 setup = session->endpoint->media.rtp.dtls_cfg.default_setup;
1732 }
1733
1734 switch (setup) {
1736 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTIVE);
1737 media->attr[media->attr_count++] = attr;
1738 break;
1740 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_PASSIVE);
1741 media->attr[media->attr_count++] = attr;
1742 break;
1744 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTPASS);
1745 media->attr[media->attr_count++] = attr;
1746 break;
1748 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_HOLDCONN);
1749 break;
1750 default:
1751 break;
1752 }
1753
1754 hash = dtls->get_fingerprint_hash(session_media->rtp);
1755 crypto_attribute = dtls->get_fingerprint(session_media->rtp);
1756 if (crypto_attribute && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
1757 RAII_VAR(struct ast_str *, fingerprint, ast_str_create(64), ast_free);
1758 if (!fingerprint) {
1759 return -1;
1760 }
1761
1762 if (hash == AST_RTP_DTLS_HASH_SHA1) {
1763 ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
1764 } else {
1765 ast_str_set(&fingerprint, 0, "SHA-256 %s", crypto_attribute);
1766 }
1767
1768 attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
1769 media->attr[media->attr_count++] = attr;
1770 }
1771 break;
1772 }
1773
1774 return 0;
1775}
static struct ast_mansession session
#define ast_free(a)
Definition: astmm.h:180
static int tmp()
Definition: bt_open.c:389
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
@ AST_SIP_MEDIA_ENCRYPT_SDES
Definition: res_pjsip.h:646
@ AST_SIP_MEDIA_TRANSPORT_INVALID
Definition: res_pjsip.h:642
@ AST_SIP_MEDIA_ENCRYPT_NONE
Definition: res_pjsip.h:644
@ AST_SIP_MEDIA_ENCRYPT_DTLS
Definition: res_pjsip.h:648
@ AST_SIP_SECURITY_NEG_MEDIASEC
Definition: res_pjsip.h:354
static int setup_dtls_srtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
ast_rtp_dtls_setup
DTLS setup types.
Definition: rtp_engine.h:564
@ AST_RTP_DTLS_SETUP_PASSIVE
Definition: rtp_engine.h:566
@ AST_RTP_DTLS_SETUP_HOLDCONN
Definition: rtp_engine.h:568
@ AST_RTP_DTLS_SETUP_ACTPASS
Definition: rtp_engine.h:567
@ AST_RTP_DTLS_SETUP_ACTIVE
Definition: rtp_engine.h:565
ast_rtp_dtls_hash
DTLS fingerprint hashes.
Definition: rtp_engine.h:578
@ AST_RTP_DTLS_HASH_SHA1
Definition: rtp_engine.h:580
@ AST_RTP_DTLS_HASH_SHA256
Definition: rtp_engine.h:579
struct ast_rtp_engine_dtls * ast_rtp_instance_get_dtls(struct ast_rtp_instance *instance)
Obtain a pointer to the DTLS support present on an RTP instance.
Definition: rtp_engine.c:3211
@ AST_RTP_DTLS_CONNECTION_NEW
Definition: rtp_engine.h:573
@ AST_RTP_DTLS_CONNECTION_EXISTING
Definition: rtp_engine.h:574
const char * ast_sdp_srtp_get_attrib(struct ast_sdp_srtp *srtp, int dtls_enabled, int default_taglen_32)
Get the crypto attribute line for the srtp structure.
Definition: sdp_srtp.c:95
struct ast_sdp_srtp * ast_sdp_srtp_alloc(void)
allocate a ast_sdp_srtp structure
Definition: sdp_srtp.c:41
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Structure that represents the optional DTLS SRTP support within an RTP engine.
Definition: rtp_engine.h:621
enum ast_rtp_dtls_setup(* get_setup)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:633
enum ast_rtp_dtls_hash(* get_fingerprint_hash)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:639
const char *(* get_fingerprint)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:641
enum ast_rtp_dtls_connection(* get_connection)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:631
structure for secure RTP audio
Definition: sdp_srtp.h:38
struct ast_sdp_srtp::@278 sdp_srtp_list
struct ast_sdp_srtp * srtp
Holds SRTP information.
struct ast_rtp_instance * rtp
RTP instance itself.
enum ast_sip_session_media_encryption encryption
What type of encryption is in use on this stream.
Support for dynamic strings.
Definition: strings.h:623
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ast_free, AST_LIST_NEXT, AST_RTP_DTLS_CONNECTION_EXISTING, AST_RTP_DTLS_CONNECTION_NEW, AST_RTP_DTLS_HASH_SHA1, AST_RTP_DTLS_HASH_SHA256, AST_RTP_DTLS_SETUP_ACTIVE, AST_RTP_DTLS_SETUP_ACTPASS, AST_RTP_DTLS_SETUP_HOLDCONN, AST_RTP_DTLS_SETUP_PASSIVE, ast_rtp_instance_get_dtls(), ast_sdp_srtp_alloc(), ast_sdp_srtp_get_attrib(), AST_SIP_MEDIA_ENCRYPT_DTLS, AST_SIP_MEDIA_ENCRYPT_NONE, AST_SIP_MEDIA_ENCRYPT_SDES, AST_SIP_MEDIA_TRANSPORT_INVALID, AST_SIP_SECURITY_NEG_MEDIASEC, ast_str_buffer(), ast_str_create, ast_str_set(), ast_sip_session_media::encryption, ast_rtp_engine_dtls::get_connection, ast_rtp_engine_dtls::get_fingerprint, ast_rtp_engine_dtls::get_fingerprint_hash, ast_rtp_engine_dtls::get_setup, RAII_VAR, ast_sip_session_media::rtp, ast_sdp_srtp::sdp_srtp_list, session, setup_dtls_srtp(), ast_sip_session_media::srtp, and tmp().

Referenced by create_outgoing_sdp_stream().

◆ add_extmap_to_stream()

static void add_extmap_to_stream ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
pj_pool_t *  pool,
pjmedia_sdp_media *  media 
)
static

Definition at line 1412 of file res_pjsip_sdp_rtp.c.

1414{
1415 int idx;
1416 char extmap_value[256];
1417
1418 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1419 return;
1420 }
1421
1422 /* RTP extension local unique identifiers start at '1' */
1423 for (idx = 1; idx <= ast_rtp_instance_extmap_count(session_media->rtp); ++idx) {
1425 const char *direction_str = "";
1426 pj_str_t stmp;
1427 pjmedia_sdp_attr *attr;
1428
1429 /* If this is an unsupported RTP extension we can't place it into the SDP */
1431 continue;
1432 }
1433
1434 switch (ast_rtp_instance_extmap_get_direction(session_media->rtp, idx)) {
1436 /* Lack of a direction indicates sendrecv, so we leave it out */
1437 direction_str = "";
1438 break;
1440 direction_str = "/sendonly";
1441 break;
1443 direction_str = "/recvonly";
1444 break;
1446 /* It is impossible for a "none" direction extension to be negotiated but just in case
1447 * we treat it as inactive.
1448 */
1450 direction_str = "/inactive";
1451 break;
1452 }
1453
1454 snprintf(extmap_value, sizeof(extmap_value), "%d%s %s", idx, direction_str,
1455 ast_rtp_instance_extmap_get_uri(session_media->rtp, idx));
1456 attr = pjmedia_sdp_attr_create(pool, "extmap", pj_cstr(&stmp, extmap_value));
1457 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1458 }
1459}
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
size_t ast_rtp_instance_extmap_count(struct ast_rtp_instance *instance)
Get the number of known unique identifiers.
Definition: rtp_engine.c:921
enum ast_rtp_extension ast_rtp_instance_extmap_get_extension(struct ast_rtp_instance *instance, int id)
Retrieve the extension for an RTP extension id.
Definition: rtp_engine.c:932
ast_rtp_extension
Known RTP extensions.
Definition: rtp_engine.h:593
@ AST_RTP_EXTENSION_UNSUPPORTED
Definition: rtp_engine.h:595
@ AST_RTP_EXTENSION_DIRECTION_SENDRECV
Definition: rtp_engine.h:831
@ AST_RTP_EXTENSION_DIRECTION_NONE
Definition: rtp_engine.h:829
@ AST_RTP_EXTENSION_DIRECTION_INACTIVE
Definition: rtp_engine.h:837
@ AST_RTP_EXTENSION_DIRECTION_RECVONLY
Definition: rtp_engine.h:835
@ AST_RTP_EXTENSION_DIRECTION_SENDONLY
Definition: rtp_engine.h:833
const char * ast_rtp_instance_extmap_get_uri(struct ast_rtp_instance *instance, int id)
Retrieve the URI for an RTP extension id.
Definition: rtp_engine.c:968
enum ast_rtp_extension_direction ast_rtp_instance_extmap_get_direction(struct ast_rtp_instance *instance, int id)
Retrieve the negotiated direction for an RTP extension id.
Definition: rtp_engine.c:952
enum ast_media_type type
Media type of this session media.
structure to hold extensions

References AST_MEDIA_TYPE_VIDEO, AST_RTP_EXTENSION_DIRECTION_INACTIVE, AST_RTP_EXTENSION_DIRECTION_NONE, AST_RTP_EXTENSION_DIRECTION_RECVONLY, AST_RTP_EXTENSION_DIRECTION_SENDONLY, AST_RTP_EXTENSION_DIRECTION_SENDRECV, AST_RTP_EXTENSION_UNSUPPORTED, ast_rtp_instance_extmap_count(), ast_rtp_instance_extmap_get_direction(), ast_rtp_instance_extmap_get_extension(), ast_rtp_instance_extmap_get_uri(), ast_sip_session_media::rtp, session, and ast_sip_session_media::type.

Referenced by create_outgoing_sdp_stream().

◆ add_ice_to_stream()

static void add_ice_to_stream ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
pj_pool_t *  pool,
pjmedia_sdp_media *  media,
unsigned int  include_candidates 
)
static

Function which adds ICE attributes to a media stream.

Definition at line 733 of file res_pjsip_sdp_rtp.c.

735{
736 struct ast_rtp_engine_ice *ice;
737 struct ao2_container *candidates;
738 const char *username, *password;
739 pj_str_t stmp;
740 pjmedia_sdp_attr *attr;
741 struct ao2_iterator it_candidates;
742 struct ast_rtp_engine_ice_candidate *candidate;
743
744 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
745 return;
746 }
747
748 if (!session_media->remote_ice) {
749 ice->stop(session_media->rtp);
750 return;
751 }
752
753 if ((username = ice->get_ufrag(session_media->rtp))) {
754 attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", pj_cstr(&stmp, username));
755 media->attr[media->attr_count++] = attr;
756 }
757
758 if ((password = ice->get_password(session_media->rtp))) {
759 attr = pjmedia_sdp_attr_create(pool, "ice-pwd", pj_cstr(&stmp, password));
760 media->attr[media->attr_count++] = attr;
761 }
762
763 if (!include_candidates) {
764 return;
765 }
766
767 candidates = ice->get_local_candidates(session_media->rtp);
768 if (!candidates) {
769 return;
770 }
771
772 it_candidates = ao2_iterator_init(candidates, 0);
773 for (; (candidate = ao2_iterator_next(&it_candidates)); ao2_ref(candidate, -1)) {
774 struct ast_str *attr_candidate = ast_str_create(128);
775
776 ast_str_set(&attr_candidate, -1, "%s %u %s %d %s ", candidate->foundation, candidate->id, candidate->transport,
777 candidate->priority, ast_sockaddr_stringify_addr_remote(&candidate->address));
778 ast_str_append(&attr_candidate, -1, "%s typ ", ast_sockaddr_stringify_port(&candidate->address));
779
780 switch (candidate->type) {
782 ast_str_append(&attr_candidate, -1, "host");
783 break;
785 ast_str_append(&attr_candidate, -1, "srflx");
786 break;
788 ast_str_append(&attr_candidate, -1, "relay");
789 break;
790 }
791
792 if (!ast_sockaddr_isnull(&candidate->relay_address)) {
793 ast_str_append(&attr_candidate, -1, " raddr %s rport", ast_sockaddr_stringify_addr_remote(&candidate->relay_address));
794 ast_str_append(&attr_candidate, -1, " %s", ast_sockaddr_stringify_port(&candidate->relay_address));
795 }
796
797 attr = pjmedia_sdp_attr_create(pool, "candidate", pj_cstr(&stmp, ast_str_buffer(attr_candidate)));
798 media->attr[media->attr_count++] = attr;
799
800 ast_free(attr_candidate);
801 }
802
803 ao2_iterator_destroy(&it_candidates);
804 ao2_ref(candidates, -1);
805}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized,...
Definition: netsock2.h:127
static char * ast_sockaddr_stringify_port(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return a port only.
Definition: netsock2.h:358
static char * ast_sockaddr_stringify_addr_remote(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Definition: netsock2.h:313
@ AST_RTP_ICE_CANDIDATE_TYPE_RELAYED
Definition: rtp_engine.h:509
@ AST_RTP_ICE_CANDIDATE_TYPE_SRFLX
Definition: rtp_engine.h:508
@ AST_RTP_ICE_CANDIDATE_TYPE_HOST
Definition: rtp_engine.h:507
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:3091
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Structure for an ICE candidate.
Definition: rtp_engine.h:525
struct ast_sockaddr address
Definition: rtp_engine.h:530
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:527
struct ast_sockaddr relay_address
Definition: rtp_engine.h:531
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:532
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:536
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:544
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:546
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:548
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:550
unsigned int remote_ice
Does remote support ice.

References ast_rtp_engine_ice_candidate::address, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_free, AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_RELAYED, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, ast_rtp_instance_get_ice(), ast_sockaddr_isnull(), ast_sockaddr_stringify_addr_remote(), ast_sockaddr_stringify_port(), ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_rtp_engine_ice_candidate::foundation, ast_rtp_engine_ice::get_local_candidates, ast_rtp_engine_ice::get_password, ast_rtp_engine_ice::get_ufrag, ast_rtp_engine_ice_candidate::id, ast_rtp_engine_ice_candidate::priority, ast_rtp_engine_ice_candidate::relay_address, ast_sip_session_media::remote_ice, ast_sip_session_media::rtp, session, ast_rtp_engine_ice::stop, ast_rtp_engine_ice_candidate::transport, and ast_rtp_engine_ice_candidate::type.

Referenced by create_outgoing_sdp_stream().

◆ add_msid_to_stream()

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,
struct ast_stream stream 
)
static

Definition at line 1330 of file res_pjsip_sdp_rtp.c.

1333{
1334 pj_str_t stmp;
1335 pjmedia_sdp_attr *attr;
1336 char msid[(AST_UUID_STR_LEN * 2) + 2];
1337 const char *stream_label = ast_stream_get_metadata(stream, "SDP:LABEL");
1338
1339 if (!session->endpoint->media.webrtc) {
1340 return;
1341 }
1342
1343 if (ast_strlen_zero(session_media->mslabel)) {
1344 /* If this stream is grouped with another then use its media stream label if possible */
1345 if (ast_stream_get_group(stream) != -1) {
1346 struct ast_sip_session_media *group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, ast_stream_get_group(stream));
1347
1348 ast_copy_string(session_media->mslabel, group_session_media->mslabel, sizeof(session_media->mslabel));
1349 }
1350
1351 if (ast_strlen_zero(session_media->mslabel)) {
1352 ast_uuid_generate_str(session_media->mslabel, sizeof(session_media->mslabel));
1353 }
1354 }
1355
1356 if (ast_strlen_zero(session_media->label)) {
1357 ast_uuid_generate_str(session_media->label, sizeof(session_media->label));
1358 /* add for stream identification to replace stream_name */
1359 ast_stream_set_metadata(stream, "MSID:LABEL", session_media->label);
1360 }
1361
1362 snprintf(msid, sizeof(msid), "%s %s", session_media->mslabel, session_media->label);
1363 ast_debug(3, "Stream msid: %p %s %s\n", stream,
1365 attr = pjmedia_sdp_attr_create(pool, "msid", pj_cstr(&stmp, msid));
1366 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1367
1368 /* 'label' must come after 'msid' */
1369 if (!ast_strlen_zero(stream_label)) {
1370 ast_debug(3, "Stream Label: %p %s %s\n", stream,
1371 ast_codec_media_type2str(ast_stream_get_type(stream)), stream_label);
1372 attr = pjmedia_sdp_attr_create(pool, "label", pj_cstr(&stmp, stream_label));
1373 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1374 }
1375}
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
Definition: codec.c:348
#define ast_debug(level,...)
Log a DEBUG message.
const char * ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key)
Get a stream metadata value.
Definition: stream.c:423
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
Definition: stream.c:460
int ast_stream_get_group(const struct ast_stream *stream)
Get the stream group that a stream is part of.
Definition: stream.c:1080
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
A structure containing SIP session media information.
char label[AST_UUID_STR_LEN]
Track label.
char mslabel[AST_UUID_STR_LEN]
Media stream label.
#define AST_UUID_STR_LEN
Definition: uuid.h:27
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References ast_codec_media_type2str(), ast_copy_string(), ast_debug, ast_stream_get_group(), ast_stream_get_metadata(), ast_stream_get_type(), ast_stream_set_metadata(), ast_strlen_zero(), ast_uuid_generate_str(), AST_UUID_STR_LEN, AST_VECTOR_GET, ast_sip_session_media::label, ast_sip_session_media::mslabel, and session.

Referenced by create_outgoing_sdp_stream().

◆ add_rtcp_fb_to_stream()

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 
)
static

Definition at line 1377 of file res_pjsip_sdp_rtp.c.

1379{
1380 pj_str_t stmp;
1381 pjmedia_sdp_attr *attr;
1382
1383 if (!session->endpoint->media.webrtc) {
1384 return;
1385 }
1386
1387 /* transport-cc is supposed to be for the entire transport, and any media sources so
1388 * while the header does not appear in audio streams and isn't negotiated there, we still
1389 * place this attribute in as Chrome does.
1390 */
1391 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* transport-cc"));
1392 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1393
1394 if (session_media->type != AST_MEDIA_TYPE_VIDEO) {
1395 return;
1396 }
1397
1398 /*
1399 * For now just automatically add it the stream even though it hasn't
1400 * necessarily been negotiated.
1401 */
1402 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* ccm fir"));
1403 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1404
1405 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* goog-remb"));
1406 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1407
1408 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* nack"));
1409 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1410}

References AST_MEDIA_TYPE_VIDEO, session, and ast_sip_session_media::type.

Referenced by create_outgoing_sdp_stream().

◆ add_ssrc_to_stream()

static void add_ssrc_to_stream ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
pj_pool_t *  pool,
pjmedia_sdp_media *  media 
)
static

Function which adds ssrc attributes to a media stream.

Definition at line 1260 of file res_pjsip_sdp_rtp.c.

1261{
1262 pj_str_t stmp;
1263 pjmedia_sdp_attr *attr;
1264 char tmp[128];
1265
1266 if (!session->endpoint->media.bundle || session_media->bundle_group == -1) {
1267 return;
1268 }
1269
1270 snprintf(tmp, sizeof(tmp), "%u cname:%s", ast_rtp_instance_get_ssrc(session_media->rtp), ast_rtp_instance_get_cname(session_media->rtp));
1271 attr = pjmedia_sdp_attr_create(pool, "ssrc", pj_cstr(&stmp, tmp));
1272 media->attr[media->attr_count++] = attr;
1273}
const char * ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp)
Retrieve the CNAME used in RTCP SDES items.
Definition: rtp_engine.c:4024
unsigned int ast_rtp_instance_get_ssrc(struct ast_rtp_instance *rtp)
Retrieve the local SSRC value that we will be using.
Definition: rtp_engine.c:4011
int bundle_group
The bundle group the stream belongs to.

References ast_rtp_instance_get_cname(), ast_rtp_instance_get_ssrc(), ast_sip_session_media::bundle_group, ast_sip_session_media::rtp, session, and tmp().

Referenced by create_outgoing_sdp_stream().

◆ apply_cap_to_bundled()

static int apply_cap_to_bundled ( struct ast_sip_session_media session_media,
struct ast_sip_session_media session_media_transport,
struct ast_stream asterisk_stream,
struct ast_format_cap joint 
)
static

Definition at line 428 of file res_pjsip_sdp_rtp.c.

431{
432 if (!joint) {
433 return -1;
434 }
435
436 ast_stream_set_formats(asterisk_stream, joint);
437
438 /* If this is a bundled stream then apply the payloads to RTP instance acting as transport to prevent conflicts */
439 if (session_media_transport != session_media && session_media->bundled) {
440 int index;
441
442 for (index = 0; index < ast_format_cap_count(joint); ++index) {
443 struct ast_format *format = ast_format_cap_get_format(joint, index);
444 int rtp_code;
445
446 /* Ensure this payload is in the bundle group transport codecs, this purposely doesn't check the return value for
447 * things as the format is guaranteed to have a payload already.
448 */
449 rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0);
450 ast_rtp_codecs_payload_set_rx(ast_rtp_instance_get_codecs(session_media_transport->rtp), rtp_code, format);
451
452 ao2_ref(format, -1);
453 }
454 }
455
456 return 0;
457}
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format)
Set a payload code for use with a specific Asterisk format.
Definition: rtp_engine.c:2075
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:749
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
Retrieve a rx mapped payload type based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:2019
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Definition: stream.c:365
Definition of a media format.
Definition: format.c:43
unsigned int bundled
Whether this stream is currently bundled or not.

References ao2_ref, ast_format_cap_count(), ast_format_cap_get_format(), ast_rtp_codecs_payload_code(), ast_rtp_codecs_payload_set_rx(), ast_rtp_instance_get_codecs(), ast_stream_set_formats(), ast_sip_session_media::bundled, and ast_sip_session_media::rtp.

Referenced by negotiate_incoming_sdp_stream(), and set_caps().

◆ apply_dtls_attrib()

static void apply_dtls_attrib ( struct ast_sip_session_media session_media,
pjmedia_sdp_attr *  attr 
)
static

Definition at line 1108 of file res_pjsip_sdp_rtp.c.

1110{
1111 struct ast_rtp_engine_dtls *dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1112 pj_str_t *value;
1113
1114 if (!attr->value.ptr || !dtls) {
1115 return;
1116 }
1117
1118 value = pj_strtrim(&attr->value);
1119
1120 if (!pj_strcmp2(&attr->name, "setup")) {
1121 if (!pj_stricmp2(value, "active")) {
1122 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTIVE);
1123 } else if (!pj_stricmp2(value, "passive")) {
1124 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_PASSIVE);
1125 } else if (!pj_stricmp2(value, "actpass")) {
1126 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTPASS);
1127 } else if (!pj_stricmp2(value, "holdconn")) {
1128 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_HOLDCONN);
1129 } else {
1130 ast_log(LOG_WARNING, "Unsupported setup attribute value '%*s'\n", (int)value->slen, value->ptr);
1131 }
1132 } else if (!pj_strcmp2(&attr->name, "connection")) {
1133 if (!pj_stricmp2(value, "new")) {
1134 dtls->reset(session_media->rtp);
1135 } else if (!pj_stricmp2(value, "existing")) {
1136 /* Do nothing */
1137 } else {
1138 ast_log(LOG_WARNING, "Unsupported connection attribute value '%*s'\n", (int)value->slen, value->ptr);
1139 }
1140 } else if (!pj_strcmp2(&attr->name, "fingerprint")) {
1141 char hash_value[256], hash[32];
1142 char fingerprint_text[value->slen + 1];
1143 ast_copy_pj_str(fingerprint_text, value, sizeof(fingerprint_text));
1144 if (sscanf(fingerprint_text, "%31s %255s", hash, hash_value) == 2) {
1145 if (!strcasecmp(hash, "sha-1")) {
1146 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
1147 } else if (!strcasecmp(hash, "sha-256")) {
1148 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA256, hash_value);
1149 } else {
1150 ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
1151 hash);
1152 }
1153 }
1154 }
1155}
#define ast_log
Definition: astobj2.c:42
#define LOG_WARNING
void ast_copy_pj_str(char *dest, const pj_str_t *src, size_t size)
Copy a pj_str_t into a standard character buffer.
Definition: res_pjsip.c:2201
void(* reset)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:629
void(* set_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint)
Definition: rtp_engine.h:637
void(* set_setup)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup)
Definition: rtp_engine.h:635
int value
Definition: syslog.c:37

References ast_copy_pj_str(), ast_log, AST_RTP_DTLS_HASH_SHA1, AST_RTP_DTLS_HASH_SHA256, AST_RTP_DTLS_SETUP_ACTIVE, AST_RTP_DTLS_SETUP_ACTPASS, AST_RTP_DTLS_SETUP_HOLDCONN, AST_RTP_DTLS_SETUP_PASSIVE, ast_rtp_instance_get_dtls(), LOG_WARNING, ast_rtp_engine_dtls::reset, ast_sip_session_media::rtp, ast_rtp_engine_dtls::set_fingerprint, ast_rtp_engine_dtls::set_setup, and value.

Referenced by parse_dtls_attrib().

◆ apply_negotiated_sdp_stream()

static int apply_negotiated_sdp_stream ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_session *  local,
const struct pjmedia_sdp_session *  remote,
int  index,
struct ast_stream asterisk_stream 
)
static

Definition at line 2216 of file res_pjsip_sdp_rtp.c.

2219{
2220 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
2221 struct pjmedia_sdp_media *remote_stream = remote->media[index];
2222 enum ast_media_type media_type = session_media->type;
2223 char host[NI_MAXHOST];
2224 int res;
2225 int rtp_timeout;
2226 struct ast_sip_session_media *session_media_transport;
2227 SCOPE_ENTER(1, "%s Stream: %s\n", ast_sip_session_get_name(session),
2228 ast_str_tmp(128, ast_stream_to_str(asterisk_stream, &STR_TMP)));
2229
2230 if (!session->channel) {
2231 SCOPE_EXIT_RTN_VALUE(1, "No channel\n");
2232 }
2233
2234 /* Ensure incoming transport is compatible with the endpoint's configuration */
2235 if (!session->endpoint->media.rtp.use_received_transport &&
2237 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
2238 }
2239
2240 /* Create an RTP instance if need be */
2241 if (!session_media->rtp && create_rtp(session, session_media, local)) {
2242 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
2243 }
2244
2245 process_ssrc_attributes(session, session_media, remote_stream);
2246 process_extmap_attributes(session, session_media, remote_stream);
2247
2248 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
2249
2250 if (session_media_transport == session_media || !session_media->bundled) {
2251 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(remote_stream, "rtcp-mux", NULL) != NULL);
2252 set_ice_components(session, session_media);
2253
2254 enable_rtcp(session, session_media, remote_stream);
2255
2256 res = setup_media_encryption(session, session_media, remote, remote_stream);
2257 if (!session->endpoint->media.rtp.encryption_optimistic && res) {
2258 /* If optimistic encryption is disabled and crypto should have been enabled but was not
2259 * this session must fail.
2260 */
2261 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
2262 }
2263
2264 if (!remote_stream->conn && !remote->conn) {
2265 SCOPE_EXIT_RTN_VALUE(1, "No connection info\n");
2266 }
2267
2268 ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
2269
2270 /* Ensure that the address provided is valid */
2271 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
2272 /* The provided host was actually invalid so we error out this negotiation */
2273 SCOPE_EXIT_RTN_VALUE(-1, "Host invalid\n");
2274 }
2275
2276 /* Apply connection information to the RTP instance */
2277 ast_sockaddr_set_port(addrs, remote_stream->desc.port);
2278 ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
2279
2283 if (!session->endpoint->media.rtcp_mux || !session_media->remote_rtcp_mux) {
2286 }
2287
2288 /* If ICE support is enabled find all the needed attributes */
2289 process_ice_attributes(session, session_media, remote, remote_stream);
2290 } else {
2291 /* This is bundled with another session, so mark it as such */
2292 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
2294 enable_rtcp(session, session_media, remote_stream);
2295 }
2296
2297 if (set_caps(session, session_media, session_media_transport, remote_stream, 0, asterisk_stream)) {
2298 SCOPE_EXIT_RTN_VALUE(-1, "set_caps failed\n");
2299 }
2300
2301 /* Set the channel uniqueid on the RTP instance now that it is becoming active */
2302 ast_channel_lock(session->channel);
2304 ast_channel_unlock(session->channel);
2305
2306 /* Ensure the RTP instance is active */
2307 ast_rtp_instance_set_stream_num(session_media->rtp, ast_stream_get_position(asterisk_stream));
2308 ast_rtp_instance_activate(session_media->rtp);
2309
2310 /* audio stream handles music on hold */
2311 if (media_type != AST_MEDIA_TYPE_AUDIO && media_type != AST_MEDIA_TYPE_VIDEO) {
2312 if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2313 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2315 }
2316 SCOPE_EXIT_RTN_VALUE(1, "moh\n");
2317 }
2318
2319 set_session_media_remotely_held(session_media, session, remote_stream, asterisk_stream, addrs);
2320
2321 if (session_media->remotely_held_changed) {
2322 if (session_media->remotely_held) {
2323 /* The remote side has put us on hold */
2324 if (!session->endpoint->suppress_moh_on_sendonly) {
2325 ast_queue_hold(session->channel, session->endpoint->mohsuggest);
2326 ast_rtp_instance_stop(session_media->rtp);
2328 }
2329 session_media->remotely_held_changed = 0;
2330 } else {
2331 /* The remote side has taken us off hold */
2332 if (!session->endpoint->suppress_moh_on_sendonly) {
2333 ast_queue_unhold(session->channel);
2335 }
2336 session_media->remotely_held_changed = 0;
2337 }
2338 } else if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2339 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2341 }
2342
2343 /* This purposely resets the encryption to the configured in case it gets added later */
2344 session_media->encryption = session->endpoint->media.rtp.encryption;
2345
2346 if (session->endpoint->media.rtp.keepalive > 0 &&
2347 (session_media->type == AST_MEDIA_TYPE_AUDIO ||
2348 session_media->type == AST_MEDIA_TYPE_VIDEO)) {
2349 ast_rtp_instance_set_keepalive(session_media->rtp, session->endpoint->media.rtp.keepalive);
2350 /* Schedule the initial keepalive early in case this is being used to punch holes through
2351 * a NAT. This way there won't be an awkward delay before media starts flowing in some
2352 * scenarios.
2353 */
2354 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2356 session_media, 1);
2357 }
2358
2359 /* As the channel lock is not held during this process the scheduled item won't block if
2360 * it is hanging up the channel at the same point we are applying this negotiated SDP.
2361 */
2362 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2363
2364 /* Due to the fact that we only ever have one scheduled timeout item for when we are both
2365 * off hold and on hold we don't need to store the two timeouts differently on the RTP
2366 * instance itself.
2367 */
2368 ast_rtp_instance_set_timeout(session_media->rtp, 0);
2369 if (session->endpoint->media.rtp.timeout && !session_media->remotely_held && !session_media->locally_held) {
2370 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout);
2371 } else if (session->endpoint->media.rtp.timeout_hold && (session_media->remotely_held || session_media->locally_held)) {
2372 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout_hold);
2373 }
2374
2375 rtp_timeout = ast_rtp_instance_get_timeout(session_media->rtp);
2376
2377 if (rtp_timeout) {
2378 session_media->timeout_sched_id = ast_sched_add_variable(sched, rtp_timeout*1000, rtp_check_timeout,
2379 session_media, 1);
2380 }
2381
2382 SCOPE_EXIT_RTN_VALUE(1, "Handled\n");
2383}
#define ast_channel_lock(chan)
Definition: channel.h:2968
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1250
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1158
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1235
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1210
#define ast_channel_unlock(chan)
Definition: channel.h:2969
ast_media_type
Types of media.
Definition: codec.h:30
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_ENTER(level,...)
@ AST_CONTROL_UPDATE_RTP_PEER
struct ast_frame ast_null_frame
Definition: main/frame.c:79
@ AST_AF_UNSPEC
Definition: netsock2.h:54
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
Definition: netsock2.c:280
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
static int send_keepalive(const void *data)
static void set_session_media_remotely_held(struct ast_sip_session_media *session_media, const struct ast_sip_session *session, const pjmedia_sdp_media *media, const struct ast_stream *stream, const struct ast_sockaddr *addrs)
static enum ast_sip_session_media_encryption check_endpoint_media_transport(struct ast_sip_endpoint *endpoint, const struct pjmedia_sdp_media *stream)
Checks whether the encryption offered in SDP is compatible with the endpoint's configuration.
static struct ast_frame * media_session_rtcp_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
static void process_ice_attributes(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
Function which processes ICE attributes in an audio stream.
static int set_caps(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_sip_session_media *session_media_transport, const struct pjmedia_sdp_media *stream, int is_offer, struct ast_stream *asterisk_stream)
static int media_session_rtp_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
static int rtp_check_timeout(const void *data)
Check whether RTP is being received or not.
static int setup_media_encryption(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
static void process_extmap_attributes(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_stream)
Function which processes extmap attributes in a stream.
static struct ast_frame * media_session_rtp_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
static void enable_rtcp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_media)
Enable RTCP on an RTP session.
static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp)
Internal function which creates an RTP instance.
static void set_ice_components(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
static void process_ssrc_attributes(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_stream)
Function which processes ssrc attributes in a stream.
int ast_sip_session_media_add_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, int fd, ast_sip_session_media_read_cb callback)
Set a read callback for a media session with a specific file descriptor.
struct ast_sip_session_media * ast_sip_session_media_get_transport(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
Retrieve the underlying media session that is acting as transport for a media session.
int ast_sip_session_media_set_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, ast_sip_session_media_write_cb callback)
Set a write callback for a media session.
const char * ast_sip_session_get_name(const struct ast_sip_session *session)
Get the channel or endpoint name associated with the session.
#define NULL
Definition: resample.c:96
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
Definition: rtp_engine.c:2359
void ast_rtp_instance_set_stream_num(struct ast_rtp_instance *instance, int stream_num)
Set the stream number for an RTP instance.
Definition: rtp_engine.c:4063
int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
Get the RTP timeout value.
Definition: rtp_engine.c:2885
int ast_rtp_instance_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
Request that an RTP instance be bundled with another.
Definition: rtp_engine.c:4037
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1138
int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
Indicate to the RTP engine that packets are now expected to be sent/received on the RTP instance.
Definition: rtp_engine.c:2847
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
Definition: rtp_engine.c:575
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:2368
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int timeout)
Set the RTP keepalive interval.
Definition: rtp_engine.c:2880
void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
Set the RTP timeout value.
Definition: rtp_engine.c:2870
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
int ast_sched_add_variable(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data, int variable) attribute_warn_unused_result
Adds a scheduled event with rescheduling support.
Definition: sched.c:526
const char * ast_stream_to_str(const struct ast_stream *stream, struct ast_str **buf)
Get a string representing the stream for debugging/display purposes.
Definition: stream.c:337
int ast_stream_get_position(const struct ast_stream *stream)
Get the position of the stream in the topology.
Definition: stream.c:500
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
Definition: strings.h:1189
unsigned int remotely_held_changed
Stream is held by remote side changed during this negotiation.
unsigned int locally_held
Stream is on hold by local side.
unsigned int remote_rtcp_mux
Does remote support rtcp_mux.
int timeout_sched_id
Scheduler ID for RTP timeout.
unsigned int remotely_held
Stream is on hold by remote side.
int keepalive_sched_id
Scheduler ID for RTP keepalive.
Socket address structure.
Definition: netsock2.h:97
Definition: sched.c:76

References AST_AF_UNSPEC, ast_channel_lock, ast_channel_uniqueid(), ast_channel_unlock, AST_CONTROL_UPDATE_RTP_PEER, ast_copy_pj_str(), ast_free, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hold(), ast_queue_unhold(), ast_rtp_instance_activate(), ast_rtp_instance_bundle(), ast_rtp_instance_fd(), ast_rtp_instance_get_timeout(), ast_rtp_instance_set_channel_id(), ast_rtp_instance_set_keepalive(), ast_rtp_instance_set_remote_address, ast_rtp_instance_set_stream_num(), ast_rtp_instance_set_timeout(), ast_rtp_instance_stop(), ast_sched_add_variable(), AST_SCHED_DEL, AST_SIP_MEDIA_TRANSPORT_INVALID, ast_sip_session_get_name(), ast_sip_session_media_add_read_callback(), ast_sip_session_media_get_transport(), ast_sip_session_media_set_write_callback(), ast_sockaddr_resolve(), ast_sockaddr_set_port, ast_str_tmp, ast_stream_get_position(), ast_stream_to_str(), ast_sip_session_media::bundled, check_endpoint_media_transport(), create_rtp(), enable_rtcp(), ast_sip_session_media::encryption, ast_sip_session_media::keepalive_sched_id, ast_sip_session_media::locally_held, media_session_rtcp_read_callback(), media_session_rtp_read_callback(), media_session_rtp_write_callback(), NULL, PARSE_PORT_FORBID, process_extmap_attributes(), process_ice_attributes(), process_ssrc_attributes(), RAII_VAR, ast_sip_session_media::remote_rtcp_mux, ast_sip_session_media::remotely_held, ast_sip_session_media::remotely_held_changed, ast_sip_session_media::rtp, rtp_check_timeout(), SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, send_keepalive(), session, set_caps(), set_ice_components(), set_session_media_remotely_held(), setup_media_encryption(), ast_sip_session_media::timeout_sched_id, and ast_sip_session_media::type.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 2549 of file res_pjsip_sdp_rtp.c.

◆ change_outgoing_sdp_stream_media_address()

static void change_outgoing_sdp_stream_media_address ( pjsip_tx_data *  tdata,
struct pjmedia_sdp_media *  stream,
struct ast_sip_transport transport 
)
static

Function which updates the media stream with external media address, if applicable.

Definition at line 2386 of file res_pjsip_sdp_rtp.c.

2387{
2389 char host[NI_MAXHOST];
2390 struct ast_sockaddr our_sdp_addr = { { 0, } };
2391
2392 /* If the stream has been rejected there will be no connection line */
2393 if (!stream->conn || !transport_state) {
2394 return;
2395 }
2396
2397 ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
2398 ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
2399
2400 /* Reversed check here. We don't check the remote endpoint being
2401 * in our local net, but whether our outgoing session IP is
2402 * local. If it is not, we won't do rewriting. No localnet
2403 * configured? Always rewrite. */
2404 if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
2405 return;
2406 }
2407 ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2408 pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2409}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define ast_sip_transport_is_nonlocal(transport_state, addr)
Definition: res_pjsip.h:209
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
Structure for SIP transport information.
Definition: res_pjsip.h:116

References ao2_cleanup, ast_copy_pj_str(), ast_debug, ast_sip_get_transport_state(), ast_sip_transport_is_nonlocal, ast_sockaddr_parse(), ast_sockaddr_stringify_addr_remote(), ast_sorcery_object_get_id(), PARSE_PORT_FORBID, RAII_VAR, and ast_sip_session_media::transport.

◆ check_endpoint_media_transport()

static enum ast_sip_session_media_encryption check_endpoint_media_transport ( struct ast_sip_endpoint endpoint,
const struct pjmedia_sdp_media *  stream 
)
static

Checks whether the encryption offered in SDP is compatible with the endpoint's configuration.

Definition at line 1028 of file res_pjsip_sdp_rtp.c.

1031{
1032 enum ast_sip_session_media_encryption incoming_encryption;
1033 char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1];
1034 unsigned int optimistic;
1035
1036 if ((transport_end == 'F' && !endpoint->media.rtp.use_avpf)
1037 || (transport_end != 'F' && endpoint->media.rtp.use_avpf)) {
1039 }
1040
1041 incoming_encryption = get_media_encryption_type(stream->desc.transport, stream, &optimistic);
1042
1043 if (incoming_encryption == endpoint->media.rtp.encryption) {
1044 return incoming_encryption;
1045 }
1046
1047 if (endpoint->media.rtp.force_avp ||
1048 endpoint->media.rtp.encryption_optimistic) {
1049 return incoming_encryption;
1050 }
1051
1052 /* If an optimistic offer has been made but encryption is not enabled consider it as having
1053 * no offer of crypto at all instead of invalid so the session proceeds.
1054 */
1055 if (optimistic) {
1057 }
1058
1060}
ast_sip_session_media_encryption
Definition: res_pjsip.h:640
static enum ast_sip_session_media_encryption get_media_encryption_type(pj_str_t transport, const struct pjmedia_sdp_media *stream, unsigned int *optimistic)
figure out media transport encryption type from the media transport string
struct ast_sip_media_rtp_configuration rtp
Definition: res_pjsip.h:910
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:991
enum ast_sip_session_media_encryption encryption
Definition: res_pjsip.h:853
unsigned int encryption_optimistic
Definition: res_pjsip.h:855

References AST_SIP_MEDIA_ENCRYPT_NONE, AST_SIP_MEDIA_TRANSPORT_INVALID, ast_sip_media_rtp_configuration::encryption, ast_sip_media_rtp_configuration::encryption_optimistic, ast_sip_media_rtp_configuration::force_avp, get_media_encryption_type(), ast_sip_endpoint::media, ast_sip_endpoint_media_configuration::rtp, and ast_sip_media_rtp_configuration::use_avpf.

Referenced by apply_negotiated_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ check_ice_support()

static void check_ice_support ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_media *  remote_stream 
)
static

Function which checks for ice attributes in an audio stream.

Definition at line 808 of file res_pjsip_sdp_rtp.c.

810{
811 struct ast_rtp_engine_ice *ice;
812 const pjmedia_sdp_attr *attr;
813 unsigned int attr_i;
814
815 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
816 session_media->remote_ice = 0;
817 return;
818 }
819
820 /* Find all of the candidates */
821 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
822 attr = remote_stream->attr[attr_i];
823 if (!pj_strcmp2(&attr->name, "candidate")) {
824 session_media->remote_ice = 1;
825 break;
826 }
827 }
828
829 if (attr_i == remote_stream->attr_count) {
830 session_media->remote_ice = 0;
831 }
832}

References ast_rtp_instance_get_ice(), ast_sip_session_media::remote_ice, ast_sip_session_media::rtp, and session.

Referenced by negotiate_incoming_sdp_stream().

◆ create_outgoing_sdp_stream()

static int create_outgoing_sdp_stream ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
struct pjmedia_sdp_session *  sdp,
const struct pjmedia_sdp_session *  remote,
struct ast_stream stream 
)
static

Function which creates an outgoing stream.

Definition at line 1778 of file res_pjsip_sdp_rtp.c.

1780{
1781 pj_pool_t *pool = session->inv_session->pool_prov;
1782 static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };
1783 static const pj_str_t STR_IN = { "IN", 2 };
1784 static const pj_str_t STR_IP4 = { "IP4", 3};
1785 static const pj_str_t STR_IP6 = { "IP6", 3};
1786 static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
1787 static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
1788 static const pj_str_t STR_INACTIVE = { "inactive", 8 };
1789 static const pj_str_t STR_RECVONLY = { "recvonly", 8 };
1790 pjmedia_sdp_media *media;
1791 const char *hostip = NULL;
1792 struct ast_sockaddr addr;
1793 char tmp[512];
1794 pj_str_t stmp;
1795 pjmedia_sdp_attr *attr;
1796 int index = 0;
1797 int noncodec = (session->dtmf == AST_SIP_DTMF_RFC_4733 || session->dtmf == AST_SIP_DTMF_AUTO || session->dtmf == AST_SIP_DTMF_AUTO_INFO) ? AST_RTP_DTMF : 0;
1798 int min_packet_size = 0, max_packet_size = 0;
1799 int rtp_code;
1800 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1801 enum ast_media_type media_type = session_media->type;
1802 struct ast_sip_session_media *session_media_transport;
1803 pj_sockaddr ip;
1804 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
1805 ast_format_cap_count(session->direct_media_cap);
1806
1807 /* Keep track of the sample rates for offered codecs so we can build matching
1808 RFC 2833/4733 payload offers. */
1809 AST_VECTOR(, int) sample_rates;
1810 /* In case we can't init the sample rates, still try to do the rest. */
1811 int build_dtmf_sample_rates = 1;
1812
1813 SCOPE_ENTER(1, "%s Type: %s %s\n", ast_sip_session_get_name(session),
1814 ast_codec_media_type2str(media_type), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
1815
1816 media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media));
1817 if (!media) {
1818 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
1819 }
1820 pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
1821
1822 /* If this is a removed (or declined) stream OR if no formats exist then construct a minimal stream in SDP */
1825 media->desc.port = 0;
1826 media->desc.port_count = 1;
1827
1828 if (remote && remote->media[ast_stream_get_position(stream)]) {
1829 pjmedia_sdp_media *remote_media = remote->media[ast_stream_get_position(stream)];
1830 int index;
1831
1832 media->desc.transport = remote_media->desc.transport;
1833
1834 /* Preserve existing behavior by copying the formats provided from the offer */
1835 for (index = 0; index < remote_media->desc.fmt_count; ++index) {
1836 media->desc.fmt[index] = remote_media->desc.fmt[index];
1837 }
1838 media->desc.fmt_count = remote_media->desc.fmt_count;
1839 } else {
1840 /* This is actually an offer so put a dummy payload in that is ignored and sane transport */
1841 media->desc.transport = STR_RTP_AVP;
1842 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], "32");
1843 }
1844
1845 sdp->media[sdp->media_count++] = media;
1847
1848 SCOPE_EXIT_RTN_VALUE(1, "Stream removed or no formats\n");
1849 }
1850
1851 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
1852 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
1853 }
1854
1855 /* If this stream has not been bundled already it is new and we need to ensure there is no SSRC conflict */
1856 if (session_media->bundle_group != -1 && !session_media->bundled) {
1857 for (index = 0; index < sdp->media_count; ++index) {
1858 struct ast_sip_session_media *other_session_media;
1859
1860 other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);
1861 if (!other_session_media->rtp || other_session_media->bundle_group != session_media->bundle_group) {
1862 continue;
1863 }
1864
1865 if (ast_rtp_instance_get_ssrc(session_media->rtp) == ast_rtp_instance_get_ssrc(other_session_media->rtp)) {
1866 ast_rtp_instance_change_source(session_media->rtp);
1867 /* Start the conflict check over again */
1868 index = -1;
1869 continue;
1870 }
1871 }
1872 }
1873
1874 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1875
1876 if (session_media_transport == session_media || !session_media->bundled) {
1877 set_ice_components(session, session_media);
1878 enable_rtcp(session, session_media, NULL);
1879
1880 /* Crypto has to be added before setting the media transport so that SRTP is properly
1881 * set up according to the configuration. This ends up changing the media transport.
1882 */
1883 if (add_crypto_to_stream(session, session_media, pool, media)) {
1884 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
1885 }
1886
1887 if (pj_strlen(&session_media->transport)) {
1888 /* If a transport has already been specified use it */
1889 media->desc.transport = session_media->transport;
1890 } else {
1891 media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
1892 /* Optimistic encryption places crypto in the normal RTP/AVP profile */
1893 !session->endpoint->media.rtp.encryption_optimistic &&
1894 (session_media->encryption == AST_SIP_MEDIA_ENCRYPT_SDES),
1895 session_media->rtp, session->endpoint->media.rtp.use_avpf,
1896 session->endpoint->media.rtp.force_avp));
1897 }
1898
1899 media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn));
1900 if (!media->conn) {
1901 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
1902 }
1903
1904 /* Add connection level details */
1905 if (direct_media_enabled) {
1907 } else if (ast_strlen_zero(session->endpoint->media.address)) {
1908 hostip = ast_sip_get_host_ip_string(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET());
1909 } else {
1910 hostip = session->endpoint->media.address;
1911 }
1912
1913 if (ast_strlen_zero(hostip)) {
1914 ast_log(LOG_ERROR, "No local host IP available for stream %s\n",
1915 ast_codec_media_type2str(session_media->type));
1916 SCOPE_EXIT_RTN_VALUE(-1, "No local host ip\n");
1917 }
1918
1919 media->conn->net_type = STR_IN;
1920 /* Assume that the connection will use IPv4 until proven otherwise */
1921 media->conn->addr_type = STR_IP4;
1922 pj_strdup2(pool, &media->conn->addr, hostip);
1923
1924 if ((pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &media->conn->addr, &ip) == PJ_SUCCESS) &&
1925 (ip.addr.sa_family == pj_AF_INET6())) {
1926 media->conn->addr_type = STR_IP6;
1927 }
1928
1929 /* Add ICE attributes and candidates */
1930 add_ice_to_stream(session, session_media, pool, media, 1);
1931
1932 ast_rtp_instance_get_local_address(session_media->rtp, &addr);
1933 media->desc.port = direct_media_enabled ? ast_sockaddr_port(&session_media->direct_media_addr) : (pj_uint16_t) ast_sockaddr_port(&addr);
1934 media->desc.port_count = 1;
1935 } else {
1936 pjmedia_sdp_media *bundle_group_stream = sdp->media[session_media_transport->stream_num];
1937
1938 /* As this is in a bundle group it shares the same details as the group instance */
1939 media->desc.transport = bundle_group_stream->desc.transport;
1940 media->conn = bundle_group_stream->conn;
1941 media->desc.port = bundle_group_stream->desc.port;
1942
1943 if (add_crypto_to_stream(session, session_media_transport, pool, media)) {
1944 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
1945 }
1946
1947 add_ice_to_stream(session, session_media_transport, pool, media, 0);
1948
1949 enable_rtcp(session, session_media, NULL);
1950 }
1951
1953 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
1954 ast_codec_media_type2str(session_media->type));
1955 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create caps\n");
1956 }
1957
1958 if (direct_media_enabled) {
1959 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
1960 } else {
1961 ast_format_cap_append_from_cap(caps, ast_stream_get_formats(stream), media_type);
1962 }
1963
1964 /* Init the sample rates before we start adding them. Assume we will have at least one. */
1965 if (AST_VECTOR_INIT(&sample_rates, 1)) {
1966 ast_log(LOG_ERROR, "Unable to add dtmf formats to SDP!\n");
1967 build_dtmf_sample_rates = 0;
1968 }
1969
1970 for (index = 0; index < ast_format_cap_count(caps); ++index) {
1971 struct ast_format *format = ast_format_cap_get_format(caps, index);
1972
1973 if (ast_format_get_type(format) != media_type) {
1974 ao2_ref(format, -1);
1975 continue;
1976 }
1977
1978 /* It is possible for some formats not to have SDP information available for them
1979 * and if this is the case, skip over them so the SDP can still be created.
1980 */
1981 if (!ast_rtp_lookup_sample_rate2(1, format, 0)) {
1982 ast_log(LOG_WARNING, "Format '%s' can not be added to SDP, consider disallowing it on endpoint '%s'\n",
1984 ao2_ref(format, -1);
1985 continue;
1986 }
1987
1988 /* If this stream is not a transport we need to use the transport codecs structure for payload management to prevent
1989 * conflicts.
1990 */
1991 if (session_media_transport != session_media) {
1992 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media_transport->rtp), 1, format, 0)) == -1) {
1993 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
1994 ao2_ref(format, -1);
1995 continue;
1996 }
1997 /* Our instance has to match the payload number though */
1998 ast_rtp_codecs_payload_set_rx(ast_rtp_instance_get_codecs(session_media->rtp), rtp_code, format);
1999 } else {
2000 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0)) == -1) {
2001 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
2002 ao2_ref(format, -1);
2003 continue;
2004 }
2005 }
2006
2007 if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 1, format, 0))) {
2008 int i, added = 0;
2009 int newrate = ast_rtp_lookup_sample_rate2(1, format, 0);
2010 if (build_dtmf_sample_rates) {
2011 for (i = 0; i < AST_VECTOR_SIZE(&sample_rates); i++) {
2012 /* Only add if we haven't already processed this sample rate. For instance
2013 A-law and u-law 'share' one 8K DTMF payload type. */
2014 if (newrate == AST_VECTOR_GET(&sample_rates, i)) {
2015 added = 1;
2016 break;
2017 }
2018 }
2019
2020 if (!added) {
2021 AST_VECTOR_APPEND(&sample_rates, newrate);
2022 }
2023 }
2024 media->attr[media->attr_count++] = attr;
2025 }
2026
2027 if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
2028 media->attr[media->attr_count++] = attr;
2029 }
2030
2031 if (ast_format_get_maximum_ms(format) &&
2032 ((ast_format_get_maximum_ms(format) < max_packet_size) || !max_packet_size)) {
2033 max_packet_size = ast_format_get_maximum_ms(format);
2034 }
2035 ao2_ref(format, -1);
2036
2037 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2038 break;
2039 }
2040 }
2041
2042 /* Add non-codec formats */
2044 && media->desc.fmt_count < PJMEDIA_MAX_SDP_FMT) {
2045 for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) {
2046 if (!(noncodec & index)) {
2047 continue;
2048 }
2049
2050 if (index != AST_RTP_DTMF) {
2051 rtp_code = ast_rtp_codecs_payload_code(
2052 ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index);
2053 if (rtp_code == -1) {
2054 continue;
2055 } else if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
2056 media->attr[media->attr_count++] = attr;
2057 }
2058 } else if (build_dtmf_sample_rates) {
2059 /*
2060 * Walk through the possible bitrates for the RFC 2833/4733 digits and generate the rtpmap
2061 * attributes.
2062 */
2063 int i, found_default_offer = 0;
2064 for (i = 0; i < AST_VECTOR_SIZE(&sample_rates); i++) {
2066 ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index, AST_VECTOR_GET(&sample_rates, i));
2067
2068 if (rtp_code == -1) {
2069 continue;
2070 }
2071
2072 if (AST_VECTOR_GET(&sample_rates, i) == DEFAULT_DTMF_SAMPLE_RATE_MS) {
2073 /* we found and added a default offer, so no need to include a default one.*/
2074 found_default_offer = 1;
2075 }
2076
2077 if ((attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index, AST_VECTOR_GET(&sample_rates, i)))) {
2078 media->attr[media->attr_count++] = attr;
2079 snprintf(tmp, sizeof(tmp), "%d 0-16", (rtp_code));
2080 attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2081 media->attr[media->attr_count++] = attr;
2082 }
2083 }
2084
2085 /* If we weren't able to add any matching RFC 2833/4733, assume this endpoint is using a
2086 * mismatched 8K offer and try to add one as a fall-back/default.
2087 */
2088 if (!found_default_offer) {
2091
2092 if (rtp_code != -1 && (attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index, DEFAULT_DTMF_SAMPLE_RATE_MS))) {
2093 media->attr[media->attr_count++] = attr;
2094 snprintf(tmp, sizeof(tmp), "%d 0-16", (rtp_code));
2095 attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2096 media->attr[media->attr_count++] = attr;
2097 }
2098 }
2099 }
2100
2101 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2102 break;
2103 }
2104 }
2105 }
2106
2107 /* we are done with the sample rates */
2108 AST_VECTOR_FREE(&sample_rates);
2109
2110 /* If no formats were actually added to the media stream don't add it to the SDP */
2111 if (!media->desc.fmt_count) {
2112 SCOPE_EXIT_RTN_VALUE(1, "No formats added to stream\n");
2113 }
2114
2115 /* If ptime is set add it as an attribute */
2116 min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(session_media->rtp));
2117 if (!min_packet_size) {
2118 min_packet_size = ast_format_cap_get_framing(caps);
2119 }
2120 if (min_packet_size) {
2121 snprintf(tmp, sizeof(tmp), "%d", min_packet_size);
2122 attr = pjmedia_sdp_attr_create(pool, "ptime", pj_cstr(&stmp, tmp));
2123 media->attr[media->attr_count++] = attr;
2124 }
2125
2126 if (max_packet_size) {
2127 snprintf(tmp, sizeof(tmp), "%d", max_packet_size);
2128 attr = pjmedia_sdp_attr_create(pool, "maxptime", pj_cstr(&stmp, tmp));
2129 media->attr[media->attr_count++] = attr;
2130 }
2131
2132 attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
2133 if (session_media->locally_held) {
2134 if (session_media->remotely_held) {
2135 attr->name = STR_INACTIVE; /* To place on hold a recvonly stream, send inactive */
2136 } else {
2137 attr->name = STR_SENDONLY; /* Send sendonly to initate a local hold */
2138 }
2139 } else {
2140 if (session_media->remotely_held) {
2141 attr->name = STR_RECVONLY; /* Remote has sent sendonly, reply recvonly */
2142 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
2143 attr->name = STR_SENDONLY; /* Stream has requested sendonly */
2144 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_RECVONLY) {
2145 attr->name = STR_RECVONLY; /* Stream has requested recvonly */
2146 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_INACTIVE) {
2147 attr->name = STR_INACTIVE; /* Stream has requested inactive */
2148 } else {
2149 attr->name = STR_SENDRECV; /* No hold in either direction */
2150 }
2151 }
2152 media->attr[media->attr_count++] = attr;
2153
2154 /* If we've got rtcp-mux enabled, add it unless we received an offer without it */
2155 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
2156 attr = pjmedia_sdp_attr_create(pool, "rtcp-mux", NULL);
2157 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
2158 }
2159
2160 add_ssrc_to_stream(session, session_media, pool, media);
2161 add_msid_to_stream(session, session_media, pool, media, stream);
2162 add_rtcp_fb_to_stream(session, session_media, pool, media);
2163 add_extmap_to_stream(session, session_media, pool, media);
2164
2165 /* Add the media stream to the SDP */
2166 sdp->media[sdp->media_count++] = media;
2167
2168 SCOPE_EXIT_RTN_VALUE(1, "RC: 1\n");
2169}
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
Get the maximum amount of media carried in this format.
Definition: format.c:369
unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
Get the global framing.
Definition: format_cap.c:438
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition: format_cap.c:628
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
int ast_format_cap_append_from_cap(struct ast_format_cap *dst, const struct ast_format_cap *src, enum ast_media_type type)
Append the formats of provided type in src to dst.
Definition: format_cap.c:269
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
#define LOG_ERROR
char * ast_sockaddr_stringify_fmt(const struct ast_sockaddr *addr, int format)
Convert a socket address to a string.
Definition: netsock2.c:65
#define AST_SOCKADDR_STR_ADDR
Definition: netsock2.h:198
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:517
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition: res_pjsip.c:2493
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:553
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:551
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:545
static pjmedia_sdp_attr * generate_rtpmap_attr2(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool, int rtp_code, int asterisk_format, struct ast_format *format, int code, int sample_rate)
static void add_ice_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media, unsigned int include_candidates)
Function which adds ICE attributes to a media stream.
static void add_extmap_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
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)
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, struct ast_stream *stream)
static pjmedia_sdp_attr * generate_rtpmap_attr(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool, int rtp_code, int asterisk_format, struct ast_format *format, int code)
static int add_crypto_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
static void add_ssrc_to_stream(struct ast_sip_session *session, struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
Function which adds ssrc attributes to a media stream.
static pjmedia_sdp_attr * generate_fmtp_attr(pj_pool_t *pool, struct ast_format *format, int rtp_code)
int ast_sip_session_is_pending_stream_default(const struct ast_sip_session *session, const struct ast_stream *stream)
Determines if a provided pending stream will be the default stream or not.
unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, const struct ast_format *format, int code)
Get the sample rate associated with known RTP payload types.
Definition: rtp_engine.c:2198
#define AST_RTP_DTMF
Definition: rtp_engine.h:294
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:665
int ast_rtp_codecs_payload_code_sample_rate(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, unsigned int sample_rate)
Retrieve a rx mapped payload type based on whether it is an Asterisk format, the code and the sample ...
Definition: rtp_engine.c:2024
void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
Indicate a new source of audio has dropped in and the ssrc should change.
Definition: rtp_engine.c:2336
#define AST_RTP_MAX
Definition: rtp_engine.h:300
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1682
#define DEFAULT_DTMF_SAMPLE_RATE_MS
Definition: rtp_engine.h:110
char * ast_sdp_get_rtp_profile(unsigned int sdes_active, struct ast_rtp_instance *instance, unsigned int using_avpf, unsigned int force_avp)
Get the RTP profile in use by a media session.
Definition: sdp_srtp.c:103
@ AST_STREAM_STATE_RECVONLY
Set when the stream is receiving media only.
Definition: stream.h:90
@ AST_STREAM_STATE_INACTIVE
Set when the stream is not sending OR receiving media.
Definition: stream.h:94
@ AST_STREAM_STATE_REMOVED
Set when the stream has been removed/declined.
Definition: stream.h:78
@ AST_STREAM_STATE_SENDONLY
Set when the stream is sending media only.
Definition: stream.h:86
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
Definition: stream.c:380
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
Definition: stream.c:373
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
Definition: stream.c:330
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
int stream_num
The stream number to place into any resulting frames.
struct ast_sockaddr direct_media_addr
Direct media address.
pj_str_t transport
The media transport in use for this stream.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44

References add_crypto_to_stream(), add_extmap_to_stream(), add_ice_to_stream(), add_msid_to_stream(), add_rtcp_fb_to_stream(), add_ssrc_to_stream(), ao2_cleanup, ao2_ref, ast_codec_media_type2str(), ast_format_cap_alloc, ast_format_cap_append_from_cap(), ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_compatible(), ast_format_cap_get_format(), ast_format_cap_get_framing(), ast_format_get_maximum_ms(), ast_format_get_name(), ast_format_get_type(), ast_log, AST_MEDIA_TYPE_VIDEO, ast_rtp_codecs_get_framing(), ast_rtp_codecs_payload_code(), ast_rtp_codecs_payload_code_sample_rate(), ast_rtp_codecs_payload_set_rx(), AST_RTP_DTMF, ast_rtp_instance_change_source(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_ssrc(), ast_rtp_lookup_sample_rate2(), AST_RTP_MAX, ast_sdp_get_rtp_profile(), AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, AST_SIP_DTMF_RFC_4733, ast_sip_get_host_ip_string(), AST_SIP_MEDIA_ENCRYPT_SDES, ast_sip_session_get_name(), ast_sip_session_is_pending_stream_default(), ast_sip_session_media_get_transport(), ast_sockaddr_isnull(), ast_sockaddr_port, AST_SOCKADDR_STR_ADDR, ast_sockaddr_stringify_fmt(), ast_sorcery_object_get_id(), ast_str_tmp, ast_stream_get_formats(), ast_stream_get_position(), ast_stream_get_state(), ast_stream_set_state(), AST_STREAM_STATE_INACTIVE, AST_STREAM_STATE_RECVONLY, AST_STREAM_STATE_REMOVED, AST_STREAM_STATE_SENDONLY, ast_stream_to_str(), ast_strlen_zero(), AST_VECTOR, AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_INIT, AST_VECTOR_SIZE, ast_sip_session_media::bundle_group, ast_sip_session_media::bundled, create_rtp(), DEFAULT_DTMF_SAMPLE_RATE_MS, ast_sip_session_media::direct_media_addr, enable_rtcp(), ast_sip_session_media::encryption, generate_fmtp_attr(), generate_rtpmap_attr(), generate_rtpmap_attr2(), ast_sip_session_media::locally_held, LOG_ERROR, LOG_WARNING, NULL, RAII_VAR, ast_sip_session_media::remote_rtcp_mux, ast_sip_session_media::remotely_held, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, set_ice_components(), ast_sip_session_media::stream_num, tmp(), ast_sip_session_media::transport, and ast_sip_session_media::type.

◆ create_rtp()

static int create_rtp ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const pjmedia_sdp_session *  sdp 
)
static

Internal function which creates an RTP instance.

Definition at line 225 of file res_pjsip_sdp_rtp.c.

227{
228 struct ast_rtp_engine_ice *ice;
229 struct ast_sockaddr temp_media_address;
230 struct ast_sockaddr *media_address = &address_rtp;
231
232 if (session->endpoint->media.bind_rtp_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
233 if (ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0)) {
234 ast_debug_rtp(1, "Endpoint %s: Binding RTP media to %s\n",
236 session->endpoint->media.address);
237 media_address = &temp_media_address;
238 } else {
239 ast_debug_rtp(1, "Endpoint %s: RTP media address invalid: %s\n",
241 session->endpoint->media.address);
242 }
243 } else {
244 struct ast_sip_transport *transport;
245
246 transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport",
247 session->endpoint->transport);
248 if (transport) {
249 struct ast_sip_transport_state *trans_state;
250
252 if (trans_state) {
253 char hoststr[PJ_INET6_ADDRSTRLEN];
254
255 pj_sockaddr_print(&trans_state->host, hoststr, sizeof(hoststr), 0);
256 if (ast_sockaddr_parse(&temp_media_address, hoststr, 0)) {
257 ast_debug_rtp(1, "Transport %s bound to %s: Using it for RTP media.\n",
258 session->endpoint->transport, hoststr);
259 media_address = &temp_media_address;
260 } else {
261 ast_debug_rtp(1, "Transport %s bound to %s: Invalid for RTP media.\n",
262 session->endpoint->transport, hoststr);
263 }
264 ao2_ref(trans_state, -1);
265 }
266 ao2_ref(transport, -1);
267 }
268 }
269
270 if (!(session_media->rtp = ast_rtp_instance_new(session->endpoint->media.rtp.engine, sched, media_address, NULL))) {
271 ast_log(LOG_ERROR, "Unable to create RTP instance using RTP engine '%s'\n", session->endpoint->media.rtp.engine);
272 return -1;
273 }
274
275 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_NAT, session->endpoint->media.rtp.symmetric);
276 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_ASYMMETRIC_CODEC, session->endpoint->asymmetric_rtp_codec);
277
278 if (!session->endpoint->media.rtp.ice_support && (ice = ast_rtp_instance_get_ice(session_media->rtp))) {
279 ice->stop(session_media->rtp);
280 }
281
285 } else if (session->dtmf == AST_SIP_DTMF_INBAND) {
287 }
288
289 if (session_media->type == AST_MEDIA_TYPE_AUDIO &&
290 (session->endpoint->media.tos_audio || session->endpoint->media.cos_audio)) {
291 ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_audio,
292 session->endpoint->media.cos_audio, "SIP RTP Audio");
293 } else if (session_media->type == AST_MEDIA_TYPE_VIDEO) {
294 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_RECV, session->endpoint->media.webrtc);
295 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_SEND, session->endpoint->media.webrtc);
296 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_REMB, session->endpoint->media.webrtc);
297 if (session->endpoint->media.webrtc) {
300 }
301 if (session->endpoint->media.tos_video || session->endpoint->media.cos_video) {
302 ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_video,
303 session->endpoint->media.cos_video, "SIP RTP Video");
304 }
305 }
306
307 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
308
309 return 0;
310}
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:547
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static struct ast_sockaddr address_rtp
Address for RTP.
static void enable_rtp_extension(struct ast_sip_session *session, struct ast_sip_session_media *session_media, enum ast_rtp_extension extension, enum ast_rtp_extension_direction direction, const pjmedia_sdp_session *sdp)
Enable an RTP extension on an RTP session.
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:487
void ast_rtp_instance_set_last_rx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP reception time.
Definition: rtp_engine.c:4006
@ AST_RTP_DTMF_MODE_RFC2833
Definition: rtp_engine.h:155
@ AST_RTP_DTMF_MODE_INBAND
Definition: rtp_engine.h:157
int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
Set the DTMF mode that should be used.
Definition: rtp_engine.c:2299
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:3099
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:727
@ AST_RTP_EXTENSION_TRANSPORT_WIDE_CC
Definition: rtp_engine.h:599
@ AST_RTP_EXTENSION_ABS_SEND_TIME
Definition: rtp_engine.h:597
@ AST_RTP_PROPERTY_NAT
Definition: rtp_engine.h:118
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition: rtp_engine.h:130
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition: rtp_engine.h:132
@ AST_RTP_PROPERTY_ASYMMETRIC_CODEC
Definition: rtp_engine.h:128
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:120
@ AST_RTP_PROPERTY_REMB
Definition: rtp_engine.h:134
int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
Set QoS parameters on an RTP session.
Definition: rtp_engine.c:2345
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1853
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:118
Transport to bind to.
Definition: res_pjsip.h:218

References address_rtp, ao2_ref, ast_debug_rtp, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, AST_RTP_DTMF_MODE_INBAND, AST_RTP_DTMF_MODE_RFC2833, AST_RTP_EXTENSION_ABS_SEND_TIME, AST_RTP_EXTENSION_DIRECTION_SENDRECV, AST_RTP_EXTENSION_TRANSPORT_WIDE_CC, ast_rtp_instance_dtmf_mode_set(), ast_rtp_instance_get_ice(), ast_rtp_instance_new(), ast_rtp_instance_set_last_rx(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_ASYMMETRIC_CODEC, AST_RTP_PROPERTY_DTMF, AST_RTP_PROPERTY_NAT, AST_RTP_PROPERTY_REMB, AST_RTP_PROPERTY_RETRANS_RECV, AST_RTP_PROPERTY_RETRANS_SEND, AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, AST_SIP_DTMF_INBAND, AST_SIP_DTMF_RFC_4733, ast_sip_get_sorcery(), ast_sip_get_transport_state(), ast_sockaddr_parse(), ast_sorcery_object_get_id(), ast_sorcery_retrieve_by_id(), ast_strlen_zero(), enable_rtp_extension(), ast_sip_transport_state::host, LOG_ERROR, NULL, ast_sip_session_media::rtp, session, ast_rtp_engine_ice::stop, ast_sip_transport_state::transport, and ast_sip_session_media::type.

Referenced by apply_negotiated_sdp_stream(), create_outgoing_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ enable_rtcp()

static void enable_rtcp ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_media *  remote_media 
)
static

Enable RTCP on an RTP session.

Definition at line 162 of file res_pjsip_sdp_rtp.c.

164{
165 enum ast_rtp_instance_rtcp rtcp_type;
166
167 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
168 rtcp_type = AST_RTP_INSTANCE_RTCP_MUX;
169 } else {
171 }
172
173 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RTCP, rtcp_type);
174}
ast_rtp_instance_rtcp
Definition: rtp_engine.h:283
@ AST_RTP_INSTANCE_RTCP_MUX
Definition: rtp_engine.h:289
@ AST_RTP_INSTANCE_RTCP_STANDARD
Definition: rtp_engine.h:287
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:126

References AST_RTP_INSTANCE_RTCP_MUX, AST_RTP_INSTANCE_RTCP_STANDARD, ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_RTCP, ast_sip_session_media::remote_rtcp_mux, ast_sip_session_media::rtp, and session.

Referenced by apply_negotiated_sdp_stream(), create_outgoing_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ enable_rtp_extension()

static void enable_rtp_extension ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
enum ast_rtp_extension  extension,
enum ast_rtp_extension_direction  direction,
const pjmedia_sdp_session *  sdp 
)
static

Enable an RTP extension on an RTP session.

Definition at line 179 of file res_pjsip_sdp_rtp.c.

182{
183 int id = -1;
184
185 /* For a bundle group the local unique identifier space is shared across all streams within
186 * it.
187 */
188 if (session_media->bundle_group != -1) {
189 int index;
190
191 for (index = 0; index < sdp->media_count; ++index) {
192 struct ast_sip_session_media *other_session_media;
193 int other_id;
194
195 if (index >= AST_VECTOR_SIZE(&session->pending_media_state->sessions)) {
196 break;
197 }
198
199 other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);
200 if (!other_session_media->rtp || other_session_media->bundle_group != session_media->bundle_group) {
201 continue;
202 }
203
204 other_id = ast_rtp_instance_extmap_get_id(other_session_media->rtp, extension);
205 if (other_id == -1) {
206 /* Worst case we have to fall back to the highest available free local unique identifier
207 * for the bundle group.
208 */
209 other_id = ast_rtp_instance_extmap_count(other_session_media->rtp) + 1;
210 if (id < other_id) {
211 id = other_id;
212 }
213 continue;
214 }
215
216 id = other_id;
217 break;
218 }
219 }
220
222}
direction
int ast_rtp_instance_extmap_enable(struct ast_rtp_instance *instance, int id, enum ast_rtp_extension extension, enum ast_rtp_extension_direction direction)
Enable support for an RTP extension on an instance.
Definition: rtp_engine.c:754
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
Definition: rtp_engine.c:908

References ast_rtp_instance_extmap_count(), ast_rtp_instance_extmap_enable(), ast_rtp_instance_extmap_get_id(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sip_session_media::bundle_group, ast_sip_session_media::rtp, and session.

Referenced by create_rtp().

◆ generate_fmtp_attr()

static pjmedia_sdp_attr * generate_fmtp_attr ( pj_pool_t *  pool,
struct ast_format format,
int  rtp_code 
)
static

Definition at line 707 of file res_pjsip_sdp_rtp.c.

708{
709 struct ast_str *fmtp0 = ast_str_alloca(256);
710 pj_str_t fmtp1;
711 pjmedia_sdp_attr *attr = NULL;
712 char *tmp;
713
714 ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
715 if (ast_str_strlen(fmtp0)) {
716 tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
717 /* remove any carriage return line feeds */
718 while (*tmp == '\r' || *tmp == '\n') --tmp;
719 *++tmp = '\0';
720 /* ast...generate gives us everything, just need value */
721 tmp = strchr(ast_str_buffer(fmtp0), ':');
722 if (tmp && tmp[1] != '\0') {
723 fmtp1 = pj_str(tmp + 1);
724 } else {
725 fmtp1 = pj_str(ast_str_buffer(fmtp0));
726 }
727 attr = pjmedia_sdp_attr_create(pool, "fmtp", &fmtp1);
728 }
729 return attr;
730}
void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
This function is used to produce an fmtp SDP line for an Asterisk format. The attributes present on t...
Definition: format.c:305
#define ast_str_alloca(init_len)
Definition: strings.h:848
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730

References ast_format_generate_sdp_fmtp(), ast_str_alloca, ast_str_buffer(), ast_str_strlen(), NULL, and tmp().

Referenced by create_outgoing_sdp_stream().

◆ generate_rtpmap_attr()

static pjmedia_sdp_attr * generate_rtpmap_attr ( struct ast_sip_session session,
pjmedia_sdp_media *  media,
pj_pool_t *  pool,
int  rtp_code,
int  asterisk_format,
struct ast_format format,
int  code 
)
static

Definition at line 636 of file res_pjsip_sdp_rtp.c.

638{
639#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
640 extern pj_bool_t pjsip_use_compact_form;
641#else
642 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
643#endif
644 pjmedia_sdp_rtpmap rtpmap;
645 pjmedia_sdp_attr *attr = NULL;
646 char tmp[64];
647 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
649
650 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
651 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
652
653 if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
654 return NULL;
655 }
656
657 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
658 rtpmap.clock_rate = ast_rtp_lookup_sample_rate2(asterisk_format, format, code);
659 pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
660 if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
661 pj_cstr(&rtpmap.param, "2");
662 } else {
663 pj_cstr(&rtpmap.param, NULL);
664 }
665
666 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
667
668 return attr;
669}
ast_rtp_options
Definition: rtp_engine.h:145
@ AST_RTP_OPT_G726_NONSTANDARD
Definition: rtp_engine.h:147
#define AST_RTP_PT_LAST_STATIC
Definition: rtp_engine.h:89
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:2168
static struct test_options options

References ast_rtp_lookup_mime_subtype2(), ast_rtp_lookup_sample_rate2(), AST_RTP_OPT_G726_NONSTANDARD, AST_RTP_PT_LAST_STATIC, NULL, options, session, and tmp().

Referenced by create_outgoing_sdp_stream().

◆ generate_rtpmap_attr2()

static pjmedia_sdp_attr * generate_rtpmap_attr2 ( struct ast_sip_session session,
pjmedia_sdp_media *  media,
pj_pool_t *  pool,
int  rtp_code,
int  asterisk_format,
struct ast_format format,
int  code,
int  sample_rate 
)
static

Definition at line 672 of file res_pjsip_sdp_rtp.c.

674{
675#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
676 extern pj_bool_t pjsip_use_compact_form;
677#else
678 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
679#endif
680 pjmedia_sdp_rtpmap rtpmap;
681 pjmedia_sdp_attr *attr = NULL;
682 char tmp[64];
683 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
685
686 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
687 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
688
689 if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
690 return NULL;
691 }
692
693 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
694 rtpmap.clock_rate = sample_rate;
695 pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
696 if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
697 pj_cstr(&rtpmap.param, "2");
698 } else {
699 pj_cstr(&rtpmap.param, NULL);
700 }
701
702 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
703
704 return attr;
705}

References ast_rtp_lookup_mime_subtype2(), AST_RTP_OPT_G726_NONSTANDARD, AST_RTP_PT_LAST_STATIC, NULL, options, session, and tmp().

Referenced by create_outgoing_sdp_stream().

◆ get_codecs()

static void get_codecs ( struct ast_sip_session session,
const struct pjmedia_sdp_media *  stream,
struct ast_rtp_codecs codecs,
struct ast_sip_session_media session_media,
struct ast_format_cap astformats 
)
static

Definition at line 312 of file res_pjsip_sdp_rtp.c.

314{
315 pjmedia_sdp_attr *attr;
316 pjmedia_sdp_rtpmap *rtpmap;
317 pjmedia_sdp_fmtp fmtp;
318 struct ast_format *format;
319 int i, num = 0, tel_event = 0;
320 char name[256];
321 char media[20];
322 char fmt_param[256];
323 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
326
328
330
331 /* Iterate through provided formats */
332 for (i = 0; i < stream->desc.fmt_count; ++i) {
333 /* The payload is kept as a string for things like t38 but for video it is always numerical */
334 ast_rtp_codecs_payloads_set_m_type(codecs, NULL, pj_strtoul(&stream->desc.fmt[i]));
335 /* Look for the optional rtpmap attribute */
336 if (!(attr = pjmedia_sdp_media_find_attr2(stream, "rtpmap", &stream->desc.fmt[i]))) {
337 continue;
338 }
339
340 /* Interpret the attribute as an rtpmap */
341 if ((pjmedia_sdp_attr_to_rtpmap(session->inv_session->pool_prov, attr, &rtpmap)) != PJ_SUCCESS) {
342 continue;
343 }
344
345 ast_copy_pj_str(name, &rtpmap->enc_name, sizeof(name));
346 if (strcmp(name, "telephone-event") == 0) {
347 if (tel_event == 0) {
348 int dtmf_rate = 0, dtmf_code = 0;
349 char dtmf_pt[8];
350 ast_copy_pj_str(dtmf_pt, &rtpmap->pt, sizeof(dtmf_pt));
351 dtmf_code = atoi(dtmf_pt);
352 dtmf_rate = rtpmap->clock_rate;
354 }
355 tel_event++;
356 }
357
358 ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media, sizeof(media));
360 pj_strtoul(&stream->desc.fmt[i]), media, name, options, rtpmap->clock_rate);
361 /* Look for an optional associated fmtp attribute */
362 if (!(attr = pjmedia_sdp_media_find_attr2(stream, "fmtp", &rtpmap->pt))) {
363 continue;
364 }
365
366 if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
367 ast_copy_pj_str(fmt_param, &fmtp.fmt, sizeof(fmt_param));
368 if (sscanf(fmt_param, "%30d", &num) != 1) {
369 continue;
370 }
371
372 if ((format = ast_rtp_codecs_get_payload_format(codecs, num))) {
373 struct ast_format *format_parsed;
374
375 ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));
376
377 format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);
378 if (format_parsed) {
380 ao2_ref(format_parsed, -1);
381 }
382 ao2_ref(format, -1);
383 }
384 }
385 }
386
387 /* Parsing done, now fill the ast_format_cap struct in the correct order */
388 for (i = 0; i < stream->desc.fmt_count; ++i) {
389 if ((format = ast_rtp_codecs_get_payload_format(codecs, pj_strtoul(&stream->desc.fmt[i])))) {
390 ast_format_cap_append(astformats, format, 0);
391 ao2_ref(format, -1);
392 }
393 }
394
395 if (session->dtmf == AST_SIP_DTMF_AUTO) {
396 if (tel_event) {
399 } else {
402 }
403 }
404
405 if (session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
406 if (tel_event) {
409 } else {
412 }
413 }
414
415
416 /* Get the packetization, if it exists */
417 if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
418 unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
419 if (framing && session->endpoint->media.rtp.use_ptime) {
421 ast_format_cap_set_framing(astformats, framing);
422 }
423 }
424
426}
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
struct ast_format * ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
This function is used to have a media format aware module parse and interpret SDP attribute informati...
Definition: format.c:286
void ast_format_cap_remove_by_type(struct ast_format_cap *cap, enum ast_media_type type)
Remove all formats matching a specific format type.
Definition: format_cap.c:523
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
void ast_format_cap_set_framing(struct ast_format_cap *cap, unsigned int framing)
Set the global framing.
Definition: format_cap.c:136
static const char name[]
Definition: format_mp3.c:68
#define SCOPE_EXIT_RTN(...)
struct ast_format * ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload)
Retrieve the actual ast_format stored on the codecs structure for a specific tx payload type.
Definition: rtp_engine.c:1650
@ AST_RTP_DTMF_MODE_NONE
Definition: rtp_engine.h:153
void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
Set the framing used for a set of codecs.
Definition: rtp_engine.c:1671
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Record tx payload type information that was seen in an m= SDP line.
Definition: rtp_engine.c:1356
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
Definition: rtp_engine.c:980
int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
Update the format associated with a tx payload type in a codecs structure.
Definition: rtp_engine.c:1616
int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt, char *mimetype, char *mimesubtype, enum ast_rtp_options options, unsigned int sample_rate)
Set tx payload type to a known MIME media type for a codec with a specific sample rate.
Definition: rtp_engine.c:1398
int ast_rtp_codecs_set_preferred_dtmf_format(struct ast_rtp_codecs *codecs, int pt, int rate)
Set the preferred dtmf format pt and sample rate.
Definition: rtp_engine.c:1607

References ao2_ref, ast_copy_pj_str(), ast_format_cap_append, ast_format_cap_remove_by_type(), ast_format_cap_set_framing(), ast_format_parse_sdp_fmtp(), AST_MEDIA_TYPE_UNKNOWN, ast_rtp_codecs_get_payload_format(), ast_rtp_codecs_payload_replace_format(), ast_rtp_codecs_payloads_initialize(), ast_rtp_codecs_payloads_set_m_type(), ast_rtp_codecs_payloads_set_rtpmap_type_rate(), ast_rtp_codecs_set_framing(), ast_rtp_codecs_set_preferred_dtmf_format(), AST_RTP_DTMF_MODE_INBAND, AST_RTP_DTMF_MODE_NONE, AST_RTP_DTMF_MODE_RFC2833, ast_rtp_instance_dtmf_mode_set(), ast_rtp_instance_set_prop(), AST_RTP_OPT_G726_NONSTANDARD, AST_RTP_PROPERTY_DTMF, AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, ast_sip_session_get_name(), codecs, name, NULL, options, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN, and session.

Referenced by set_caps(), and set_incoming_call_offer_cap().

◆ get_media_encryption_type()

static enum ast_sip_session_media_encryption get_media_encryption_type ( pj_str_t  transport,
const struct pjmedia_sdp_media *  stream,
unsigned int *  optimistic 
)
static

figure out media transport encryption type from the media transport string

Definition at line 996 of file res_pjsip_sdp_rtp.c.

998{
999 RAII_VAR(char *, transport_str, ast_strndup(transport.ptr, transport.slen), ast_free);
1000
1001 *optimistic = 0;
1002
1003 if (!transport_str) {
1005 }
1006 if (strstr(transport_str, "UDP/TLS")) {
1008 } else if (strstr(transport_str, "SAVP")) {
1010 } else if (media_stream_has_crypto(stream)) {
1011 *optimistic = 1;
1013 } else {
1015 }
1016}
#define ast_strndup(str, len)
A wrapper for strndup()
Definition: astmm.h:256
static int media_stream_has_crypto(const struct pjmedia_sdp_media *stream)
figure out if media stream has crypto lines for sdes

References ast_free, AST_SIP_MEDIA_ENCRYPT_DTLS, AST_SIP_MEDIA_ENCRYPT_NONE, AST_SIP_MEDIA_ENCRYPT_SDES, AST_SIP_MEDIA_TRANSPORT_INVALID, ast_strndup, media_stream_has_crypto(), RAII_VAR, and ast_rtp_engine_ice_candidate::transport.

Referenced by check_endpoint_media_transport().

◆ load_module()

static int load_module ( void  )
static

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 2506 of file res_pjsip_sdp_rtp.c.

2507{
2508 if (ast_check_ipv6()) {
2510 } else {
2511 ast_sockaddr_parse(&address_rtp, "0.0.0.0", 0);
2512 }
2513
2514 if (!(sched = ast_sched_context_create())) {
2515 ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
2516 goto end;
2517 }
2518
2520 ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
2521 goto end;
2522 }
2523
2525 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_AUDIO);
2526 goto end;
2527 }
2528
2530 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_VIDEO);
2531 goto end;
2532 }
2533
2535
2537end:
2538 unload_module();
2539
2541}
char * end
Definition: eagi_proxy.c:73
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static const char STR_AUDIO[]
static struct ast_sip_session_sdp_handler audio_sdp_handler
SDP handler for 'audio' media stream.
static const char STR_VIDEO[]
static struct ast_sip_session_sdp_handler video_sdp_handler
SDP handler for 'video' media stream.
static int unload_module(void)
Unloads the sdp RTP/AVP module from Asterisk.
static struct ast_sip_session_supplement video_info_supplement
int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Register an SDP handler.
#define ast_sip_session_register_supplement(supplement)
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition: utils.c:2792

References address_rtp, ast_check_ipv6(), ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_sched_context_create(), ast_sched_start_thread(), ast_sip_session_register_sdp_handler(), ast_sip_session_register_supplement, ast_sockaddr_parse(), audio_sdp_handler, end, LOG_ERROR, STR_AUDIO, STR_VIDEO, unload_module(), video_info_supplement, and video_sdp_handler.

◆ media_session_rtcp_read_callback()

static struct ast_frame * media_session_rtcp_read_callback ( struct ast_sip_session session,
struct ast_sip_session_media session_media 
)
static

Definition at line 2189 of file res_pjsip_sdp_rtp.c.

2190{
2191 struct ast_frame *f;
2192
2193 if (!session_media->rtp) {
2194 return &ast_null_frame;
2195 }
2196
2197 f = ast_rtp_instance_read(session_media->rtp, 1);
2198 if (!f) {
2199 return NULL;
2200 }
2201
2202 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2203
2204 return f;
2205}
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:600
Data structure associated with a single frame of data.

References ast_null_frame, ast_rtp_instance_read(), ast_rtp_instance_set_last_rx(), NULL, and ast_sip_session_media::rtp.

Referenced by apply_negotiated_sdp_stream().

◆ media_session_rtp_read_callback()

static struct ast_frame * media_session_rtp_read_callback ( struct ast_sip_session session,
struct ast_sip_session_media session_media 
)
static

Definition at line 2171 of file res_pjsip_sdp_rtp.c.

2172{
2173 struct ast_frame *f;
2174
2175 if (!session_media->rtp) {
2176 return &ast_null_frame;
2177 }
2178
2179 f = ast_rtp_instance_read(session_media->rtp, 0);
2180 if (!f) {
2181 return NULL;
2182 }
2183
2184 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2185
2186 return f;
2187}

References ast_null_frame, ast_rtp_instance_read(), ast_rtp_instance_set_last_rx(), NULL, and ast_sip_session_media::rtp.

Referenced by apply_negotiated_sdp_stream().

◆ media_session_rtp_write_callback()

static int media_session_rtp_write_callback ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
struct ast_frame frame 
)
static

Definition at line 2207 of file res_pjsip_sdp_rtp.c.

2208{
2209 if (!session_media->rtp) {
2210 return 0;
2211 }
2212
2213 return ast_rtp_instance_write(session_media->rtp, frame);
2214}
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:590

References ast_rtp_instance_write(), and ast_sip_session_media::rtp.

Referenced by apply_negotiated_sdp_stream().

◆ media_stream_has_crypto()

static int media_stream_has_crypto ( const struct pjmedia_sdp_media *  stream)
static

figure out if media stream has crypto lines for sdes

Definition at line 976 of file res_pjsip_sdp_rtp.c.

977{
978 int i;
979
980 for (i = 0; i < stream->attr_count; i++) {
981 pjmedia_sdp_attr *attr;
982
983 /* check the stream for the required crypto attribute */
984 attr = stream->attr[i];
985 if (pj_strcmp2(&attr->name, "crypto")) {
986 continue;
987 }
988
989 return 1;
990 }
991
992 return 0;
993}

Referenced by get_media_encryption_type().

◆ negotiate_incoming_sdp_stream()

static int negotiate_incoming_sdp_stream ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const pjmedia_sdp_session *  sdp,
int  index,
struct ast_stream asterisk_stream 
)
static

Function which negotiates an incoming media stream.

Definition at line 1543 of file res_pjsip_sdp_rtp.c.

1546{
1547 char host[NI_MAXHOST];
1548 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
1549 pjmedia_sdp_media *stream = sdp->media[index];
1550 struct ast_sip_session_media *session_media_transport;
1551 enum ast_media_type media_type = session_media->type;
1553 struct ast_format_cap *joint;
1554 int res;
1556
1557 /* If no type formats have been configured reject this stream */
1558 if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
1559 ast_debug(3, "Endpoint has no codecs for media type '%s', declining stream\n",
1560 ast_codec_media_type2str(session_media->type));
1561 SCOPE_EXIT_RTN_VALUE(0, "Endpoint has no codecs\n");
1562 }
1563
1564 /* Ensure incoming transport is compatible with the endpoint's configuration */
1565 if (!session->endpoint->media.rtp.use_received_transport) {
1566 encryption = check_endpoint_media_transport(session->endpoint, stream);
1567
1568 if (encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) {
1569 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
1570 }
1571 }
1572
1573 ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
1574
1575 /* Ensure that the address provided is valid */
1576 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1577 /* The provided host was actually invalid so we error out this negotiation */
1578 SCOPE_EXIT_RTN_VALUE(-1, "Invalid host\n");
1579 }
1580
1581 /* Using the connection information create an appropriate RTP instance */
1582 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
1583 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
1584 }
1585
1586 process_ssrc_attributes(session, session_media, stream);
1587 process_extmap_attributes(session, session_media, stream);
1588 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1589
1590 if (session_media_transport == session_media || !session_media->bundled) {
1591 /* If this media session is carrying actual traffic then set up those aspects */
1592 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(stream, "rtcp-mux", NULL) != NULL);
1593 set_ice_components(session, session_media);
1594
1595 enable_rtcp(session, session_media, stream);
1596
1597 res = setup_media_encryption(session, session_media, sdp, stream);
1598 if (res) {
1599 if (!session->endpoint->media.rtp.encryption_optimistic ||
1600 !pj_strncmp2(&stream->desc.transport, "RTP/SAVP", 8)) {
1601 /* If optimistic encryption is disabled and crypto should have been enabled
1602 * but was not this session must fail. This must also fail if crypto was
1603 * required in the offer but could not be set up.
1604 */
1605 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
1606 }
1607 /* There is no encryption, sad. */
1608 session_media->encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
1609 }
1610
1611 /* If we've been explicitly configured to use the received transport OR if
1612 * encryption is on and crypto is present use the received transport.
1613 * This is done in case of optimistic because it may come in as RTP/AVP or RTP/SAVP depending
1614 * on the configuration of the remote endpoint (optimistic themselves or mandatory).
1615 */
1616 if ((session->endpoint->media.rtp.use_received_transport) ||
1617 ((encryption == AST_SIP_MEDIA_ENCRYPT_SDES) && !res)) {
1618 pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport);
1619 }
1620 } else {
1621 /* This is bundled with another session, so mark it as such */
1622 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
1623
1624 enable_rtcp(session, session_media, stream);
1625 }
1626
1627 /* If ICE support is enabled find all the needed attributes */
1628 check_ice_support(session, session_media, stream);
1629
1630 /* If ICE support is enabled then check remote ICE started? */
1631 if (session_media->remote_ice) {
1632 process_ice_auth_attrb(session, session_media, sdp, stream);
1633 }
1634
1635 /* Check if incoming SDP is changing the remotely held state */
1636 set_session_media_remotely_held(session_media, session, stream, asterisk_stream, addrs);
1637
1638 joint = set_incoming_call_offer_cap(session, session_media, stream);
1639 res = apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
1640 ao2_cleanup(joint);
1641 if (res != 0) {
1642 SCOPE_EXIT_RTN_VALUE(0, "Something failed\n");
1643 }
1644
1646}
int ast_format_cap_has_type(const struct ast_format_cap *cap, enum ast_media_type type)
Find out if the capabilities structure has any formats of a specific type.
Definition: format_cap.c:613
static void check_ice_support(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *remote_stream)
Function which checks for ice attributes in an audio stream.
static int apply_cap_to_bundled(struct ast_sip_session_media *session_media, struct ast_sip_session_media *session_media_transport, struct ast_stream *asterisk_stream, struct ast_format_cap *joint)
static struct ast_format_cap * set_incoming_call_offer_cap(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream)
static void process_ice_auth_attrb(struct ast_sip_session *session, struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)

References ao2_cleanup, apply_cap_to_bundled(), AST_AF_UNSPEC, ast_codec_media_type2str(), ast_copy_pj_str(), ast_debug, ast_format_cap_has_type(), ast_free, ast_rtp_instance_bundle(), AST_SIP_MEDIA_ENCRYPT_NONE, AST_SIP_MEDIA_ENCRYPT_SDES, AST_SIP_MEDIA_TRANSPORT_INVALID, ast_sip_session_get_name(), ast_sip_session_media_get_transport(), ast_sockaddr_resolve(), ast_sip_session_media::bundled, check_endpoint_media_transport(), check_ice_support(), create_rtp(), enable_rtcp(), ast_sip_session_media::encryption, NULL, PARSE_PORT_FORBID, process_extmap_attributes(), process_ice_auth_attrb(), process_ssrc_attributes(), RAII_VAR, ast_sip_session_media::remote_ice, ast_sip_session_media::remote_rtcp_mux, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, set_ice_components(), set_incoming_call_offer_cap(), set_session_media_remotely_held(), setup_media_encryption(), ast_sip_session_media::transport, and ast_sip_session_media::type.

◆ parse_dtls_attrib()

static int parse_dtls_attrib ( struct ast_sip_session_media session_media,
const struct pjmedia_sdp_session *  sdp,
const struct pjmedia_sdp_media *  stream 
)
static

Definition at line 1157 of file res_pjsip_sdp_rtp.c.

1160{
1161 int i;
1162
1163 for (i = 0; i < sdp->attr_count; i++) {
1164 apply_dtls_attrib(session_media, sdp->attr[i]);
1165 }
1166
1167 for (i = 0; i < stream->attr_count; i++) {
1168 apply_dtls_attrib(session_media, stream->attr[i]);
1169 }
1170
1172
1173 return 0;
1174}
static void apply_dtls_attrib(struct ast_sip_session_media *session_media, pjmedia_sdp_attr *attr)
#define AST_SRTP_CRYPTO_OFFER_OK
Definition: sdp_srtp.h:45
#define ast_set_flag(p, flag)
Definition: utils.h:70

References apply_dtls_attrib(), ast_set_flag, AST_SRTP_CRYPTO_OFFER_OK, and ast_sip_session_media::srtp.

Referenced by setup_media_encryption().

◆ process_extmap_attributes()

static void process_extmap_attributes ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_media *  remote_stream 
)
static

Function which processes extmap attributes in a stream.

Definition at line 1462 of file res_pjsip_sdp_rtp.c.

1464{
1465 int index;
1466
1467 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1468 return;
1469 }
1470
1471 ast_rtp_instance_extmap_clear(session_media->rtp);
1472
1473 for (index = 0; index < remote_stream->attr_count; ++index) {
1474 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1475 char attr_value[pj_strlen(&attr->value) + 1];
1476 char *uri;
1477 int id;
1478 char direction_str[10] = "";
1479 char *attributes;
1481
1482 /* We only care about extmap attributes */
1483 if (pj_strcmp2(&attr->name, "extmap")) {
1484 continue;
1485 }
1486
1487 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1488
1489 /* Split the combined unique identifier and direction away from the URI and attributes for easier parsing */
1490 uri = strchr(attr_value, ' ');
1491 if (ast_strlen_zero(uri)) {
1492 continue;
1493 }
1494 *uri++ = '\0';
1495
1496 if ((sscanf(attr_value, "%30d%9s", &id, direction_str) < 1) || (id < 1)) {
1497 /* We require at a minimum the unique identifier */
1498 continue;
1499 }
1500
1501 /* Convert from the string to the internal representation */
1502 if (!strcasecmp(direction_str, "/sendonly")) {
1504 } else if (!strcasecmp(direction_str, "/recvonly")) {
1506 } else if (!strcasecmp(direction_str, "/inactive")) {
1508 }
1509
1510 attributes = strchr(uri, ' ');
1511 if (!ast_strlen_zero(attributes)) {
1512 *attributes++ = '\0';
1513 }
1514
1515 ast_rtp_instance_extmap_negotiate(session_media->rtp, id, direction, uri, attributes);
1516 }
1517}
enum queue_result id
Definition: app_queue.c:1667
ast_rtp_extension_direction
Directions for RTP extensions.
Definition: rtp_engine.h:827
int ast_rtp_instance_extmap_negotiate(struct ast_rtp_instance *instance, int id, enum ast_rtp_extension_direction direction, const char *uri, const char *attributes)
Negotiate received RTP extension information.
Definition: rtp_engine.c:840
void ast_rtp_instance_extmap_clear(struct ast_rtp_instance *instance)
Clear negotiated RTP extension information.
Definition: rtp_engine.c:884

References ast_copy_pj_str(), AST_MEDIA_TYPE_VIDEO, AST_RTP_EXTENSION_DIRECTION_INACTIVE, AST_RTP_EXTENSION_DIRECTION_RECVONLY, AST_RTP_EXTENSION_DIRECTION_SENDONLY, AST_RTP_EXTENSION_DIRECTION_SENDRECV, ast_rtp_instance_extmap_clear(), ast_rtp_instance_extmap_negotiate(), ast_strlen_zero(), id, ast_sip_session_media::rtp, session, and ast_sip_session_media::type.

Referenced by apply_negotiated_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ process_ice_attributes()

static void process_ice_attributes ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_session *  remote,
const struct pjmedia_sdp_media *  remote_stream 
)
static

Function which processes ICE attributes in an audio stream.

Definition at line 872 of file res_pjsip_sdp_rtp.c.

874{
875 struct ast_rtp_engine_ice *ice;
876 const pjmedia_sdp_attr *attr;
877 char attr_value[256];
878 unsigned int attr_i;
879
880 /* If ICE support is not enabled or available exit early */
881 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
882 return;
883 }
884
885 ast_debug_ice(2, "(%p) ICE process attributes\n", session_media->rtp);
886
887 attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
888 if (!attr) {
889 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
890 }
891 if (attr) {
892 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
893 ice->set_authentication(session_media->rtp, attr_value, NULL);
894 } else {
895 ast_debug_ice(2, "(%p) ICE no, or invalid ice-ufrag\n", session_media->rtp);
896 return;
897 }
898
899 attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL);
900 if (!attr) {
901 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
902 }
903 if (attr) {
904 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
905 ice->set_authentication(session_media->rtp, NULL, attr_value);
906 } else {
907 ast_debug_ice(2, "(%p) ICE no, or invalid ice-pwd\n", session_media->rtp);
908 return;
909 }
910
911 if (pjmedia_sdp_media_find_attr2(remote_stream, "ice-lite", NULL)) {
912 ice->ice_lite(session_media->rtp);
913 }
914
915 /* Find all of the candidates */
916 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
917 char foundation[33], transport[32], address[PJ_INET6_ADDRSTRLEN + 1], cand_type[6], relay_address[PJ_INET6_ADDRSTRLEN + 1] = "";
918 unsigned int port, relay_port = 0;
919 struct ast_rtp_engine_ice_candidate candidate = { 0, };
920
921 attr = remote_stream->attr[attr_i];
922
923 /* If this is not a candidate line skip it */
924 if (pj_strcmp2(&attr->name, "candidate")) {
925 continue;
926 }
927
928 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
929
930 if (sscanf(attr_value, "%32s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u", foundation, &candidate.id, transport,
931 (unsigned *)&candidate.priority, address, &port, cand_type, relay_address, &relay_port) < 7) {
932 /* Candidate did not parse properly */
933 continue;
934 }
935
936 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux && candidate.id > 1) {
937 /* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,
938 * then we should ignore RTCP candidates.
939 */
940 continue;
941 }
942
943 candidate.foundation = foundation;
944 candidate.transport = transport;
945
947 ast_sockaddr_set_port(&candidate.address, port);
948
949 if (!strcasecmp(cand_type, "host")) {
951 } else if (!strcasecmp(cand_type, "srflx")) {
953 } else if (!strcasecmp(cand_type, "relay")) {
955 } else {
956 continue;
957 }
958
961 }
962
963 if (relay_port) {
964 ast_sockaddr_set_port(&candidate.relay_address, relay_port);
965 }
966
967 ice->add_remote_candidate(session_media->rtp, &candidate);
968 }
969
970 ice->set_role(session_media->rtp, pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_TRUE ?
972 ice->start(session_media->rtp);
973}
char * address
Definition: f2c.h:59
@ AST_RTP_ICE_ROLE_CONTROLLING
Definition: rtp_engine.h:521
@ AST_RTP_ICE_ROLE_CONTROLLED
Definition: rtp_engine.h:520
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:3145
void(* ice_lite)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:552
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition: rtp_engine.h:538
void(* start)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:542
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
Definition: rtp_engine.h:540
void(* set_role)(struct ast_rtp_instance *instance, enum ast_rtp_ice_role role)
Definition: rtp_engine.h:554

References ast_rtp_engine_ice::add_remote_candidate, ast_rtp_engine_ice_candidate::address, ast_copy_pj_str(), ast_debug_ice, AST_RTP_ICE_CANDIDATE_TYPE_HOST, AST_RTP_ICE_CANDIDATE_TYPE_RELAYED, AST_RTP_ICE_CANDIDATE_TYPE_SRFLX, AST_RTP_ICE_ROLE_CONTROLLED, AST_RTP_ICE_ROLE_CONTROLLING, ast_rtp_instance_get_ice(), ast_sockaddr_parse(), ast_sockaddr_set_port, ast_strlen_zero(), ast_rtp_engine_ice_candidate::foundation, ast_rtp_engine_ice::ice_lite, ast_rtp_engine_ice_candidate::id, NULL, PARSE_PORT_FORBID, ast_rtp_engine_ice_candidate::priority, ast_rtp_engine_ice_candidate::relay_address, ast_sip_session_media::remote_rtcp_mux, ast_sip_session_media::rtp, session, ast_rtp_engine_ice::set_authentication, ast_rtp_engine_ice::set_role, ast_rtp_engine_ice::start, ast_rtp_engine_ice_candidate::transport, and ast_rtp_engine_ice_candidate::type.

Referenced by apply_negotiated_sdp_stream().

◆ process_ice_auth_attrb()

static void process_ice_auth_attrb ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_session *  remote,
const struct pjmedia_sdp_media *  remote_stream 
)
static

Definition at line 834 of file res_pjsip_sdp_rtp.c.

836{
837 struct ast_rtp_engine_ice *ice;
838 const pjmedia_sdp_attr *ufrag_attr, *passwd_attr;
839 char ufrag_attr_value[256];
840 char passwd_attr_value[256];
841
842 /* If ICE support is not enabled or available exit early */
843 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
844 return;
845 }
846
847 ufrag_attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
848 if (!ufrag_attr) {
849 ufrag_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
850 }
851 if (ufrag_attr) {
852 ast_copy_pj_str(ufrag_attr_value, (pj_str_t*)&ufrag_attr->value, sizeof(ufrag_attr_value));
853 } else {
854 return;
855 }
856 passwd_attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL);
857 if (!passwd_attr) {
858 passwd_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
859 }
860 if (passwd_attr) {
861 ast_copy_pj_str(passwd_attr_value, (pj_str_t*)&passwd_attr->value, sizeof(passwd_attr_value));
862 } else {
863 return;
864 }
865
866 if (ufrag_attr && passwd_attr) {
867 ice->set_authentication(session_media->rtp, ufrag_attr_value, passwd_attr_value);
868 }
869}

References ast_copy_pj_str(), ast_rtp_instance_get_ice(), NULL, ast_sip_session_media::rtp, session, and ast_rtp_engine_ice::set_authentication.

Referenced by negotiate_incoming_sdp_stream().

◆ process_ssrc_attributes()

static void process_ssrc_attributes ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_media *  remote_stream 
)
static

Function which processes ssrc attributes in a stream.

Definition at line 1276 of file res_pjsip_sdp_rtp.c.

1278{
1279 int index;
1280
1281 if (!session->endpoint->media.bundle) {
1282 return;
1283 }
1284
1285 for (index = 0; index < remote_stream->attr_count; ++index) {
1286 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1287 char attr_value[pj_strlen(&attr->value) + 1];
1288 char *ssrc_attribute_name, *ssrc_attribute_value = NULL;
1289 unsigned int ssrc;
1290
1291 /* We only care about ssrc attributes */
1292 if (pj_strcmp2(&attr->name, "ssrc")) {
1293 continue;
1294 }
1295
1296 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1297
1298 if ((ssrc_attribute_name = strchr(attr_value, ' '))) {
1299 /* This has an actual attribute */
1300 *ssrc_attribute_name++ = '\0';
1301 ssrc_attribute_value = strchr(ssrc_attribute_name, ':');
1302 if (ssrc_attribute_value) {
1303 /* Values are actually optional according to the spec */
1304 *ssrc_attribute_value++ = '\0';
1305 }
1306 }
1307
1308 if (sscanf(attr_value, "%30u", &ssrc) < 1) {
1309 continue;
1310 }
1311
1312 /* If we are currently negotiating as a result of the remote side renegotiating then
1313 * determine if the source for this stream has changed.
1314 */
1315 if (pjmedia_sdp_neg_get_state(session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
1316 session->active_media_state) {
1317 struct ast_rtp_instance_stats stats = { 0, };
1318
1320 stats.remote_ssrc != ssrc) {
1321 session_media->changed = 1;
1322 }
1323 }
1324
1325 ast_rtp_instance_set_remote_ssrc(session_media->rtp, ssrc);
1326 break;
1327 }
1328}
@ AST_RTP_INSTANCE_STAT_REMOTE_SSRC
Definition: rtp_engine.h:251
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
Definition: rtp_engine.c:2622
void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc)
Set the remote SSRC for an RTP instance.
Definition: rtp_engine.c:4054
unsigned int remote_ssrc
Definition: rtp_engine.h:454
unsigned int changed
The underlying session has been changed in some fashion.

References ast_copy_pj_str(), ast_rtp_instance_get_stats(), ast_rtp_instance_set_remote_ssrc(), AST_RTP_INSTANCE_STAT_REMOTE_SSRC, ast_sip_session_media::changed, NULL, ast_rtp_instance_stats::remote_ssrc, ast_sip_session_media::rtp, and session.

Referenced by apply_negotiated_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ rtp_check_timeout()

static int rtp_check_timeout ( const void *  data)
static

Check whether RTP is being received or not.

Definition at line 105 of file res_pjsip_sdp_rtp.c.

106{
107 struct ast_sip_session_media *session_media = (struct ast_sip_session_media *)data;
108 struct ast_rtp_instance *rtp = session_media->rtp;
109 struct ast_channel *chan;
110 int elapsed;
111 int now;
112 int timeout;
113
114 if (!rtp) {
115 return 0;
116 }
117
119 if (!chan) {
120 return 0;
121 }
122
123 /* Store these values locally to avoid multiple function calls */
124 now = time(NULL);
125 timeout = ast_rtp_instance_get_timeout(rtp);
126
127 /* If the channel is not in UP state or call is redirected
128 * outside Asterisk return for later check.
129 */
130 if (ast_channel_state(chan) != AST_STATE_UP || !ast_sockaddr_isnull(&session_media->direct_media_addr)) {
131 /* Avoiding immediately disconnect after channel up or direct media has been stopped */
133 ast_channel_unref(chan);
134 /* Recheck after half timeout for avoiding possible races
135 * and faster reacting to cases while there is no an RTP at all.
136 */
137 return timeout * 500;
138 }
139
140 elapsed = now - ast_rtp_instance_get_last_rx(rtp);
141 if (elapsed < timeout) {
142 ast_channel_unref(chan);
143 return (timeout - elapsed) * 1000;
144 }
145
146 ast_log(LOG_NOTICE, "Disconnecting channel '%s' for lack of %s RTP activity in %d seconds\n",
147 ast_channel_name(chan), ast_codec_media_type2str(session_media->type), elapsed);
148
149 ast_channel_lock(chan);
151 ast_channel_unlock(chan);
152
154 ast_channel_unref(chan);
155
156 return 0;
157}
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition: causes.h:125
const char * ast_channel_name(const struct ast_channel *chan)
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2490
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
#define LOG_NOTICE
time_t ast_rtp_instance_get_last_rx(const struct ast_rtp_instance *rtp)
Get the last RTP reception time.
Definition: rtp_engine.c:4001
const char * ast_rtp_instance_get_channel_id(struct ast_rtp_instance *instance)
Get the unique ID of the channel that owns this RTP instance.
Definition: rtp_engine.c:570
Main Channel structure associated with a channel.

References AST_CAUSE_REQUESTED_CHAN_UNAVAIL, ast_channel_get_by_name(), ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_codec_media_type2str(), ast_log, ast_rtp_instance_get_channel_id(), ast_rtp_instance_get_last_rx(), ast_rtp_instance_get_timeout(), ast_rtp_instance_set_last_rx(), ast_sockaddr_isnull(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_STATE_UP, ast_sip_session_media::direct_media_addr, LOG_NOTICE, NULL, ast_sip_session_media::rtp, and ast_sip_session_media::type.

Referenced by apply_negotiated_sdp_stream().

◆ send_keepalive()

static int send_keepalive ( const void *  data)
static

Definition at line 71 of file res_pjsip_sdp_rtp.c.

72{
73 struct ast_sip_session_media *session_media = (struct ast_sip_session_media *) data;
74 struct ast_rtp_instance *rtp = session_media->rtp;
75 int keepalive;
76 time_t interval;
78
79 if (!rtp) {
80 return 0;
81 }
82
84
85 if (!ast_sockaddr_isnull(&session_media->direct_media_addr)) {
86 ast_debug_rtp(3, "(%p) RTP not sending keepalive since direct media is in use\n", rtp);
87 return keepalive * 1000;
88 }
89
90 interval = time(NULL) - ast_rtp_instance_get_last_tx(rtp);
91 send_keepalive = interval >= keepalive;
92
93 ast_debug_rtp(3, "(%p) RTP it has been %d seconds since RTP was last sent. %sending keepalive\n",
94 rtp, (int) interval, send_keepalive ? "S" : "Not s");
95
96 if (send_keepalive) {
98 return keepalive * 1000;
99 }
100
101 return (keepalive - interval) * 1000;
102}
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
Get the RTP keepalive interval.
Definition: rtp_engine.c:2895
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp)
Get the last RTP transmission time.
Definition: rtp_engine.c:3991
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
Send a comfort noise packet to the RTP instance.
Definition: rtp_engine.c:2972

References ast_debug_rtp, ast_rtp_instance_get_keepalive(), ast_rtp_instance_get_last_tx(), ast_rtp_instance_sendcng(), ast_sockaddr_isnull(), ast_sip_session_media::direct_media_addr, ast_rtp_instance::keepalive, NULL, ast_sip_session_media::rtp, and send_keepalive().

Referenced by apply_negotiated_sdp_stream(), and send_keepalive().

◆ set_caps()

static int set_caps ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
struct ast_sip_session_media session_media_transport,
const struct pjmedia_sdp_media *  stream,
int  is_offer,
struct ast_stream asterisk_stream 
)
static

Definition at line 504 of file res_pjsip_sdp_rtp.c.

509{
510 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
511 RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
512 RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
513 enum ast_media_type media_type = session_media->type;
515 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
516 ast_format_cap_count(session->direct_media_cap);
517 int dsp_features = 0;
518 SCOPE_ENTER(1, "%s %s\n", ast_sip_session_get_name(session), is_offer ? "OFFER" : "ANSWER");
519
523 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
524 ast_codec_media_type2str(session_media->type));
525 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create %s capabilities\n",
526 ast_codec_media_type2str(session_media->type));
527 }
528
529 /* get the endpoint capabilities */
530 if (direct_media_enabled) {
531 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
532 } else {
533 ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
534 }
535
536 /* get the capabilities on the peer */
537 get_codecs(session, stream, &codecs, session_media, peer);
538
539 /* get the joint capabilities between peer and endpoint */
540 ast_format_cap_get_compatible(caps, peer, joint);
541 if (!ast_format_cap_count(joint)) {
544
546 ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
547 ast_codec_media_type2str(session_media->type),
548 ast_format_cap_get_names(caps, &usbuf),
549 ast_format_cap_get_names(peer, &thembuf));
550 SCOPE_EXIT_RTN_VALUE(-1, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
551 ast_codec_media_type2str(session_media->type),
552 ast_format_cap_get_names(caps, &usbuf),
553 ast_format_cap_get_names(peer, &thembuf));
554 } else {
555 struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
556
558 ao2_ref(preferred_fmt, -1);
559 }
560
561 if (is_offer) {
562 /*
563 * Setup rx payload type mapping to prefer the mapping
564 * from the peer that the RFC says we SHOULD use.
565 */
567 }
569 session_media->rtp);
570
571 apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
572
573 if (session->channel && ast_sip_session_is_pending_stream_default(session, asterisk_stream)) {
574 ast_channel_lock(session->channel);
578 ast_format_cap_remove_by_type(caps, media_type);
579
580 if (session->endpoint->preferred_codec_only) {
581 struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
582 ast_format_cap_append(caps, preferred_fmt, 0);
583 ao2_ref(preferred_fmt, -1);
584 } else if (!session->endpoint->asymmetric_rtp_codec) {
585 struct ast_format *best;
586 /*
587 * If we don't allow the sending codec to be changed on our side
588 * then get the best codec from the joint capabilities of the media
589 * type and use only that. This ensures the core won't start sending
590 * out a format that we aren't currently sending.
591 */
592
593 best = ast_format_cap_get_best_by_type(joint, media_type);
594 if (best) {
596 ao2_ref(best, -1);
597 }
598 } else {
599 ast_format_cap_append_from_cap(caps, joint, media_type);
600 }
601
602 /*
603 * Apply the new formats to the channel, potentially changing
604 * raw read/write formats and translation path while doing so.
605 */
607 if (media_type == AST_MEDIA_TYPE_AUDIO) {
610 }
611
612 if ( ((session->dtmf == AST_SIP_DTMF_AUTO) || (session->dtmf == AST_SIP_DTMF_AUTO_INFO) )
614 && (session->dsp)) {
615 dsp_features = ast_dsp_get_features(session->dsp);
616 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
617 if (dsp_features) {
618 ast_dsp_set_features(session->dsp, dsp_features);
619 } else {
620 ast_dsp_free(session->dsp);
621 session->dsp = NULL;
622 }
623 }
624
625 if (ast_channel_is_bridged(session->channel)) {
627 }
628
629 ast_channel_unlock(session->channel);
630 }
631
634}
void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value)
Variant of ast_channel_set_unbridged. Use this if the channel is already locked prior to calling.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5781
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10567
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5822
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition: dsp.c:1777
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
struct ast_format * ast_format_cap_get_best_by_type(const struct ast_format_cap *cap, enum ast_media_type type)
Get the most preferred format for a particular media type.
Definition: format_cap.c:417
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs, struct ast_sip_session_media *session_media, struct ast_format_cap *astformats)
void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
Destroy the contents of an RTP codecs structure (but not the structure itself)
Definition: rtp_engine.c:996
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
Definition: rtp_engine.c:2313
void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
Copy payload information from one RTP instance to another.
Definition: rtp_engine.c:1273
#define AST_RTP_CODECS_NULL_INIT
Definition: rtp_engine.h:773
void ast_rtp_codecs_payloads_xover(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
Crossover copy the tx payload mapping of src to the rx payload mapping of dest.
Definition: rtp_engine.c:1309
int ast_rtp_codecs_set_preferred_format(struct ast_rtp_codecs *codecs, struct ast_format *format)
Set the preferred format.
Definition: rtp_engine.c:1581

References ao2_cleanup, ao2_ref, apply_cap_to_bundled(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_nativeformats(), ast_channel_nativeformats_set(), ast_channel_readformat(), ast_channel_set_unbridged_nolock(), ast_channel_unlock, ast_channel_writeformat(), ast_codec_media_type2str(), ast_dsp_free(), ast_dsp_get_features(), ast_dsp_set_features(), ast_format_cap_alloc, ast_format_cap_append, ast_format_cap_append_from_cap(), ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_best_by_type(), ast_format_cap_get_compatible(), ast_format_cap_get_format(), ast_format_cap_get_framing(), ast_format_cap_get_names(), AST_FORMAT_CAP_NAMES_LEN, ast_format_cap_remove_by_type(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_UNKNOWN, AST_RTP_CODECS_NULL_INIT, ast_rtp_codecs_payloads_copy(), ast_rtp_codecs_payloads_destroy(), ast_rtp_codecs_payloads_xover(), ast_rtp_codecs_set_preferred_format(), AST_RTP_DTMF_MODE_RFC2833, ast_rtp_instance_dtmf_mode_get(), ast_rtp_instance_get_codecs(), ast_set_read_format(), ast_set_write_format(), AST_SIP_DTMF_AUTO, AST_SIP_DTMF_AUTO_INFO, ast_sip_session_get_name(), ast_sip_session_is_pending_stream_default(), ast_sockaddr_isnull(), ast_str_alloca, codecs, ast_sip_session_media::direct_media_addr, get_codecs(), LOG_ERROR, LOG_NOTICE, NULL, RAII_VAR, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, and ast_sip_session_media::type.

Referenced by apply_negotiated_sdp_stream().

◆ set_ice_components()

static void set_ice_components ( struct ast_sip_session session,
struct ast_sip_session_media session_media 
)
static

Definition at line 1239 of file res_pjsip_sdp_rtp.c.

1240{
1241 struct ast_rtp_engine_ice *ice;
1242
1243 ast_assert(session_media->rtp != NULL);
1244
1245 ice = ast_rtp_instance_get_ice(session_media->rtp);
1246 if (!session->endpoint->media.rtp.ice_support || !ice) {
1247 return;
1248 }
1249
1250 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
1251 /* We both support RTCP mux. Only one ICE component necessary */
1252 ice->change_components(session_media->rtp, 1);
1253 } else {
1254 /* They either don't support RTCP mux or we don't know if they do yet. */
1255 ice->change_components(session_media->rtp, 2);
1256 }
1257}
void(* change_components)(struct ast_rtp_instance *instance, int num_components)
Definition: rtp_engine.h:560
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_rtp_instance_get_ice(), ast_rtp_engine_ice::change_components, NULL, ast_sip_session_media::remote_rtcp_mux, ast_sip_session_media::rtp, and session.

Referenced by apply_negotiated_sdp_stream(), create_outgoing_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ set_incoming_call_offer_cap()

static struct ast_format_cap * set_incoming_call_offer_cap ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_media *  stream 
)
static

Definition at line 459 of file res_pjsip_sdp_rtp.c.

462{
463 struct ast_format_cap *incoming_call_offer_cap;
464 struct ast_format_cap *remote;
467
468
470 if (!remote) {
471 ast_log(LOG_ERROR, "Failed to allocate %s incoming remote capabilities\n",
472 ast_codec_media_type2str(session_media->type));
473 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't allocate caps\n");
474 }
475
476 /* Get the peer's capabilities*/
477 get_codecs(session, stream, &codecs, session_media, remote);
478
479 incoming_call_offer_cap = ast_sip_session_create_joint_call_cap(
480 session, session_media->type, remote);
481
482 ao2_ref(remote, -1);
483
484 if (!incoming_call_offer_cap || ast_format_cap_empty(incoming_call_offer_cap)) {
485 ao2_cleanup(incoming_call_offer_cap);
487 SCOPE_EXIT_RTN_VALUE(NULL, "No incoming call offer caps\n");
488 }
489
490 /*
491 * Setup rx payload type mapping to prefer the mapping
492 * from the peer that the RFC says we SHOULD use.
493 */
495
497 ast_rtp_instance_get_codecs(session_media->rtp), session_media->rtp);
498
500
501 SCOPE_EXIT_RTN_VALUE(incoming_call_offer_cap);
502}
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition: format_cap.c:744
struct ast_format_cap * ast_sip_session_create_joint_call_cap(const struct ast_sip_session *session, enum ast_media_type media_type, const struct ast_format_cap *remote)
Create joint capabilities.

References ao2_cleanup, ao2_ref, ast_codec_media_type2str(), ast_format_cap_alloc, ast_format_cap_empty(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_log, AST_RTP_CODECS_NULL_INIT, ast_rtp_codecs_payloads_copy(), ast_rtp_codecs_payloads_destroy(), ast_rtp_codecs_payloads_xover(), ast_rtp_instance_get_codecs(), ast_sip_session_create_joint_call_cap(), ast_sip_session_get_name(), codecs, get_codecs(), LOG_ERROR, NULL, ast_sip_session_media::rtp, SCOPE_ENTER, SCOPE_EXIT_RTN_VALUE, session, and ast_sip_session_media::type.

Referenced by negotiate_incoming_sdp_stream().

◆ set_session_media_remotely_held()

static void set_session_media_remotely_held ( struct ast_sip_session_media session_media,
const struct ast_sip_session session,
const pjmedia_sdp_media *  media,
const struct ast_stream stream,
const struct ast_sockaddr addrs 
)
static

Definition at line 1519 of file res_pjsip_sdp_rtp.c.

1524{
1526 (session_media->type == AST_MEDIA_TYPE_AUDIO)) {
1527 if (((addrs != NULL) && ast_sockaddr_isnull(addrs)) ||
1528 ((addrs != NULL) && ast_sockaddr_is_any(addrs)) ||
1529 pjmedia_sdp_media_find_attr2(media, "sendonly", NULL) ||
1530 pjmedia_sdp_media_find_attr2(media, "inactive", NULL)) {
1531 if (!session_media->remotely_held) {
1532 session_media->remotely_held = 1;
1533 session_media->remotely_held_changed = 1;
1534 }
1535 } else if (session_media->remotely_held) {
1536 session_media->remotely_held = 0;
1537 session_media->remotely_held_changed = 1;
1538 }
1539 }
1540}
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
Definition: netsock2.c:534

References AST_MEDIA_TYPE_AUDIO, ast_sip_session_is_pending_stream_default(), ast_sockaddr_is_any(), ast_sockaddr_isnull(), NULL, ast_sip_session_media::remotely_held, ast_sip_session_media::remotely_held_changed, session, and ast_sip_session_media::type.

Referenced by apply_negotiated_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ setup_dtls_srtp()

static int setup_dtls_srtp ( struct ast_sip_session session,
struct ast_sip_session_media session_media 
)
static

Definition at line 1081 of file res_pjsip_sdp_rtp.c.

1083{
1084 struct ast_rtp_engine_dtls *dtls;
1085
1086 if (!session->endpoint->media.rtp.dtls_cfg.enabled || !session_media->rtp) {
1087 return -1;
1088 }
1089
1090 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1091 if (!dtls) {
1092 return -1;
1093 }
1094
1095 session->endpoint->media.rtp.dtls_cfg.suite = ((session->endpoint->media.rtp.srtp_tag_32) ? AST_AES_CM_128_HMAC_SHA1_32 : AST_AES_CM_128_HMAC_SHA1_80);
1096 if (dtls->set_configuration(session_media->rtp, &session->endpoint->media.rtp.dtls_cfg)) {
1097 ast_log(LOG_ERROR, "Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
1098 session_media->rtp);
1099 return -1;
1100 }
1101
1102 if (setup_srtp(session_media)) {
1103 return -1;
1104 }
1105 return 0;
1106}
static int setup_srtp(struct ast_sip_session_media *session_media)
@ AST_AES_CM_128_HMAC_SHA1_80
Definition: res_srtp.h:58
@ AST_AES_CM_128_HMAC_SHA1_32
Definition: res_srtp.h:59
int(* set_configuration)(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
Definition: rtp_engine.h:623

References AST_AES_CM_128_HMAC_SHA1_32, AST_AES_CM_128_HMAC_SHA1_80, ast_log, ast_rtp_instance_get_dtls(), LOG_ERROR, ast_sip_session_media::rtp, session, ast_rtp_engine_dtls::set_configuration, and setup_srtp().

Referenced by add_crypto_to_stream(), and setup_media_encryption().

◆ setup_media_encryption()

static int setup_media_encryption ( struct ast_sip_session session,
struct ast_sip_session_media session_media,
const struct pjmedia_sdp_session *  sdp,
const struct pjmedia_sdp_media *  stream 
)
static

Definition at line 1212 of file res_pjsip_sdp_rtp.c.

1216{
1217 switch (session_media->encryption) {
1219 if (setup_sdes_srtp(session_media, stream)) {
1220 return -1;
1221 }
1222 break;
1224 if (setup_dtls_srtp(session, session_media)) {
1225 return -1;
1226 }
1227 if (parse_dtls_attrib(session_media, sdp, stream)) {
1228 return -1;
1229 }
1230 break;
1233 break;
1234 }
1235
1236 return 0;
1237}
static int parse_dtls_attrib(struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_media *stream)
static int setup_sdes_srtp(struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream)

References AST_SIP_MEDIA_ENCRYPT_DTLS, AST_SIP_MEDIA_ENCRYPT_NONE, AST_SIP_MEDIA_ENCRYPT_SDES, AST_SIP_MEDIA_TRANSPORT_INVALID, ast_sip_session_media::encryption, parse_dtls_attrib(), session, setup_dtls_srtp(), and setup_sdes_srtp().

Referenced by apply_negotiated_sdp_stream(), and negotiate_incoming_sdp_stream().

◆ setup_sdes_srtp()

static int setup_sdes_srtp ( struct ast_sip_session_media session_media,
const struct pjmedia_sdp_media *  stream 
)
static

Definition at line 1176 of file res_pjsip_sdp_rtp.c.

1178{
1179 int i;
1180
1181 for (i = 0; i < stream->attr_count; i++) {
1182 pjmedia_sdp_attr *attr;
1183 RAII_VAR(char *, crypto_str, NULL, ast_free);
1184
1185 /* check the stream for the required crypto attribute */
1186 attr = stream->attr[i];
1187 if (pj_strcmp2(&attr->name, "crypto")) {
1188 continue;
1189 }
1190
1191 crypto_str = ast_strndup(attr->value.ptr, attr->value.slen);
1192 if (!crypto_str) {
1193 return -1;
1194 }
1195
1196 if (setup_srtp(session_media)) {
1197 return -1;
1198 }
1199
1200 if (!ast_sdp_crypto_process(session_media->rtp, session_media->srtp, crypto_str)) {
1201 /* found a valid crypto attribute */
1202 return 0;
1203 }
1204
1205 ast_debug(1, "Ignoring crypto offer with unsupported parameters: %s\n", crypto_str);
1206 }
1207
1208 /* no usable crypto attributes found */
1209 return -1;
1210}
int ast_sdp_crypto_process(struct ast_rtp_instance *rtp, struct ast_sdp_srtp *srtp, const char *attr)
Parse the a=crypto line from SDP and set appropriate values on the ast_sdp_crypto struct.
Definition: sdp_srtp.c:79

References ast_debug, ast_free, ast_sdp_crypto_process(), ast_strndup, NULL, RAII_VAR, ast_sip_session_media::rtp, setup_srtp(), and ast_sip_session_media::srtp.

Referenced by setup_media_encryption().

◆ setup_srtp()

static int setup_srtp ( struct ast_sip_session_media session_media)
static

Definition at line 1062 of file res_pjsip_sdp_rtp.c.

1063{
1064 if (!session_media->srtp) {
1065 session_media->srtp = ast_sdp_srtp_alloc();
1066 if (!session_media->srtp) {
1067 return -1;
1068 }
1069 }
1070
1071 if (!session_media->srtp->crypto) {
1072 session_media->srtp->crypto = ast_sdp_crypto_alloc();
1073 if (!session_media->srtp->crypto) {
1074 return -1;
1075 }
1076 }
1077
1078 return 0;
1079}
struct ast_sdp_crypto * ast_sdp_crypto_alloc(void)
Initialize an return an ast_sdp_crypto struct.
Definition: sdp_srtp.c:71
struct ast_sdp_crypto * crypto
Definition: sdp_srtp.h:40

References ast_sdp_crypto_alloc(), ast_sdp_srtp_alloc(), ast_sdp_srtp::crypto, and ast_sip_session_media::srtp.

Referenced by setup_dtls_srtp(), and setup_sdes_srtp().

◆ stream_destroy()

static void stream_destroy ( struct ast_sip_session_media session_media)
static

Function which destroys the RTP instance when session ends.

Definition at line 2424 of file res_pjsip_sdp_rtp.c.

2425{
2426 if (session_media->rtp) {
2427 stream_stop(session_media);
2428 ast_rtp_instance_destroy(session_media->rtp);
2429 }
2430 session_media->rtp = NULL;
2431}
static void stream_stop(struct ast_sip_session_media *session_media)
Function which stops the RTP instance.
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458

References ast_rtp_instance_destroy(), NULL, ast_sip_session_media::rtp, and stream_stop().

◆ stream_stop()

static void stream_stop ( struct ast_sip_session_media session_media)
static

Function which stops the RTP instance.

Definition at line 2412 of file res_pjsip_sdp_rtp.c.

2413{
2414 if (!session_media->rtp) {
2415 return;
2416 }
2417
2418 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2419 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2420 ast_rtp_instance_stop(session_media->rtp);
2421}

References ast_rtp_instance_stop(), AST_SCHED_DEL, ast_sip_session_media::keepalive_sched_id, ast_sip_session_media::rtp, and ast_sip_session_media::timeout_sched_id.

Referenced by stream_destroy().

◆ unload_module()

static int unload_module ( void  )
static

Unloads the sdp RTP/AVP module from Asterisk.

Definition at line 2483 of file res_pjsip_sdp_rtp.c.

2484{
2488
2489 if (sched) {
2491 }
2492
2493 return 0;
2494}
void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Unregister an SDP handler.
void ast_sip_session_unregister_supplement(struct ast_sip_session_supplement *supplement)
Unregister a an supplement to SIP session processing.
Definition: pjsip_session.c:63
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271

References ast_sched_context_destroy(), ast_sip_session_unregister_sdp_handler(), ast_sip_session_unregister_supplement(), audio_sdp_handler, STR_AUDIO, STR_VIDEO, video_info_supplement, and video_sdp_handler.

Referenced by load_module().

◆ video_info_incoming_request()

static int video_info_incoming_request ( struct ast_sip_session session,
struct pjsip_rx_data *  rdata 
)
static

Definition at line 2455 of file res_pjsip_sdp_rtp.c.

2456{
2457 struct pjsip_transaction *tsx;
2458 pjsip_tx_data *tdata;
2459
2460 if (!session->channel
2461 || !ast_sip_are_media_types_equal(&rdata->msg_info.msg->body->content_type,
2463 return 0;
2464 }
2465
2466 tsx = pjsip_rdata_get_tsx(rdata);
2467
2469
2470 if (pjsip_dlg_create_response(session->inv_session->dlg, rdata, 200, NULL, &tdata) == PJ_SUCCESS) {
2471 pjsip_dlg_send_response(session->inv_session->dlg, tsx, tdata);
2472 }
2473
2474 return 0;
2475}
@ AST_CONTROL_VIDUPDATE
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition: res_pjsip.c:3910
int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
Compare pjsip media types.
Definition: res_pjsip.c:2219

References AST_CONTROL_VIDUPDATE, ast_queue_control(), ast_sip_are_media_types_equal(), NULL, pjsip_media_type_application_media_control_xml, and session.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "PJSIP SDP RTP/AVP stream handler" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .requires = "res_pjsip,res_pjsip_session", }
static

Definition at line 2549 of file res_pjsip_sdp_rtp.c.

◆ address_rtp

struct ast_sockaddr address_rtp
static

Address for RTP.

Definition at line 66 of file res_pjsip_sdp_rtp.c.

Referenced by create_rtp(), and load_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2549 of file res_pjsip_sdp_rtp.c.

◆ audio_sdp_handler

struct ast_sip_session_sdp_handler audio_sdp_handler
static

SDP handler for 'audio' media stream.

Definition at line 2434 of file res_pjsip_sdp_rtp.c.

Referenced by load_module(), and unload_module().

◆ sched

struct ast_sched_context* sched
static

Scheduler for RTCP purposes.

Definition at line 63 of file res_pjsip_sdp_rtp.c.

◆ STR_AUDIO

const char STR_AUDIO[] = "audio"
static

Definition at line 68 of file res_pjsip_sdp_rtp.c.

Referenced by load_module(), and unload_module().

◆ STR_VIDEO

const char STR_VIDEO[] = "video"
static

Definition at line 69 of file res_pjsip_sdp_rtp.c.

Referenced by load_module(), and unload_module().

◆ video_info_supplement

struct ast_sip_session_supplement video_info_supplement
static
Initial value:
= {
.method = "INFO",
.incoming_request = video_info_incoming_request,
}
static int video_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)

Definition at line 2477 of file res_pjsip_sdp_rtp.c.

Referenced by load_module(), and unload_module().

◆ video_sdp_handler

struct ast_sip_session_sdp_handler video_sdp_handler
static

SDP handler for 'video' media stream.

Definition at line 2445 of file res_pjsip_sdp_rtp.c.

Referenced by load_module(), and unload_module().