Asterisk - The Open Source Telephony Project GIT-master-d856a3e
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 if (tel_event == 0) {
348 int dtmf_rate = 0, dtmf_code = 0;
349 char dtmf_pt[8];
350 ast_copy_pj_str(dtmf_pt, &rtpmap->pt, sizeof(dtmf_pt));
351 dtmf_code = atoi(dtmf_pt);
352 dtmf_rate = rtpmap->clock_rate;
354 }
355 tel_event++;
356 }
357
358 ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media, sizeof(media));
360 pj_strtoul(&stream->desc.fmt[i]), media, name, options, rtpmap->clock_rate);
361 /* Look for an optional associated fmtp attribute */
362 if (!(attr = pjmedia_sdp_media_find_attr2(stream, "fmtp", &rtpmap->pt))) {
363 continue;
364 }
365
366 if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
367 ast_copy_pj_str(fmt_param, &fmtp.fmt, sizeof(fmt_param));
368 if (sscanf(fmt_param, "%30d", &num) != 1) {
369 continue;
370 }
371
372 if ((format = ast_rtp_codecs_get_payload_format(codecs, num))) {
373 struct ast_format *format_parsed;
374
375 ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));
376
377 format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);
378 if (format_parsed) {
380 ao2_ref(format_parsed, -1);
381 }
382 ao2_ref(format, -1);
383 }
384 }
385 }
386
387 /* Parsing done, now fill the ast_format_cap struct in the correct order */
388 for (i = 0; i < stream->desc.fmt_count; ++i) {
389 if ((format = ast_rtp_codecs_get_payload_format(codecs, pj_strtoul(&stream->desc.fmt[i])))) {
390 ast_format_cap_append(astformats, format, 0);
391 ao2_ref(format, -1);
392 }
393 }
394
395 if (session->dtmf == AST_SIP_DTMF_AUTO) {
396 if (tel_event) {
399 } else {
402 }
403 }
404
405 if (session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
406 if (tel_event) {
409 } else {
412 }
413 }
414
415
416 /* Get the packetization, if it exists */
417 if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
418 unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
419 if (framing && session->endpoint->media.rtp.use_ptime) {
421 ast_format_cap_set_framing(astformats, framing);
422 }
423 }
424
426}
427
428static int apply_cap_to_bundled(struct ast_sip_session_media *session_media,
429 struct ast_sip_session_media *session_media_transport,
430 struct ast_stream *asterisk_stream, struct ast_format_cap *joint)
431{
432 if (!joint) {
433 return -1;
434 }
435
436 ast_stream_set_formats(asterisk_stream, joint);
437
438 /* If this is a bundled stream then apply the payloads to RTP instance acting as transport to prevent conflicts */
439 if (session_media_transport != session_media && session_media->bundled) {
440 int index;
441
442 for (index = 0; index < ast_format_cap_count(joint); ++index) {
443 struct ast_format *format = ast_format_cap_get_format(joint, index);
444 int rtp_code;
445
446 /* Ensure this payload is in the bundle group transport codecs, this purposely doesn't check the return value for
447 * things as the format is guaranteed to have a payload already.
448 */
449 rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0);
450 ast_rtp_codecs_payload_set_rx(ast_rtp_instance_get_codecs(session_media_transport->rtp), rtp_code, format);
451
452 ao2_ref(format, -1);
453 }
454 }
455
456 return 0;
457}
458
460 struct ast_sip_session *session, struct ast_sip_session_media *session_media,
461 const struct pjmedia_sdp_media *stream)
462{
463 struct ast_format_cap *incoming_call_offer_cap;
464 struct ast_format_cap *remote;
467
468
470 if (!remote) {
471 ast_log(LOG_ERROR, "Failed to allocate %s incoming remote capabilities\n",
472 ast_codec_media_type2str(session_media->type));
473 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't allocate caps\n");
474 }
475
476 /* Get the peer's capabilities*/
477 get_codecs(session, stream, &codecs, session_media, remote);
478
479 incoming_call_offer_cap = ast_sip_session_create_joint_call_cap(
480 session, session_media->type, remote);
481
482 ao2_ref(remote, -1);
483
484 if (!incoming_call_offer_cap || ast_format_cap_empty(incoming_call_offer_cap)) {
485 ao2_cleanup(incoming_call_offer_cap);
487 SCOPE_EXIT_RTN_VALUE(NULL, "No incoming call offer caps\n");
488 }
489
490 /*
491 * Setup rx payload type mapping to prefer the mapping
492 * from the peer that the RFC says we SHOULD use.
493 */
495
497 ast_rtp_instance_get_codecs(session_media->rtp), session_media->rtp);
498
500
501 SCOPE_EXIT_RTN_VALUE(incoming_call_offer_cap);
502}
503
505 struct ast_sip_session_media *session_media,
506 struct ast_sip_session_media *session_media_transport,
507 const struct pjmedia_sdp_media *stream,
508 int is_offer, struct ast_stream *asterisk_stream)
509{
510 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
511 RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
512 RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
513 enum ast_media_type media_type = session_media->type;
515 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
516 ast_format_cap_count(session->direct_media_cap);
517 int dsp_features = 0;
518 SCOPE_ENTER(1, "%s %s\n", ast_sip_session_get_name(session), is_offer ? "OFFER" : "ANSWER");
519
523 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
524 ast_codec_media_type2str(session_media->type));
525 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create %s capabilities\n",
526 ast_codec_media_type2str(session_media->type));
527 }
528
529 /* get the endpoint capabilities */
530 if (direct_media_enabled) {
531 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
532 } else {
533 ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
534 }
535
536 /* get the capabilities on the peer */
537 get_codecs(session, stream, &codecs, session_media, peer);
538
539 /* get the joint capabilities between peer and endpoint */
540 ast_format_cap_get_compatible(caps, peer, joint);
541 if (!ast_format_cap_count(joint)) {
544
546 ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
547 ast_codec_media_type2str(session_media->type),
548 ast_format_cap_get_names(caps, &usbuf),
549 ast_format_cap_get_names(peer, &thembuf));
550 SCOPE_EXIT_RTN_VALUE(-1, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
551 ast_codec_media_type2str(session_media->type),
552 ast_format_cap_get_names(caps, &usbuf),
553 ast_format_cap_get_names(peer, &thembuf));
554 } else {
555 struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
556
558 ao2_ref(preferred_fmt, -1);
559 }
560
561 if (is_offer) {
562 /*
563 * Setup rx payload type mapping to prefer the mapping
564 * from the peer that the RFC says we SHOULD use.
565 */
567 }
569 session_media->rtp);
570
571 apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
572
573 if (session->channel && ast_sip_session_is_pending_stream_default(session, asterisk_stream)) {
574 ast_channel_lock(session->channel);
578 ast_format_cap_remove_by_type(caps, media_type);
579
580 if (session->endpoint->preferred_codec_only) {
581 struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
582 ast_format_cap_append(caps, preferred_fmt, 0);
583 ao2_ref(preferred_fmt, -1);
584 } else if (!session->endpoint->asymmetric_rtp_codec) {
585 struct ast_format *best;
586 /*
587 * If we don't allow the sending codec to be changed on our side
588 * then get the best codec from the joint capabilities of the media
589 * type and use only that. This ensures the core won't start sending
590 * out a format that we aren't currently sending.
591 */
592
593 best = ast_format_cap_get_best_by_type(joint, media_type);
594 if (best) {
596 ao2_ref(best, -1);
597 }
598 } else {
599 ast_format_cap_append_from_cap(caps, joint, media_type);
600 }
601
602 /*
603 * Apply the new formats to the channel, potentially changing
604 * raw read/write formats and translation path while doing so.
605 */
607 if (media_type == AST_MEDIA_TYPE_AUDIO) {
610 }
611
612 if ( ((session->dtmf == AST_SIP_DTMF_AUTO) || (session->dtmf == AST_SIP_DTMF_AUTO_INFO) )
614 && (session->dsp)) {
615 dsp_features = ast_dsp_get_features(session->dsp);
616 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
617 if (dsp_features) {
618 ast_dsp_set_features(session->dsp, dsp_features);
619 } else {
620 ast_dsp_free(session->dsp);
621 session->dsp = NULL;
622 }
623 }
624
625 if (ast_channel_is_bridged(session->channel)) {
627 }
628
629 ast_channel_unlock(session->channel);
630 }
631
634}
635
636static pjmedia_sdp_attr* generate_rtpmap_attr(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
637 int rtp_code, int asterisk_format, struct ast_format *format, int code)
638{
639#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
640 extern pj_bool_t pjsip_use_compact_form;
641#else
642 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
643#endif
644 pjmedia_sdp_rtpmap rtpmap;
645 pjmedia_sdp_attr *attr = NULL;
646 char tmp[64];
647 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
649
650 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
651 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
652
653 if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
654 return NULL;
655 }
656
657 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
658 rtpmap.clock_rate = ast_rtp_lookup_sample_rate2(asterisk_format, format, code);
659 pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
660 if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
661 pj_cstr(&rtpmap.param, "2");
662 } else {
663 pj_cstr(&rtpmap.param, NULL);
664 }
665
666 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
667
668 return attr;
669}
670
671
672static pjmedia_sdp_attr* generate_rtpmap_attr2(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
673 int rtp_code, int asterisk_format, struct ast_format *format, int code, int sample_rate)
674{
675#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
676 extern pj_bool_t pjsip_use_compact_form;
677#else
678 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
679#endif
680 pjmedia_sdp_rtpmap rtpmap;
681 pjmedia_sdp_attr *attr = NULL;
682 char tmp[64];
683 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
685
686 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
687 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
688
689 if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
690 return NULL;
691 }
692
693 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
694 rtpmap.clock_rate = sample_rate;
695 pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
696 if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
697 pj_cstr(&rtpmap.param, "2");
698 } else {
699 pj_cstr(&rtpmap.param, NULL);
700 }
701
702 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
703
704 return attr;
705}
706
707static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *format, int rtp_code)
708{
709 struct ast_str *fmtp0 = ast_str_alloca(256);
710 pj_str_t fmtp1;
711 pjmedia_sdp_attr *attr = NULL;
712 char *tmp;
713
714 ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
715 if (ast_str_strlen(fmtp0)) {
716 tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
717 /* remove any carriage return line feeds */
718 while (*tmp == '\r' || *tmp == '\n') --tmp;
719 *++tmp = '\0';
720 /* ast...generate gives us everything, just need value */
721 tmp = strchr(ast_str_buffer(fmtp0), ':');
722 if (tmp && tmp[1] != '\0') {
723 fmtp1 = pj_str(tmp + 1);
724 } else {
725 fmtp1 = pj_str(ast_str_buffer(fmtp0));
726 }
727 attr = pjmedia_sdp_attr_create(pool, "fmtp", &fmtp1);
728 }
729 return attr;
730}
731
732/*! \brief Function which adds ICE attributes to a media stream */
733static 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,
734 unsigned int include_candidates)
735{
736 struct ast_rtp_engine_ice *ice;
737 struct ao2_container *candidates;
738 const char *username, *password;
739 pj_str_t stmp;
740 pjmedia_sdp_attr *attr;
741 struct ao2_iterator it_candidates;
742 struct ast_rtp_engine_ice_candidate *candidate;
743
744 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
745 return;
746 }
747
748 if (!session_media->remote_ice) {
749 ice->stop(session_media->rtp);
750 return;
751 }
752
753 if ((username = ice->get_ufrag(session_media->rtp))) {
754 attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", pj_cstr(&stmp, username));
755 media->attr[media->attr_count++] = attr;
756 }
757
758 if ((password = ice->get_password(session_media->rtp))) {
759 attr = pjmedia_sdp_attr_create(pool, "ice-pwd", pj_cstr(&stmp, password));
760 media->attr[media->attr_count++] = attr;
761 }
762
763 if (!include_candidates) {
764 return;
765 }
766
767 candidates = ice->get_local_candidates(session_media->rtp);
768 if (!candidates) {
769 return;
770 }
771
772 it_candidates = ao2_iterator_init(candidates, 0);
773 for (; (candidate = ao2_iterator_next(&it_candidates)); ao2_ref(candidate, -1)) {
774 struct ast_str *attr_candidate = ast_str_create(128);
775
776 ast_str_set(&attr_candidate, -1, "%s %u %s %d %s ", candidate->foundation, candidate->id, candidate->transport,
777 candidate->priority, ast_sockaddr_stringify_addr_remote(&candidate->address));
778 ast_str_append(&attr_candidate, -1, "%s typ ", ast_sockaddr_stringify_port(&candidate->address));
779
780 switch (candidate->type) {
782 ast_str_append(&attr_candidate, -1, "host");
783 break;
785 ast_str_append(&attr_candidate, -1, "srflx");
786 break;
788 ast_str_append(&attr_candidate, -1, "relay");
789 break;
790 }
791
792 if (!ast_sockaddr_isnull(&candidate->relay_address)) {
793 ast_str_append(&attr_candidate, -1, " raddr %s rport", ast_sockaddr_stringify_addr_remote(&candidate->relay_address));
794 ast_str_append(&attr_candidate, -1, " %s", ast_sockaddr_stringify_port(&candidate->relay_address));
795 }
796
797 attr = pjmedia_sdp_attr_create(pool, "candidate", pj_cstr(&stmp, ast_str_buffer(attr_candidate)));
798 media->attr[media->attr_count++] = attr;
799
800 ast_free(attr_candidate);
801 }
802
803 ao2_iterator_destroy(&it_candidates);
804 ao2_ref(candidates, -1);
805}
806
807/*! \brief Function which checks for ice attributes in an audio stream */
808static void check_ice_support(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
809 const struct pjmedia_sdp_media *remote_stream)
810{
811 struct ast_rtp_engine_ice *ice;
812 const pjmedia_sdp_attr *attr;
813 unsigned int attr_i;
814
815 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
816 session_media->remote_ice = 0;
817 return;
818 }
819
820 /* Find all of the candidates */
821 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
822 attr = remote_stream->attr[attr_i];
823 if (!pj_strcmp2(&attr->name, "candidate")) {
824 session_media->remote_ice = 1;
825 break;
826 }
827 }
828
829 if (attr_i == remote_stream->attr_count) {
830 session_media->remote_ice = 0;
831 }
832}
833
834static void process_ice_auth_attrb(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
835 const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
836{
837 struct ast_rtp_engine_ice *ice;
838 const pjmedia_sdp_attr *ufrag_attr, *passwd_attr;
839 char ufrag_attr_value[256];
840 char passwd_attr_value[256];
841
842 /* If ICE support is not enabled or available exit early */
843 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
844 return;
845 }
846
847 ufrag_attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
848 if (!ufrag_attr) {
849 ufrag_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
850 }
851 if (ufrag_attr) {
852 ast_copy_pj_str(ufrag_attr_value, (pj_str_t*)&ufrag_attr->value, sizeof(ufrag_attr_value));
853 } else {
854 return;
855 }
856 passwd_attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL);
857 if (!passwd_attr) {
858 passwd_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
859 }
860 if (passwd_attr) {
861 ast_copy_pj_str(passwd_attr_value, (pj_str_t*)&passwd_attr->value, sizeof(passwd_attr_value));
862 } else {
863 return;
864 }
865
866 if (ufrag_attr && passwd_attr) {
867 ice->set_authentication(session_media->rtp, ufrag_attr_value, passwd_attr_value);
868 }
869}
870
871/*! \brief Function which processes ICE attributes in an audio stream */
872static void process_ice_attributes(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
873 const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
874{
875 struct ast_rtp_engine_ice *ice;
876 const pjmedia_sdp_attr *attr;
877 char attr_value[256];
878 unsigned int attr_i;
879
880 /* If ICE support is not enabled or available exit early */
881 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
882 return;
883 }
884
885 ast_debug_ice(2, "(%p) ICE process attributes\n", session_media->rtp);
886
887 attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
888 if (!attr) {
889 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
890 }
891 if (attr) {
892 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
893 ice->set_authentication(session_media->rtp, attr_value, NULL);
894 } else {
895 ast_debug_ice(2, "(%p) ICE no, or invalid ice-ufrag\n", session_media->rtp);
896 return;
897 }
898
899 attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-pwd", NULL);
900 if (!attr) {
901 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
902 }
903 if (attr) {
904 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
905 ice->set_authentication(session_media->rtp, NULL, attr_value);
906 } else {
907 ast_debug_ice(2, "(%p) ICE no, or invalid ice-pwd\n", session_media->rtp);
908 return;
909 }
910
911 if (pjmedia_sdp_media_find_attr2(remote_stream, "ice-lite", NULL)) {
912 ice->ice_lite(session_media->rtp);
913 }
914
915 /* Find all of the candidates */
916 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
917 char foundation[33], transport[32], address[PJ_INET6_ADDRSTRLEN + 1], cand_type[6], relay_address[PJ_INET6_ADDRSTRLEN + 1] = "";
918 unsigned int port, relay_port = 0;
919 struct ast_rtp_engine_ice_candidate candidate = { 0, };
920
921 attr = remote_stream->attr[attr_i];
922
923 /* If this is not a candidate line skip it */
924 if (pj_strcmp2(&attr->name, "candidate")) {
925 continue;
926 }
927
928 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
929
930 if (sscanf(attr_value, "%32s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u", foundation, &candidate.id, transport,
931 (unsigned *)&candidate.priority, address, &port, cand_type, relay_address, &relay_port) < 7) {
932 /* Candidate did not parse properly */
933 continue;
934 }
935
936 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux && candidate.id > 1) {
937 /* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,
938 * then we should ignore RTCP candidates.
939 */
940 continue;
941 }
942
943 candidate.foundation = foundation;
944 candidate.transport = transport;
945
947 ast_sockaddr_set_port(&candidate.address, port);
948
949 if (!strcasecmp(cand_type, "host")) {
951 } else if (!strcasecmp(cand_type, "srflx")) {
953 } else if (!strcasecmp(cand_type, "relay")) {
955 } else {
956 continue;
957 }
958
961 }
962
963 if (relay_port) {
964 ast_sockaddr_set_port(&candidate.relay_address, relay_port);
965 }
966
967 ice->add_remote_candidate(session_media->rtp, &candidate);
968 }
969
970 ice->set_role(session_media->rtp, pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_TRUE ?
972 ice->start(session_media->rtp);
973}
974
975/*! \brief figure out if media stream has crypto lines for sdes */
976static int media_stream_has_crypto(const struct pjmedia_sdp_media *stream)
977{
978 int i;
979
980 for (i = 0; i < stream->attr_count; i++) {
981 pjmedia_sdp_attr *attr;
982
983 /* check the stream for the required crypto attribute */
984 attr = stream->attr[i];
985 if (pj_strcmp2(&attr->name, "crypto")) {
986 continue;
987 }
988
989 return 1;
990 }
991
992 return 0;
993}
994
995/*! \brief figure out media transport encryption type from the media transport string */
997 const struct pjmedia_sdp_media *stream, unsigned int *optimistic)
998{
999 RAII_VAR(char *, transport_str, ast_strndup(transport.ptr, transport.slen), ast_free);
1000
1001 *optimistic = 0;
1002
1003 if (!transport_str) {
1005 }
1006 if (strstr(transport_str, "UDP/TLS")) {
1008 } else if (strstr(transport_str, "SAVP")) {
1010 } else if (media_stream_has_crypto(stream)) {
1011 *optimistic = 1;
1013 } else {
1015 }
1016}
1017
1018/*!
1019 * \brief Checks whether the encryption offered in SDP is compatible with the endpoint's configuration
1020 * \internal
1021 *
1022 * \param endpoint Media encryption configured for the endpoint
1023 * \param stream pjmedia_sdp_media stream description
1024 *
1025 * \retval AST_SIP_MEDIA_TRANSPORT_INVALID on encryption mismatch
1026 * \retval The encryption requested in the SDP
1027 */
1029 struct ast_sip_endpoint *endpoint,
1030 const struct pjmedia_sdp_media *stream)
1031{
1032 enum ast_sip_session_media_encryption incoming_encryption;
1033 char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1];
1034 unsigned int optimistic;
1035
1036 if ((transport_end == 'F' && !endpoint->media.rtp.use_avpf)
1037 || (transport_end != 'F' && endpoint->media.rtp.use_avpf)) {
1039 }
1040
1041 incoming_encryption = get_media_encryption_type(stream->desc.transport, stream, &optimistic);
1042
1043 if (incoming_encryption == endpoint->media.rtp.encryption) {
1044 return incoming_encryption;
1045 }
1046
1047 if (endpoint->media.rtp.force_avp ||
1048 endpoint->media.rtp.encryption_optimistic) {
1049 return incoming_encryption;
1050 }
1051
1052 /* If an optimistic offer has been made but encryption is not enabled consider it as having
1053 * no offer of crypto at all instead of invalid so the session proceeds.
1054 */
1055 if (optimistic) {
1057 }
1058
1060}
1061
1062static int setup_srtp(struct ast_sip_session_media *session_media)
1063{
1064 if (!session_media->srtp) {
1065 session_media->srtp = ast_sdp_srtp_alloc();
1066 if (!session_media->srtp) {
1067 return -1;
1068 }
1069 }
1070
1071 if (!session_media->srtp->crypto) {
1072 session_media->srtp->crypto = ast_sdp_crypto_alloc();
1073 if (!session_media->srtp->crypto) {
1074 return -1;
1075 }
1076 }
1077
1078 return 0;
1079}
1080
1082 struct ast_sip_session_media *session_media)
1083{
1084 struct ast_rtp_engine_dtls *dtls;
1085
1086 if (!session->endpoint->media.rtp.dtls_cfg.enabled || !session_media->rtp) {
1087 return -1;
1088 }
1089
1090 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1091 if (!dtls) {
1092 return -1;
1093 }
1094
1095 session->endpoint->media.rtp.dtls_cfg.suite = ((session->endpoint->media.rtp.srtp_tag_32) ? AST_AES_CM_128_HMAC_SHA1_32 : AST_AES_CM_128_HMAC_SHA1_80);
1096 if (dtls->set_configuration(session_media->rtp, &session->endpoint->media.rtp.dtls_cfg)) {
1097 ast_log(LOG_ERROR, "Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
1098 session_media->rtp);
1099 return -1;
1100 }
1101
1102 if (setup_srtp(session_media)) {
1103 return -1;
1104 }
1105 return 0;
1106}
1107
1108static void apply_dtls_attrib(struct ast_sip_session_media *session_media,
1109 pjmedia_sdp_attr *attr)
1110{
1111 struct ast_rtp_engine_dtls *dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1112 pj_str_t *value;
1113
1114 if (!attr->value.ptr || !dtls) {
1115 return;
1116 }
1117
1118 value = pj_strtrim(&attr->value);
1119
1120 if (!pj_strcmp2(&attr->name, "setup")) {
1121 if (!pj_stricmp2(value, "active")) {
1122 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTIVE);
1123 } else if (!pj_stricmp2(value, "passive")) {
1124 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_PASSIVE);
1125 } else if (!pj_stricmp2(value, "actpass")) {
1126 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTPASS);
1127 } else if (!pj_stricmp2(value, "holdconn")) {
1128 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_HOLDCONN);
1129 } else {
1130 ast_log(LOG_WARNING, "Unsupported setup attribute value '%*s'\n", (int)value->slen, value->ptr);
1131 }
1132 } else if (!pj_strcmp2(&attr->name, "connection")) {
1133 if (!pj_stricmp2(value, "new")) {
1134 dtls->reset(session_media->rtp);
1135 } else if (!pj_stricmp2(value, "existing")) {
1136 /* Do nothing */
1137 } else {
1138 ast_log(LOG_WARNING, "Unsupported connection attribute value '%*s'\n", (int)value->slen, value->ptr);
1139 }
1140 } else if (!pj_strcmp2(&attr->name, "fingerprint")) {
1141 char hash_value[256], hash[32];
1142 char fingerprint_text[value->slen + 1];
1143 ast_copy_pj_str(fingerprint_text, value, sizeof(fingerprint_text));
1144 if (sscanf(fingerprint_text, "%31s %255s", hash, hash_value) == 2) {
1145 if (!strcasecmp(hash, "sha-1")) {
1146 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
1147 } else if (!strcasecmp(hash, "sha-256")) {
1148 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA256, hash_value);
1149 } else {
1150 ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
1151 hash);
1152 }
1153 }
1154 }
1155}
1156
1157static int parse_dtls_attrib(struct ast_sip_session_media *session_media,
1158 const struct pjmedia_sdp_session *sdp,
1159 const struct pjmedia_sdp_media *stream)
1160{
1161 int i;
1162
1163 for (i = 0; i < sdp->attr_count; i++) {
1164 apply_dtls_attrib(session_media, sdp->attr[i]);
1165 }
1166
1167 for (i = 0; i < stream->attr_count; i++) {
1168 apply_dtls_attrib(session_media, stream->attr[i]);
1169 }
1170
1172
1173 return 0;
1174}
1175
1176static int setup_sdes_srtp(struct ast_sip_session_media *session_media,
1177 const struct pjmedia_sdp_media *stream)
1178{
1179 int i;
1180
1181 for (i = 0; i < stream->attr_count; i++) {
1182 pjmedia_sdp_attr *attr;
1183 RAII_VAR(char *, crypto_str, NULL, ast_free);
1184
1185 /* check the stream for the required crypto attribute */
1186 attr = stream->attr[i];
1187 if (pj_strcmp2(&attr->name, "crypto")) {
1188 continue;
1189 }
1190
1191 crypto_str = ast_strndup(attr->value.ptr, attr->value.slen);
1192 if (!crypto_str) {
1193 return -1;
1194 }
1195
1196 if (setup_srtp(session_media)) {
1197 return -1;
1198 }
1199
1200 if (!ast_sdp_crypto_process(session_media->rtp, session_media->srtp, crypto_str)) {
1201 /* found a valid crypto attribute */
1202 return 0;
1203 }
1204
1205 ast_debug(1, "Ignoring crypto offer with unsupported parameters: %s\n", crypto_str);
1206 }
1207
1208 /* no usable crypto attributes found */
1209 return -1;
1210}
1211
1213 struct ast_sip_session_media *session_media,
1214 const struct pjmedia_sdp_session *sdp,
1215 const struct pjmedia_sdp_media *stream)
1216{
1217 switch (session_media->encryption) {
1219 if (setup_sdes_srtp(session_media, stream)) {
1220 return -1;
1221 }
1222 break;
1224 if (setup_dtls_srtp(session, session_media)) {
1225 return -1;
1226 }
1227 if (parse_dtls_attrib(session_media, sdp, stream)) {
1228 return -1;
1229 }
1230 break;
1233 break;
1234 }
1235
1236 return 0;
1237}
1238
1239static void set_ice_components(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
1240{
1241 struct ast_rtp_engine_ice *ice;
1242
1243 ast_assert(session_media->rtp != NULL);
1244
1245 ice = ast_rtp_instance_get_ice(session_media->rtp);
1246 if (!session->endpoint->media.rtp.ice_support || !ice) {
1247 return;
1248 }
1249
1250 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
1251 /* We both support RTCP mux. Only one ICE component necessary */
1252 ice->change_components(session_media->rtp, 1);
1253 } else {
1254 /* They either don't support RTCP mux or we don't know if they do yet. */
1255 ice->change_components(session_media->rtp, 2);
1256 }
1257}
1258
1259/*! \brief Function which adds ssrc attributes to a media stream */
1260static 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)
1261{
1262 pj_str_t stmp;
1263 pjmedia_sdp_attr *attr;
1264 char tmp[128];
1265
1266 if (!session->endpoint->media.bundle || session_media->bundle_group == -1) {
1267 return;
1268 }
1269
1270 snprintf(tmp, sizeof(tmp), "%u cname:%s", ast_rtp_instance_get_ssrc(session_media->rtp), ast_rtp_instance_get_cname(session_media->rtp));
1271 attr = pjmedia_sdp_attr_create(pool, "ssrc", pj_cstr(&stmp, tmp));
1272 media->attr[media->attr_count++] = attr;
1273}
1274
1275/*! \brief Function which processes ssrc attributes in a stream */
1277 const struct pjmedia_sdp_media *remote_stream)
1278{
1279 int index;
1280
1281 if (!session->endpoint->media.bundle) {
1282 return;
1283 }
1284
1285 for (index = 0; index < remote_stream->attr_count; ++index) {
1286 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1287 char attr_value[pj_strlen(&attr->value) + 1];
1288 char *ssrc_attribute_name, *ssrc_attribute_value = NULL;
1289 unsigned int ssrc;
1290
1291 /* We only care about ssrc attributes */
1292 if (pj_strcmp2(&attr->name, "ssrc")) {
1293 continue;
1294 }
1295
1296 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1297
1298 if ((ssrc_attribute_name = strchr(attr_value, ' '))) {
1299 /* This has an actual attribute */
1300 *ssrc_attribute_name++ = '\0';
1301 ssrc_attribute_value = strchr(ssrc_attribute_name, ':');
1302 if (ssrc_attribute_value) {
1303 /* Values are actually optional according to the spec */
1304 *ssrc_attribute_value++ = '\0';
1305 }
1306 }
1307
1308 if (sscanf(attr_value, "%30u", &ssrc) < 1) {
1309 continue;
1310 }
1311
1312 /* If we are currently negotiating as a result of the remote side renegotiating then
1313 * determine if the source for this stream has changed.
1314 */
1315 if (pjmedia_sdp_neg_get_state(session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
1316 session->active_media_state) {
1317 struct ast_rtp_instance_stats stats = { 0, };
1318
1320 stats.remote_ssrc != ssrc) {
1321 session_media->changed = 1;
1322 }
1323 }
1324
1325 ast_rtp_instance_set_remote_ssrc(session_media->rtp, ssrc);
1326 break;
1327 }
1328}
1329
1331 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media,
1332 struct ast_stream *stream)
1333{
1334 pj_str_t stmp;
1335 pjmedia_sdp_attr *attr;
1336 char msid[(AST_UUID_STR_LEN * 2) + 2];
1337 const char *stream_label = ast_stream_get_metadata(stream, "SDP:LABEL");
1338
1339 if (!session->endpoint->media.webrtc) {
1340 return;
1341 }
1342
1343 if (ast_strlen_zero(session_media->mslabel)) {
1344 /* If this stream is grouped with another then use its media stream label if possible */
1345 if (ast_stream_get_group(stream) != -1) {
1346 struct ast_sip_session_media *group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, ast_stream_get_group(stream));
1347
1348 ast_copy_string(session_media->mslabel, group_session_media->mslabel, sizeof(session_media->mslabel));
1349 }
1350
1351 if (ast_strlen_zero(session_media->mslabel)) {
1352 ast_uuid_generate_str(session_media->mslabel, sizeof(session_media->mslabel));
1353 }
1354 }
1355
1356 if (ast_strlen_zero(session_media->label)) {
1357 ast_uuid_generate_str(session_media->label, sizeof(session_media->label));
1358 /* add for stream identification to replace stream_name */
1359 ast_stream_set_metadata(stream, "MSID:LABEL", session_media->label);
1360 }
1361
1362 snprintf(msid, sizeof(msid), "%s %s", session_media->mslabel, session_media->label);
1363 ast_debug(3, "Stream msid: %p %s %s\n", stream,
1365 attr = pjmedia_sdp_attr_create(pool, "msid", pj_cstr(&stmp, msid));
1366 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1367
1368 /* 'label' must come after 'msid' */
1369 if (!ast_strlen_zero(stream_label)) {
1370 ast_debug(3, "Stream Label: %p %s %s\n", stream,
1371 ast_codec_media_type2str(ast_stream_get_type(stream)), stream_label);
1372 attr = pjmedia_sdp_attr_create(pool, "label", pj_cstr(&stmp, stream_label));
1373 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1374 }
1375}
1376
1378 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
1379{
1380 pj_str_t stmp;
1381 pjmedia_sdp_attr *attr;
1382
1383 if (!session->endpoint->media.webrtc) {
1384 return;
1385 }
1386
1387 /* transport-cc is supposed to be for the entire transport, and any media sources so
1388 * while the header does not appear in audio streams and isn't negotiated there, we still
1389 * place this attribute in as Chrome does.
1390 */
1391 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* transport-cc"));
1392 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1393
1394 if (session_media->type != AST_MEDIA_TYPE_VIDEO) {
1395 return;
1396 }
1397
1398 /*
1399 * For now just automatically add it the stream even though it hasn't
1400 * necessarily been negotiated.
1401 */
1402 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* ccm fir"));
1403 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1404
1405 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* goog-remb"));
1406 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1407
1408 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* nack"));
1409 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1410}
1411
1413 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
1414{
1415 int idx;
1416 char extmap_value[256];
1417
1418 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1419 return;
1420 }
1421
1422 /* RTP extension local unique identifiers start at '1' */
1423 for (idx = 1; idx <= ast_rtp_instance_extmap_count(session_media->rtp); ++idx) {
1425 const char *direction_str = "";
1426 pj_str_t stmp;
1427 pjmedia_sdp_attr *attr;
1428
1429 /* If this is an unsupported RTP extension we can't place it into the SDP */
1431 continue;
1432 }
1433
1434 switch (ast_rtp_instance_extmap_get_direction(session_media->rtp, idx)) {
1436 /* Lack of a direction indicates sendrecv, so we leave it out */
1437 direction_str = "";
1438 break;
1440 direction_str = "/sendonly";
1441 break;
1443 direction_str = "/recvonly";
1444 break;
1446 /* It is impossible for a "none" direction extension to be negotiated but just in case
1447 * we treat it as inactive.
1448 */
1450 direction_str = "/inactive";
1451 break;
1452 }
1453
1454 snprintf(extmap_value, sizeof(extmap_value), "%d%s %s", idx, direction_str,
1455 ast_rtp_instance_extmap_get_uri(session_media->rtp, idx));
1456 attr = pjmedia_sdp_attr_create(pool, "extmap", pj_cstr(&stmp, extmap_value));
1457 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1458 }
1459}
1460
1461/*! \brief Function which processes extmap attributes in a stream */
1463 const struct pjmedia_sdp_media *remote_stream)
1464{
1465 int index;
1466
1467 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1468 return;
1469 }
1470
1471 ast_rtp_instance_extmap_clear(session_media->rtp);
1472
1473 for (index = 0; index < remote_stream->attr_count; ++index) {
1474 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1475 char attr_value[pj_strlen(&attr->value) + 1];
1476 char *uri;
1477 int id;
1478 char direction_str[10] = "";
1479 char *attributes;
1481
1482 /* We only care about extmap attributes */
1483 if (pj_strcmp2(&attr->name, "extmap")) {
1484 continue;
1485 }
1486
1487 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1488
1489 /* Split the combined unique identifier and direction away from the URI and attributes for easier parsing */
1490 uri = strchr(attr_value, ' ');
1491 if (ast_strlen_zero(uri)) {
1492 continue;
1493 }
1494 *uri++ = '\0';
1495
1496 if ((sscanf(attr_value, "%30d%9s", &id, direction_str) < 1) || (id < 1)) {
1497 /* We require at a minimum the unique identifier */
1498 continue;
1499 }
1500
1501 /* Convert from the string to the internal representation */
1502 if (!strcasecmp(direction_str, "/sendonly")) {
1504 } else if (!strcasecmp(direction_str, "/recvonly")) {
1506 } else if (!strcasecmp(direction_str, "/inactive")) {
1508 }
1509
1510 attributes = strchr(uri, ' ');
1511 if (!ast_strlen_zero(attributes)) {
1512 *attributes++ = '\0';
1513 }
1514
1515 ast_rtp_instance_extmap_negotiate(session_media->rtp, id, direction, uri, attributes);
1516 }
1517}
1518
1520 const struct ast_sip_session *session,
1521 const pjmedia_sdp_media *media,
1522 const struct ast_stream *stream,
1523 const struct ast_sockaddr *addrs)
1524{
1526 (session_media->type == AST_MEDIA_TYPE_AUDIO)) {
1527 if (((addrs != NULL) && ast_sockaddr_isnull(addrs)) ||
1528 ((addrs != NULL) && ast_sockaddr_is_any(addrs)) ||
1529 pjmedia_sdp_media_find_attr2(media, "sendonly", NULL) ||
1530 pjmedia_sdp_media_find_attr2(media, "inactive", NULL)) {
1531 if (!session_media->remotely_held) {
1532 session_media->remotely_held = 1;
1533 session_media->remotely_held_changed = 1;
1534 }
1535 } else if (session_media->remotely_held) {
1536 session_media->remotely_held = 0;
1537 session_media->remotely_held_changed = 1;
1538 }
1539 }
1540}
1541
1542/*! \brief Function which negotiates an incoming media stream */
1544 struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp,
1545 int index, struct ast_stream *asterisk_stream)
1546{
1547 char host[NI_MAXHOST];
1548 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
1549 pjmedia_sdp_media *stream = sdp->media[index];
1550 struct ast_sip_session_media *session_media_transport;
1551 enum ast_media_type media_type = session_media->type;
1553 struct ast_format_cap *joint;
1554 int res;
1556
1557 /* If no type formats have been configured reject this stream */
1558 if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
1559 ast_debug(3, "Endpoint has no codecs for media type '%s', declining stream\n",
1560 ast_codec_media_type2str(session_media->type));
1561 SCOPE_EXIT_RTN_VALUE(0, "Endpoint has no codecs\n");
1562 }
1563
1564 /* Ensure incoming transport is compatible with the endpoint's configuration */
1565 if (!session->endpoint->media.rtp.use_received_transport) {
1566 encryption = check_endpoint_media_transport(session->endpoint, stream);
1567
1568 if (encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) {
1569 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
1570 }
1571 }
1572
1573 ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
1574
1575 /* Ensure that the address provided is valid */
1576 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1577 /* The provided host was actually invalid so we error out this negotiation */
1578 SCOPE_EXIT_RTN_VALUE(-1, "Invalid host\n");
1579 }
1580
1581 /* Using the connection information create an appropriate RTP instance */
1582 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
1583 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
1584 }
1585
1586 process_ssrc_attributes(session, session_media, stream);
1587 process_extmap_attributes(session, session_media, stream);
1588 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1589
1590 if (session_media_transport == session_media || !session_media->bundled) {
1591 /* If this media session is carrying actual traffic then set up those aspects */
1592 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(stream, "rtcp-mux", NULL) != NULL);
1593 set_ice_components(session, session_media);
1594
1595 enable_rtcp(session, session_media, stream);
1596
1597 res = setup_media_encryption(session, session_media, sdp, stream);
1598 if (res) {
1599 if (!session->endpoint->media.rtp.encryption_optimistic ||
1600 !pj_strncmp2(&stream->desc.transport, "RTP/SAVP", 8)) {
1601 /* If optimistic encryption is disabled and crypto should have been enabled
1602 * but was not this session must fail. This must also fail if crypto was
1603 * required in the offer but could not be set up.
1604 */
1605 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
1606 }
1607 /* There is no encryption, sad. */
1608 session_media->encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
1609 }
1610
1611 /* If we've been explicitly configured to use the received transport OR if
1612 * encryption is on and crypto is present use the received transport.
1613 * This is done in case of optimistic because it may come in as RTP/AVP or RTP/SAVP depending
1614 * on the configuration of the remote endpoint (optimistic themselves or mandatory).
1615 */
1616 if ((session->endpoint->media.rtp.use_received_transport) ||
1617 ((encryption == AST_SIP_MEDIA_ENCRYPT_SDES) && !res)) {
1618 pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport);
1619 }
1620 } else {
1621 /* This is bundled with another session, so mark it as such */
1622 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
1623
1624 enable_rtcp(session, session_media, stream);
1625 }
1626
1627 /* If ICE support is enabled find all the needed attributes */
1628 check_ice_support(session, session_media, stream);
1629
1630 /* If ICE support is enabled then check remote ICE started? */
1631 if (session_media->remote_ice) {
1632 process_ice_auth_attrb(session, session_media, sdp, stream);
1633 }
1634
1635 /* Check if incoming SDP is changing the remotely held state */
1636 set_session_media_remotely_held(session_media, session, stream, asterisk_stream, addrs);
1637
1638 joint = set_incoming_call_offer_cap(session, session_media, stream);
1639 res = apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
1640 ao2_cleanup(joint);
1641 if (res != 0) {
1642 SCOPE_EXIT_RTN_VALUE(0, "Something failed\n");
1643 }
1644
1646}
1647
1649 struct ast_sip_session_media *session_media,
1650 pj_pool_t *pool, pjmedia_sdp_media *media)
1651{
1652 pj_str_t stmp;
1653 pjmedia_sdp_attr *attr;
1654 enum ast_rtp_dtls_hash hash;
1655 const char *crypto_attribute;
1656 struct ast_rtp_engine_dtls *dtls;
1657 struct ast_sdp_srtp *tmp;
1658 static const pj_str_t STR_NEW = { "new", 3 };
1659 static const pj_str_t STR_EXISTING = { "existing", 8 };
1660 static const pj_str_t STR_ACTIVE = { "active", 6 };
1661 static const pj_str_t STR_PASSIVE = { "passive", 7 };
1662 static const pj_str_t STR_ACTPASS = { "actpass", 7 };
1663 static const pj_str_t STR_HOLDCONN = { "holdconn", 8 };
1664 static const pj_str_t STR_MEDSECREQ = { "requested", 9 };
1665 enum ast_rtp_dtls_setup setup;
1666
1667 switch (session_media->encryption) {
1670 break;
1672 if (!session_media->srtp) {
1673 session_media->srtp = ast_sdp_srtp_alloc();
1674 if (!session_media->srtp) {
1675 return -1;
1676 }
1677 }
1678
1679 tmp = session_media->srtp;
1680
1681 do {
1682 crypto_attribute = ast_sdp_srtp_get_attrib(tmp,
1683 0 /* DTLS running? No */,
1684 session->endpoint->media.rtp.srtp_tag_32 /* 32 byte tag length? */);
1685 if (!crypto_attribute) {
1686 /* No crypto attribute to add, bad news */
1687 return -1;
1688 }
1689
1690 attr = pjmedia_sdp_attr_create(pool, "crypto",
1691 pj_cstr(&stmp, crypto_attribute));
1692 media->attr[media->attr_count++] = attr;
1693 } while ((tmp = AST_LIST_NEXT(tmp, sdp_srtp_list)));
1694
1695 if (session->endpoint->security_negotiation == AST_SIP_SECURITY_NEG_MEDIASEC) {
1696 attr = pjmedia_sdp_attr_create(pool, "3ge2ae", &STR_MEDSECREQ);
1697 media->attr[media->attr_count++] = attr;
1698 }
1699
1700 break;
1702 if (setup_dtls_srtp(session, session_media)) {
1703 return -1;
1704 }
1705
1706 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1707 if (!dtls) {
1708 return -1;
1709 }
1710
1711 switch (dtls->get_connection(session_media->rtp)) {
1713 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_NEW);
1714 media->attr[media->attr_count++] = attr;
1715 break;
1717 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_EXISTING);
1718 media->attr[media->attr_count++] = attr;
1719 break;
1720 default:
1721 break;
1722 }
1723
1724 /* If this is an answer we need to use our current state, if it's an offer we need to use
1725 * the configured value.
1726 */
1727 if (session->inv_session->neg
1728 && pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
1729 setup = dtls->get_setup(session_media->rtp);
1730 } else {
1731 setup = session->endpoint->media.rtp.dtls_cfg.default_setup;
1732 }
1733
1734 switch (setup) {
1736 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTIVE);
1737 media->attr[media->attr_count++] = attr;
1738 break;
1740 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_PASSIVE);
1741 media->attr[media->attr_count++] = attr;
1742 break;
1744 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTPASS);
1745 media->attr[media->attr_count++] = attr;
1746 break;
1748 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_HOLDCONN);
1749 break;
1750 default:
1751 break;
1752 }
1753
1754 hash = dtls->get_fingerprint_hash(session_media->rtp);
1755 crypto_attribute = dtls->get_fingerprint(session_media->rtp);
1756 if (crypto_attribute && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
1757 RAII_VAR(struct ast_str *, fingerprint, ast_str_create(64), ast_free);
1758 if (!fingerprint) {
1759 return -1;
1760 }
1761
1762 if (hash == AST_RTP_DTLS_HASH_SHA1) {
1763 ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
1764 } else {
1765 ast_str_set(&fingerprint, 0, "SHA-256 %s", crypto_attribute);
1766 }
1767
1768 attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
1769 media->attr[media->attr_count++] = attr;
1770 }
1771 break;
1772 }
1773
1774 return 0;
1775}
1776
1777/*! \brief Function which creates an outgoing stream */
1779 struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
1780{
1781 pj_pool_t *pool = session->inv_session->pool_prov;
1782 static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };
1783 static const pj_str_t STR_IN = { "IN", 2 };
1784 static const pj_str_t STR_IP4 = { "IP4", 3};
1785 static const pj_str_t STR_IP6 = { "IP6", 3};
1786 static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
1787 static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
1788 static const pj_str_t STR_INACTIVE = { "inactive", 8 };
1789 static const pj_str_t STR_RECVONLY = { "recvonly", 8 };
1790 pjmedia_sdp_media *media;
1791 const char *hostip = NULL;
1792 struct ast_sockaddr addr;
1793 char tmp[512];
1794 pj_str_t stmp;
1795 pjmedia_sdp_attr *attr;
1796 int index = 0;
1797 int noncodec = (session->dtmf == AST_SIP_DTMF_RFC_4733 || session->dtmf == AST_SIP_DTMF_AUTO || session->dtmf == AST_SIP_DTMF_AUTO_INFO) ? AST_RTP_DTMF : 0;
1798 int min_packet_size = 0, max_packet_size = 0;
1799 int rtp_code;
1800 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1801 enum ast_media_type media_type = session_media->type;
1802 struct ast_sip_session_media *session_media_transport;
1803 pj_sockaddr ip;
1804 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
1805 ast_format_cap_count(session->direct_media_cap);
1806
1807 /* Keep track of the sample rates for offered codecs so we can build matching
1808 RFC 2833/4733 payload offers. */
1809 AST_VECTOR(, int) sample_rates;
1810 /* In case we can't init the sample rates, still try to do the rest. */
1811 int build_dtmf_sample_rates = 1;
1812
1813 SCOPE_ENTER(1, "%s Type: %s %s\n", ast_sip_session_get_name(session),
1814 ast_codec_media_type2str(media_type), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
1815
1816 media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media));
1817 if (!media) {
1818 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
1819 }
1820 pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
1821
1822 /* If this is a removed (or declined) stream OR if no formats exist then construct a minimal stream in SDP */
1825 media->desc.port = 0;
1826 media->desc.port_count = 1;
1827
1828 if (remote && remote->media[ast_stream_get_position(stream)]) {
1829 pjmedia_sdp_media *remote_media = remote->media[ast_stream_get_position(stream)];
1830 int index;
1831
1832 media->desc.transport = remote_media->desc.transport;
1833
1834 /* Preserve existing behavior by copying the formats provided from the offer */
1835 for (index = 0; index < remote_media->desc.fmt_count; ++index) {
1836 media->desc.fmt[index] = remote_media->desc.fmt[index];
1837 }
1838 media->desc.fmt_count = remote_media->desc.fmt_count;
1839 } else {
1840 /* This is actually an offer so put a dummy payload in that is ignored and sane transport */
1841 media->desc.transport = STR_RTP_AVP;
1842 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], "32");
1843 }
1844
1845 sdp->media[sdp->media_count++] = media;
1847
1848 SCOPE_EXIT_RTN_VALUE(1, "Stream removed or no formats\n");
1849 }
1850
1851 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
1852 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
1853 }
1854
1855 /* If this stream has not been bundled already it is new and we need to ensure there is no SSRC conflict */
1856 if (session_media->bundle_group != -1 && !session_media->bundled) {
1857 for (index = 0; index < sdp->media_count; ++index) {
1858 struct ast_sip_session_media *other_session_media;
1859
1860 other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);
1861 if (!other_session_media->rtp || other_session_media->bundle_group != session_media->bundle_group) {
1862 continue;
1863 }
1864
1865 if (ast_rtp_instance_get_ssrc(session_media->rtp) == ast_rtp_instance_get_ssrc(other_session_media->rtp)) {
1866 ast_rtp_instance_change_source(session_media->rtp);
1867 /* Start the conflict check over again */
1868 index = -1;
1869 continue;
1870 }
1871 }
1872 }
1873
1874 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1875
1876 if (session_media_transport == session_media || !session_media->bundled) {
1877 set_ice_components(session, session_media);
1878 enable_rtcp(session, session_media, NULL);
1879
1880 /* Crypto has to be added before setting the media transport so that SRTP is properly
1881 * set up according to the configuration. This ends up changing the media transport.
1882 */
1883 if (add_crypto_to_stream(session, session_media, pool, media)) {
1884 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
1885 }
1886
1887 if (pj_strlen(&session_media->transport)) {
1888 /* If a transport has already been specified use it */
1889 media->desc.transport = session_media->transport;
1890 } else {
1891 media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
1892 /* Optimistic encryption places crypto in the normal RTP/AVP profile */
1893 !session->endpoint->media.rtp.encryption_optimistic &&
1894 (session_media->encryption == AST_SIP_MEDIA_ENCRYPT_SDES),
1895 session_media->rtp, session->endpoint->media.rtp.use_avpf,
1896 session->endpoint->media.rtp.force_avp));
1897 }
1898
1899 media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn));
1900 if (!media->conn) {
1901 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
1902 }
1903
1904 /* Add connection level details */
1905 if (direct_media_enabled) {
1907 } else if (ast_strlen_zero(session->endpoint->media.address)) {
1908 hostip = ast_sip_get_host_ip_string(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET());
1909 } else {
1910 hostip = session->endpoint->media.address;
1911 }
1912
1913 if (ast_strlen_zero(hostip)) {
1914 ast_log(LOG_ERROR, "No local host IP available for stream %s\n",
1915 ast_codec_media_type2str(session_media->type));
1916 SCOPE_EXIT_RTN_VALUE(-1, "No local host ip\n");
1917 }
1918
1919 media->conn->net_type = STR_IN;
1920 /* Assume that the connection will use IPv4 until proven otherwise */
1921 media->conn->addr_type = STR_IP4;
1922 pj_strdup2(pool, &media->conn->addr, hostip);
1923
1924 if ((pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &media->conn->addr, &ip) == PJ_SUCCESS) &&
1925 (ip.addr.sa_family == pj_AF_INET6())) {
1926 media->conn->addr_type = STR_IP6;
1927 }
1928
1929 /* Add ICE attributes and candidates */
1930 add_ice_to_stream(session, session_media, pool, media, 1);
1931
1932 ast_rtp_instance_get_local_address(session_media->rtp, &addr);
1933 media->desc.port = direct_media_enabled ? ast_sockaddr_port(&session_media->direct_media_addr) : (pj_uint16_t) ast_sockaddr_port(&addr);
1934 media->desc.port_count = 1;
1935 } else {
1936 pjmedia_sdp_media *bundle_group_stream = sdp->media[session_media_transport->stream_num];
1937
1938 /* As this is in a bundle group it shares the same details as the group instance */
1939 media->desc.transport = bundle_group_stream->desc.transport;
1940 media->conn = bundle_group_stream->conn;
1941 media->desc.port = bundle_group_stream->desc.port;
1942
1943 if (add_crypto_to_stream(session, session_media_transport, pool, media)) {
1944 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
1945 }
1946
1947 add_ice_to_stream(session, session_media_transport, pool, media, 0);
1948
1949 enable_rtcp(session, session_media, NULL);
1950 }
1951
1953 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
1954 ast_codec_media_type2str(session_media->type));
1955 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create caps\n");
1956 }
1957
1958 if (direct_media_enabled) {
1959 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
1960 } else {
1961 ast_format_cap_append_from_cap(caps, ast_stream_get_formats(stream), media_type);
1962 }
1963
1964 /* Init the sample rates before we start adding them. Assume we will have at least one. */
1965 if (AST_VECTOR_INIT(&sample_rates, 1)) {
1966 ast_log(LOG_ERROR, "Unable to add dtmf formats to SDP!\n");
1967 build_dtmf_sample_rates = 0;
1968 }
1969
1970 for (index = 0; index < ast_format_cap_count(caps); ++index) {
1971 struct ast_format *format = ast_format_cap_get_format(caps, index);
1972
1973 if (ast_format_get_type(format) != media_type) {
1974 ao2_ref(format, -1);
1975 continue;
1976 }
1977
1978 /* It is possible for some formats not to have SDP information available for them
1979 * and if this is the case, skip over them so the SDP can still be created.
1980 */
1981 if (!ast_rtp_lookup_sample_rate2(1, format, 0)) {
1982 ast_log(LOG_WARNING, "Format '%s' can not be added to SDP, consider disallowing it on endpoint '%s'\n",
1984 ao2_ref(format, -1);
1985 continue;
1986 }
1987
1988 /* If this stream is not a transport we need to use the transport codecs structure for payload management to prevent
1989 * conflicts.
1990 */
1991 if (session_media_transport != session_media) {
1992 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media_transport->rtp), 1, format, 0)) == -1) {
1993 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
1994 ao2_ref(format, -1);
1995 continue;
1996 }
1997 /* Our instance has to match the payload number though */
1998 ast_rtp_codecs_payload_set_rx(ast_rtp_instance_get_codecs(session_media->rtp), rtp_code, format);
1999 } else {
2000 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0)) == -1) {
2001 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
2002 ao2_ref(format, -1);
2003 continue;
2004 }
2005 }
2006
2007 if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 1, format, 0))) {
2008 int i, added = 0;
2009 int newrate = ast_rtp_lookup_sample_rate2(1, format, 0);
2010 if (build_dtmf_sample_rates) {
2011 for (i = 0; i < AST_VECTOR_SIZE(&sample_rates); i++) {
2012 /* Only add if we haven't already processed this sample rate. For instance
2013 A-law and u-law 'share' one 8K DTMF payload type. */
2014 if (newrate == AST_VECTOR_GET(&sample_rates, i)) {
2015 added = 1;
2016 break;
2017 }
2018 }
2019
2020 if (!added) {
2021 AST_VECTOR_APPEND(&sample_rates, newrate);
2022 }
2023 }
2024 media->attr[media->attr_count++] = attr;
2025 }
2026
2027 if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
2028 media->attr[media->attr_count++] = attr;
2029 }
2030
2031 if (ast_format_get_maximum_ms(format) &&
2032 ((ast_format_get_maximum_ms(format) < max_packet_size) || !max_packet_size)) {
2033 max_packet_size = ast_format_get_maximum_ms(format);
2034 }
2035 ao2_ref(format, -1);
2036
2037 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2038 break;
2039 }
2040 }
2041
2042 /* Add non-codec formats */
2044 && media->desc.fmt_count < PJMEDIA_MAX_SDP_FMT) {
2045 for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) {
2046 if (!(noncodec & index)) {
2047 continue;
2048 }
2049
2050 if (index != AST_RTP_DTMF) {
2051 rtp_code = ast_rtp_codecs_payload_code(
2052 ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index);
2053 if (rtp_code == -1) {
2054 continue;
2055 } else if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
2056 media->attr[media->attr_count++] = attr;
2057 }
2058 } else if (build_dtmf_sample_rates) {
2059 /*
2060 * Walk through the possible bitrates for the RFC 2833/4733 digits and generate the rtpmap
2061 * attributes.
2062 */
2063 int i, found_default_offer = 0;
2064 for (i = 0; i < AST_VECTOR_SIZE(&sample_rates); i++) {
2066 ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index, AST_VECTOR_GET(&sample_rates, i));
2067
2068 if (rtp_code == -1) {
2069 continue;
2070 }
2071
2072 if (AST_VECTOR_GET(&sample_rates, i) == DEFAULT_DTMF_SAMPLE_RATE_MS) {
2073 /* we found and added a default offer, so no need to include a default one.*/
2074 found_default_offer = 1;
2075 }
2076
2077 if ((attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index, AST_VECTOR_GET(&sample_rates, i)))) {
2078 media->attr[media->attr_count++] = attr;
2079 snprintf(tmp, sizeof(tmp), "%d 0-16", (rtp_code));
2080 attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2081 media->attr[media->attr_count++] = attr;
2082 }
2083 }
2084
2085 /* If we weren't able to add any matching RFC 2833/4733, assume this endpoint is using a
2086 * mismatched 8K offer and try to add one as a fall-back/default.
2087 */
2088 if (!found_default_offer) {
2091
2092 if (rtp_code != -1 && (attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index, DEFAULT_DTMF_SAMPLE_RATE_MS))) {
2093 media->attr[media->attr_count++] = attr;
2094 snprintf(tmp, sizeof(tmp), "%d 0-16", (rtp_code));
2095 attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2096 media->attr[media->attr_count++] = attr;
2097 }
2098 }
2099 }
2100
2101 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2102 break;
2103 }
2104 }
2105 }
2106
2107 /* we are done with the sample rates */
2108 AST_VECTOR_FREE(&sample_rates);
2109
2110 /* If no formats were actually added to the media stream don't add it to the SDP */
2111 if (!media->desc.fmt_count) {
2112 SCOPE_EXIT_RTN_VALUE(1, "No formats added to stream\n");
2113 }
2114
2115 /* If ptime is set add it as an attribute */
2116 min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(session_media->rtp));
2117 if (!min_packet_size) {
2118 min_packet_size = ast_format_cap_get_framing(caps);
2119 }
2120 if (min_packet_size) {
2121 snprintf(tmp, sizeof(tmp), "%d", min_packet_size);
2122 attr = pjmedia_sdp_attr_create(pool, "ptime", pj_cstr(&stmp, tmp));
2123 media->attr[media->attr_count++] = attr;
2124 }
2125
2126 if (max_packet_size) {
2127 snprintf(tmp, sizeof(tmp), "%d", max_packet_size);
2128 attr = pjmedia_sdp_attr_create(pool, "maxptime", pj_cstr(&stmp, tmp));
2129 media->attr[media->attr_count++] = attr;
2130 }
2131
2132 attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
2133 if (session_media->locally_held) {
2134 if (session_media->remotely_held) {
2135 attr->name = STR_INACTIVE; /* To place on hold a recvonly stream, send inactive */
2136 } else {
2137 attr->name = STR_SENDONLY; /* Send sendonly to initate a local hold */
2138 }
2139 } else {
2140 if (session_media->remotely_held) {
2141 attr->name = STR_RECVONLY; /* Remote has sent sendonly, reply recvonly */
2142 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
2143 attr->name = STR_SENDONLY; /* Stream has requested sendonly */
2144 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_RECVONLY) {
2145 attr->name = STR_RECVONLY; /* Stream has requested recvonly */
2146 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_INACTIVE) {
2147 attr->name = STR_INACTIVE; /* Stream has requested inactive */
2148 } else {
2149 attr->name = STR_SENDRECV; /* No hold in either direction */
2150 }
2151 }
2152 media->attr[media->attr_count++] = attr;
2153
2154 /* If we've got rtcp-mux enabled, add it unless we received an offer without it */
2155 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
2156 attr = pjmedia_sdp_attr_create(pool, "rtcp-mux", NULL);
2157 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
2158 }
2159
2160 add_ssrc_to_stream(session, session_media, pool, media);
2161 add_msid_to_stream(session, session_media, pool, media, stream);
2162 add_rtcp_fb_to_stream(session, session_media, pool, media);
2163 add_extmap_to_stream(session, session_media, pool, media);
2164
2165 /* Add the media stream to the SDP */
2166 sdp->media[sdp->media_count++] = media;
2167
2168 SCOPE_EXIT_RTN_VALUE(1, "RC: 1\n");
2169}
2170
2172{
2173 struct ast_frame *f;
2174
2175 if (!session_media->rtp) {
2176 return &ast_null_frame;
2177 }
2178
2179 f = ast_rtp_instance_read(session_media->rtp, 0);
2180 if (!f) {
2181 return NULL;
2182 }
2183
2184 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2185
2186 return f;
2187}
2188
2190{
2191 struct ast_frame *f;
2192
2193 if (!session_media->rtp) {
2194 return &ast_null_frame;
2195 }
2196
2197 f = ast_rtp_instance_read(session_media->rtp, 1);
2198 if (!f) {
2199 return NULL;
2200 }
2201
2202 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2203
2204 return f;
2205}
2206
2207static int media_session_rtp_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
2208{
2209 if (!session_media->rtp) {
2210 return 0;
2211 }
2212
2213 return ast_rtp_instance_write(session_media->rtp, frame);
2214}
2215
2217 struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local,
2218 const struct pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
2219{
2220 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
2221 struct pjmedia_sdp_media *remote_stream = remote->media[index];
2222 enum ast_media_type media_type = session_media->type;
2223 char host[NI_MAXHOST];
2224 int res;
2225 int rtp_timeout;
2226 struct ast_sip_session_media *session_media_transport;
2227 SCOPE_ENTER(1, "%s Stream: %s\n", ast_sip_session_get_name(session),
2228 ast_str_tmp(128, ast_stream_to_str(asterisk_stream, &STR_TMP)));
2229
2230 if (!session->channel) {
2231 SCOPE_EXIT_RTN_VALUE(1, "No channel\n");
2232 }
2233
2234 /* Ensure incoming transport is compatible with the endpoint's configuration */
2235 if (!session->endpoint->media.rtp.use_received_transport &&
2237 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
2238 }
2239
2240 /* Create an RTP instance if need be */
2241 if (!session_media->rtp && create_rtp(session, session_media, local)) {
2242 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
2243 }
2244
2245 process_ssrc_attributes(session, session_media, remote_stream);
2246 process_extmap_attributes(session, session_media, remote_stream);
2247
2248 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
2249
2250 if (session_media_transport == session_media || !session_media->bundled) {
2251 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(remote_stream, "rtcp-mux", NULL) != NULL);
2252 set_ice_components(session, session_media);
2253
2254 enable_rtcp(session, session_media, remote_stream);
2255
2256 res = setup_media_encryption(session, session_media, remote, remote_stream);
2257 if (!session->endpoint->media.rtp.encryption_optimistic && res) {
2258 /* If optimistic encryption is disabled and crypto should have been enabled but was not
2259 * this session must fail.
2260 */
2261 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
2262 }
2263
2264 if (!remote_stream->conn && !remote->conn) {
2265 SCOPE_EXIT_RTN_VALUE(1, "No connection info\n");
2266 }
2267
2268 ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
2269
2270 /* Ensure that the address provided is valid */
2271 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
2272 /* The provided host was actually invalid so we error out this negotiation */
2273 SCOPE_EXIT_RTN_VALUE(-1, "Host invalid\n");
2274 }
2275
2276 /* Apply connection information to the RTP instance */
2277 ast_sockaddr_set_port(addrs, remote_stream->desc.port);
2278 ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
2279
2283 if (!session->endpoint->media.rtcp_mux || !session_media->remote_rtcp_mux) {
2286 }
2287
2288 /* If ICE support is enabled find all the needed attributes */
2289 process_ice_attributes(session, session_media, remote, remote_stream);
2290 } else {
2291 /* This is bundled with another session, so mark it as such */
2292 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
2294 enable_rtcp(session, session_media, remote_stream);
2295 }
2296
2297 if (set_caps(session, session_media, session_media_transport, remote_stream, 0, asterisk_stream)) {
2298 SCOPE_EXIT_RTN_VALUE(-1, "set_caps failed\n");
2299 }
2300
2301 /* Set the channel uniqueid on the RTP instance now that it is becoming active */
2302 ast_channel_lock(session->channel);
2304 ast_channel_unlock(session->channel);
2305
2306 /* Ensure the RTP instance is active */
2307 ast_rtp_instance_set_stream_num(session_media->rtp, ast_stream_get_position(asterisk_stream));
2308 ast_rtp_instance_activate(session_media->rtp);
2309
2310 /* audio stream handles music on hold */
2311 if (media_type != AST_MEDIA_TYPE_AUDIO && media_type != AST_MEDIA_TYPE_VIDEO) {
2312 if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2313 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2315 }
2316 SCOPE_EXIT_RTN_VALUE(1, "moh\n");
2317 }
2318
2319 set_session_media_remotely_held(session_media, session, remote_stream, asterisk_stream, addrs);
2320
2321 if (session_media->remotely_held_changed) {
2322 if (session_media->remotely_held) {
2323 /* The remote side has put us on hold */
2324 ast_queue_hold(session->channel, session->endpoint->mohsuggest);
2325 ast_rtp_instance_stop(session_media->rtp);
2327 session_media->remotely_held_changed = 0;
2328 } else {
2329 /* The remote side has taken us off hold */
2330 ast_queue_unhold(session->channel);
2332 session_media->remotely_held_changed = 0;
2333 }
2334 } else if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2335 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2337 }
2338
2339 /* This purposely resets the encryption to the configured in case it gets added later */
2340 session_media->encryption = session->endpoint->media.rtp.encryption;
2341
2342 if (session->endpoint->media.rtp.keepalive > 0 &&
2343 (session_media->type == AST_MEDIA_TYPE_AUDIO ||
2344 session_media->type == AST_MEDIA_TYPE_VIDEO)) {
2345 ast_rtp_instance_set_keepalive(session_media->rtp, session->endpoint->media.rtp.keepalive);
2346 /* Schedule the initial keepalive early in case this is being used to punch holes through
2347 * a NAT. This way there won't be an awkward delay before media starts flowing in some
2348 * scenarios.
2349 */
2350 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2352 session_media, 1);
2353 }
2354
2355 /* As the channel lock is not held during this process the scheduled item won't block if
2356 * it is hanging up the channel at the same point we are applying this negotiated SDP.
2357 */
2358 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2359
2360 /* Due to the fact that we only ever have one scheduled timeout item for when we are both
2361 * off hold and on hold we don't need to store the two timeouts differently on the RTP
2362 * instance itself.
2363 */
2364 ast_rtp_instance_set_timeout(session_media->rtp, 0);
2365 if (session->endpoint->media.rtp.timeout && !session_media->remotely_held && !session_media->locally_held) {
2366 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout);
2367 } else if (session->endpoint->media.rtp.timeout_hold && (session_media->remotely_held || session_media->locally_held)) {
2368 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout_hold);
2369 }
2370
2371 rtp_timeout = ast_rtp_instance_get_timeout(session_media->rtp);
2372
2373 if (rtp_timeout) {
2374 session_media->timeout_sched_id = ast_sched_add_variable(sched, rtp_timeout*1000, rtp_check_timeout,
2375 session_media, 1);
2376 }
2377
2378 SCOPE_EXIT_RTN_VALUE(1, "Handled\n");
2379}
2380
2381/*! \brief Function which updates the media stream with external media address, if applicable */
2382static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struct pjmedia_sdp_media *stream, struct ast_sip_transport *transport)
2383{
2385 char host[NI_MAXHOST];
2386 struct ast_sockaddr our_sdp_addr = { { 0, } };
2387
2388 /* If the stream has been rejected there will be no connection line */
2389 if (!stream->conn || !transport_state) {
2390 return;
2391 }
2392
2393 ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
2394 ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
2395
2396 /* Reversed check here. We don't check the remote endpoint being
2397 * in our local net, but whether our outgoing session IP is
2398 * local. If it is not, we won't do rewriting. No localnet
2399 * configured? Always rewrite. */
2400 if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
2401 return;
2402 }
2403 ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2404 pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2405}
2406
2407/*! \brief Function which stops the RTP instance */
2408static void stream_stop(struct ast_sip_session_media *session_media)
2409{
2410 if (!session_media->rtp) {
2411 return;
2412 }
2413
2414 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2415 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2416 ast_rtp_instance_stop(session_media->rtp);
2417}
2418
2419/*! \brief Function which destroys the RTP instance when session ends */
2420static void stream_destroy(struct ast_sip_session_media *session_media)
2421{
2422 if (session_media->rtp) {
2423 stream_stop(session_media);
2424 ast_rtp_instance_destroy(session_media->rtp);
2425 }
2426 session_media->rtp = NULL;
2427}
2428
2429/*! \brief SDP handler for 'audio' media stream */
2431 .id = STR_AUDIO,
2432 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
2433 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
2434 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
2435 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
2436 .stream_stop = stream_stop,
2437 .stream_destroy = stream_destroy,
2438};
2439
2440/*! \brief SDP handler for 'video' media stream */
2442 .id = STR_VIDEO,
2443 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
2444 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
2445 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
2446 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
2447 .stream_stop = stream_stop,
2448 .stream_destroy = stream_destroy,
2449};
2450
2451static int video_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
2452{
2453 struct pjsip_transaction *tsx;
2454 pjsip_tx_data *tdata;
2455
2456 if (!session->channel
2457 || !ast_sip_are_media_types_equal(&rdata->msg_info.msg->body->content_type,
2459 return 0;
2460 }
2461
2462 tsx = pjsip_rdata_get_tsx(rdata);
2463
2465
2466 if (pjsip_dlg_create_response(session->inv_session->dlg, rdata, 200, NULL, &tdata) == PJ_SUCCESS) {
2467 pjsip_dlg_send_response(session->inv_session->dlg, tsx, tdata);
2468 }
2469
2470 return 0;
2471}
2472
2474 .method = "INFO",
2475 .incoming_request = video_info_incoming_request,
2476};
2477
2478/*! \brief Unloads the sdp RTP/AVP module from Asterisk */
2479static int unload_module(void)
2480{
2484
2485 if (sched) {
2487 }
2488
2489 return 0;
2490}
2491
2492/*!
2493 * \brief Load the module
2494 *
2495 * Module loading including tests for configuration or dependencies.
2496 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
2497 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
2498 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
2499 * configuration file or other non-critical problem return
2500 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
2501 */
2502static int load_module(void)
2503{
2504 if (ast_check_ipv6()) {
2506 } else {
2507 ast_sockaddr_parse(&address_rtp, "0.0.0.0", 0);
2508 }
2509
2510 if (!(sched = ast_sched_context_create())) {
2511 ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
2512 goto end;
2513 }
2514
2516 ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
2517 goto end;
2518 }
2519
2521 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_AUDIO);
2522 goto end;
2523 }
2524
2526 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_VIDEO);
2527 goto end;
2528 }
2529
2531
2533end:
2534 unload_module();
2535
2537}
2538
2539AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP SDP RTP/AVP stream handler",
2540 .support_level = AST_MODULE_SUPPORT_CORE,
2541 .load = load_module,
2542 .unload = unload_module,
2543 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
2544 .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:2968
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:1250
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1158
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5781
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10567
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2490
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition: channel.c:1235
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition: channel.c:1210
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1141
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5822
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
#define ast_channel_unlock(chan)
Definition: channel.h:2969
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:331
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CHANNEL_DRIVER
Definition: module.h:341
@ 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:643
@ AST_SIP_MEDIA_ENCRYPT_SDES
Definition: res_pjsip.h:649
@ AST_SIP_MEDIA_TRANSPORT_INVALID
Definition: res_pjsip.h:645
@ AST_SIP_MEDIA_ENCRYPT_NONE
Definition: res_pjsip.h:647
@ AST_SIP_MEDIA_ENCRYPT_DTLS
Definition: res_pjsip.h:651
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 pjmedia_sdp_attr * generate_rtpmap_attr2(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool, int rtp_code, int asterisk_format, struct ast_format *format, int code, int sample_rate)
static void 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:564
@ AST_RTP_DTLS_SETUP_PASSIVE
Definition: rtp_engine.h:566
@ AST_RTP_DTLS_SETUP_HOLDCONN
Definition: rtp_engine.h:568
@ AST_RTP_DTLS_SETUP_ACTPASS
Definition: rtp_engine.h:567
@ AST_RTP_DTLS_SETUP_ACTIVE
Definition: rtp_engine.h:565
unsigned int ast_rtp_lookup_sample_rate2(int asterisk_format, const struct ast_format *format, int code)
Get the sample rate associated with known RTP payload types.
Definition: rtp_engine.c:2198
@ AST_RTP_ICE_ROLE_CONTROLLING
Definition: rtp_engine.h:521
@ AST_RTP_ICE_ROLE_CONTROLLED
Definition: rtp_engine.h:520
struct ast_format * ast_rtp_codecs_get_payload_format(struct ast_rtp_codecs *codecs, int payload)
Retrieve the actual ast_format stored on the codecs structure for a specific tx payload type.
Definition: rtp_engine.c:1650
void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
Destroy the contents of an RTP codecs structure (but not the structure itself)
Definition: rtp_engine.c:996
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
Definition: rtp_engine.c:2313
int ast_rtp_codecs_payload_set_rx(struct ast_rtp_codecs *codecs, int code, struct ast_format *format)
Set a payload code for use with a specific Asterisk format.
Definition: rtp_engine.c:2075
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:487
void ast_rtp_instance_set_last_rx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP reception time.
Definition: rtp_engine.c:4006
ast_rtp_dtls_hash
DTLS fingerprint hashes.
Definition: rtp_engine.h:578
@ AST_RTP_DTLS_HASH_SHA1
Definition: rtp_engine.h:580
@ AST_RTP_DTLS_HASH_SHA256
Definition: rtp_engine.h:579
@ AST_RTP_DTMF_MODE_RFC2833
Definition: rtp_engine.h:155
@ AST_RTP_DTMF_MODE_INBAND
Definition: rtp_engine.h:157
@ AST_RTP_DTMF_MODE_NONE
Definition: rtp_engine.h:153
int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
Set the DTMF mode that should be used.
Definition: rtp_engine.c:2299
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
Definition: rtp_engine.c:2359
#define AST_RTP_DTMF
Definition: rtp_engine.h:294
ast_rtp_instance_rtcp
Definition: rtp_engine.h:283
@ AST_RTP_INSTANCE_RTCP_MUX
Definition: rtp_engine.h:289
@ AST_RTP_INSTANCE_RTCP_STANDARD
Definition: rtp_engine.h:287
void ast_rtp_codecs_payloads_copy(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
Copy payload information from one RTP instance to another.
Definition: rtp_engine.c:1273
size_t ast_rtp_instance_extmap_count(struct ast_rtp_instance *instance)
Get the number of known unique identifiers.
Definition: rtp_engine.c:921
int ast_rtp_instance_extmap_enable(struct ast_rtp_instance *instance, int id, enum ast_rtp_extension extension, enum ast_rtp_extension_direction direction)
Enable support for an RTP extension on an instance.
Definition: rtp_engine.c:754
@ AST_RTP_INSTANCE_STAT_REMOTE_SSRC
Definition: rtp_engine.h:251
void ast_rtp_instance_set_stream_num(struct ast_rtp_instance *instance, int stream_num)
Set the stream number for an RTP instance.
Definition: rtp_engine.c:4063
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
Get the RTP keepalive interval.
Definition: rtp_engine.c:2895
const char * ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp)
Retrieve the CNAME used in RTCP SDES items.
Definition: rtp_engine.c:4024
int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
Get the RTP timeout value.
Definition: rtp_engine.c:2885
struct ast_rtp_engine_dtls * ast_rtp_instance_get_dtls(struct ast_rtp_instance *instance)
Obtain a pointer to the DTLS support present on an RTP instance.
Definition: rtp_engine.c:3211
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
Definition: rtp_engine.h:3099
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:600
int ast_rtp_instance_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
Request that an RTP instance be bundled with another.
Definition: rtp_engine.c:4037
void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
Set the framing used for a set of codecs.
Definition: rtp_engine.c:1671
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp)
Get the last RTP transmission time.
Definition: rtp_engine.c:3991
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Record tx payload type information that was seen in an m= SDP line.
Definition: rtp_engine.c:1356
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:727
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:665
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
Definition: rtp_engine.c:2622
@ AST_RTP_ICE_CANDIDATE_TYPE_RELAYED
Definition: rtp_engine.h:509
@ AST_RTP_ICE_CANDIDATE_TYPE_SRFLX
Definition: rtp_engine.h:508
@ AST_RTP_ICE_CANDIDATE_TYPE_HOST
Definition: rtp_engine.h:507
int ast_rtp_codecs_payload_code_sample_rate(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code, unsigned int sample_rate)
Retrieve a rx mapped payload type based on whether it is an Asterisk format, the code and the sample ...
Definition: rtp_engine.c:2024
enum ast_rtp_extension ast_rtp_instance_extmap_get_extension(struct ast_rtp_instance *instance, int id)
Retrieve the extension for an RTP extension id.
Definition: rtp_engine.c:932
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:590
ast_rtp_extension
Known RTP extensions.
Definition: rtp_engine.h:593
@ AST_RTP_EXTENSION_TRANSPORT_WIDE_CC
Definition: rtp_engine.h:599
@ AST_RTP_EXTENSION_ABS_SEND_TIME
Definition: rtp_engine.h:597
@ AST_RTP_EXTENSION_UNSUPPORTED
Definition: rtp_engine.h:595
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1138
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
Send a comfort noise packet to the RTP instance.
Definition: rtp_engine.c:2972
void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc)
Set the remote SSRC for an RTP instance.
Definition: rtp_engine.c:4054
struct ast_rtp_engine_ice * ast_rtp_instance_get_ice(struct ast_rtp_instance *instance)
Obtain a pointer to the ICE support present on an RTP instance.
Definition: rtp_engine.c:3091
ast_rtp_options
Definition: rtp_engine.h:145
@ AST_RTP_OPT_G726_NONSTANDARD
Definition: rtp_engine.h:147
@ AST_RTP_DTLS_CONNECTION_NEW
Definition: rtp_engine.h:573
@ AST_RTP_DTLS_CONNECTION_EXISTING
Definition: rtp_engine.h:574
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
Definition: rtp_engine.c:980
@ AST_RTP_PROPERTY_NAT
Definition: rtp_engine.h:118
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition: rtp_engine.h:130
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition: rtp_engine.h:132
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:126
@ AST_RTP_PROPERTY_ASYMMETRIC_CODEC
Definition: rtp_engine.h:128
@ AST_RTP_PROPERTY_DTMF
Definition: rtp_engine.h:120
@ AST_RTP_PROPERTY_REMB
Definition: rtp_engine.h:134
#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:3145
int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
Indicate to the RTP engine that packets are now expected to be sent/received on the RTP instance.
Definition: rtp_engine.c:2847
const char * ast_rtp_lookup_mime_subtype2(const int asterisk_format, const struct ast_format *format, int code, enum ast_rtp_options options)
Retrieve mime subtype information on a payload.
Definition: rtp_engine.c:2168
time_t ast_rtp_instance_get_last_rx(const struct ast_rtp_instance *rtp)
Get the last RTP reception time.
Definition: rtp_engine.c:4001
int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
Set QoS parameters on an RTP session.
Definition: rtp_engine.c:2345
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
Definition: rtp_engine.c:575
ast_rtp_extension_direction
Directions for RTP extensions.
Definition: rtp_engine.h:827
@ AST_RTP_EXTENSION_DIRECTION_SENDRECV
Definition: rtp_engine.h:831
@ AST_RTP_EXTENSION_DIRECTION_NONE
Definition: rtp_engine.h:829
@ AST_RTP_EXTENSION_DIRECTION_INACTIVE
Definition: rtp_engine.h:837
@ AST_RTP_EXTENSION_DIRECTION_RECVONLY
Definition: rtp_engine.h:835
@ AST_RTP_EXTENSION_DIRECTION_SENDONLY
Definition: rtp_engine.h:833
int ast_rtp_codecs_payload_replace_format(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
Update the format associated with a tx payload type in a codecs structure.
Definition: rtp_engine.c:1616
const char * ast_rtp_instance_extmap_get_uri(struct ast_rtp_instance *instance, int id)
Retrieve the URI for an RTP extension id.
Definition: rtp_engine.c:968
int ast_rtp_codecs_payloads_set_rtpmap_type_rate(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int pt, char *mimetype, char *mimesubtype, enum ast_rtp_options options, unsigned int sample_rate)
Set tx payload type to a known MIME media type for a codec with a specific sample rate.
Definition: rtp_engine.c:1398
int ast_rtp_codecs_set_preferred_dtmf_format(struct ast_rtp_codecs *codecs, int pt, int rate)
Set the preferred dtmf format pt and sample rate.
Definition: rtp_engine.c:1607
#define AST_RTP_CODECS_NULL_INIT
Definition: rtp_engine.h:773
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
Definition: rtp_engine.c:908
void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
Indicate a new source of audio has dropped in and the ssrc should change.
Definition: rtp_engine.c:2336
int ast_rtp_instance_extmap_negotiate(struct ast_rtp_instance *instance, int id, enum ast_rtp_extension_direction direction, const char *uri, const char *attributes)
Negotiate received RTP extension information.
Definition: rtp_engine.c:840
void ast_rtp_instance_extmap_clear(struct ast_rtp_instance *instance)
Clear negotiated RTP extension information.
Definition: rtp_engine.c:884
#define AST_RTP_MAX
Definition: rtp_engine.h:300
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:749
const char * ast_rtp_instance_get_channel_id(struct ast_rtp_instance *instance)
Get the unique ID of the channel that owns this RTP instance.
Definition: rtp_engine.c:570
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:2368
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1682
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int timeout)
Set the RTP keepalive interval.
Definition: rtp_engine.c:2880
unsigned int ast_rtp_instance_get_ssrc(struct ast_rtp_instance *rtp)
Retrieve the local SSRC value that we will be using.
Definition: rtp_engine.c:4011
#define DEFAULT_DTMF_SAMPLE_RATE_MS
Definition: rtp_engine.h:110
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, int asterisk_format, struct ast_format *format, int code)
Retrieve a rx mapped payload type based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:2019
enum ast_rtp_extension_direction ast_rtp_instance_extmap_get_direction(struct ast_rtp_instance *instance, int id)
Retrieve the negotiated direction for an RTP extension id.
Definition: rtp_engine.c:952
void ast_rtp_codecs_payloads_xover(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
Crossover copy the tx payload mapping of src to the rx payload mapping of dest.
Definition: rtp_engine.c:1309
void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
Set the RTP timeout value.
Definition: rtp_engine.c:2870
int ast_rtp_codecs_set_preferred_format(struct ast_rtp_codecs *codecs, struct ast_format *format)
Set the preferred format.
Definition: rtp_engine.c:1581
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:2317
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:621
int(* set_configuration)(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
Definition: rtp_engine.h:623
enum ast_rtp_dtls_setup(* get_setup)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:633
enum ast_rtp_dtls_hash(* get_fingerprint_hash)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:639
const char *(* get_fingerprint)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:641
void(* reset)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:629
void(* set_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint)
Definition: rtp_engine.h:637
enum ast_rtp_dtls_connection(* get_connection)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:631
void(* set_setup)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup)
Definition: rtp_engine.h:635
Structure for an ICE candidate.
Definition: rtp_engine.h:525
struct ast_sockaddr address
Definition: rtp_engine.h:530
enum ast_rtp_ice_component_type id
Definition: rtp_engine.h:527
struct ast_sockaddr relay_address
Definition: rtp_engine.h:531
enum ast_rtp_ice_candidate_type type
Definition: rtp_engine.h:532
Structure that represents the optional ICE support within an RTP engine.
Definition: rtp_engine.h:536
void(* ice_lite)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:552
void(* stop)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:544
void(* change_components)(struct ast_rtp_instance *instance, int num_components)
Definition: rtp_engine.h:560
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
Definition: rtp_engine.h:538
void(* start)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:542
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:546
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
Definition: rtp_engine.h:540
const char *(* get_password)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:548
void(* set_role)(struct ast_rtp_instance *instance, enum ast_rtp_ice_role role)
Definition: rtp_engine.h:554
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
Definition: rtp_engine.h:550
unsigned int remote_ssrc
Definition: rtp_engine.h:454
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:913
An entity with which Asterisk communicates.
Definition: res_pjsip.h:961
struct ast_sip_endpoint_media_configuration media
Definition: res_pjsip.h:996
enum ast_sip_session_media_encryption encryption
Definition: res_pjsip.h:856
unsigned int encryption_optimistic
Definition: res_pjsip.h:858
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_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680