Asterisk - The Open Source Telephony Project GIT-master-a358458
res_pjsip_sdp_rtp.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@digium.com>
7 * Kevin Harwell <kharwell@digium.com>
8 *
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
14 *
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
18 */
19
20/*! \file
21 *
22 * \author Joshua Colp <jcolp@digium.com>
23 *
24 * \brief SIP SDP media stream handling
25 */
26
27/*** MODULEINFO
28 <depend>pjproject</depend>
29 <depend>res_pjsip</depend>
30 <depend>res_pjsip_session</depend>
31 <support_level>core</support_level>
32 ***/
33
34#include "asterisk.h"
35
36#include <pjsip.h>
37#include <pjsip_ua.h>
38#include <pjmedia.h>
39#include <pjlib.h>
40
41#include "asterisk/utils.h"
42#include "asterisk/module.h"
43#include "asterisk/format.h"
44#include "asterisk/format_cap.h"
45#include "asterisk/rtp_engine.h"
46#include "asterisk/netsock2.h"
47#include "asterisk/channel.h"
48#include "asterisk/causes.h"
49#include "asterisk/sched.h"
50#include "asterisk/acl.h"
51#include "asterisk/sdp_srtp.h"
52#include "asterisk/dsp.h"
53#include "asterisk/linkedlists.h" /* for AST_LIST_NEXT */
54#include "asterisk/stream.h"
57
58#include "asterisk/res_pjsip.h"
61
62/*! \brief Scheduler for RTCP purposes */
63static struct ast_sched_context *sched;
64
65/*! \brief Address for RTP */
67
68static const char STR_AUDIO[] = "audio";
69static const char STR_VIDEO[] = "video";
70
71static int send_keepalive(const void *data)
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}
103
104/*! \brief Check whether RTP is being received or not */
105static int rtp_check_timeout(const void *data)
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}
158
159/*!
160 * \brief Enable RTCP on an RTP session.
161 */
162static void enable_rtcp(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
163 const struct pjmedia_sdp_media *remote_media)
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}
175
176/*!
177 * \brief Enable an RTP extension on an RTP session.
178 */
179static void enable_rtp_extension(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
181 const pjmedia_sdp_session *sdp)
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}
223
224/*! \brief Internal function which creates an RTP instance */
225static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
226 const pjmedia_sdp_session *sdp)
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}
311
312static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs,
313 struct ast_sip_session_media *session_media, struct ast_format_cap *astformats)
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 tel_event++;
348 }
349
350 ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media, sizeof(media));
352 pj_strtoul(&stream->desc.fmt[i]), media, name, options, rtpmap->clock_rate);
353 /* Look for an optional associated fmtp attribute */
354 if (!(attr = pjmedia_sdp_media_find_attr2(stream, "fmtp", &rtpmap->pt))) {
355 continue;
356 }
357
358 if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
359 ast_copy_pj_str(fmt_param, &fmtp.fmt, sizeof(fmt_param));
360 if (sscanf(fmt_param, "%30d", &num) != 1) {
361 continue;
362 }
363
364 if ((format = ast_rtp_codecs_get_payload_format(codecs, num))) {
365 struct ast_format *format_parsed;
366
367 ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));
368
369 format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);
370 if (format_parsed) {
372 ao2_ref(format_parsed, -1);
373 }
374 ao2_ref(format, -1);
375 }
376 }
377 }
378
379 /* Parsing done, now fill the ast_format_cap struct in the correct order */
380 for (i = 0; i < stream->desc.fmt_count; ++i) {
381 if ((format = ast_rtp_codecs_get_payload_format(codecs, pj_strtoul(&stream->desc.fmt[i])))) {
382 ast_format_cap_append(astformats, format, 0);
383 ao2_ref(format, -1);
384 }
385 }
386
387 if (!tel_event && (session->dtmf == AST_SIP_DTMF_AUTO)) {
390 }
391
392 if (session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
393 if (tel_event) {
396 } else {
399 }
400 }
401
402
403 /* Get the packetization, if it exists */
404 if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
405 unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
406 if (framing && session->endpoint->media.rtp.use_ptime) {
408 ast_format_cap_set_framing(astformats, framing);
409 }
410 }
411
413}
414
415static int apply_cap_to_bundled(struct ast_sip_session_media *session_media,
416 struct ast_sip_session_media *session_media_transport,
417 struct ast_stream *asterisk_stream, struct ast_format_cap *joint)
418{
419 if (!joint) {
420 return -1;
421 }
422
423 ast_stream_set_formats(asterisk_stream, joint);
424
425 /* If this is a bundled stream then apply the payloads to RTP instance acting as transport to prevent conflicts */
426 if (session_media_transport != session_media && session_media->bundled) {
427 int index;
428
429 for (index = 0; index < ast_format_cap_count(joint); ++index) {
430 struct ast_format *format = ast_format_cap_get_format(joint, index);
431 int rtp_code;
432
433 /* Ensure this payload is in the bundle group transport codecs, this purposely doesn't check the return value for
434 * things as the format is guaranteed to have a payload already.
435 */
436 rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0);
437 ast_rtp_codecs_payload_set_rx(ast_rtp_instance_get_codecs(session_media_transport->rtp), rtp_code, format);
438
439 ao2_ref(format, -1);
440 }
441 }
442
443 return 0;
444}
445
447 struct ast_sip_session *session, struct ast_sip_session_media *session_media,
448 const struct pjmedia_sdp_media *stream)
449{
450 struct ast_format_cap *incoming_call_offer_cap;
451 struct ast_format_cap *remote;
454
455
457 if (!remote) {
458 ast_log(LOG_ERROR, "Failed to allocate %s incoming remote capabilities\n",
459 ast_codec_media_type2str(session_media->type));
460 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't allocate caps\n");
461 }
462
463 /* Get the peer's capabilities*/
464 get_codecs(session, stream, &codecs, session_media, remote);
465
466 incoming_call_offer_cap = ast_sip_session_create_joint_call_cap(
467 session, session_media->type, remote);
468
469 ao2_ref(remote, -1);
470
471 if (!incoming_call_offer_cap || ast_format_cap_empty(incoming_call_offer_cap)) {
472 ao2_cleanup(incoming_call_offer_cap);
474 SCOPE_EXIT_RTN_VALUE(NULL, "No incoming call offer caps\n");
475 }
476
477 /*
478 * Setup rx payload type mapping to prefer the mapping
479 * from the peer that the RFC says we SHOULD use.
480 */
482
484 ast_rtp_instance_get_codecs(session_media->rtp), session_media->rtp);
485
487
488 SCOPE_EXIT_RTN_VALUE(incoming_call_offer_cap);
489}
490
492 struct ast_sip_session_media *session_media,
493 struct ast_sip_session_media *session_media_transport,
494 const struct pjmedia_sdp_media *stream,
495 int is_offer, struct ast_stream *asterisk_stream)
496{
497 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
498 RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
499 RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
500 enum ast_media_type media_type = session_media->type;
502 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
503 ast_format_cap_count(session->direct_media_cap);
504 int dsp_features = 0;
505 SCOPE_ENTER(1, "%s %s\n", ast_sip_session_get_name(session), is_offer ? "OFFER" : "ANSWER");
506
510 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
511 ast_codec_media_type2str(session_media->type));
512 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create %s capabilities\n",
513 ast_codec_media_type2str(session_media->type));
514 }
515
516 /* get the endpoint capabilities */
517 if (direct_media_enabled) {
518 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
519 } else {
520 ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
521 }
522
523 /* get the capabilities on the peer */
524 get_codecs(session, stream, &codecs, session_media, peer);
525
526 /* get the joint capabilities between peer and endpoint */
527 ast_format_cap_get_compatible(caps, peer, joint);
528 if (!ast_format_cap_count(joint)) {
531
533 ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
534 ast_codec_media_type2str(session_media->type),
535 ast_format_cap_get_names(caps, &usbuf),
536 ast_format_cap_get_names(peer, &thembuf));
537 SCOPE_EXIT_RTN_VALUE(-1, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
538 ast_codec_media_type2str(session_media->type),
539 ast_format_cap_get_names(caps, &usbuf),
540 ast_format_cap_get_names(peer, &thembuf));
541 }
542
543 if (is_offer) {
544 /*
545 * Setup rx payload type mapping to prefer the mapping
546 * from the peer that the RFC says we SHOULD use.
547 */
549 }
551 session_media->rtp);
552
553 apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
554
555 if (session->channel && ast_sip_session_is_pending_stream_default(session, asterisk_stream)) {
556 ast_channel_lock(session->channel);
560 ast_format_cap_remove_by_type(caps, media_type);
561
562 if (session->endpoint->preferred_codec_only){
563 struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
564 ast_format_cap_append(caps, preferred_fmt, 0);
565 ao2_ref(preferred_fmt, -1);
566 } else if (!session->endpoint->asymmetric_rtp_codec) {
567 struct ast_format *best;
568 /*
569 * If we don't allow the sending codec to be changed on our side
570 * then get the best codec from the joint capabilities of the media
571 * type and use only that. This ensures the core won't start sending
572 * out a format that we aren't currently sending.
573 */
574
575 best = ast_format_cap_get_best_by_type(joint, media_type);
576 if (best) {
578 ao2_ref(best, -1);
579 }
580 } else {
581 ast_format_cap_append_from_cap(caps, joint, media_type);
582 }
583
584 /*
585 * Apply the new formats to the channel, potentially changing
586 * raw read/write formats and translation path while doing so.
587 */
589 if (media_type == AST_MEDIA_TYPE_AUDIO) {
592 }
593
594 if ( ((session->dtmf == AST_SIP_DTMF_AUTO) || (session->dtmf == AST_SIP_DTMF_AUTO_INFO) )
596 && (session->dsp)) {
597 dsp_features = ast_dsp_get_features(session->dsp);
598 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
599 if (dsp_features) {
600 ast_dsp_set_features(session->dsp, dsp_features);
601 } else {
602 ast_dsp_free(session->dsp);
603 session->dsp = NULL;
604 }
605 }
606
607 if (ast_channel_is_bridged(session->channel)) {
609 }
610
611 ast_channel_unlock(session->channel);
612 }
613
616}
617
618static pjmedia_sdp_attr* generate_rtpmap_attr(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
619 int rtp_code, int asterisk_format, struct ast_format *format, int code)
620{
621#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
622 extern pj_bool_t pjsip_use_compact_form;
623#else
624 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
625#endif
626 pjmedia_sdp_rtpmap rtpmap;
627 pjmedia_sdp_attr *attr = NULL;
628 char tmp[64];
629 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
631
632 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
633 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
634
635 if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
636 return NULL;
637 }
638
639 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
640 rtpmap.clock_rate = ast_rtp_lookup_sample_rate2(asterisk_format, format, code);
641 pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
642 if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
643 pj_cstr(&rtpmap.param, "2");
644 } else {
645 pj_cstr(&rtpmap.param, NULL);
646 }
647
648 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
649
650 return attr;
651}
652
653static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *format, int rtp_code)
654{
655 struct ast_str *fmtp0 = ast_str_alloca(256);
656 pj_str_t fmtp1;
657 pjmedia_sdp_attr *attr = NULL;
658 char *tmp;
659
660 ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
661 if (ast_str_strlen(fmtp0)) {
662 tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
663 /* remove any carriage return line feeds */
664 while (*tmp == '\r' || *tmp == '\n') --tmp;
665 *++tmp = '\0';
666 /* ast...generate gives us everything, just need value */
667 tmp = strchr(ast_str_buffer(fmtp0), ':');
668 if (tmp && tmp[1] != '\0') {
669 fmtp1 = pj_str(tmp + 1);
670 } else {
671 fmtp1 = pj_str(ast_str_buffer(fmtp0));
672 }
673 attr = pjmedia_sdp_attr_create(pool, "fmtp", &fmtp1);
674 }
675 return attr;
676}
677
678/*! \brief Function which adds ICE attributes to a media stream */
679static 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,
680 unsigned int include_candidates)
681{
682 struct ast_rtp_engine_ice *ice;
683 struct ao2_container *candidates;
684 const char *username, *password;
685 pj_str_t stmp;
686 pjmedia_sdp_attr *attr;
687 struct ao2_iterator it_candidates;
688 struct ast_rtp_engine_ice_candidate *candidate;
689
690 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
691 return;
692 }
693
694 if (!session_media->remote_ice) {
695 ice->stop(session_media->rtp);
696 return;
697 }
698
699 if ((username = ice->get_ufrag(session_media->rtp))) {
700 attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", pj_cstr(&stmp, username));
701 media->attr[media->attr_count++] = attr;
702 }
703
704 if ((password = ice->get_password(session_media->rtp))) {
705 attr = pjmedia_sdp_attr_create(pool, "ice-pwd", pj_cstr(&stmp, password));
706 media->attr[media->attr_count++] = attr;
707 }
708
709 if (!include_candidates) {
710 return;
711 }
712
713 candidates = ice->get_local_candidates(session_media->rtp);
714 if (!candidates) {
715 return;
716 }
717
718 it_candidates = ao2_iterator_init(candidates, 0);
719 for (; (candidate = ao2_iterator_next(&it_candidates)); ao2_ref(candidate, -1)) {
720 struct ast_str *attr_candidate = ast_str_create(128);
721
722 ast_str_set(&attr_candidate, -1, "%s %u %s %d %s ", candidate->foundation, candidate->id, candidate->transport,
723 candidate->priority, ast_sockaddr_stringify_addr_remote(&candidate->address));
724 ast_str_append(&attr_candidate, -1, "%s typ ", ast_sockaddr_stringify_port(&candidate->address));
725
726 switch (candidate->type) {
728 ast_str_append(&attr_candidate, -1, "host");
729 break;
731 ast_str_append(&attr_candidate, -1, "srflx");
732 break;
734 ast_str_append(&attr_candidate, -1, "relay");
735 break;
736 }
737
738 if (!ast_sockaddr_isnull(&candidate->relay_address)) {
739 ast_str_append(&attr_candidate, -1, " raddr %s rport", ast_sockaddr_stringify_addr_remote(&candidate->relay_address));
740 ast_str_append(&attr_candidate, -1, " %s", ast_sockaddr_stringify_port(&candidate->relay_address));
741 }
742
743 attr = pjmedia_sdp_attr_create(pool, "candidate", pj_cstr(&stmp, ast_str_buffer(attr_candidate)));
744 media->attr[media->attr_count++] = attr;
745
746 ast_free(attr_candidate);
747 }
748
749 ao2_iterator_destroy(&it_candidates);
750 ao2_ref(candidates, -1);
751}
752
753/*! \brief Function which checks for ice attributes in an audio stream */
754static void check_ice_support(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
755 const struct pjmedia_sdp_media *remote_stream)
756{
757 struct ast_rtp_engine_ice *ice;
758 const pjmedia_sdp_attr *attr;
759 unsigned int attr_i;
760
761 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
762 session_media->remote_ice = 0;
763 return;
764 }
765
766 /* Find all of the candidates */
767 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
768 attr = remote_stream->attr[attr_i];
769 if (!pj_strcmp2(&attr->name, "candidate")) {
770 session_media->remote_ice = 1;
771 break;
772 }
773 }
774
775 if (attr_i == remote_stream->attr_count) {
776 session_media->remote_ice = 0;
777 }
778}
779
780static void process_ice_auth_attrb(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
781 const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
782{
783 struct ast_rtp_engine_ice *ice;
784 const pjmedia_sdp_attr *ufrag_attr, *passwd_attr;
785 char ufrag_attr_value[256];
786 char passwd_attr_value[256];
787
788 /* If ICE support is not enabled or available exit early */
789 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
790 return;
791 }
792
793 ufrag_attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
794 if (!ufrag_attr) {
795 ufrag_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
796 }
797 if (ufrag_attr) {
798 ast_copy_pj_str(ufrag_attr_value, (pj_str_t*)&ufrag_attr->value, sizeof(ufrag_attr_value));
799 } else {
800 return;
801 }
802 passwd_attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL);
803 if (!passwd_attr) {
804 passwd_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
805 }
806 if (passwd_attr) {
807 ast_copy_pj_str(passwd_attr_value, (pj_str_t*)&passwd_attr->value, sizeof(passwd_attr_value));
808 } else {
809 return;
810 }
811
812 if (ufrag_attr && passwd_attr) {
813 ice->set_authentication(session_media->rtp, ufrag_attr_value, passwd_attr_value);
814 }
815}
816
817/*! \brief Function which processes ICE attributes in an audio stream */
818static void process_ice_attributes(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
819 const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
820{
821 struct ast_rtp_engine_ice *ice;
822 const pjmedia_sdp_attr *attr;
823 char attr_value[256];
824 unsigned int attr_i;
825
826 /* If ICE support is not enabled or available exit early */
827 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
828 return;
829 }
830
831 ast_debug_ice(2, "(%p) ICE process attributes\n", session_media->rtp);
832
833 attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
834 if (!attr) {
835 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
836 }
837 if (attr) {
838 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
839 ice->set_authentication(session_media->rtp, attr_value, NULL);
840 } else {
841 ast_debug_ice(2, "(%p) ICE no, or invalid ice-ufrag\n", session_media->rtp);
842 return;
843 }
844
845 attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL);
846 if (!attr) {
847 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
848 }
849 if (attr) {
850 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
851 ice->set_authentication(session_media->rtp, NULL, attr_value);
852 } else {
853 ast_debug_ice(2, "(%p) ICE no, or invalid ice-pwd\n", session_media->rtp);
854 return;
855 }
856
857 if (pjmedia_sdp_media_find_attr2(remote_stream, "ice-lite", NULL)) {
858 ice->ice_lite(session_media->rtp);
859 }
860
861 /* Find all of the candidates */
862 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
863 char foundation[33], transport[32], address[PJ_INET6_ADDRSTRLEN + 1], cand_type[6], relay_address[PJ_INET6_ADDRSTRLEN + 1] = "";
864 unsigned int port, relay_port = 0;
865 struct ast_rtp_engine_ice_candidate candidate = { 0, };
866
867 attr = remote_stream->attr[attr_i];
868
869 /* If this is not a candidate line skip it */
870 if (pj_strcmp2(&attr->name, "candidate")) {
871 continue;
872 }
873
874 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
875
876 if (sscanf(attr_value, "%32s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u", foundation, &candidate.id, transport,
877 (unsigned *)&candidate.priority, address, &port, cand_type, relay_address, &relay_port) < 7) {
878 /* Candidate did not parse properly */
879 continue;
880 }
881
882 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux && candidate.id > 1) {
883 /* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,
884 * then we should ignore RTCP candidates.
885 */
886 continue;
887 }
888
889 candidate.foundation = foundation;
890 candidate.transport = transport;
891
893 ast_sockaddr_set_port(&candidate.address, port);
894
895 if (!strcasecmp(cand_type, "host")) {
897 } else if (!strcasecmp(cand_type, "srflx")) {
899 } else if (!strcasecmp(cand_type, "relay")) {
901 } else {
902 continue;
903 }
904
907 }
908
909 if (relay_port) {
910 ast_sockaddr_set_port(&candidate.relay_address, relay_port);
911 }
912
913 ice->add_remote_candidate(session_media->rtp, &candidate);
914 }
915
916 ice->set_role(session_media->rtp, pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_TRUE ?
918 ice->start(session_media->rtp);
919}
920
921/*! \brief figure out if media stream has crypto lines for sdes */
922static int media_stream_has_crypto(const struct pjmedia_sdp_media *stream)
923{
924 int i;
925
926 for (i = 0; i < stream->attr_count; i++) {
927 pjmedia_sdp_attr *attr;
928
929 /* check the stream for the required crypto attribute */
930 attr = stream->attr[i];
931 if (pj_strcmp2(&attr->name, "crypto")) {
932 continue;
933 }
934
935 return 1;
936 }
937
938 return 0;
939}
940
941/*! \brief figure out media transport encryption type from the media transport string */
943 const struct pjmedia_sdp_media *stream, unsigned int *optimistic)
944{
945 RAII_VAR(char *, transport_str, ast_strndup(transport.ptr, transport.slen), ast_free);
946
947 *optimistic = 0;
948
949 if (!transport_str) {
951 }
952 if (strstr(transport_str, "UDP/TLS")) {
954 } else if (strstr(transport_str, "SAVP")) {
956 } else if (media_stream_has_crypto(stream)) {
957 *optimistic = 1;
959 } else {
961 }
962}
963
964/*!
965 * \brief Checks whether the encryption offered in SDP is compatible with the endpoint's configuration
966 * \internal
967 *
968 * \param endpoint Media encryption configured for the endpoint
969 * \param stream pjmedia_sdp_media stream description
970 *
971 * \retval AST_SIP_MEDIA_TRANSPORT_INVALID on encryption mismatch
972 * \retval The encryption requested in the SDP
973 */
975 struct ast_sip_endpoint *endpoint,
976 const struct pjmedia_sdp_media *stream)
977{
978 enum ast_sip_session_media_encryption incoming_encryption;
979 char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1];
980 unsigned int optimistic;
981
982 if ((transport_end == 'F' && !endpoint->media.rtp.use_avpf)
983 || (transport_end != 'F' && endpoint->media.rtp.use_avpf)) {
985 }
986
987 incoming_encryption = get_media_encryption_type(stream->desc.transport, stream, &optimistic);
988
989 if (incoming_encryption == endpoint->media.rtp.encryption) {
990 return incoming_encryption;
991 }
992
993 if (endpoint->media.rtp.force_avp ||
994 endpoint->media.rtp.encryption_optimistic) {
995 return incoming_encryption;
996 }
997
998 /* If an optimistic offer has been made but encryption is not enabled consider it as having
999 * no offer of crypto at all instead of invalid so the session proceeds.
1000 */
1001 if (optimistic) {
1003 }
1004
1006}
1007
1008static int setup_srtp(struct ast_sip_session_media *session_media)
1009{
1010 if (!session_media->srtp) {
1011 session_media->srtp = ast_sdp_srtp_alloc();
1012 if (!session_media->srtp) {
1013 return -1;
1014 }
1015 }
1016
1017 if (!session_media->srtp->crypto) {
1018 session_media->srtp->crypto = ast_sdp_crypto_alloc();
1019 if (!session_media->srtp->crypto) {
1020 return -1;
1021 }
1022 }
1023
1024 return 0;
1025}
1026
1028 struct ast_sip_session_media *session_media)
1029{
1030 struct ast_rtp_engine_dtls *dtls;
1031
1032 if (!session->endpoint->media.rtp.dtls_cfg.enabled || !session_media->rtp) {
1033 return -1;
1034 }
1035
1036 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1037 if (!dtls) {
1038 return -1;
1039 }
1040
1041 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);
1042 if (dtls->set_configuration(session_media->rtp, &session->endpoint->media.rtp.dtls_cfg)) {
1043 ast_log(LOG_ERROR, "Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
1044 session_media->rtp);
1045 return -1;
1046 }
1047
1048 if (setup_srtp(session_media)) {
1049 return -1;
1050 }
1051 return 0;
1052}
1053
1054static void apply_dtls_attrib(struct ast_sip_session_media *session_media,
1055 pjmedia_sdp_attr *attr)
1056{
1057 struct ast_rtp_engine_dtls *dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1058 pj_str_t *value;
1059
1060 if (!attr->value.ptr || !dtls) {
1061 return;
1062 }
1063
1064 value = pj_strtrim(&attr->value);
1065
1066 if (!pj_strcmp2(&attr->name, "setup")) {
1067 if (!pj_stricmp2(value, "active")) {
1068 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTIVE);
1069 } else if (!pj_stricmp2(value, "passive")) {
1070 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_PASSIVE);
1071 } else if (!pj_stricmp2(value, "actpass")) {
1072 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTPASS);
1073 } else if (!pj_stricmp2(value, "holdconn")) {
1074 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_HOLDCONN);
1075 } else {
1076 ast_log(LOG_WARNING, "Unsupported setup attribute value '%*s'\n", (int)value->slen, value->ptr);
1077 }
1078 } else if (!pj_strcmp2(&attr->name, "connection")) {
1079 if (!pj_stricmp2(value, "new")) {
1080 dtls->reset(session_media->rtp);
1081 } else if (!pj_stricmp2(value, "existing")) {
1082 /* Do nothing */
1083 } else {
1084 ast_log(LOG_WARNING, "Unsupported connection attribute value '%*s'\n", (int)value->slen, value->ptr);
1085 }
1086 } else if (!pj_strcmp2(&attr->name, "fingerprint")) {
1087 char hash_value[256], hash[32];
1088 char fingerprint_text[value->slen + 1];
1089 ast_copy_pj_str(fingerprint_text, value, sizeof(fingerprint_text));
1090 if (sscanf(fingerprint_text, "%31s %255s", hash, hash_value) == 2) {
1091 if (!strcasecmp(hash, "sha-1")) {
1092 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
1093 } else if (!strcasecmp(hash, "sha-256")) {
1094 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA256, hash_value);
1095 } else {
1096 ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
1097 hash);
1098 }
1099 }
1100 }
1101}
1102
1103static int parse_dtls_attrib(struct ast_sip_session_media *session_media,
1104 const struct pjmedia_sdp_session *sdp,
1105 const struct pjmedia_sdp_media *stream)
1106{
1107 int i;
1108
1109 for (i = 0; i < sdp->attr_count; i++) {
1110 apply_dtls_attrib(session_media, sdp->attr[i]);
1111 }
1112
1113 for (i = 0; i < stream->attr_count; i++) {
1114 apply_dtls_attrib(session_media, stream->attr[i]);
1115 }
1116
1118
1119 return 0;
1120}
1121
1122static int setup_sdes_srtp(struct ast_sip_session_media *session_media,
1123 const struct pjmedia_sdp_media *stream)
1124{
1125 int i;
1126
1127 for (i = 0; i < stream->attr_count; i++) {
1128 pjmedia_sdp_attr *attr;
1129 RAII_VAR(char *, crypto_str, NULL, ast_free);
1130
1131 /* check the stream for the required crypto attribute */
1132 attr = stream->attr[i];
1133 if (pj_strcmp2(&attr->name, "crypto")) {
1134 continue;
1135 }
1136
1137 crypto_str = ast_strndup(attr->value.ptr, attr->value.slen);
1138 if (!crypto_str) {
1139 return -1;
1140 }
1141
1142 if (setup_srtp(session_media)) {
1143 return -1;
1144 }
1145
1146 if (!ast_sdp_crypto_process(session_media->rtp, session_media->srtp, crypto_str)) {
1147 /* found a valid crypto attribute */
1148 return 0;
1149 }
1150
1151 ast_debug(1, "Ignoring crypto offer with unsupported parameters: %s\n", crypto_str);
1152 }
1153
1154 /* no usable crypto attributes found */
1155 return -1;
1156}
1157
1159 struct ast_sip_session_media *session_media,
1160 const struct pjmedia_sdp_session *sdp,
1161 const struct pjmedia_sdp_media *stream)
1162{
1163 switch (session_media->encryption) {
1165 if (setup_sdes_srtp(session_media, stream)) {
1166 return -1;
1167 }
1168 break;
1170 if (setup_dtls_srtp(session, session_media)) {
1171 return -1;
1172 }
1173 if (parse_dtls_attrib(session_media, sdp, stream)) {
1174 return -1;
1175 }
1176 break;
1179 break;
1180 }
1181
1182 return 0;
1183}
1184
1185static void set_ice_components(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
1186{
1187 struct ast_rtp_engine_ice *ice;
1188
1189 ast_assert(session_media->rtp != NULL);
1190
1191 ice = ast_rtp_instance_get_ice(session_media->rtp);
1192 if (!session->endpoint->media.rtp.ice_support || !ice) {
1193 return;
1194 }
1195
1196 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
1197 /* We both support RTCP mux. Only one ICE component necessary */
1198 ice->change_components(session_media->rtp, 1);
1199 } else {
1200 /* They either don't support RTCP mux or we don't know if they do yet. */
1201 ice->change_components(session_media->rtp, 2);
1202 }
1203}
1204
1205/*! \brief Function which adds ssrc attributes to a media stream */
1206static 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)
1207{
1208 pj_str_t stmp;
1209 pjmedia_sdp_attr *attr;
1210 char tmp[128];
1211
1212 if (!session->endpoint->media.bundle || session_media->bundle_group == -1) {
1213 return;
1214 }
1215
1216 snprintf(tmp, sizeof(tmp), "%u cname:%s", ast_rtp_instance_get_ssrc(session_media->rtp), ast_rtp_instance_get_cname(session_media->rtp));
1217 attr = pjmedia_sdp_attr_create(pool, "ssrc", pj_cstr(&stmp, tmp));
1218 media->attr[media->attr_count++] = attr;
1219}
1220
1221/*! \brief Function which processes ssrc attributes in a stream */
1223 const struct pjmedia_sdp_media *remote_stream)
1224{
1225 int index;
1226
1227 if (!session->endpoint->media.bundle) {
1228 return;
1229 }
1230
1231 for (index = 0; index < remote_stream->attr_count; ++index) {
1232 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1233 char attr_value[pj_strlen(&attr->value) + 1];
1234 char *ssrc_attribute_name, *ssrc_attribute_value = NULL;
1235 unsigned int ssrc;
1236
1237 /* We only care about ssrc attributes */
1238 if (pj_strcmp2(&attr->name, "ssrc")) {
1239 continue;
1240 }
1241
1242 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1243
1244 if ((ssrc_attribute_name = strchr(attr_value, ' '))) {
1245 /* This has an actual attribute */
1246 *ssrc_attribute_name++ = '\0';
1247 ssrc_attribute_value = strchr(ssrc_attribute_name, ':');
1248 if (ssrc_attribute_value) {
1249 /* Values are actually optional according to the spec */
1250 *ssrc_attribute_value++ = '\0';
1251 }
1252 }
1253
1254 if (sscanf(attr_value, "%30u", &ssrc) < 1) {
1255 continue;
1256 }
1257
1258 /* If we are currently negotiating as a result of the remote side renegotiating then
1259 * determine if the source for this stream has changed.
1260 */
1261 if (pjmedia_sdp_neg_get_state(session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
1262 session->active_media_state) {
1263 struct ast_rtp_instance_stats stats = { 0, };
1264
1266 stats.remote_ssrc != ssrc) {
1267 session_media->changed = 1;
1268 }
1269 }
1270
1271 ast_rtp_instance_set_remote_ssrc(session_media->rtp, ssrc);
1272 break;
1273 }
1274}
1275
1277 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media,
1278 struct ast_stream *stream)
1279{
1280 pj_str_t stmp;
1281 pjmedia_sdp_attr *attr;
1282 char msid[(AST_UUID_STR_LEN * 2) + 2];
1283 const char *stream_label = ast_stream_get_metadata(stream, "SDP:LABEL");
1284
1285 if (!session->endpoint->media.webrtc) {
1286 return;
1287 }
1288
1289 if (ast_strlen_zero(session_media->mslabel)) {
1290 /* If this stream is grouped with another then use its media stream label if possible */
1291 if (ast_stream_get_group(stream) != -1) {
1292 struct ast_sip_session_media *group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, ast_stream_get_group(stream));
1293
1294 ast_copy_string(session_media->mslabel, group_session_media->mslabel, sizeof(session_media->mslabel));
1295 }
1296
1297 if (ast_strlen_zero(session_media->mslabel)) {
1298 ast_uuid_generate_str(session_media->mslabel, sizeof(session_media->mslabel));
1299 }
1300 }
1301
1302 if (ast_strlen_zero(session_media->label)) {
1303 ast_uuid_generate_str(session_media->label, sizeof(session_media->label));
1304 /* add for stream identification to replace stream_name */
1305 ast_stream_set_metadata(stream, "MSID:LABEL", session_media->label);
1306 }
1307
1308 snprintf(msid, sizeof(msid), "%s %s", session_media->mslabel, session_media->label);
1309 ast_debug(3, "Stream msid: %p %s %s\n", stream,
1311 attr = pjmedia_sdp_attr_create(pool, "msid", pj_cstr(&stmp, msid));
1312 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1313
1314 /* 'label' must come after 'msid' */
1315 if (!ast_strlen_zero(stream_label)) {
1316 ast_debug(3, "Stream Label: %p %s %s\n", stream,
1317 ast_codec_media_type2str(ast_stream_get_type(stream)), stream_label);
1318 attr = pjmedia_sdp_attr_create(pool, "label", pj_cstr(&stmp, stream_label));
1319 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1320 }
1321}
1322
1324 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
1325{
1326 pj_str_t stmp;
1327 pjmedia_sdp_attr *attr;
1328
1329 if (!session->endpoint->media.webrtc) {
1330 return;
1331 }
1332
1333 /* transport-cc is supposed to be for the entire transport, and any media sources so
1334 * while the header does not appear in audio streams and isn't negotiated there, we still
1335 * place this attribute in as Chrome does.
1336 */
1337 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* transport-cc"));
1338 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1339
1340 if (session_media->type != AST_MEDIA_TYPE_VIDEO) {
1341 return;
1342 }
1343
1344 /*
1345 * For now just automatically add it the stream even though it hasn't
1346 * necessarily been negotiated.
1347 */
1348 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* ccm fir"));
1349 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1350
1351 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* goog-remb"));
1352 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1353
1354 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* nack"));
1355 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1356}
1357
1359 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
1360{
1361 int idx;
1362 char extmap_value[256];
1363
1364 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1365 return;
1366 }
1367
1368 /* RTP extension local unique identifiers start at '1' */
1369 for (idx = 1; idx <= ast_rtp_instance_extmap_count(session_media->rtp); ++idx) {
1371 const char *direction_str = "";
1372 pj_str_t stmp;
1373 pjmedia_sdp_attr *attr;
1374
1375 /* If this is an unsupported RTP extension we can't place it into the SDP */
1377 continue;
1378 }
1379
1380 switch (ast_rtp_instance_extmap_get_direction(session_media->rtp, idx)) {
1382 /* Lack of a direction indicates sendrecv, so we leave it out */
1383 direction_str = "";
1384 break;
1386 direction_str = "/sendonly";
1387 break;
1389 direction_str = "/recvonly";
1390 break;
1392 /* It is impossible for a "none" direction extension to be negotiated but just in case
1393 * we treat it as inactive.
1394 */
1396 direction_str = "/inactive";
1397 break;
1398 }
1399
1400 snprintf(extmap_value, sizeof(extmap_value), "%d%s %s", idx, direction_str,
1401 ast_rtp_instance_extmap_get_uri(session_media->rtp, idx));
1402 attr = pjmedia_sdp_attr_create(pool, "extmap", pj_cstr(&stmp, extmap_value));
1403 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1404 }
1405}
1406
1407/*! \brief Function which processes extmap attributes in a stream */
1409 const struct pjmedia_sdp_media *remote_stream)
1410{
1411 int index;
1412
1413 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1414 return;
1415 }
1416
1417 ast_rtp_instance_extmap_clear(session_media->rtp);
1418
1419 for (index = 0; index < remote_stream->attr_count; ++index) {
1420 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1421 char attr_value[pj_strlen(&attr->value) + 1];
1422 char *uri;
1423 int id;
1424 char direction_str[10] = "";
1425 char *attributes;
1427
1428 /* We only care about extmap attributes */
1429 if (pj_strcmp2(&attr->name, "extmap")) {
1430 continue;
1431 }
1432
1433 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1434
1435 /* Split the combined unique identifier and direction away from the URI and attributes for easier parsing */
1436 uri = strchr(attr_value, ' ');
1437 if (ast_strlen_zero(uri)) {
1438 continue;
1439 }
1440 *uri++ = '\0';
1441
1442 if ((sscanf(attr_value, "%30d%9s", &id, direction_str) < 1) || (id < 1)) {
1443 /* We require at a minimum the unique identifier */
1444 continue;
1445 }
1446
1447 /* Convert from the string to the internal representation */
1448 if (!strcasecmp(direction_str, "/sendonly")) {
1450 } else if (!strcasecmp(direction_str, "/recvonly")) {
1452 } else if (!strcasecmp(direction_str, "/inactive")) {
1454 }
1455
1456 attributes = strchr(uri, ' ');
1457 if (!ast_strlen_zero(attributes)) {
1458 *attributes++ = '\0';
1459 }
1460
1461 ast_rtp_instance_extmap_negotiate(session_media->rtp, id, direction, uri, attributes);
1462 }
1463}
1464
1466 const struct ast_sip_session *session,
1467 const pjmedia_sdp_media *media,
1468 const struct ast_stream *stream,
1469 const struct ast_sockaddr *addrs)
1470{
1472 (session_media->type == AST_MEDIA_TYPE_AUDIO)) {
1473 if (((addrs != NULL) && ast_sockaddr_isnull(addrs)) ||
1474 ((addrs != NULL) && ast_sockaddr_is_any(addrs)) ||
1475 pjmedia_sdp_media_find_attr2(media, "sendonly", NULL) ||
1476 pjmedia_sdp_media_find_attr2(media, "inactive", NULL)) {
1477 if (!session_media->remotely_held) {
1478 session_media->remotely_held = 1;
1479 session_media->remotely_held_changed = 1;
1480 }
1481 } else if (session_media->remotely_held) {
1482 session_media->remotely_held = 0;
1483 session_media->remotely_held_changed = 1;
1484 }
1485 }
1486}
1487
1488/*! \brief Function which negotiates an incoming media stream */
1490 struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp,
1491 int index, struct ast_stream *asterisk_stream)
1492{
1493 char host[NI_MAXHOST];
1494 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
1495 pjmedia_sdp_media *stream = sdp->media[index];
1496 struct ast_sip_session_media *session_media_transport;
1497 enum ast_media_type media_type = session_media->type;
1499 struct ast_format_cap *joint;
1500 int res;
1502
1503 /* If no type formats have been configured reject this stream */
1504 if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
1505 ast_debug(3, "Endpoint has no codecs for media type '%s', declining stream\n",
1506 ast_codec_media_type2str(session_media->type));
1507 SCOPE_EXIT_RTN_VALUE(0, "Endpoint has no codecs\n");
1508 }
1509
1510 /* Ensure incoming transport is compatible with the endpoint's configuration */
1511 if (!session->endpoint->media.rtp.use_received_transport) {
1512 encryption = check_endpoint_media_transport(session->endpoint, stream);
1513
1514 if (encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) {
1515 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
1516 }
1517 }
1518
1519 ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
1520
1521 /* Ensure that the address provided is valid */
1522 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1523 /* The provided host was actually invalid so we error out this negotiation */
1524 SCOPE_EXIT_RTN_VALUE(-1, "Invalid host\n");
1525 }
1526
1527 /* Using the connection information create an appropriate RTP instance */
1528 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
1529 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
1530 }
1531
1532 process_ssrc_attributes(session, session_media, stream);
1533 process_extmap_attributes(session, session_media, stream);
1534 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1535
1536 if (session_media_transport == session_media || !session_media->bundled) {
1537 /* If this media session is carrying actual traffic then set up those aspects */
1538 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(stream, "rtcp-mux", NULL) != NULL);
1539 set_ice_components(session, session_media);
1540
1541 enable_rtcp(session, session_media, stream);
1542
1543 res = setup_media_encryption(session, session_media, sdp, stream);
1544 if (res) {
1545 if (!session->endpoint->media.rtp.encryption_optimistic ||
1546 !pj_strncmp2(&stream->desc.transport, "RTP/SAVP", 8)) {
1547 /* If optimistic encryption is disabled and crypto should have been enabled
1548 * but was not this session must fail. This must also fail if crypto was
1549 * required in the offer but could not be set up.
1550 */
1551 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
1552 }
1553 /* There is no encryption, sad. */
1554 session_media->encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
1555 }
1556
1557 /* If we've been explicitly configured to use the received transport OR if
1558 * encryption is on and crypto is present use the received transport.
1559 * This is done in case of optimistic because it may come in as RTP/AVP or RTP/SAVP depending
1560 * on the configuration of the remote endpoint (optimistic themselves or mandatory).
1561 */
1562 if ((session->endpoint->media.rtp.use_received_transport) ||
1563 ((encryption == AST_SIP_MEDIA_ENCRYPT_SDES) && !res)) {
1564 pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport);
1565 }
1566 } else {
1567 /* This is bundled with another session, so mark it as such */
1568 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
1569
1570 enable_rtcp(session, session_media, stream);
1571 }
1572
1573 /* If ICE support is enabled find all the needed attributes */
1574 check_ice_support(session, session_media, stream);
1575
1576 /* If ICE support is enabled then check remote ICE started? */
1577 if (session_media->remote_ice) {
1578 process_ice_auth_attrb(session, session_media, sdp, stream);
1579 }
1580
1581 /* Check if incoming SDP is changing the remotely held state */
1582 set_session_media_remotely_held(session_media, session, stream, asterisk_stream, addrs);
1583
1584 joint = set_incoming_call_offer_cap(session, session_media, stream);
1585 res = apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
1586 ao2_cleanup(joint);
1587 if (res != 0) {
1588 SCOPE_EXIT_RTN_VALUE(0, "Something failed\n");
1589 }
1590
1592}
1593
1595 struct ast_sip_session_media *session_media,
1596 pj_pool_t *pool, pjmedia_sdp_media *media)
1597{
1598 pj_str_t stmp;
1599 pjmedia_sdp_attr *attr;
1600 enum ast_rtp_dtls_hash hash;
1601 const char *crypto_attribute;
1602 struct ast_rtp_engine_dtls *dtls;
1603 struct ast_sdp_srtp *tmp;
1604 static const pj_str_t STR_NEW = { "new", 3 };
1605 static const pj_str_t STR_EXISTING = { "existing", 8 };
1606 static const pj_str_t STR_ACTIVE = { "active", 6 };
1607 static const pj_str_t STR_PASSIVE = { "passive", 7 };
1608 static const pj_str_t STR_ACTPASS = { "actpass", 7 };
1609 static const pj_str_t STR_HOLDCONN = { "holdconn", 8 };
1610 static const pj_str_t STR_MEDSECREQ = { "requested", 9 };
1611 enum ast_rtp_dtls_setup setup;
1612
1613 switch (session_media->encryption) {
1616 break;
1618 if (!session_media->srtp) {
1619 session_media->srtp = ast_sdp_srtp_alloc();
1620 if (!session_media->srtp) {
1621 return -1;
1622 }
1623 }
1624
1625 tmp = session_media->srtp;
1626
1627 do {
1628 crypto_attribute = ast_sdp_srtp_get_attrib(tmp,
1629 0 /* DTLS running? No */,
1630 session->endpoint->media.rtp.srtp_tag_32 /* 32 byte tag length? */);
1631 if (!crypto_attribute) {
1632 /* No crypto attribute to add, bad news */
1633 return -1;
1634 }
1635
1636 attr = pjmedia_sdp_attr_create(pool, "crypto",
1637 pj_cstr(&stmp, crypto_attribute));
1638 media->attr[media->attr_count++] = attr;
1639 } while ((tmp = AST_LIST_NEXT(tmp, sdp_srtp_list)));
1640
1641 if (session->endpoint->security_negotiation == AST_SIP_SECURITY_NEG_MEDIASEC) {
1642 attr = pjmedia_sdp_attr_create(pool, "3ge2ae", &STR_MEDSECREQ);
1643 media->attr[media->attr_count++] = attr;
1644 }
1645
1646 break;
1648 if (setup_dtls_srtp(session, session_media)) {
1649 return -1;
1650 }
1651
1652 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1653 if (!dtls) {
1654 return -1;
1655 }
1656
1657 switch (dtls->get_connection(session_media->rtp)) {
1659 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_NEW);
1660 media->attr[media->attr_count++] = attr;
1661 break;
1663 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_EXISTING);
1664 media->attr[media->attr_count++] = attr;
1665 break;
1666 default:
1667 break;
1668 }
1669
1670 /* If this is an answer we need to use our current state, if it's an offer we need to use
1671 * the configured value.
1672 */
1673 if (session->inv_session->neg
1674 && pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
1675 setup = dtls->get_setup(session_media->rtp);
1676 } else {
1677 setup = session->endpoint->media.rtp.dtls_cfg.default_setup;
1678 }
1679
1680 switch (setup) {
1682 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTIVE);
1683 media->attr[media->attr_count++] = attr;
1684 break;
1686 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_PASSIVE);
1687 media->attr[media->attr_count++] = attr;
1688 break;
1690 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTPASS);
1691 media->attr[media->attr_count++] = attr;
1692 break;
1694 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_HOLDCONN);
1695 break;
1696 default:
1697 break;
1698 }
1699
1700 hash = dtls->get_fingerprint_hash(session_media->rtp);
1701 crypto_attribute = dtls->get_fingerprint(session_media->rtp);
1702 if (crypto_attribute && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
1703 RAII_VAR(struct ast_str *, fingerprint, ast_str_create(64), ast_free);
1704 if (!fingerprint) {
1705 return -1;
1706 }
1707
1708 if (hash == AST_RTP_DTLS_HASH_SHA1) {
1709 ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
1710 } else {
1711 ast_str_set(&fingerprint, 0, "SHA-256 %s", crypto_attribute);
1712 }
1713
1714 attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
1715 media->attr[media->attr_count++] = attr;
1716 }
1717 break;
1718 }
1719
1720 return 0;
1721}
1722
1723/*! \brief Function which creates an outgoing stream */
1725 struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
1726{
1727 pj_pool_t *pool = session->inv_session->pool_prov;
1728 static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };
1729 static const pj_str_t STR_IN = { "IN", 2 };
1730 static const pj_str_t STR_IP4 = { "IP4", 3};
1731 static const pj_str_t STR_IP6 = { "IP6", 3};
1732 static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
1733 static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
1734 static const pj_str_t STR_INACTIVE = { "inactive", 8 };
1735 static const pj_str_t STR_RECVONLY = { "recvonly", 8 };
1736 pjmedia_sdp_media *media;
1737 const char *hostip = NULL;
1738 struct ast_sockaddr addr;
1739 char tmp[512];
1740 pj_str_t stmp;
1741 pjmedia_sdp_attr *attr;
1742 int index = 0;
1743 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;
1744 int min_packet_size = 0, max_packet_size = 0;
1745 int rtp_code;
1746 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1747 enum ast_media_type media_type = session_media->type;
1748 struct ast_sip_session_media *session_media_transport;
1749 pj_sockaddr ip;
1750 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
1751 ast_format_cap_count(session->direct_media_cap);
1752 SCOPE_ENTER(1, "%s Type: %s %s\n", ast_sip_session_get_name(session),
1753 ast_codec_media_type2str(media_type), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
1754
1755 media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media));
1756 if (!media) {
1757 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
1758 }
1759 pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
1760
1761 /* If this is a removed (or declined) stream OR if no formats exist then construct a minimal stream in SDP */
1764 media->desc.port = 0;
1765 media->desc.port_count = 1;
1766
1767 if (remote && remote->media[ast_stream_get_position(stream)]) {
1768 pjmedia_sdp_media *remote_media = remote->media[ast_stream_get_position(stream)];
1769 int index;
1770
1771 media->desc.transport = remote_media->desc.transport;
1772
1773 /* Preserve existing behavior by copying the formats provided from the offer */
1774 for (index = 0; index < remote_media->desc.fmt_count; ++index) {
1775 media->desc.fmt[index] = remote_media->desc.fmt[index];
1776 }
1777 media->desc.fmt_count = remote_media->desc.fmt_count;
1778 } else {
1779 /* This is actually an offer so put a dummy payload in that is ignored and sane transport */
1780 media->desc.transport = STR_RTP_AVP;
1781 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], "32");
1782 }
1783
1784 sdp->media[sdp->media_count++] = media;
1786
1787 SCOPE_EXIT_RTN_VALUE(1, "Stream removed or no formats\n");
1788 }
1789
1790 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
1791 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
1792 }
1793
1794 /* If this stream has not been bundled already it is new and we need to ensure there is no SSRC conflict */
1795 if (session_media->bundle_group != -1 && !session_media->bundled) {
1796 for (index = 0; index < sdp->media_count; ++index) {
1797 struct ast_sip_session_media *other_session_media;
1798
1799 other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);
1800 if (!other_session_media->rtp || other_session_media->bundle_group != session_media->bundle_group) {
1801 continue;
1802 }
1803
1804 if (ast_rtp_instance_get_ssrc(session_media->rtp) == ast_rtp_instance_get_ssrc(other_session_media->rtp)) {
1805 ast_rtp_instance_change_source(session_media->rtp);
1806 /* Start the conflict check over again */
1807 index = -1;
1808 continue;
1809 }
1810 }
1811 }
1812
1813 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1814
1815 if (session_media_transport == session_media || !session_media->bundled) {
1816 set_ice_components(session, session_media);
1817 enable_rtcp(session, session_media, NULL);
1818
1819 /* Crypto has to be added before setting the media transport so that SRTP is properly
1820 * set up according to the configuration. This ends up changing the media transport.
1821 */
1822 if (add_crypto_to_stream(session, session_media, pool, media)) {
1823 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
1824 }
1825
1826 if (pj_strlen(&session_media->transport)) {
1827 /* If a transport has already been specified use it */
1828 media->desc.transport = session_media->transport;
1829 } else {
1830 media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
1831 /* Optimistic encryption places crypto in the normal RTP/AVP profile */
1832 !session->endpoint->media.rtp.encryption_optimistic &&
1833 (session_media->encryption == AST_SIP_MEDIA_ENCRYPT_SDES),
1834 session_media->rtp, session->endpoint->media.rtp.use_avpf,
1835 session->endpoint->media.rtp.force_avp));
1836 }
1837
1838 media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn));
1839 if (!media->conn) {
1840 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
1841 }
1842
1843 /* Add connection level details */
1844 if (direct_media_enabled) {
1846 } else if (ast_strlen_zero(session->endpoint->media.address)) {
1847 hostip = ast_sip_get_host_ip_string(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET());
1848 } else {
1849 hostip = session->endpoint->media.address;
1850 }
1851
1852 if (ast_strlen_zero(hostip)) {
1853 ast_log(LOG_ERROR, "No local host IP available for stream %s\n",
1854 ast_codec_media_type2str(session_media->type));
1855 SCOPE_EXIT_RTN_VALUE(-1, "No local host ip\n");
1856 }
1857
1858 media->conn->net_type = STR_IN;
1859 /* Assume that the connection will use IPv4 until proven otherwise */
1860 media->conn->addr_type = STR_IP4;
1861 pj_strdup2(pool, &media->conn->addr, hostip);
1862
1863 if ((pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &media->conn->addr, &ip) == PJ_SUCCESS) &&
1864 (ip.addr.sa_family == pj_AF_INET6())) {
1865 media->conn->addr_type = STR_IP6;
1866 }
1867
1868 /* Add ICE attributes and candidates */
1869 add_ice_to_stream(session, session_media, pool, media, 1);
1870
1871 ast_rtp_instance_get_local_address(session_media->rtp, &addr);
1872 media->desc.port = direct_media_enabled ? ast_sockaddr_port(&session_media->direct_media_addr) : (pj_uint16_t) ast_sockaddr_port(&addr);
1873 media->desc.port_count = 1;
1874 } else {
1875 pjmedia_sdp_media *bundle_group_stream = sdp->media[session_media_transport->stream_num];
1876
1877 /* As this is in a bundle group it shares the same details as the group instance */
1878 media->desc.transport = bundle_group_stream->desc.transport;
1879 media->conn = bundle_group_stream->conn;
1880 media->desc.port = bundle_group_stream->desc.port;
1881
1882 if (add_crypto_to_stream(session, session_media_transport, pool, media)) {
1883 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
1884 }
1885
1886 add_ice_to_stream(session, session_media_transport, pool, media, 0);
1887
1888 enable_rtcp(session, session_media, NULL);
1889 }
1890
1892 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
1893 ast_codec_media_type2str(session_media->type));
1894 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create caps\n");
1895 }
1896
1897 if (direct_media_enabled) {
1898 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
1899 } else {
1900 ast_format_cap_append_from_cap(caps, ast_stream_get_formats(stream), media_type);
1901 }
1902
1903 for (index = 0; index < ast_format_cap_count(caps); ++index) {
1904 struct ast_format *format = ast_format_cap_get_format(caps, index);
1905
1906 if (ast_format_get_type(format) != media_type) {
1907 ao2_ref(format, -1);
1908 continue;
1909 }
1910
1911 /* It is possible for some formats not to have SDP information available for them
1912 * and if this is the case, skip over them so the SDP can still be created.
1913 */
1914 if (!ast_rtp_lookup_sample_rate2(1, format, 0)) {
1915 ast_log(LOG_WARNING, "Format '%s' can not be added to SDP, consider disallowing it on endpoint '%s'\n",
1917 ao2_ref(format, -1);
1918 continue;
1919 }
1920
1921 /* If this stream is not a transport we need to use the transport codecs structure for payload management to prevent
1922 * conflicts.
1923 */
1924 if (session_media_transport != session_media) {
1925 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media_transport->rtp), 1, format, 0)) == -1) {
1926 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
1927 ao2_ref(format, -1);
1928 continue;
1929 }
1930 /* Our instance has to match the payload number though */
1931 ast_rtp_codecs_payload_set_rx(ast_rtp_instance_get_codecs(session_media->rtp), rtp_code, format);
1932 } else {
1933 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0)) == -1) {
1934 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
1935 ao2_ref(format, -1);
1936 continue;
1937 }
1938 }
1939
1940 if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 1, format, 0))) {
1941 media->attr[media->attr_count++] = attr;
1942 }
1943
1944 if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
1945 media->attr[media->attr_count++] = attr;
1946 }
1947
1948 if (ast_format_get_maximum_ms(format) &&
1949 ((ast_format_get_maximum_ms(format) < max_packet_size) || !max_packet_size)) {
1950 max_packet_size = ast_format_get_maximum_ms(format);
1951 }
1952 ao2_ref(format, -1);
1953
1954 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
1955 break;
1956 }
1957 }
1958
1959 /* Add non-codec formats */
1961 && media->desc.fmt_count < PJMEDIA_MAX_SDP_FMT) {
1962 for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) {
1963 if (!(noncodec & index)) {
1964 continue;
1965 }
1966 rtp_code = ast_rtp_codecs_payload_code(
1967 ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index);
1968 if (rtp_code == -1) {
1969 continue;
1970 }
1971
1972 if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
1973 media->attr[media->attr_count++] = attr;
1974 }
1975
1976 if (index == AST_RTP_DTMF) {
1977 snprintf(tmp, sizeof(tmp), "%d 0-16", rtp_code);
1978 attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
1979 media->attr[media->attr_count++] = attr;
1980 }
1981
1982 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
1983 break;
1984 }
1985 }
1986 }
1987
1988
1989 /* If no formats were actually added to the media stream don't add it to the SDP */
1990 if (!media->desc.fmt_count) {
1991 SCOPE_EXIT_RTN_VALUE(1, "No formats added to stream\n");
1992 }
1993
1994 /* If ptime is set add it as an attribute */
1995 min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(session_media->rtp));
1996 if (!min_packet_size) {
1997 min_packet_size = ast_format_cap_get_framing(caps);
1998 }
1999 if (min_packet_size) {
2000 snprintf(tmp, sizeof(tmp), "%d", min_packet_size);
2001 attr = pjmedia_sdp_attr_create(pool, "ptime", pj_cstr(&stmp, tmp));
2002 media->attr[media->attr_count++] = attr;
2003 }
2004
2005 if (max_packet_size) {
2006 snprintf(tmp, sizeof(tmp), "%d", max_packet_size);
2007 attr = pjmedia_sdp_attr_create(pool, "maxptime", pj_cstr(&stmp, tmp));
2008 media->attr[media->attr_count++] = attr;
2009 }
2010
2011 attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
2012 if (session_media->locally_held) {
2013 if (session_media->remotely_held) {
2014 attr->name = STR_INACTIVE; /* To place on hold a recvonly stream, send inactive */
2015 } else {
2016 attr->name = STR_SENDONLY; /* Send sendonly to initate a local hold */
2017 }
2018 } else {
2019 if (session_media->remotely_held) {
2020 attr->name = STR_RECVONLY; /* Remote has sent sendonly, reply recvonly */
2021 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
2022 attr->name = STR_SENDONLY; /* Stream has requested sendonly */
2023 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_RECVONLY) {
2024 attr->name = STR_RECVONLY; /* Stream has requested recvonly */
2025 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_INACTIVE) {
2026 attr->name = STR_INACTIVE; /* Stream has requested inactive */
2027 } else {
2028 attr->name = STR_SENDRECV; /* No hold in either direction */
2029 }
2030 }
2031 media->attr[media->attr_count++] = attr;
2032
2033 /* If we've got rtcp-mux enabled, add it unless we received an offer without it */
2034 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
2035 attr = pjmedia_sdp_attr_create(pool, "rtcp-mux", NULL);
2036 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
2037 }
2038
2039 add_ssrc_to_stream(session, session_media, pool, media);
2040 add_msid_to_stream(session, session_media, pool, media, stream);
2041 add_rtcp_fb_to_stream(session, session_media, pool, media);
2042 add_extmap_to_stream(session, session_media, pool, media);
2043
2044 /* Add the media stream to the SDP */
2045 sdp->media[sdp->media_count++] = media;
2046
2047 SCOPE_EXIT_RTN_VALUE(1, "RC: 1\n");
2048}
2049
2051{
2052 struct ast_frame *f;
2053
2054 if (!session_media->rtp) {
2055 return &ast_null_frame;
2056 }
2057
2058 f = ast_rtp_instance_read(session_media->rtp, 0);
2059 if (!f) {
2060 return NULL;
2061 }
2062
2063 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2064
2065 return f;
2066}
2067
2069{
2070 struct ast_frame *f;
2071
2072 if (!session_media->rtp) {
2073 return &ast_null_frame;
2074 }
2075
2076 f = ast_rtp_instance_read(session_media->rtp, 1);
2077 if (!f) {
2078 return NULL;
2079 }
2080
2081 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2082
2083 return f;
2084}
2085
2086static int media_session_rtp_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
2087{
2088 if (!session_media->rtp) {
2089 return 0;
2090 }
2091
2092 return ast_rtp_instance_write(session_media->rtp, frame);
2093}
2094
2096 struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local,
2097 const struct pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
2098{
2099 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
2100 struct pjmedia_sdp_media *remote_stream = remote->media[index];
2101 enum ast_media_type media_type = session_media->type;
2102 char host[NI_MAXHOST];
2103 int res;
2104 struct ast_sip_session_media *session_media_transport;
2105 SCOPE_ENTER(1, "%s Stream: %s\n", ast_sip_session_get_name(session),
2106 ast_str_tmp(128, ast_stream_to_str(asterisk_stream, &STR_TMP)));
2107
2108 if (!session->channel) {
2109 SCOPE_EXIT_RTN_VALUE(1, "No channel\n");
2110 }
2111
2112 /* Ensure incoming transport is compatible with the endpoint's configuration */
2113 if (!session->endpoint->media.rtp.use_received_transport &&
2115 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
2116 }
2117
2118 /* Create an RTP instance if need be */
2119 if (!session_media->rtp && create_rtp(session, session_media, local)) {
2120 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
2121 }
2122
2123 process_ssrc_attributes(session, session_media, remote_stream);
2124 process_extmap_attributes(session, session_media, remote_stream);
2125
2126 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
2127
2128 if (session_media_transport == session_media || !session_media->bundled) {
2129 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(remote_stream, "rtcp-mux", NULL) != NULL);
2130 set_ice_components(session, session_media);
2131
2132 enable_rtcp(session, session_media, remote_stream);
2133
2134 res = setup_media_encryption(session, session_media, remote, remote_stream);
2135 if (!session->endpoint->media.rtp.encryption_optimistic && res) {
2136 /* If optimistic encryption is disabled and crypto should have been enabled but was not
2137 * this session must fail.
2138 */
2139 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
2140 }
2141
2142 if (!remote_stream->conn && !remote->conn) {
2143 SCOPE_EXIT_RTN_VALUE(1, "No connection info\n");
2144 }
2145
2146 ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
2147
2148 /* Ensure that the address provided is valid */
2149 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
2150 /* The provided host was actually invalid so we error out this negotiation */
2151 SCOPE_EXIT_RTN_VALUE(-1, "Host invalid\n");
2152 }
2153
2154 /* Apply connection information to the RTP instance */
2155 ast_sockaddr_set_port(addrs, remote_stream->desc.port);
2156 ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
2157
2161 if (!session->endpoint->media.rtcp_mux || !session_media->remote_rtcp_mux) {
2164 }
2165
2166 /* If ICE support is enabled find all the needed attributes */
2167 process_ice_attributes(session, session_media, remote, remote_stream);
2168 } else {
2169 /* This is bundled with another session, so mark it as such */
2170 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
2172 enable_rtcp(session, session_media, remote_stream);
2173 }
2174
2175 if (set_caps(session, session_media, session_media_transport, remote_stream, 0, asterisk_stream)) {
2176 SCOPE_EXIT_RTN_VALUE(-1, "set_caps failed\n");
2177 }
2178
2179 /* Set the channel uniqueid on the RTP instance now that it is becoming active */
2180 ast_channel_lock(session->channel);
2182 ast_channel_unlock(session->channel);
2183
2184 /* Ensure the RTP instance is active */
2185 ast_rtp_instance_set_stream_num(session_media->rtp, ast_stream_get_position(asterisk_stream));
2186 ast_rtp_instance_activate(session_media->rtp);
2187
2188 /* audio stream handles music on hold */
2189 if (media_type != AST_MEDIA_TYPE_AUDIO && media_type != AST_MEDIA_TYPE_VIDEO) {
2190 if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2191 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2193 }
2194 SCOPE_EXIT_RTN_VALUE(1, "moh\n");
2195 }
2196
2197 set_session_media_remotely_held(session_media, session, remote_stream, asterisk_stream, addrs);
2198
2199 if (session_media->remotely_held_changed) {
2200 if (session_media->remotely_held) {
2201 /* The remote side has put us on hold */
2202 ast_queue_hold(session->channel, session->endpoint->mohsuggest);
2203 ast_rtp_instance_stop(session_media->rtp);
2205 session_media->remotely_held_changed = 0;
2206 } else {
2207 /* The remote side has taken us off hold */
2208 ast_queue_unhold(session->channel);
2210 session_media->remotely_held_changed = 0;
2211 }
2212 } else if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2213 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2215 }
2216
2217 /* This purposely resets the encryption to the configured in case it gets added later */
2218 session_media->encryption = session->endpoint->media.rtp.encryption;
2219
2220 if (session->endpoint->media.rtp.keepalive > 0 &&
2221 (session_media->type == AST_MEDIA_TYPE_AUDIO ||
2222 session_media->type == AST_MEDIA_TYPE_VIDEO)) {
2223 ast_rtp_instance_set_keepalive(session_media->rtp, session->endpoint->media.rtp.keepalive);
2224 /* Schedule the initial keepalive early in case this is being used to punch holes through
2225 * a NAT. This way there won't be an awkward delay before media starts flowing in some
2226 * scenarios.
2227 */
2228 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2230 session_media, 1);
2231 }
2232
2233 /* As the channel lock is not held during this process the scheduled item won't block if
2234 * it is hanging up the channel at the same point we are applying this negotiated SDP.
2235 */
2236 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2237
2238 /* Due to the fact that we only ever have one scheduled timeout item for when we are both
2239 * off hold and on hold we don't need to store the two timeouts differently on the RTP
2240 * instance itself.
2241 */
2242 ast_rtp_instance_set_timeout(session_media->rtp, 0);
2243 if (session->endpoint->media.rtp.timeout && !session_media->remotely_held && !session_media->locally_held) {
2244 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout);
2245 } else if (session->endpoint->media.rtp.timeout_hold && (session_media->remotely_held || session_media->locally_held)) {
2246 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout_hold);
2247 }
2248
2249 if (ast_rtp_instance_get_timeout(session_media->rtp)) {
2251 session_media, 1);
2252 }
2253
2254 SCOPE_EXIT_RTN_VALUE(1, "Handled\n");
2255}
2256
2257/*! \brief Function which updates the media stream with external media address, if applicable */
2258static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struct pjmedia_sdp_media *stream, struct ast_sip_transport *transport)
2259{
2261 char host[NI_MAXHOST];
2262 struct ast_sockaddr our_sdp_addr = { { 0, } };
2263
2264 /* If the stream has been rejected there will be no connection line */
2265 if (!stream->conn || !transport_state) {
2266 return;
2267 }
2268
2269 ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
2270 ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
2271
2272 /* Reversed check here. We don't check the remote endpoint being
2273 * in our local net, but whether our outgoing session IP is
2274 * local. If it is not, we won't do rewriting. No localnet
2275 * configured? Always rewrite. */
2276 if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
2277 return;
2278 }
2279 ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2280 pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2281}
2282
2283/*! \brief Function which stops the RTP instance */
2284static void stream_stop(struct ast_sip_session_media *session_media)
2285{
2286 if (!session_media->rtp) {
2287 return;
2288 }
2289
2290 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2291 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2292 ast_rtp_instance_stop(session_media->rtp);
2293}
2294
2295/*! \brief Function which destroys the RTP instance when session ends */
2296static void stream_destroy(struct ast_sip_session_media *session_media)
2297{
2298 if (session_media->rtp) {
2299 stream_stop(session_media);
2300 ast_rtp_instance_destroy(session_media->rtp);
2301 }
2302 session_media->rtp = NULL;
2303}
2304
2305/*! \brief SDP handler for 'audio' media stream */
2307 .id = STR_AUDIO,
2308 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
2309 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
2310 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
2311 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
2312 .stream_stop = stream_stop,
2313 .stream_destroy = stream_destroy,
2314};
2315
2316/*! \brief SDP handler for 'video' media stream */
2318 .id = STR_VIDEO,
2319 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
2320 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
2321 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
2322 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
2323 .stream_stop = stream_stop,
2324 .stream_destroy = stream_destroy,
2325};
2326
2327static int video_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
2328{
2329 struct pjsip_transaction *tsx;
2330 pjsip_tx_data *tdata;
2331
2332 if (!session->channel
2333 || !ast_sip_are_media_types_equal(&rdata->msg_info.msg->body->content_type,
2335 return 0;
2336 }
2337
2338 tsx = pjsip_rdata_get_tsx(rdata);
2339
2341
2342 if (pjsip_dlg_create_response(session->inv_session->dlg, rdata, 200, NULL, &tdata) == PJ_SUCCESS) {
2343 pjsip_dlg_send_response(session->inv_session->dlg, tsx, tdata);
2344 }
2345
2346 return 0;
2347}
2348
2350 .method = "INFO",
2351 .incoming_request = video_info_incoming_request,
2352};
2353
2354/*! \brief Unloads the sdp RTP/AVP module from Asterisk */
2355static int unload_module(void)
2356{
2360
2361 if (sched) {
2363 }
2364
2365 return 0;
2366}
2367
2368/*!
2369 * \brief Load the module
2370 *
2371 * Module loading including tests for configuration or dependencies.
2372 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
2373 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
2374 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
2375 * configuration file or other non-critical problem return
2376 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
2377 */
2378static int load_module(void)
2379{
2380 if (ast_check_ipv6()) {
2382 } else {
2383 ast_sockaddr_parse(&address_rtp, "0.0.0.0", 0);
2384 }
2385
2386 if (!(sched = ast_sched_context_create())) {
2387 ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
2388 goto end;
2389 }
2390
2392 ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
2393 goto end;
2394 }
2395
2397 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_AUDIO);
2398 goto end;
2399 }
2400
2402 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_VIDEO);
2403 goto end;
2404 }
2405
2407
2409end:
2410 unload_module();
2411
2413}
2414
2415AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP SDP RTP/AVP stream handler",
2416 .support_level = AST_MODULE_SUPPORT_CORE,
2417 .load = load_module,
2418 .unload = unload_module,
2419 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
2420 .requires = "res_pjsip,res_pjsip_session",
Access Control of various sorts.
enum queue_result id
Definition: app_queue.c:1638
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_mansession session
#define ast_free(a)
Definition: astmm.h:180
#define ast_strndup(str, len)
A wrapper for strndup()
Definition: astmm.h:256
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
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 tmp()
Definition: bt_open.c:389
Internal Asterisk hangup causes.
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition: causes.h:125
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
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)
#define ast_channel_lock(chan)
Definition: channel.h:2922
struct ast_format_cap * ast_channel_nativeformats(const struct ast_channel *chan)
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
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:1139
const char * ast_channel_uniqueid(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:5762
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10545
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1216
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1191
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5803
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:1454
#define ast_channel_unlock(chan)
Definition: channel.h:2923
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
static struct ao2_container * codecs
Registered codecs.
Definition: codec.c:48
ast_media_type
Types of media.
Definition: codec.h:30
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_UNKNOWN
Definition: codec.h:31
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
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
Convenient Signal Processing routines.
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
char * end
Definition: eagi_proxy.c:73
char * address
Definition: f2c.h:59
Media Format API.
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
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
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
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
Media Format Cache API.
Format Capabilities API.
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
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 * 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
unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
Get the global framing.
Definition: format_cap.c:438
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
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
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
@ 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
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
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
#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
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
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
static const char name[]
Definition: format_mp3.c:68
direction
#define SCOPE_EXIT_RTN(...)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_ENTER(level,...)
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_UPDATE_RTP_PEER
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
A set of macros to manage forward-linked lists.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_CHANNEL_DRIVER
Definition: module.h:327
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ 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
Network socket handling.
char * ast_sockaddr_stringify_fmt(const struct ast_sockaddr *addr, int format)
Convert a socket address to a string.
Definition: netsock2.c:65
@ AST_AF_UNSPEC
Definition: netsock2.h:54
#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
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
Definition: netsock2.c:534
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
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
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
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:532
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
const char * ast_sip_get_host_ip_string(int af)
Retrieve the local host address in string form.
Definition: res_pjsip.c:2493
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition: res_pjsip.c:3910
ast_sip_session_media_encryption
Definition: res_pjsip.h:645
@ AST_SIP_MEDIA_ENCRYPT_SDES
Definition: res_pjsip.h:651
@ AST_SIP_MEDIA_TRANSPORT_INVALID
Definition: res_pjsip.h:647
@ AST_SIP_MEDIA_ENCRYPT_NONE
Definition: res_pjsip.h:649
@ AST_SIP_MEDIA_ENCRYPT_DTLS
Definition: res_pjsip.h:653
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
int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
Compare pjsip media types.
Definition: res_pjsip.c:2219
@ AST_SIP_DTMF_AUTO_INFO
Definition: res_pjsip.h:556
@ AST_SIP_DTMF_AUTO
Definition: res_pjsip.h:554
@ AST_SIP_DTMF_INBAND
Definition: res_pjsip.h:550
@ AST_SIP_DTMF_RFC_4733
Definition: res_pjsip.h:548
#define ast_sip_transport_is_nonlocal(transport_state, addr)
Definition: res_pjsip.h:212
struct ast_sip_transport_state * ast_sip_get_transport_state(const char *transport_id)
Retrieve transport state.
@ AST_SIP_SECURITY_NEG_MEDIASEC
Definition: res_pjsip.h:357
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
static int send_keepalive(const void *data)
static void apply_dtls_attrib(struct ast_sip_session_media *session_media, pjmedia_sdp_attr *attr)
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.
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 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 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_sched_context * sched
Scheduler for RTCP purposes.
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 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 const char STR_AUDIO[]
static struct ast_sip_session_sdp_handler audio_sdp_handler
SDP handler for 'audio' media 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 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 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 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 void stream_stop(struct ast_sip_session_media *session_media)
Function which stops the RTP instance.
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 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.
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 const char STR_VIDEO[]
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.
static int media_stream_has_crypto(const struct pjmedia_sdp_media *stream)
figure out if media stream has crypto lines for sdes
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.
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 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 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 struct ast_sockaddr address_rtp
Address for RTP.
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 struct ast_sip_session_sdp_handler video_sdp_handler
SDP handler for 'video' media stream.
static int load_module(void)
Load the module.
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 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
static int unload_module(void)
Unloads the sdp RTP/AVP module from Asterisk.
static int video_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
static struct ast_sip_session_supplement video_info_supplement
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 struct ast_frame * media_session_rtp_read_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
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.
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)
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 setup_sdes_srtp(struct ast_sip_session_media *session_media, const struct pjmedia_sdp_media *stream)
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 int setup_dtls_srtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
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.
void ast_sip_session_unregister_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Unregister an SDP handler.
int ast_sip_session_register_sdp_handler(struct ast_sip_session_sdp_handler *handler, const char *stream_type)
Register an SDP handler.
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.
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.
#define ast_sip_session_register_supplement(supplement)
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
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.
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.
@ AST_AES_CM_128_HMAC_SHA1_80
Definition: res_srtp.h:58
@ AST_AES_CM_128_HMAC_SHA1_32
Definition: res_srtp.h:59
#define NULL
Definition: resample.c:96
Pluggable RTP Architecture.
ast_rtp_dtls_setup
DTLS setup types.
Definition: rtp_engine.h:559
@ AST_RTP_DTLS_SETUP_PASSIVE
Definition: rtp_engine.h:561
@ AST_RTP_DTLS_SETUP_HOLDCONN
Definition: rtp_engine.h:563
@ AST_RTP_DTLS_SETUP_ACTPASS
Definition: rtp_engine.h:562
@ AST_RTP_DTLS_SETUP_ACTIVE
Definition: rtp_engine.h:560
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:2035
@ AST_RTP_ICE_ROLE_CONTROLLING
Definition: rtp_engine.h:516
@ AST_RTP_ICE_ROLE_CONTROLLED
Definition: rtp_engine.h:515
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:1550
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:995
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:457
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:2150
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:1936
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:486
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:3838
ast_rtp_dtls_hash
DTLS fingerprint hashes.
Definition: rtp_engine.h:573
@ AST_RTP_DTLS_HASH_SHA1
Definition: rtp_engine.h:575
@ AST_RTP_DTLS_HASH_SHA256
Definition: rtp_engine.h:574
@ AST_RTP_DTMF_MODE_RFC2833
Definition: rtp_engine.h:152
@ AST_RTP_DTMF_MODE_INBAND
Definition: rtp_engine.h:154
@ AST_RTP_DTMF_MODE_NONE
Definition: rtp_engine.h:150
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:2136
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
Definition: rtp_engine.c:2196
#define AST_RTP_DTMF
Definition: rtp_engine.h:291
ast_rtp_instance_rtcp
Definition: rtp_engine.h:280
@ AST_RTP_INSTANCE_RTCP_MUX
Definition: rtp_engine.h:286
@ AST_RTP_INSTANCE_RTCP_STANDARD
Definition: rtp_engine.h:284
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:1237
size_t ast_rtp_instance_extmap_count(struct ast_rtp_instance *instance)
Get the number of known unique identifiers.
Definition: rtp_engine.c:920
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:753
@ AST_RTP_INSTANCE_STAT_REMOTE_SSRC
Definition: rtp_engine.h:248
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:3895
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
Get the RTP keepalive interval.
Definition: rtp_engine.c:2732
const char * ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp)
Retrieve the CNAME used in RTCP SDES items.
Definition: rtp_engine.c:3856
int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
Get the RTP timeout value.
Definition: rtp_engine.c:2722
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:3048
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:2906
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:599
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:3869
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:1571
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp)
Get the last RTP transmission time.
Definition: rtp_engine.c:3823
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:1314
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:726
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:664
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:2459
@ AST_RTP_ICE_CANDIDATE_TYPE_RELAYED
Definition: rtp_engine.h:504
@ AST_RTP_ICE_CANDIDATE_TYPE_SRFLX
Definition: rtp_engine.h:503
@ AST_RTP_ICE_CANDIDATE_TYPE_HOST
Definition: rtp_engine.h:502
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:931
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:589
ast_rtp_extension
Known RTP extensions.
Definition: rtp_engine.h:588
@ AST_RTP_EXTENSION_TRANSPORT_WIDE_CC
Definition: rtp_engine.h:594
@ AST_RTP_EXTENSION_ABS_SEND_TIME
Definition: rtp_engine.h:592
@ AST_RTP_EXTENSION_UNSUPPORTED
Definition: rtp_engine.h:590
#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:1126
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:2809
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:3886
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:2928
ast_rtp_options
Definition: rtp_engine.h:142
@ AST_RTP_OPT_G726_NONSTANDARD
Definition: rtp_engine.h:144
@ AST_RTP_DTLS_CONNECTION_NEW
Definition: rtp_engine.h:568
@ AST_RTP_DTLS_CONNECTION_EXISTING
Definition: rtp_engine.h:569
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
Definition: rtp_engine.c:979
@ AST_RTP_PROPERTY_NAT
Definition: rtp_engine.h:115
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition: rtp_engine.h:127
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition: rtp_engine.h:129
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:123
@ AST_RTP_PROPERTY_ASYMMETRIC_CODEC
Definition: rtp_engine.h:125
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:117
@ AST_RTP_PROPERTY_REMB
Definition: rtp_engine.h:131
#define AST_RTP_PT_LAST_STATIC
Definition: rtp_engine.h:89
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
Definition: rtp_engine.h:2952
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:2684
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:2005
time_t ast_rtp_instance_get_last_rx(const struct ast_rtp_instance *rtp)
Get the last RTP reception time.
Definition: rtp_engine.c:3833
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:2182
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:574
ast_rtp_extension_direction
Directions for RTP extensions.
Definition: rtp_engine.h:815
@ AST_RTP_EXTENSION_DIRECTION_SENDRECV
Definition: rtp_engine.h:819
@ AST_RTP_EXTENSION_DIRECTION_NONE
Definition: rtp_engine.h:817
@ AST_RTP_EXTENSION_DIRECTION_INACTIVE
Definition: rtp_engine.h:825
@ AST_RTP_EXTENSION_DIRECTION_RECVONLY
Definition: rtp_engine.h:823
@ AST_RTP_EXTENSION_DIRECTION_SENDONLY
Definition: rtp_engine.h:821
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:1516
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:967
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:1356
#define AST_RTP_CODECS_NULL_INIT
Definition: rtp_engine.h:762
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:907
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:2173
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:839
void ast_rtp_instance_extmap_clear(struct ast_rtp_instance *instance)
Clear negotiated RTP extension information.
Definition: rtp_engine.c:883
#define AST_RTP_MAX
Definition: rtp_engine.h:297
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:748
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:569
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:2205
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:1582
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int timeout)
Set the RTP keepalive interval.
Definition: rtp_engine.c:2717
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:3843
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:1886
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:951
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:1270
void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
Set the RTP timeout value.
Definition: rtp_engine.c:2707
Scheduler Routines (derived from cheops)
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
Definition: sched.h:46
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
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
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
SRTP and SDP Security descriptions.
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_crypto * ast_sdp_crypto_alloc(void)
Initialize an return an ast_sdp_crypto struct.
Definition: sdp_srtp.c:71
struct ast_sdp_srtp * ast_sdp_srtp_alloc(void)
allocate a ast_sdp_srtp structure
Definition: sdp_srtp.c:41
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
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
#define AST_SRTP_CRYPTO_OFFER_OK
Definition: sdp_srtp.h:45
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
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
Media Stream API.
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
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
@ 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
int ast_stream_get_position(const struct ast_stream *stream)
Get the position of the stream in the topology.
Definition: stream.c:500
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
int ast_stream_get_group(const struct ast_stream *stream)
Get the stream group that a stream is part of.
Definition: stream.c:1077
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition: stream.c:316
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
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
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
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
Definition: strings.h:1189
#define ast_str_alloca(init_len)
Definition: strings.h:848
#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
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
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
Main Channel structure associated with a channel.
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
Data structure associated with a single frame of data.
Structure that represents the optional DTLS SRTP support within an RTP engine.
Definition: rtp_engine.h:616
int(* set_configuration)(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
Definition: rtp_engine.h:618
enum ast_rtp_dtls_setup(* get_setup)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:628
enum ast_rtp_dtls_hash(* get_fingerprint_hash)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:634
const char *(* get_fingerprint)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:636
void(* reset)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:624
void(* set_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint)
Definition: rtp_engine.h:632
enum ast_rtp_dtls_connection(* get_connection)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:626
void(* set_setup)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup)
Definition: rtp_engine.h:630
Structure for an ICE candidate.
Definition: rtp_engine.h:520
struct ast_sockaddr address
Definition: rtp_engine.h:525
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:522
struct ast_sockaddr relay_address
Definition: rtp_engine.h:526
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:527
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:531
void(* ice_lite)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:547
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:539
void(* change_components)(struct ast_rtp_instance *instance, int num_components)
Definition: rtp_engine.h:555
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition: rtp_engine.h:533
void(* start)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:537
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:541
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
Definition: rtp_engine.h:535
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:543
void(* set_role)(struct ast_rtp_instance *instance, enum ast_rtp_ice_role role)
Definition: rtp_engine.h:549
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:545
unsigned int remote_ssrc
Definition: rtp_engine.h:449
structure for secure RTP audio
Definition: sdp_srtp.h:38
struct ast_sdp_srtp::@278 sdp_srtp_list
struct ast_sdp_crypto * crypto
Definition: sdp_srtp.h:40
struct ast_sip_media_rtp_configuration rtp
Definition: res_pjsip.h:915
An entity with which Asterisk communicates.
Definition: res_pjsip.h:963
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:996
enum ast_sip_session_media_encryption encryption
Definition: res_pjsip.h:858
unsigned int encryption_optimistic
Definition: res_pjsip.h:860
A structure containing SIP session media information.
struct ast_sdp_srtp * srtp
Holds SRTP information.
unsigned int remotely_held_changed
Stream is held by remote side changed during this negotiation.
char label[AST_UUID_STR_LEN]
Track label.
unsigned int remote_ice
Does remote support ice.
enum ast_media_type type
Media type of this session media.
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.
int stream_num
The stream number to place into any resulting frames.
int bundle_group
The bundle group the stream belongs to.
unsigned int remotely_held
Stream is on hold by remote side.
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.
struct ast_sockaddr direct_media_addr
Direct media address.
char mslabel[AST_UUID_STR_LEN]
Media stream label.
pj_str_t transport
The media transport in use for this stream.
unsigned int bundled
Whether this stream is currently bundled or not.
unsigned int changed
The underlying session has been changed in some fashion.
int keepalive_sched_id
Scheduler ID for RTP keepalive.
A handler for SDPs in SIP sessions.
A supplement to SIP message processing.
A structure describing a SIP session.
Structure for SIP transport information.
Definition: res_pjsip.h:119
struct pjsip_transport * transport
Transport itself.
Definition: res_pjsip.h:121
Transport to bind to.
Definition: res_pjsip.h:221
Socket address structure.
Definition: netsock2.h:97
Support for dynamic strings.
Definition: strings.h:623
structure to hold extensions
Definition: sched.c:76
int value
Definition: syslog.c:37
static struct test_options options
Utility functions.
#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
#define ast_assert(a)
Definition: utils.h:739
#define ast_set_flag(p, flag)
Definition: utils.h:70
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition: utils.c:2792
#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_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680