Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
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->endpoint->media.rtp.port_start && session->endpoint->media.rtp.port_end) {
272 .port_start = session->endpoint->media.rtp.port_start,
273 .port_end = session->endpoint->media.rtp.port_end,
274 };
275 if (!(session_media->rtp = ast_rtp_instance_new_with_options(
276 session->endpoint->media.rtp.engine, sched, media_address, NULL,
277 &options))) {
278 ast_log(LOG_ERROR, "Unable to create RTP instance using RTP engine '%s' with port range %u-%u\n",
279 session->endpoint->media.rtp.engine,
280 session->endpoint->media.rtp.port_start,
281 session->endpoint->media.rtp.port_end);
282 return -1;
283 }
284 } else {
285 if (!(session_media->rtp = ast_rtp_instance_new(session->endpoint->media.rtp.engine, sched, media_address, NULL))) {
286 ast_log(LOG_ERROR, "Unable to create RTP instance using RTP engine '%s'\n", session->endpoint->media.rtp.engine);
287 return -1;
288 }
289 }
290
291 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_NAT, session->endpoint->media.rtp.symmetric);
292 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_ASYMMETRIC_CODEC, session->endpoint->asymmetric_rtp_codec);
293
294 if (!session->endpoint->media.rtp.ice_support && (ice = ast_rtp_instance_get_ice(session_media->rtp))) {
295 ice->stop(session_media->rtp);
296 }
297
301 } else if (session->dtmf == AST_SIP_DTMF_INBAND) {
303 }
304
305 if (session_media->type == AST_MEDIA_TYPE_AUDIO &&
306 (session->endpoint->media.tos_audio || session->endpoint->media.cos_audio)) {
307 ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_audio,
308 session->endpoint->media.cos_audio, "SIP RTP Audio");
309 } else if (session_media->type == AST_MEDIA_TYPE_VIDEO) {
310 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_RECV, session->endpoint->media.webrtc);
311 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_RETRANS_SEND, session->endpoint->media.webrtc);
312 ast_rtp_instance_set_prop(session_media->rtp, AST_RTP_PROPERTY_REMB, session->endpoint->media.webrtc);
313 if (session->endpoint->media.webrtc) {
316 }
317 if (session->endpoint->media.tos_video || session->endpoint->media.cos_video) {
318 ast_rtp_instance_set_qos(session_media->rtp, session->endpoint->media.tos_video,
319 session->endpoint->media.cos_video, "SIP RTP Video");
320 }
321 }
322
323 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
324
325 return 0;
326}
327
328static void get_codecs(struct ast_sip_session *session, const struct pjmedia_sdp_media *stream, struct ast_rtp_codecs *codecs,
329 struct ast_sip_session_media *session_media, struct ast_format_cap *astformats)
330{
331 pjmedia_sdp_attr *attr;
332 pjmedia_sdp_rtpmap *rtpmap;
333 pjmedia_sdp_fmtp fmtp;
334 struct ast_format *format;
335 int i, num = 0, tel_event = 0;
336 char name[256];
337 char media[20];
338 char fmt_param[256];
339 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
342
344
346
347 /* Iterate through provided formats */
348 for (i = 0; i < stream->desc.fmt_count; ++i) {
349 /* The payload is kept as a string for things like t38 but for video it is always numerical */
350 ast_rtp_codecs_payloads_set_m_type(codecs, NULL, pj_strtoul(&stream->desc.fmt[i]));
351 /* Look for the optional rtpmap attribute */
352 if (!(attr = pjmedia_sdp_media_find_attr2(stream, "rtpmap", &stream->desc.fmt[i]))) {
353 continue;
354 }
355
356 /* Interpret the attribute as an rtpmap */
357 if ((pjmedia_sdp_attr_to_rtpmap(session->inv_session->pool_prov, attr, &rtpmap)) != PJ_SUCCESS) {
358 continue;
359 }
360
361 ast_copy_pj_str(name, &rtpmap->enc_name, sizeof(name));
362 if (strcmp(name, "telephone-event") == 0) {
363 if (tel_event == 0) {
364 int dtmf_rate = 0, dtmf_code = 0;
365 char dtmf_pt[8];
366 ast_copy_pj_str(dtmf_pt, &rtpmap->pt, sizeof(dtmf_pt));
367 dtmf_code = atoi(dtmf_pt);
368 dtmf_rate = rtpmap->clock_rate;
370 }
371 tel_event++;
372 }
373
374 ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media, sizeof(media));
376 pj_strtoul(&stream->desc.fmt[i]), media, name, options, rtpmap->clock_rate);
377 /* Look for an optional associated fmtp attribute */
378 if (!(attr = pjmedia_sdp_media_find_attr2(stream, "fmtp", &rtpmap->pt))) {
379 continue;
380 }
381
382 if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
383 ast_copy_pj_str(fmt_param, &fmtp.fmt, sizeof(fmt_param));
384 if (sscanf(fmt_param, "%30d", &num) != 1) {
385 continue;
386 }
387
388 if ((format = ast_rtp_codecs_get_payload_format(codecs, num))) {
389 struct ast_format *format_parsed;
390
391 ast_copy_pj_str(fmt_param, &fmtp.fmt_param, sizeof(fmt_param));
392
393 format_parsed = ast_format_parse_sdp_fmtp(format, fmt_param);
394 if (format_parsed) {
396 ao2_ref(format_parsed, -1);
397 }
398 ao2_ref(format, -1);
399 }
400 }
401 }
402
403 /* Parsing done, now fill the ast_format_cap struct in the correct order */
404 for (i = 0; i < stream->desc.fmt_count; ++i) {
405 if ((format = ast_rtp_codecs_get_payload_format(codecs, pj_strtoul(&stream->desc.fmt[i])))) {
406 ast_format_cap_append(astformats, format, 0);
407 ao2_ref(format, -1);
408 }
409 }
410
411 if (session->dtmf == AST_SIP_DTMF_AUTO) {
412 if (tel_event) {
415 } else {
418 }
419 }
420
421 if (session->dtmf == AST_SIP_DTMF_AUTO_INFO) {
422 if (tel_event) {
425 } else {
428 }
429 }
430
431
432 /* Get the packetization, if it exists */
433 if ((attr = pjmedia_sdp_media_find_attr2(stream, "ptime", NULL))) {
434 unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
435 if (framing && session->endpoint->media.rtp.use_ptime) {
437 ast_format_cap_set_framing(astformats, framing);
438 }
439 }
440
442}
443
444
445/*! \brief Determine whether a payload type is already advertised in a BUNDLE group. */
447 const pjmedia_sdp_session *sdp, const pjmedia_sdp_media *media,
448 int bundle_group, int payload)
449{
450 int media_index;
451
452 for (media_index = 0; media_index < sdp->media_count; ++media_index) {
453 struct ast_sip_session_media *other_session_media;
454 int format_index;
455
456 if (media_index >= AST_VECTOR_SIZE(&session->pending_media_state->sessions)) {
457 break;
458 }
459
460 other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, media_index);
461 if (!other_session_media || other_session_media->bundle_group != bundle_group) {
462 continue;
463 }
464
465 for (format_index = 0; format_index < sdp->media[media_index]->desc.fmt_count; ++format_index) {
466 if (pj_strtoul(&sdp->media[media_index]->desc.fmt[format_index]) == payload) {
467 return 1;
468 }
469 }
470 }
471
472 /* The current media section is not in the SDP yet, so inspect it separately. */
473 for (media_index = 0; media_index < media->desc.fmt_count; ++media_index) {
474 if (pj_strtoul(&media->desc.fmt[media_index]) == payload) {
475 return 1;
476 }
477 }
478
479 return 0;
480}
481
482/*! \brief Check whether a payload slot is either free or already mapped to the requested format. */
483static int payload_type_compatible(struct ast_rtp_codecs *codecs, int payload,
484 struct ast_format *format)
485{
487 int compatible;
488
490 if (!type) {
491 return 1;
492 }
493
494 compatible = type->asterisk_format
496 ao2_ref(type, -1);
497
498 return compatible;
499}
500
501/*! \brief Ensure an RTP codecs structure can receive a format using a payload type. */
503 struct ast_format *format)
504{
506 int matches;
507
509 if (type) {
510 matches = type->asterisk_format
512 ao2_ref(type, -1);
513 return matches ? 0 : -1;
514 }
515
516 return ast_rtp_codecs_payload_set_rx(codecs, payload, format) < 0 ? -1 : 0;
517}
518
519/*! \brief Assign a payload type that is unique across the generated BUNDLE group. */
521 struct ast_sip_session_media *session_media,
522 struct ast_sip_session_media *session_media_transport,
523 const pjmedia_sdp_session *sdp, const pjmedia_sdp_media *media,
524 struct ast_format *format)
525{
526 struct ast_rtp_codecs *transport_codecs =
527 ast_rtp_instance_get_codecs(session_media_transport->rtp);
528 struct ast_rtp_codecs *stream_codecs =
529 ast_rtp_instance_get_codecs(session_media->rtp);
530 int preferred;
531 int candidate;
532 int offset;
533
534 preferred = ast_rtp_codecs_payload_code(stream_codecs, 1, format, 0);
535 if (preferred < 0) {
536 return -1;
537 }
538
539 /* Preserve the stream's normal payload when it is not used by another m= section. */
540 if (!bundle_payload_type_used(session, sdp, media, session_media->bundle_group, preferred)
541 && payload_type_compatible(transport_codecs, preferred, format)
542 && payload_type_compatible(stream_codecs, preferred, format)) {
543 candidate = preferred;
544 goto configure;
545 }
546
547 /* Remap duplicate static or dynamic payloads into the dynamic range. */
548 candidate = preferred >= AST_RTP_PT_FIRST_DYNAMIC
549 ? preferred + 1 : AST_RTP_PT_FIRST_DYNAMIC;
550 for (offset = 0; offset < AST_RTP_MAX_PT - AST_RTP_PT_FIRST_DYNAMIC; ++offset) {
551 if (candidate >= AST_RTP_MAX_PT) {
552 candidate = AST_RTP_PT_FIRST_DYNAMIC;
553 }
554
555 if (!bundle_payload_type_used(session, sdp, media, session_media->bundle_group, candidate)
556 && payload_type_compatible(transport_codecs, candidate, format)
557 && payload_type_compatible(stream_codecs, candidate, format)) {
558 goto configure;
559 }
560
561 ++candidate;
562 }
563
564 ast_log(LOG_WARNING, "No unique dynamic RTP payload type available for bundled stream %s format %s\n",
565 S_OR(session_media->mid, "<unknown>"), ast_format_get_name(format));
566 return -1;
567
568configure:
569 if (ensure_payload_type_mapping(transport_codecs, candidate, format)
570 || ensure_payload_type_mapping(stream_codecs, candidate, format)) {
571 ast_log(LOG_WARNING, "Unable to configure RTP payload type %d for bundled stream %s format %s\n",
572 candidate, S_OR(session_media->mid, "<unknown>"), ast_format_get_name(format));
573 return -1;
574 }
575
576 ast_debug(2, "Assigned RTP payload type %d to bundled stream %s format %s\n",
577 candidate, S_OR(session_media->mid, "<unknown>"), ast_format_get_name(format));
578 return candidate;
579}
580
581/*! \brief Determine whether the SDP currently being generated is a local offer. */
583{
584 return !session->inv_session->neg
585 || pjmedia_sdp_neg_get_state(session->inv_session->neg) == PJMEDIA_SDP_NEG_STATE_DONE;
586}
587
588static int apply_cap_to_bundled(struct ast_sip_session_media *session_media,
589 struct ast_sip_session_media *session_media_transport,
590 struct ast_stream *asterisk_stream, struct ast_format_cap *joint)
591{
592 if (!joint) {
593 return -1;
594 }
595
596 ast_stream_set_formats(asterisk_stream, joint);
597
598 /* If this is a bundled stream then apply the payloads to RTP instance acting as transport to prevent conflicts */
599 if (session_media_transport != session_media && session_media->bundled) {
600 int index;
601
602 for (index = 0; index < ast_format_cap_count(joint); ++index) {
603 struct ast_format *format = ast_format_cap_get_format(joint, index);
604 int rtp_code;
605
606 /* Ensure this payload is in the bundle group transport codecs, this purposely doesn't check the return value for
607 * things as the format is guaranteed to have a payload already.
608 */
609 rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0);
610 ast_rtp_codecs_payload_set_rx(ast_rtp_instance_get_codecs(session_media_transport->rtp), rtp_code, format);
611
612 ao2_ref(format, -1);
613 }
614 }
615
616 return 0;
617}
618
620 struct ast_sip_session *session, struct ast_sip_session_media *session_media,
621 const struct pjmedia_sdp_media *stream)
622{
623 struct ast_format_cap *incoming_call_offer_cap;
624 struct ast_format_cap *remote;
627
628
630 if (!remote) {
631 ast_log(LOG_ERROR, "Failed to allocate %s incoming remote capabilities\n",
632 ast_codec_media_type2str(session_media->type));
633 SCOPE_EXIT_RTN_VALUE(NULL, "Couldn't allocate caps\n");
634 }
635
636 /* Get the peer's capabilities*/
637 get_codecs(session, stream, &codecs, session_media, remote);
638
639 incoming_call_offer_cap = ast_sip_session_create_joint_call_cap(
640 session, session_media->type, remote);
641
642 ao2_ref(remote, -1);
643
644 if (!incoming_call_offer_cap || ast_format_cap_empty(incoming_call_offer_cap)) {
645 ao2_cleanup(incoming_call_offer_cap);
647 SCOPE_EXIT_RTN_VALUE(NULL, "No incoming call offer caps\n");
648 }
649
650 /*
651 * Setup rx payload type mapping to prefer the mapping
652 * from the peer that the RFC says we SHOULD use.
653 */
655
656 /*
657 * This only merges the newly offered payloads into the live RTP instance
658 * rather than doing a destructive replace, so any format the channel is
659 * still actively sending in (e.g. while a reINVITE is in flight) remains
660 * usable right up until set_caps() commits the channel to the new
661 * negotiated format. A destructive replace here, before the channel's
662 * own read/write format has caught up, is what let a concurrent bridge
663 * write briefly land on a payload mapping that no longer had its format.
664 */
666 ast_rtp_instance_get_codecs(session_media->rtp), session_media->rtp);
667
669
670 SCOPE_EXIT_RTN_VALUE(incoming_call_offer_cap);
671}
672
674 struct ast_sip_session_media *session_media,
675 struct ast_sip_session_media *session_media_transport,
676 const struct pjmedia_sdp_media *stream,
677 int is_offer, struct ast_stream *asterisk_stream)
678{
679 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
680 RAII_VAR(struct ast_format_cap *, peer, NULL, ao2_cleanup);
681 RAII_VAR(struct ast_format_cap *, joint, NULL, ao2_cleanup);
682 enum ast_media_type media_type = session_media->type;
684 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
685 ast_format_cap_count(session->direct_media_cap);
686 int dsp_features = 0;
687 SCOPE_ENTER(1, "%s %s\n", ast_sip_session_get_name(session), is_offer ? "OFFER" : "ANSWER");
688
692 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
693 ast_codec_media_type2str(session_media->type));
694 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create %s capabilities\n",
695 ast_codec_media_type2str(session_media->type));
696 }
697
698 /* get the endpoint capabilities */
699 if (direct_media_enabled) {
700 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
701 } else {
702 ast_format_cap_append_from_cap(caps, session->endpoint->media.codecs, media_type);
703 }
704
705 /* get the capabilities on the peer */
706 get_codecs(session, stream, &codecs, session_media, peer);
707
708 /* get the joint capabilities between peer and endpoint */
709 ast_format_cap_get_compatible(caps, peer, joint);
710 if (!ast_format_cap_count(joint)) {
713
715 ast_log(LOG_NOTICE, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
716 ast_codec_media_type2str(session_media->type),
717 ast_format_cap_get_names(caps, &usbuf),
718 ast_format_cap_get_names(peer, &thembuf));
719 SCOPE_EXIT_RTN_VALUE(-1, "No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
720 ast_codec_media_type2str(session_media->type),
721 ast_format_cap_get_names(caps, &usbuf),
722 ast_format_cap_get_names(peer, &thembuf));
723 } else {
724 struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
725
727 ao2_ref(preferred_fmt, -1);
728 }
729
730 if (is_offer) {
731 /*
732 * Setup rx payload type mapping to prefer the mapping
733 * from the peer that the RFC says we SHOULD use.
734 */
736 }
737
738 if (session->channel) {
739 ast_channel_lock(session->channel);
740 }
741
743 session_media->rtp);
744
745 apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
746
747 if (session->channel && ast_sip_session_is_pending_stream_default(session, asterisk_stream)) {
751 ast_format_cap_remove_by_type(caps, media_type);
752
753 if (session->endpoint->preferred_codec_only) {
754 struct ast_format *preferred_fmt = ast_format_cap_get_format(joint, 0);
755 ast_format_cap_append(caps, preferred_fmt, 0);
756 ao2_ref(preferred_fmt, -1);
757 } else if (!session->endpoint->asymmetric_rtp_codec) {
758 struct ast_format *best;
759 /*
760 * If we don't allow the sending codec to be changed on our side
761 * then get the best codec from the joint capabilities of the media
762 * type and use only that. This ensures the core won't start sending
763 * out a format that we aren't currently sending.
764 */
765
766 best = ast_format_cap_get_best_by_type(joint, media_type);
767 if (best) {
769 ao2_ref(best, -1);
770 }
771 } else {
772 ast_format_cap_append_from_cap(caps, joint, media_type);
773 }
774
775 /*
776 * Apply the new formats to the channel, potentially changing
777 * raw read/write formats and translation path while doing so.
778 */
780 if (media_type == AST_MEDIA_TYPE_AUDIO) {
783 }
784
785 if ( ((session->dtmf == AST_SIP_DTMF_AUTO) || (session->dtmf == AST_SIP_DTMF_AUTO_INFO) )
787 && (session->dsp)) {
788 dsp_features = ast_dsp_get_features(session->dsp);
789 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
790 if (dsp_features) {
791 ast_dsp_set_features(session->dsp, dsp_features);
792 } else {
793 ast_dsp_free(session->dsp);
794 session->dsp = NULL;
795 }
796 }
797
798 if (ast_channel_is_bridged(session->channel)) {
800 }
801 }
802
803 if (session->channel) {
804 ast_channel_unlock(session->channel);
805 }
806
809}
810
811static pjmedia_sdp_attr* generate_rtpmap_attr(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
812 int rtp_code, int asterisk_format, struct ast_format *format, int code)
813{
814#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
815 extern pj_bool_t pjsip_use_compact_form;
816#else
817 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
818#endif
819 pjmedia_sdp_rtpmap rtpmap;
820 pjmedia_sdp_attr *attr = NULL;
821 char tmp[64];
822 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
824
825 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
826 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
827
828 if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
829 return NULL;
830 }
831
832 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
833 rtpmap.clock_rate = ast_rtp_lookup_sample_rate2(asterisk_format, format, code);
834 pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
835 if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
836 pj_cstr(&rtpmap.param, "2");
837 } else {
838 pj_cstr(&rtpmap.param, NULL);
839 }
840
841 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
842
843 return attr;
844}
845
846
847static pjmedia_sdp_attr* generate_rtpmap_attr2(struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
848 int rtp_code, int asterisk_format, struct ast_format *format, int code, int sample_rate)
849{
850#ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
851 extern pj_bool_t pjsip_use_compact_form;
852#else
853 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
854#endif
855 pjmedia_sdp_rtpmap rtpmap;
856 pjmedia_sdp_attr *attr = NULL;
857 char tmp[64];
858 enum ast_rtp_options options = session->endpoint->media.g726_non_standard ?
860
861 snprintf(tmp, sizeof(tmp), "%d", rtp_code);
862 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
863
864 if (rtp_code <= AST_RTP_PT_LAST_STATIC && pjsip_use_compact_form) {
865 return NULL;
866 }
867
868 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
869 rtpmap.clock_rate = sample_rate;
870 pj_strdup2(pool, &rtpmap.enc_name, ast_rtp_lookup_mime_subtype2(asterisk_format, format, code, options));
871 if (!pj_stricmp2(&rtpmap.enc_name, "opus")) {
872 pj_cstr(&rtpmap.param, "2");
873 } else {
874 pj_cstr(&rtpmap.param, NULL);
875 }
876
877 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
878
879 return attr;
880}
881
882static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool, struct ast_format *format, int rtp_code)
883{
884 struct ast_str *fmtp0 = ast_str_alloca(256);
885 pj_str_t fmtp1;
886 pjmedia_sdp_attr *attr = NULL;
887 char *tmp;
888
889 ast_format_generate_sdp_fmtp(format, rtp_code, &fmtp0);
890 if (ast_str_strlen(fmtp0)) {
891 tmp = ast_str_buffer(fmtp0) + ast_str_strlen(fmtp0) - 1;
892 /* remove any carriage return line feeds */
893 while (*tmp == '\r' || *tmp == '\n') --tmp;
894 *++tmp = '\0';
895 /* ast...generate gives us everything, just need value */
896 tmp = strchr(ast_str_buffer(fmtp0), ':');
897 if (tmp && tmp[1] != '\0') {
898 fmtp1 = pj_str(tmp + 1);
899 } else {
900 fmtp1 = pj_str(ast_str_buffer(fmtp0));
901 }
902 attr = pjmedia_sdp_attr_create(pool, "fmtp", &fmtp1);
903 }
904 return attr;
905}
906
907/*! \brief Function which adds ICE attributes to a media stream */
908static 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,
909 unsigned int include_candidates)
910{
911 struct ast_rtp_engine_ice *ice;
912 struct ao2_container *candidates;
913 const char *username, *password;
914 pj_str_t stmp;
915 pjmedia_sdp_attr *attr;
916 struct ao2_iterator it_candidates;
917 struct ast_rtp_engine_ice_candidate *candidate;
918
919 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
920 return;
921 }
922
923 if (!session_media->remote_ice) {
924 ice->stop(session_media->rtp);
925 return;
926 }
927
928 if ((username = ice->get_ufrag(session_media->rtp))) {
929 attr = pjmedia_sdp_attr_create(pool, "ice-ufrag", pj_cstr(&stmp, username));
930 media->attr[media->attr_count++] = attr;
931 }
932
933 if ((password = ice->get_password(session_media->rtp))) {
934 attr = pjmedia_sdp_attr_create(pool, "ice-pwd", pj_cstr(&stmp, password));
935 media->attr[media->attr_count++] = attr;
936 }
937
938 if (!include_candidates) {
939 return;
940 }
941
942 candidates = ice->get_local_candidates(session_media->rtp);
943 if (!candidates) {
944 return;
945 }
946
947 it_candidates = ao2_iterator_init(candidates, 0);
948 for (; (candidate = ao2_iterator_next(&it_candidates)); ao2_ref(candidate, -1)) {
949 struct ast_str *attr_candidate = ast_str_create(128);
950
951 ast_str_set(&attr_candidate, -1, "%s %u %s %d %s ", candidate->foundation, candidate->id, candidate->transport,
952 candidate->priority, ast_sockaddr_stringify_addr_remote(&candidate->address));
953 ast_str_append(&attr_candidate, -1, "%s typ ", ast_sockaddr_stringify_port(&candidate->address));
954
955 switch (candidate->type) {
957 ast_str_append(&attr_candidate, -1, "host");
958 break;
960 ast_str_append(&attr_candidate, -1, "srflx");
961 break;
963 ast_str_append(&attr_candidate, -1, "relay");
964 break;
965 }
966
967 if (!ast_sockaddr_isnull(&candidate->relay_address)) {
968 ast_str_append(&attr_candidate, -1, " raddr %s rport", ast_sockaddr_stringify_addr_remote(&candidate->relay_address));
969 ast_str_append(&attr_candidate, -1, " %s", ast_sockaddr_stringify_port(&candidate->relay_address));
970 }
971
972 attr = pjmedia_sdp_attr_create(pool, "candidate", pj_cstr(&stmp, ast_str_buffer(attr_candidate)));
973 media->attr[media->attr_count++] = attr;
974
975 ast_free(attr_candidate);
976 }
977
978 ao2_iterator_destroy(&it_candidates);
979 ao2_ref(candidates, -1);
980}
981
982/*! \brief Function which checks for ice attributes in an audio stream */
983static void check_ice_support(struct ast_sip_session *session, struct ast_sip_session_media *session_media,
984 const struct pjmedia_sdp_media *remote_stream)
985{
986 struct ast_rtp_engine_ice *ice;
987 const pjmedia_sdp_attr *attr;
988 unsigned int attr_i;
989
990 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
991 session_media->remote_ice = 0;
992 return;
993 }
994
995 /* Find all of the candidates */
996 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
997 attr = remote_stream->attr[attr_i];
998 if (!pj_strcmp2(&attr->name, "candidate")) {
999 session_media->remote_ice = 1;
1000 break;
1001 }
1002 }
1003
1004 if (attr_i == remote_stream->attr_count) {
1005 session_media->remote_ice = 0;
1006 }
1007}
1008
1010 const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
1011{
1012 struct ast_rtp_engine_ice *ice;
1014 char ufrag_attr_value[256];
1015 char passwd_attr_value[256];
1016
1017 /* If ICE support is not enabled or available exit early */
1018 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
1019 return;
1020 }
1021
1023 if (!ufrag_attr) {
1024 ufrag_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
1025 }
1026 if (ufrag_attr) {
1028 } else {
1029 return;
1030 }
1032 if (!passwd_attr) {
1033 passwd_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
1034 }
1035 if (passwd_attr) {
1037 } else {
1038 return;
1039 }
1040
1041 if (ufrag_attr && passwd_attr) {
1043 }
1044}
1045
1046/*! \brief Function which processes ICE attributes in an audio stream */
1048 const struct pjmedia_sdp_session *remote, const struct pjmedia_sdp_media *remote_stream)
1049{
1050 struct ast_rtp_engine_ice *ice;
1051 const pjmedia_sdp_attr *attr;
1052 char attr_value[256];
1053 unsigned int attr_i;
1054
1055 /* If ICE support is not enabled or available exit early */
1056 if (!session->endpoint->media.rtp.ice_support || !(ice = ast_rtp_instance_get_ice(session_media->rtp))) {
1057 return;
1058 }
1059
1060 ast_debug_ice(2, "(%p) ICE process attributes\n", session_media->rtp);
1061
1062 attr = pjmedia_sdp_media_find_attr2(remote_stream, "ice-ufrag", NULL);
1063 if (!attr) {
1064 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-ufrag", NULL);
1065 }
1066 if (attr) {
1067 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
1069 } else {
1070 ast_debug_ice(2, "(%p) ICE no, or invalid ice-ufrag\n", session_media->rtp);
1071 return;
1072 }
1073
1075 if (!attr) {
1076 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr, "ice-pwd", NULL);
1077 }
1078 if (attr) {
1079 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
1081 } else {
1082 ast_debug_ice(2, "(%p) ICE no, or invalid ice-pwd\n", session_media->rtp);
1083 return;
1084 }
1085
1087 ice->ice_lite(session_media->rtp);
1088 }
1089
1090 /* Find all of the candidates */
1091 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
1092 char foundation[33], transport[32], address[PJ_INET6_ADDRSTRLEN + 1], cand_type[6], relay_address[PJ_INET6_ADDRSTRLEN + 1] = "";
1093 unsigned int port, relay_port = 0;
1094 struct ast_rtp_engine_ice_candidate candidate = { 0, };
1095
1096 attr = remote_stream->attr[attr_i];
1097
1098 /* If this is not a candidate line skip it */
1099 if (pj_strcmp2(&attr->name, "candidate")) {
1100 continue;
1101 }
1102
1103 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value, sizeof(attr_value));
1104
1105 if (sscanf(attr_value, "%32s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u", foundation, &candidate.id, transport,
1106 (unsigned *)&candidate.priority, address, &port, cand_type, relay_address, &relay_port) < 7) {
1107 /* Candidate did not parse properly */
1108 continue;
1109 }
1110
1111 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux && candidate.id > 1) {
1112 /* Remote side may have offered RTP and RTCP candidates. However, if we're using RTCP MUX,
1113 * then we should ignore RTCP candidates.
1114 */
1115 continue;
1116 }
1117
1118 candidate.foundation = foundation;
1119 candidate.transport = transport;
1120
1122 ast_sockaddr_set_port(&candidate.address, port);
1123
1124 if (!strcasecmp(cand_type, "host")) {
1126 } else if (!strcasecmp(cand_type, "srflx")) {
1128 } else if (!strcasecmp(cand_type, "relay")) {
1130 } else {
1131 continue;
1132 }
1133
1136 }
1137
1138 if (relay_port) {
1139 ast_sockaddr_set_port(&candidate.relay_address, relay_port);
1140 }
1141
1142 ice->add_remote_candidate(session_media->rtp, &candidate);
1143 }
1144
1145 ice->set_role(session_media->rtp, pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_TRUE ?
1147 ice->start(session_media->rtp);
1148}
1149
1150/*! \brief figure out if media stream has crypto lines for sdes */
1151static int media_stream_has_crypto(const struct pjmedia_sdp_media *stream)
1152{
1153 int i;
1154
1155 for (i = 0; i < stream->attr_count; i++) {
1156 pjmedia_sdp_attr *attr;
1157
1158 /* check the stream for the required crypto attribute */
1159 attr = stream->attr[i];
1160 if (pj_strcmp2(&attr->name, "crypto")) {
1161 continue;
1162 }
1163
1164 return 1;
1165 }
1166
1167 return 0;
1168}
1169
1170/*! \brief figure out media transport encryption type from the media transport string */
1172 const struct pjmedia_sdp_media *stream, unsigned int *optimistic)
1173{
1174 RAII_VAR(char *, transport_str, ast_strndup(transport.ptr, transport.slen), ast_free);
1175
1176 *optimistic = 0;
1177
1178 if (!transport_str) {
1180 }
1181 if (strstr(transport_str, "UDP/TLS")) {
1183 } else if (strstr(transport_str, "SAVP")) {
1185 } else if (media_stream_has_crypto(stream)) {
1186 *optimistic = 1;
1188 } else {
1190 }
1191}
1192
1193/*!
1194 * \brief Checks whether the encryption offered in SDP is compatible with the endpoint's configuration
1195 * \internal
1196 *
1197 * \param endpoint Media encryption configured for the endpoint
1198 * \param stream pjmedia_sdp_media stream description
1199 *
1200 * \retval AST_SIP_MEDIA_TRANSPORT_INVALID on encryption mismatch
1201 * \retval The encryption requested in the SDP
1202 */
1204 struct ast_sip_endpoint *endpoint,
1205 const struct pjmedia_sdp_media *stream)
1206{
1207 enum ast_sip_session_media_encryption incoming_encryption;
1208 char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1];
1209 unsigned int optimistic;
1210
1211 if ((transport_end == 'F' && !endpoint->media.rtp.use_avpf)
1212 || (transport_end != 'F' && endpoint->media.rtp.use_avpf)) {
1214 }
1215
1216 incoming_encryption = get_media_encryption_type(stream->desc.transport, stream, &optimistic);
1217
1218 if (incoming_encryption == endpoint->media.rtp.encryption) {
1219 return incoming_encryption;
1220 }
1221
1222 if (endpoint->media.rtp.force_avp ||
1223 endpoint->media.rtp.encryption_optimistic) {
1224 return incoming_encryption;
1225 }
1226
1227 /* If an optimistic offer has been made but encryption is not enabled consider it as having
1228 * no offer of crypto at all instead of invalid so the session proceeds.
1229 */
1230 if (optimistic) {
1232 }
1233
1235}
1236
1237static int setup_srtp(struct ast_sip_session_media *session_media)
1238{
1239 if (!session_media->srtp) {
1240 session_media->srtp = ast_sdp_srtp_alloc();
1241 if (!session_media->srtp) {
1242 return -1;
1243 }
1244 }
1245
1246 if (!session_media->srtp->crypto) {
1247 session_media->srtp->crypto = ast_sdp_crypto_alloc();
1248 if (!session_media->srtp->crypto) {
1249 return -1;
1250 }
1251 }
1252
1253 return 0;
1254}
1255
1257 struct ast_sip_session_media *session_media)
1258{
1259 struct ast_rtp_engine_dtls *dtls;
1260
1261 if (!session->endpoint->media.rtp.dtls_cfg.enabled || !session_media->rtp) {
1262 return -1;
1263 }
1264
1265 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1266 if (!dtls) {
1267 return -1;
1268 }
1269
1270 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);
1271 if (dtls->set_configuration(session_media->rtp, &session->endpoint->media.rtp.dtls_cfg)) {
1272 ast_log(LOG_ERROR, "Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
1273 session_media->rtp);
1274 return -1;
1275 }
1276
1277 if (setup_srtp(session_media)) {
1278 return -1;
1279 }
1280 return 0;
1281}
1282
1283static void apply_dtls_attrib(struct ast_sip_session_media *session_media,
1284 pjmedia_sdp_attr *attr)
1285{
1286 struct ast_rtp_engine_dtls *dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1287 pj_str_t *value;
1288
1289 if (!attr->value.ptr || !dtls) {
1290 return;
1291 }
1292
1293 value = pj_strtrim(&attr->value);
1294
1295 if (!pj_strcmp2(&attr->name, "setup")) {
1296 if (!pj_stricmp2(value, "active")) {
1297 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTIVE);
1298 } else if (!pj_stricmp2(value, "passive")) {
1299 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_PASSIVE);
1300 } else if (!pj_stricmp2(value, "actpass")) {
1301 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTPASS);
1302 } else if (!pj_stricmp2(value, "holdconn")) {
1303 dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_HOLDCONN);
1304 } else {
1305 ast_log(LOG_WARNING, "Unsupported setup attribute value '%*s'\n", (int)value->slen, value->ptr);
1306 }
1307 } else if (!pj_strcmp2(&attr->name, "connection")) {
1308 if (!pj_stricmp2(value, "new")) {
1309 dtls->reset(session_media->rtp);
1310 } else if (!pj_stricmp2(value, "existing")) {
1311 /* Do nothing */
1312 } else {
1313 ast_log(LOG_WARNING, "Unsupported connection attribute value '%*s'\n", (int)value->slen, value->ptr);
1314 }
1315 } else if (!pj_strcmp2(&attr->name, "fingerprint")) {
1316 char hash_value[256], hash[32];
1317 char fingerprint_text[value->slen + 1];
1318 ast_copy_pj_str(fingerprint_text, value, sizeof(fingerprint_text));
1319 if (sscanf(fingerprint_text, "%31s %255s", hash, hash_value) == 2) {
1320 if (!strcasecmp(hash, "sha-1")) {
1321 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
1322 } else if (!strcasecmp(hash, "sha-256")) {
1323 dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA256, hash_value);
1324 } else {
1325 ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
1326 hash);
1327 }
1328 }
1329 }
1330}
1331
1332static int parse_dtls_attrib(struct ast_sip_session_media *session_media,
1333 const struct pjmedia_sdp_session *sdp,
1334 const struct pjmedia_sdp_media *stream)
1335{
1336 int i;
1337
1338 for (i = 0; i < sdp->attr_count; i++) {
1339 apply_dtls_attrib(session_media, sdp->attr[i]);
1340 }
1341
1342 for (i = 0; i < stream->attr_count; i++) {
1343 apply_dtls_attrib(session_media, stream->attr[i]);
1344 }
1345
1347
1348 return 0;
1349}
1350
1351static int setup_sdes_srtp(struct ast_sip_session_media *session_media,
1352 const struct pjmedia_sdp_media *stream)
1353{
1354 int i;
1355
1356 for (i = 0; i < stream->attr_count; i++) {
1357 pjmedia_sdp_attr *attr;
1358 RAII_VAR(char *, crypto_str, NULL, ast_free);
1359
1360 /* check the stream for the required crypto attribute */
1361 attr = stream->attr[i];
1362 if (pj_strcmp2(&attr->name, "crypto")) {
1363 continue;
1364 }
1365
1366 crypto_str = ast_strndup(attr->value.ptr, attr->value.slen);
1367 if (!crypto_str) {
1368 return -1;
1369 }
1370
1371 if (setup_srtp(session_media)) {
1372 return -1;
1373 }
1374
1375 if (!ast_sdp_crypto_process(session_media->rtp, session_media->srtp, crypto_str)) {
1376 /* found a valid crypto attribute */
1377 return 0;
1378 }
1379
1380 ast_debug(1, "Ignoring crypto offer with unsupported parameters: %s\n", crypto_str);
1381 }
1382
1383 /* no usable crypto attributes found */
1384 return -1;
1385}
1386
1388 struct ast_sip_session_media *session_media,
1389 const struct pjmedia_sdp_session *sdp,
1390 const struct pjmedia_sdp_media *stream)
1391{
1392 switch (session_media->encryption) {
1394 if (setup_sdes_srtp(session_media, stream)) {
1395 return -1;
1396 }
1397 break;
1399 if (setup_dtls_srtp(session, session_media)) {
1400 return -1;
1401 }
1402 if (parse_dtls_attrib(session_media, sdp, stream)) {
1403 return -1;
1404 }
1405 break;
1408 break;
1409 }
1410
1411 return 0;
1412}
1413
1414static void set_ice_components(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
1415{
1416 struct ast_rtp_engine_ice *ice;
1417
1418 ast_assert(session_media->rtp != NULL);
1419
1421 if (!session->endpoint->media.rtp.ice_support || !ice) {
1422 return;
1423 }
1424
1425 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
1426 /* We both support RTCP mux. Only one ICE component necessary */
1427 ice->change_components(session_media->rtp, 1);
1428 } else {
1429 /* They either don't support RTCP mux or we don't know if they do yet. */
1430 ice->change_components(session_media->rtp, 2);
1431 }
1432}
1433
1434/*! \brief Function which adds ssrc attributes to a media stream */
1436{
1437 pj_str_t stmp;
1438 pjmedia_sdp_attr *attr;
1439 char tmp[128];
1440
1441 if (!session->endpoint->media.bundle || session_media->bundle_group == -1) {
1442 return;
1443 }
1444
1446 attr = pjmedia_sdp_attr_create(pool, "ssrc", pj_cstr(&stmp, tmp));
1447 media->attr[media->attr_count++] = attr;
1448}
1449
1450/*! \brief Function which processes ssrc attributes in a stream */
1452 const struct pjmedia_sdp_media *remote_stream)
1453{
1454 int index;
1455
1456 if (!session->endpoint->media.bundle) {
1457 return;
1458 }
1459
1460 for (index = 0; index < remote_stream->attr_count; ++index) {
1461 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1462 char attr_value[pj_strlen(&attr->value) + 1];
1464 unsigned int ssrc;
1465
1466 /* We only care about ssrc attributes */
1467 if (pj_strcmp2(&attr->name, "ssrc")) {
1468 continue;
1469 }
1470
1471 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1472
1473 if ((ssrc_attribute_name = strchr(attr_value, ' '))) {
1474 /* This has an actual attribute */
1475 *ssrc_attribute_name++ = '\0';
1478 /* Values are actually optional according to the spec */
1479 *ssrc_attribute_value++ = '\0';
1480 }
1481 }
1482
1483 if (sscanf(attr_value, "%30u", &ssrc) < 1) {
1484 continue;
1485 }
1486
1487 /* If we are currently negotiating as a result of the remote side renegotiating then
1488 * determine if the source for this stream has changed.
1489 */
1491 session->active_media_state) {
1492 struct ast_rtp_instance_stats stats = { 0, };
1493
1495 stats.remote_ssrc != ssrc) {
1496 session_media->changed = 1;
1497 }
1498 }
1499
1500 ast_rtp_instance_set_remote_ssrc(session_media->rtp, ssrc);
1501 break;
1502 }
1503}
1504
1506 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media,
1507 struct ast_stream *stream)
1508{
1509 pj_str_t stmp;
1510 pjmedia_sdp_attr *attr;
1511 char msid[(AST_UUID_STR_LEN * 2) + 2];
1512 const char *stream_label = ast_stream_get_metadata(stream, "SDP:LABEL");
1513
1514 if (!session->endpoint->media.webrtc) {
1515 return;
1516 }
1517
1518 if (ast_strlen_zero(session_media->mslabel)) {
1519 /* If this stream is grouped with another then use its media stream label if possible */
1520 if (ast_stream_get_group(stream) != -1) {
1521 struct ast_sip_session_media *group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, ast_stream_get_group(stream));
1522
1523 ast_copy_string(session_media->mslabel, group_session_media->mslabel, sizeof(session_media->mslabel));
1524 }
1525
1526 if (ast_strlen_zero(session_media->mslabel)) {
1527 ast_uuid_generate_str(session_media->mslabel, sizeof(session_media->mslabel));
1528 }
1529 }
1530
1531 if (ast_strlen_zero(session_media->label)) {
1532 ast_uuid_generate_str(session_media->label, sizeof(session_media->label));
1533 /* add for stream identification to replace stream_name */
1534 ast_stream_set_metadata(stream, "MSID:LABEL", session_media->label);
1535 }
1536
1537 snprintf(msid, sizeof(msid), "%s %s", session_media->mslabel, session_media->label);
1538 ast_debug(3, "Stream msid: %p %s %s\n", stream,
1540 attr = pjmedia_sdp_attr_create(pool, "msid", pj_cstr(&stmp, msid));
1541 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1542
1543 /* 'label' must come after 'msid' */
1544 if (!ast_strlen_zero(stream_label)) {
1545 ast_debug(3, "Stream Label: %p %s %s\n", stream,
1546 ast_codec_media_type2str(ast_stream_get_type(stream)), stream_label);
1547 attr = pjmedia_sdp_attr_create(pool, "label", pj_cstr(&stmp, stream_label));
1548 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1549 }
1550}
1551
1553 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
1554{
1555 pj_str_t stmp;
1556 pjmedia_sdp_attr *attr;
1557
1558 if (!session->endpoint->media.webrtc) {
1559 return;
1560 }
1561
1562 /* transport-cc is supposed to be for the entire transport, and any media sources so
1563 * while the header does not appear in audio streams and isn't negotiated there, we still
1564 * place this attribute in as Chrome does.
1565 */
1566 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* transport-cc"));
1567 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1568
1569 if (session_media->type != AST_MEDIA_TYPE_VIDEO) {
1570 return;
1571 }
1572
1573 /*
1574 * For now just automatically add it the stream even though it hasn't
1575 * necessarily been negotiated.
1576 */
1577 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* ccm fir"));
1578 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1579
1580 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* goog-remb"));
1581 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1582
1583 attr = pjmedia_sdp_attr_create(pool, "rtcp-fb", pj_cstr(&stmp, "* nack"));
1584 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1585}
1586
1588 struct ast_sip_session_media *session_media, pj_pool_t *pool, pjmedia_sdp_media *media)
1589{
1590 int idx;
1591 char extmap_value[256];
1592
1593 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1594 return;
1595 }
1596
1597 /* RTP extension local unique identifiers start at '1' */
1598 for (idx = 1; idx <= ast_rtp_instance_extmap_count(session_media->rtp); ++idx) {
1600 const char *direction_str = "";
1601 pj_str_t stmp;
1602 pjmedia_sdp_attr *attr;
1603
1604 /* If this is an unsupported RTP extension we can't place it into the SDP */
1606 continue;
1607 }
1608
1609 switch (ast_rtp_instance_extmap_get_direction(session_media->rtp, idx)) {
1611 /* Lack of a direction indicates sendrecv, so we leave it out */
1612 direction_str = "";
1613 break;
1615 direction_str = "/sendonly";
1616 break;
1618 direction_str = "/recvonly";
1619 break;
1621 /* It is impossible for a "none" direction extension to be negotiated but just in case
1622 * we treat it as inactive.
1623 */
1625 direction_str = "/inactive";
1626 break;
1627 }
1628
1629 snprintf(extmap_value, sizeof(extmap_value), "%d%s %s", idx, direction_str,
1630 ast_rtp_instance_extmap_get_uri(session_media->rtp, idx));
1631 attr = pjmedia_sdp_attr_create(pool, "extmap", pj_cstr(&stmp, extmap_value));
1632 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1633 }
1634}
1635
1636/*! \brief Function which processes extmap attributes in a stream */
1638 const struct pjmedia_sdp_media *remote_stream)
1639{
1640 int index;
1641
1642 if (!session->endpoint->media.webrtc || session_media->type != AST_MEDIA_TYPE_VIDEO) {
1643 return;
1644 }
1645
1646 ast_rtp_instance_extmap_clear(session_media->rtp);
1647
1648 for (index = 0; index < remote_stream->attr_count; ++index) {
1649 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1650 char attr_value[pj_strlen(&attr->value) + 1];
1651 char *uri;
1652 int id;
1653 char direction_str[10] = "";
1654 char *attributes;
1656
1657 /* We only care about extmap attributes */
1658 if (pj_strcmp2(&attr->name, "extmap")) {
1659 continue;
1660 }
1661
1662 ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value));
1663
1664 /* Split the combined unique identifier and direction away from the URI and attributes for easier parsing */
1665 uri = strchr(attr_value, ' ');
1666 if (ast_strlen_zero(uri)) {
1667 continue;
1668 }
1669 *uri++ = '\0';
1670
1671 if ((sscanf(attr_value, "%30d%9s", &id, direction_str) < 1) || (id < 1)) {
1672 /* We require at a minimum the unique identifier */
1673 continue;
1674 }
1675
1676 /* Convert from the string to the internal representation */
1677 if (!strcasecmp(direction_str, "/sendonly")) {
1679 } else if (!strcasecmp(direction_str, "/recvonly")) {
1681 } else if (!strcasecmp(direction_str, "/inactive")) {
1683 }
1684
1685 attributes = strchr(uri, ' ');
1686 if (!ast_strlen_zero(attributes)) {
1687 *attributes++ = '\0';
1688 }
1689
1690 ast_rtp_instance_extmap_negotiate(session_media->rtp, id, direction, uri, attributes);
1691 }
1692}
1693
1695 const struct ast_sip_session *session,
1696 const pjmedia_sdp_media *media,
1697 const struct ast_stream *stream,
1698 const struct ast_sockaddr *addrs)
1699{
1701 (session_media->type == AST_MEDIA_TYPE_AUDIO)) {
1702 if (((addrs != NULL) && ast_sockaddr_isnull(addrs)) ||
1703 ((addrs != NULL) && ast_sockaddr_is_any(addrs)) ||
1704 pjmedia_sdp_media_find_attr2(media, "sendonly", NULL) ||
1705 pjmedia_sdp_media_find_attr2(media, "inactive", NULL)) {
1706 if (!session_media->remotely_held) {
1707 session_media->remotely_held = 1;
1708 session_media->remotely_held_changed = 1;
1709 }
1710 } else if (session_media->remotely_held) {
1711 session_media->remotely_held = 0;
1712 session_media->remotely_held_changed = 1;
1713 }
1714 }
1715}
1716
1717/*! \brief Function which negotiates an incoming media stream */
1719 struct ast_sip_session_media *session_media, const pjmedia_sdp_session *sdp,
1720 int index, struct ast_stream *asterisk_stream)
1721{
1722 char host[NI_MAXHOST];
1723 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
1724 pjmedia_sdp_media *stream = sdp->media[index];
1725 struct ast_sip_session_media *session_media_transport;
1726 enum ast_media_type media_type = session_media->type;
1728 struct ast_format_cap *joint;
1729 int res;
1731
1732 /* If no type formats have been configured reject this stream */
1733 if (!ast_format_cap_has_type(session->endpoint->media.codecs, media_type)) {
1734 ast_debug(3, "Endpoint has no codecs for media type '%s', declining stream\n",
1735 ast_codec_media_type2str(session_media->type));
1736 SCOPE_EXIT_RTN_VALUE(0, "Endpoint has no codecs\n");
1737 }
1738
1739 /* Ensure incoming transport is compatible with the endpoint's configuration */
1740 if (!session->endpoint->media.rtp.use_received_transport) {
1741 encryption = check_endpoint_media_transport(session->endpoint, stream);
1742
1743 if (encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) {
1744 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
1745 }
1746 }
1747
1748 ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr, sizeof(host));
1749
1750 /* Ensure that the address provided is valid */
1751 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
1752 /* The provided host was actually invalid so we error out this negotiation */
1753 SCOPE_EXIT_RTN_VALUE(-1, "Invalid host\n");
1754 }
1755
1756 /* Using the connection information create an appropriate RTP instance */
1757 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
1758 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
1759 }
1760
1761 process_ssrc_attributes(session, session_media, stream);
1762 process_extmap_attributes(session, session_media, stream);
1763 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1764
1765 if (session_media_transport == session_media || !session_media->bundled) {
1766 /* If this media session is carrying actual traffic then set up those aspects */
1767 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(stream, "rtcp-mux", NULL) != NULL);
1768 set_ice_components(session, session_media);
1769
1770 enable_rtcp(session, session_media, stream);
1771
1772 res = setup_media_encryption(session, session_media, sdp, stream);
1773 if (res) {
1774 if (!session->endpoint->media.rtp.encryption_optimistic ||
1775 !pj_strncmp2(&stream->desc.transport, "RTP/SAVP", 8)) {
1776 /* If optimistic encryption is disabled and crypto should have been enabled
1777 * but was not this session must fail. This must also fail if crypto was
1778 * required in the offer but could not be set up.
1779 */
1780 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
1781 }
1782 /* There is no encryption, sad. */
1783 session_media->encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
1784 }
1785
1786 /* If we've been explicitly configured to use the received transport OR if
1787 * encryption is on and crypto is present use the received transport.
1788 * This is done in case of optimistic because it may come in as RTP/AVP or RTP/SAVP depending
1789 * on the configuration of the remote endpoint (optimistic themselves or mandatory).
1790 */
1791 if ((session->endpoint->media.rtp.use_received_transport) ||
1792 ((encryption == AST_SIP_MEDIA_ENCRYPT_SDES) && !res)) {
1793 pj_strdup(session->inv_session->pool, &session_media->transport, &stream->desc.transport);
1794 }
1795 } else {
1796 /* This is bundled with another session, so mark it as such */
1797 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
1798
1799 enable_rtcp(session, session_media, stream);
1800 }
1801
1802 /* If ICE support is enabled find all the needed attributes */
1803 check_ice_support(session, session_media, stream);
1804
1805 /* If ICE support is enabled then check remote ICE started? */
1806 if (session_media->remote_ice) {
1807 process_ice_auth_attrb(session, session_media, sdp, stream);
1808 }
1809
1810 /* Check if incoming SDP is changing the remotely held state */
1811 set_session_media_remotely_held(session_media, session, stream, asterisk_stream, addrs);
1812
1813 joint = set_incoming_call_offer_cap(session, session_media, stream);
1814 res = apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
1815 ao2_cleanup(joint);
1816 if (res != 0) {
1817 SCOPE_EXIT_RTN_VALUE(0, "Something failed\n");
1818 }
1819
1821}
1822
1824 struct ast_sip_session_media *session_media,
1825 pj_pool_t *pool, pjmedia_sdp_media *media)
1826{
1827 pj_str_t stmp;
1828 pjmedia_sdp_attr *attr;
1829 enum ast_rtp_dtls_hash hash;
1830 const char *crypto_attribute;
1831 struct ast_rtp_engine_dtls *dtls;
1832 struct ast_sdp_srtp *tmp;
1833 static const pj_str_t STR_NEW = { "new", 3 };
1834 static const pj_str_t STR_EXISTING = { "existing", 8 };
1835 static const pj_str_t STR_ACTIVE = { "active", 6 };
1836 static const pj_str_t STR_PASSIVE = { "passive", 7 };
1837 static const pj_str_t STR_ACTPASS = { "actpass", 7 };
1838 static const pj_str_t STR_HOLDCONN = { "holdconn", 8 };
1839 static const pj_str_t STR_MEDSECREQ = { "requested", 9 };
1840 enum ast_rtp_dtls_setup setup;
1841
1842 switch (session_media->encryption) {
1845 break;
1847 if (!session_media->srtp) {
1848 session_media->srtp = ast_sdp_srtp_alloc();
1849 if (!session_media->srtp) {
1850 return -1;
1851 }
1852 }
1853
1854 tmp = session_media->srtp;
1855
1856 do {
1857 crypto_attribute = ast_sdp_srtp_get_attrib(tmp,
1858 0 /* DTLS running? No */,
1859 session->endpoint->media.rtp.srtp_tag_32 /* 32 byte tag length? */);
1860 if (!crypto_attribute) {
1861 /* No crypto attribute to add, bad news */
1862 return -1;
1863 }
1864
1865 attr = pjmedia_sdp_attr_create(pool, "crypto",
1866 pj_cstr(&stmp, crypto_attribute));
1867 media->attr[media->attr_count++] = attr;
1868 } while ((tmp = AST_LIST_NEXT(tmp, sdp_srtp_list)));
1869
1870 if (session->endpoint->security_negotiation == AST_SIP_SECURITY_NEG_MEDIASEC) {
1871 attr = pjmedia_sdp_attr_create(pool, "3ge2ae", &STR_MEDSECREQ);
1872 media->attr[media->attr_count++] = attr;
1873 }
1874
1875 break;
1877 if (setup_dtls_srtp(session, session_media)) {
1878 return -1;
1879 }
1880
1881 dtls = ast_rtp_instance_get_dtls(session_media->rtp);
1882 if (!dtls) {
1883 return -1;
1884 }
1885
1886 switch (dtls->get_connection(session_media->rtp)) {
1888 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_NEW);
1889 media->attr[media->attr_count++] = attr;
1890 break;
1892 attr = pjmedia_sdp_attr_create(pool, "connection", &STR_EXISTING);
1893 media->attr[media->attr_count++] = attr;
1894 break;
1895 default:
1896 break;
1897 }
1898
1899 /* If this is an answer we need to use our current state, if it's an offer we need to use
1900 * the configured value.
1901 */
1902 if (session->inv_session->neg
1903 && pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
1904 setup = dtls->get_setup(session_media->rtp);
1905 } else {
1906 setup = session->endpoint->media.rtp.dtls_cfg.default_setup;
1907 }
1908
1909 switch (setup) {
1911 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTIVE);
1912 media->attr[media->attr_count++] = attr;
1913 break;
1915 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_PASSIVE);
1916 media->attr[media->attr_count++] = attr;
1917 break;
1919 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_ACTPASS);
1920 media->attr[media->attr_count++] = attr;
1921 break;
1923 attr = pjmedia_sdp_attr_create(pool, "setup", &STR_HOLDCONN);
1924 break;
1925 default:
1926 break;
1927 }
1928
1929 hash = dtls->get_fingerprint_hash(session_media->rtp);
1930 crypto_attribute = dtls->get_fingerprint(session_media->rtp);
1931 if (crypto_attribute && (hash == AST_RTP_DTLS_HASH_SHA1 || hash == AST_RTP_DTLS_HASH_SHA256)) {
1932 RAII_VAR(struct ast_str *, fingerprint, ast_str_create(64), ast_free);
1933 if (!fingerprint) {
1934 return -1;
1935 }
1936
1937 if (hash == AST_RTP_DTLS_HASH_SHA1) {
1938 ast_str_set(&fingerprint, 0, "SHA-1 %s", crypto_attribute);
1939 } else {
1940 ast_str_set(&fingerprint, 0, "SHA-256 %s", crypto_attribute);
1941 }
1942
1943 attr = pjmedia_sdp_attr_create(pool, "fingerprint", pj_cstr(&stmp, ast_str_buffer(fingerprint)));
1944 media->attr[media->attr_count++] = attr;
1945 }
1946 break;
1947 }
1948
1949 return 0;
1950}
1951
1952/*! \brief Function which creates an outgoing stream */
1954 struct pjmedia_sdp_session *sdp, const struct pjmedia_sdp_session *remote, struct ast_stream *stream)
1955{
1956 pj_pool_t *pool = session->inv_session->pool_prov;
1957 static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };
1958 static const pj_str_t STR_IN = { "IN", 2 };
1959 static const pj_str_t STR_IP4 = { "IP4", 3};
1960 static const pj_str_t STR_IP6 = { "IP6", 3};
1961 static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
1962 static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
1963 static const pj_str_t STR_INACTIVE = { "inactive", 8 };
1964 static const pj_str_t STR_RECVONLY = { "recvonly", 8 };
1965 pjmedia_sdp_media *media;
1966 const char *hostip = NULL;
1967 struct ast_sockaddr addr;
1968 char tmp[512];
1969 pj_str_t stmp;
1970 pjmedia_sdp_attr *attr;
1971 int index = 0;
1972 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;
1973 int min_packet_size = 0, max_packet_size = 0;
1974 int rtp_code;
1975 RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
1976 enum ast_media_type media_type = session_media->type;
1977 struct ast_sip_session_media *session_media_transport;
1978 pj_sockaddr ip;
1979 int direct_media_enabled = !ast_sockaddr_isnull(&session_media->direct_media_addr) &&
1980 ast_format_cap_count(session->direct_media_cap);
1981
1982 /* Keep track of the sample rates for offered codecs so we can build matching
1983 RFC 2833/4733 payload offers. */
1984 AST_VECTOR(, int) sample_rates;
1985 /* In case we can't init the sample rates, still try to do the rest. */
1986 int build_dtmf_sample_rates = 1;
1987
1988 SCOPE_ENTER(1, "%s Type: %s %s\n", ast_sip_session_get_name(session),
1989 ast_codec_media_type2str(media_type), ast_str_tmp(128, ast_stream_to_str(stream, &STR_TMP)));
1990
1991 media = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_media));
1992 if (!media) {
1993 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
1994 }
1995 pj_strdup2(pool, &media->desc.media, ast_codec_media_type2str(session_media->type));
1996
1997 /* If this is a removed (or declined) stream OR if no formats exist then construct a minimal stream in SDP */
2000 media->desc.port = 0;
2001 media->desc.port_count = 1;
2002
2003 if (remote && remote->media[ast_stream_get_position(stream)]) {
2004 pjmedia_sdp_media *remote_media = remote->media[ast_stream_get_position(stream)];
2005 int index;
2006
2007 media->desc.transport = remote_media->desc.transport;
2008
2009 /* Preserve existing behavior by copying the formats provided from the offer */
2010 for (index = 0; index < remote_media->desc.fmt_count; ++index) {
2011 media->desc.fmt[index] = remote_media->desc.fmt[index];
2012 }
2013 media->desc.fmt_count = remote_media->desc.fmt_count;
2014 } else {
2015 /* This is actually an offer so put a dummy payload in that is ignored and sane transport */
2016 media->desc.transport = STR_RTP_AVP;
2017 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], "32");
2018 }
2019
2020 sdp->media[sdp->media_count++] = media;
2022
2023 SCOPE_EXIT_RTN_VALUE(1, "Stream removed or no formats\n");
2024 }
2025
2026 if (!session_media->rtp && create_rtp(session, session_media, sdp)) {
2027 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
2028 }
2029
2030 /* If this stream has not been bundled already it is new and we need to ensure there is no SSRC conflict */
2031 if (session_media->bundle_group != -1 && !session_media->bundled) {
2032 for (index = 0; index < sdp->media_count; ++index) {
2033 struct ast_sip_session_media *other_session_media;
2034
2035 other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index);
2036 if (!other_session_media->rtp || other_session_media->bundle_group != session_media->bundle_group) {
2037 continue;
2038 }
2039
2040 if (ast_rtp_instance_get_ssrc(session_media->rtp) == ast_rtp_instance_get_ssrc(other_session_media->rtp)) {
2041 ast_rtp_instance_change_source(session_media->rtp);
2042 /* Start the conflict check over again */
2043 index = -1;
2044 continue;
2045 }
2046 }
2047 }
2048
2049 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
2050
2051 if (session_media_transport == session_media || !session_media->bundled) {
2052 set_ice_components(session, session_media);
2053 enable_rtcp(session, session_media, NULL);
2054
2055 /* Crypto has to be added before setting the media transport so that SRTP is properly
2056 * set up according to the configuration. This ends up changing the media transport.
2057 */
2058 if (add_crypto_to_stream(session, session_media, pool, media)) {
2059 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
2060 }
2061
2062 if (pj_strlen(&session_media->transport)) {
2063 /* If a transport has already been specified use it */
2064 media->desc.transport = session_media->transport;
2065 } else {
2066 media->desc.transport = pj_str(ast_sdp_get_rtp_profile(
2067 /* Optimistic encryption places crypto in the normal RTP/AVP profile */
2068 !session->endpoint->media.rtp.encryption_optimistic &&
2069 (session_media->encryption == AST_SIP_MEDIA_ENCRYPT_SDES),
2070 session_media->rtp, session->endpoint->media.rtp.use_avpf,
2071 session->endpoint->media.rtp.force_avp));
2072 }
2073
2074 media->conn = pj_pool_zalloc(pool, sizeof(struct pjmedia_sdp_conn));
2075 if (!media->conn) {
2076 SCOPE_EXIT_RTN_VALUE(-1, "Pool alloc failure\n");
2077 }
2078
2079 /* Add connection level details */
2080 if (direct_media_enabled) {
2082 } else if (ast_strlen_zero(session->endpoint->media.address)) {
2083 hostip = ast_sip_get_host_ip_string(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET());
2084 } else {
2085 hostip = session->endpoint->media.address;
2086 }
2087
2088 if (ast_strlen_zero(hostip)) {
2089 ast_log(LOG_ERROR, "No local host IP available for stream %s\n",
2090 ast_codec_media_type2str(session_media->type));
2091 SCOPE_EXIT_RTN_VALUE(-1, "No local host ip\n");
2092 }
2093
2094 media->conn->net_type = STR_IN;
2095 /* Assume that the connection will use IPv4 until proven otherwise */
2096 media->conn->addr_type = STR_IP4;
2097 pj_strdup2(pool, &media->conn->addr, hostip);
2098
2099 if ((pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &media->conn->addr, &ip) == PJ_SUCCESS) &&
2100 (ip.addr.sa_family == pj_AF_INET6())) {
2101 media->conn->addr_type = STR_IP6;
2102 }
2103
2104 /* Add ICE attributes and candidates */
2105 add_ice_to_stream(session, session_media, pool, media, 1);
2106
2107 ast_rtp_instance_get_local_address(session_media->rtp, &addr);
2108 media->desc.port = direct_media_enabled ? ast_sockaddr_port(&session_media->direct_media_addr) : (pj_uint16_t) ast_sockaddr_port(&addr);
2109 media->desc.port_count = 1;
2110 } else {
2111 pjmedia_sdp_media *bundle_group_stream = sdp->media[session_media_transport->stream_num];
2112
2113 /* As this is in a bundle group it shares the same details as the group instance */
2114 media->desc.transport = bundle_group_stream->desc.transport;
2115 media->conn = bundle_group_stream->conn;
2116 media->desc.port = bundle_group_stream->desc.port;
2117
2118 if (add_crypto_to_stream(session, session_media_transport, pool, media)) {
2119 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't add crypto\n");
2120 }
2121
2122 add_ice_to_stream(session, session_media_transport, pool, media, 0);
2123
2124 enable_rtcp(session, session_media, NULL);
2125 }
2126
2128 ast_log(LOG_ERROR, "Failed to allocate %s capabilities\n",
2129 ast_codec_media_type2str(session_media->type));
2130 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create caps\n");
2131 }
2132
2133 if (direct_media_enabled) {
2134 ast_format_cap_get_compatible(session->endpoint->media.codecs, session->direct_media_cap, caps);
2135 } else {
2136 ast_format_cap_append_from_cap(caps, ast_stream_get_formats(stream), media_type);
2137 }
2138
2139 /* Init the sample rates before we start adding them. Assume we will have at least one. */
2140 if (AST_VECTOR_INIT(&sample_rates, 1)) {
2141 ast_log(LOG_ERROR, "Unable to add dtmf formats to SDP!\n");
2142 build_dtmf_sample_rates = 0;
2143 }
2144
2145 for (index = 0; index < ast_format_cap_count(caps); ++index) {
2146 struct ast_format *format = ast_format_cap_get_format(caps, index);
2147
2148 if (ast_format_get_type(format) != media_type) {
2149 ao2_ref(format, -1);
2150 continue;
2151 }
2152
2153 /* It is possible for some formats not to have SDP information available for them
2154 * and if this is the case, skip over them so the SDP can still be created.
2155 */
2156 if (!ast_rtp_lookup_sample_rate2(1, format, 0)) {
2157 ast_log(LOG_WARNING, "Format '%s' can not be added to SDP, consider disallowing it on endpoint '%s'\n",
2159 ao2_ref(format, -1);
2160 continue;
2161 }
2162
2163 /* If this stream is not a transport we need to use the transport codecs structure for payload management to prevent
2164 * conflicts.
2165 */
2166 if (session_media_transport != session_media) {
2168 rtp_code = assign_unique_bundle_payload(session, session_media,
2169 session_media_transport, sdp, media, format);
2170 } else {
2171 rtp_code = ast_rtp_codecs_payload_code(
2172 ast_rtp_instance_get_codecs(session_media_transport->rtp), 1, format, 0);
2173 if (rtp_code != -1) {
2174 /* Our instance has to match the offered payload number. */
2176 ast_rtp_instance_get_codecs(session_media->rtp), rtp_code, format);
2177 }
2178 }
2179
2180 if (rtp_code == -1) {
2181 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
2182 ao2_ref(format, -1);
2183 continue;
2184 }
2185 } else {
2186 if ((rtp_code = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(session_media->rtp), 1, format, 0)) == -1) {
2187 ast_log(LOG_WARNING,"Unable to get rtp codec payload code for %s\n", ast_format_get_name(format));
2188 ao2_ref(format, -1);
2189 continue;
2190 }
2191 }
2192
2193 if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 1, format, 0))) {
2194 int i, added = 0;
2195 int newrate = ast_rtp_lookup_sample_rate2(1, format, 0);
2196 if (build_dtmf_sample_rates) {
2197 for (i = 0; i < AST_VECTOR_SIZE(&sample_rates); i++) {
2198 /* Only add if we haven't already processed this sample rate. For instance
2199 A-law and u-law 'share' one 8K DTMF payload type. */
2200 if (newrate == AST_VECTOR_GET(&sample_rates, i)) {
2201 added = 1;
2202 break;
2203 }
2204 }
2205
2206 if (!added) {
2207 AST_VECTOR_APPEND(&sample_rates, newrate);
2208 }
2209 }
2210 media->attr[media->attr_count++] = attr;
2211 }
2212
2213 if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
2214 media->attr[media->attr_count++] = attr;
2215 }
2216
2217 if (ast_format_get_maximum_ms(format) &&
2218 ((ast_format_get_maximum_ms(format) < max_packet_size) || !max_packet_size)) {
2219 max_packet_size = ast_format_get_maximum_ms(format);
2220 }
2221 ao2_ref(format, -1);
2222
2223 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2224 break;
2225 }
2226 }
2227
2228 /* Add non-codec formats */
2230 && media->desc.fmt_count < PJMEDIA_MAX_SDP_FMT) {
2231 for (index = 1LL; index <= AST_RTP_MAX; index <<= 1) {
2232 if (!(noncodec & index)) {
2233 continue;
2234 }
2235
2236 if (index != AST_RTP_DTMF) {
2237 rtp_code = ast_rtp_codecs_payload_code(
2238 ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index);
2239 if (rtp_code == -1) {
2240 continue;
2241 } else if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
2242 media->attr[media->attr_count++] = attr;
2243 }
2244 } else if (build_dtmf_sample_rates) {
2245 /*
2246 * Walk through the possible bitrates for the RFC 2833/4733 digits and generate the rtpmap
2247 * attributes.
2248 */
2249 int i, found_default_offer = 0;
2250 for (i = 0; i < AST_VECTOR_SIZE(&sample_rates); i++) {
2252 ast_rtp_instance_get_codecs(session_media->rtp), 0, NULL, index, AST_VECTOR_GET(&sample_rates, i));
2253
2254 if (rtp_code == -1) {
2255 continue;
2256 }
2257
2258 if (AST_VECTOR_GET(&sample_rates, i) == DEFAULT_DTMF_SAMPLE_RATE_MS) {
2259 /* we found and added a default offer, so no need to include a default one.*/
2260 found_default_offer = 1;
2261 }
2262
2263 if ((attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index, AST_VECTOR_GET(&sample_rates, i)))) {
2264 media->attr[media->attr_count++] = attr;
2265 snprintf(tmp, sizeof(tmp), "%d 0-16", (rtp_code));
2266 attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2267 media->attr[media->attr_count++] = attr;
2268 }
2269 }
2270
2271 /* If we weren't able to add any matching RFC 2833/4733, assume this endpoint is using a
2272 * mismatched 8K offer and try to add one as a fall-back/default.
2273 */
2274 if (!found_default_offer) {
2277
2278 if (rtp_code != -1 && (attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index, DEFAULT_DTMF_SAMPLE_RATE_MS))) {
2279 media->attr[media->attr_count++] = attr;
2280 snprintf(tmp, sizeof(tmp), "%d 0-16", (rtp_code));
2281 attr = pjmedia_sdp_attr_create(pool, "fmtp", pj_cstr(&stmp, tmp));
2282 media->attr[media->attr_count++] = attr;
2283 }
2284 }
2285 }
2286
2287 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2288 break;
2289 }
2290 }
2291 }
2292
2293 /* we are done with the sample rates */
2294 AST_VECTOR_FREE(&sample_rates);
2295
2296 /* If no formats were actually added to the media stream don't add it to the SDP */
2297 if (!media->desc.fmt_count) {
2298 SCOPE_EXIT_RTN_VALUE(1, "No formats added to stream\n");
2299 }
2300
2301 /* If ptime is set add it as an attribute */
2302 min_packet_size = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(session_media->rtp));
2303 if (!min_packet_size) {
2304 min_packet_size = ast_format_cap_get_framing(caps);
2305 }
2306 if (min_packet_size) {
2307 snprintf(tmp, sizeof(tmp), "%d", min_packet_size);
2308 attr = pjmedia_sdp_attr_create(pool, "ptime", pj_cstr(&stmp, tmp));
2309 media->attr[media->attr_count++] = attr;
2310 }
2311
2312 if (max_packet_size) {
2313 snprintf(tmp, sizeof(tmp), "%d", max_packet_size);
2314 attr = pjmedia_sdp_attr_create(pool, "maxptime", pj_cstr(&stmp, tmp));
2315 media->attr[media->attr_count++] = attr;
2316 }
2317
2318 attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
2319 if (session_media->locally_held) {
2320 if (session_media->remotely_held) {
2321 attr->name = STR_INACTIVE; /* To place on hold a recvonly stream, send inactive */
2322 } else {
2323 attr->name = STR_SENDONLY; /* Send sendonly to initate a local hold */
2324 }
2325 } else {
2326 if (session_media->remotely_held) {
2327 attr->name = STR_RECVONLY; /* Remote has sent sendonly, reply recvonly */
2328 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
2329 attr->name = STR_SENDONLY; /* Stream has requested sendonly */
2330 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_RECVONLY) {
2331 attr->name = STR_RECVONLY; /* Stream has requested recvonly */
2332 } else if (ast_stream_get_state(stream) == AST_STREAM_STATE_INACTIVE) {
2333 attr->name = STR_INACTIVE; /* Stream has requested inactive */
2334 } else {
2335 attr->name = STR_SENDRECV; /* No hold in either direction */
2336 }
2337 }
2338 media->attr[media->attr_count++] = attr;
2339
2340 /* If we've got rtcp-mux enabled, add it unless we received an offer without it */
2341 if (session->endpoint->media.rtcp_mux && session_media->remote_rtcp_mux) {
2342 attr = pjmedia_sdp_attr_create(pool, "rtcp-mux", NULL);
2343 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
2344 }
2345
2346 add_ssrc_to_stream(session, session_media, pool, media);
2347 add_msid_to_stream(session, session_media, pool, media, stream);
2348 add_rtcp_fb_to_stream(session, session_media, pool, media);
2349 add_extmap_to_stream(session, session_media, pool, media);
2350
2351 /* Add the media stream to the SDP */
2352 sdp->media[sdp->media_count++] = media;
2353
2354 SCOPE_EXIT_RTN_VALUE(1, "RC: 1\n");
2355}
2356
2358{
2359 struct ast_frame *f;
2360
2361 if (!session_media->rtp) {
2362 return &ast_null_frame;
2363 }
2364
2365 f = ast_rtp_instance_read(session_media->rtp, 0);
2366 if (!f) {
2367 return NULL;
2368 }
2369
2370 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2371
2372 return f;
2373}
2374
2376{
2377 struct ast_frame *f;
2378
2379 if (!session_media->rtp) {
2380 return &ast_null_frame;
2381 }
2382
2383 f = ast_rtp_instance_read(session_media->rtp, 1);
2384 if (!f) {
2385 return NULL;
2386 }
2387
2388 ast_rtp_instance_set_last_rx(session_media->rtp, time(NULL));
2389
2390 return f;
2391}
2392
2393static int media_session_rtp_write_callback(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_frame *frame)
2394{
2395 if (!session_media->rtp) {
2396 return 0;
2397 }
2398
2399 return ast_rtp_instance_write(session_media->rtp, frame);
2400}
2401
2403 struct ast_sip_session_media *session_media, const struct pjmedia_sdp_session *local,
2404 const struct pjmedia_sdp_session *remote, int index, struct ast_stream *asterisk_stream)
2405{
2406 RAII_VAR(struct ast_sockaddr *, addrs, NULL, ast_free);
2407 struct pjmedia_sdp_media *remote_stream = remote->media[index];
2408 enum ast_media_type media_type = session_media->type;
2409 char host[NI_MAXHOST];
2410 int res;
2411 int rtp_timeout;
2412 struct ast_sip_session_media *session_media_transport;
2413 SCOPE_ENTER(1, "%s Stream: %s\n", ast_sip_session_get_name(session),
2414 ast_str_tmp(128, ast_stream_to_str(asterisk_stream, &STR_TMP)));
2415
2416 if (!session->channel) {
2417 SCOPE_EXIT_RTN_VALUE(1, "No channel\n");
2418 }
2419
2420 /* Ensure incoming transport is compatible with the endpoint's configuration */
2421 if (!session->endpoint->media.rtp.use_received_transport &&
2423 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible transport\n");
2424 }
2425
2426 /* Create an RTP instance if need be */
2427 if (!session_media->rtp && create_rtp(session, session_media, local)) {
2428 SCOPE_EXIT_RTN_VALUE(-1, "Couldn't create rtp\n");
2429 }
2430
2431 process_ssrc_attributes(session, session_media, remote_stream);
2432 process_extmap_attributes(session, session_media, remote_stream);
2433
2434 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
2435
2436 if (session_media_transport == session_media || !session_media->bundled) {
2437 session_media->remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(remote_stream, "rtcp-mux", NULL) != NULL);
2438 set_ice_components(session, session_media);
2439
2440 enable_rtcp(session, session_media, remote_stream);
2441
2442 res = setup_media_encryption(session, session_media, remote, remote_stream);
2443 if (!session->endpoint->media.rtp.encryption_optimistic && res) {
2444 /* If optimistic encryption is disabled and crypto should have been enabled but was not
2445 * this session must fail.
2446 */
2447 SCOPE_EXIT_RTN_VALUE(-1, "Incompatible crypto\n");
2448 }
2449
2450 if (!remote_stream->conn && !remote->conn) {
2451 SCOPE_EXIT_RTN_VALUE(1, "No connection info\n");
2452 }
2453
2454 ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr, sizeof(host));
2455
2456 /* Ensure that the address provided is valid */
2457 if (ast_sockaddr_resolve(&addrs, host, PARSE_PORT_FORBID, AST_AF_UNSPEC) <= 0) {
2458 /* The provided host was actually invalid so we error out this negotiation */
2459 SCOPE_EXIT_RTN_VALUE(-1, "Host invalid\n");
2460 }
2461
2462 /* Apply connection information to the RTP instance */
2463 ast_sockaddr_set_port(addrs, remote_stream->desc.port);
2464 ast_rtp_instance_set_remote_address(session_media->rtp, addrs);
2465
2469 if (!session->endpoint->media.rtcp_mux || !session_media->remote_rtcp_mux) {
2472 }
2473
2474 /* If ICE support is enabled find all the needed attributes */
2475 process_ice_attributes(session, session_media, remote, remote_stream);
2476 } else {
2477 /* This is bundled with another session, so mark it as such */
2478 ast_rtp_instance_bundle(session_media->rtp, session_media_transport->rtp);
2480 enable_rtcp(session, session_media, remote_stream);
2481 }
2482
2483 if (set_caps(session, session_media, session_media_transport, remote_stream, 0, asterisk_stream)) {
2484 SCOPE_EXIT_RTN_VALUE(-1, "set_caps failed\n");
2485 }
2486
2487 /* Set the channel uniqueid on the RTP instance now that it is becoming active */
2488 ast_channel_lock(session->channel);
2490 ast_channel_unlock(session->channel);
2491
2492 /* Ensure the RTP instance is active */
2493 ast_rtp_instance_set_stream_num(session_media->rtp, ast_stream_get_position(asterisk_stream));
2494 ast_rtp_instance_activate(session_media->rtp);
2495
2496 /* audio stream handles music on hold */
2497 if (media_type != AST_MEDIA_TYPE_AUDIO && media_type != AST_MEDIA_TYPE_VIDEO) {
2498 if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2499 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2501 }
2502 SCOPE_EXIT_RTN_VALUE(1, "moh\n");
2503 }
2504
2505 set_session_media_remotely_held(session_media, session, remote_stream, asterisk_stream, addrs);
2506
2507 if (session_media->remotely_held_changed) {
2508 if (session_media->remotely_held) {
2509 /* The remote side has put us on hold */
2510 if (!session->endpoint->suppress_moh_on_sendonly) {
2511 ast_queue_hold(session->channel, session->endpoint->mohsuggest);
2512 ast_rtp_instance_stop(session_media->rtp);
2514 }
2515 session_media->remotely_held_changed = 0;
2516 } else {
2517 /* The remote side has taken us off hold */
2518 if (!session->endpoint->suppress_moh_on_sendonly) {
2519 ast_queue_unhold(session->channel);
2521 }
2522 session_media->remotely_held_changed = 0;
2523 }
2524 } else if ((pjmedia_sdp_neg_was_answer_remote(session->inv_session->neg) == PJ_FALSE)
2525 && (session->inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2527 }
2528
2529 /* This purposely resets the encryption to the configured in case it gets added later */
2530 session_media->encryption = session->endpoint->media.rtp.encryption;
2531
2532 if (session->endpoint->media.rtp.keepalive > 0 &&
2533 (session_media->type == AST_MEDIA_TYPE_AUDIO ||
2534 session_media->type == AST_MEDIA_TYPE_VIDEO)) {
2535 ast_rtp_instance_set_keepalive(session_media->rtp, session->endpoint->media.rtp.keepalive);
2536 /* Schedule the initial keepalive early in case this is being used to punch holes through
2537 * a NAT. This way there won't be an awkward delay before media starts flowing in some
2538 * scenarios.
2539 */
2540 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2542 session_media, 1);
2543 }
2544
2545 /* As the channel lock is not held during this process the scheduled item won't block if
2546 * it is hanging up the channel at the same point we are applying this negotiated SDP.
2547 */
2548 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2549
2550 /* Due to the fact that we only ever have one scheduled timeout item for when we are both
2551 * off hold and on hold we don't need to store the two timeouts differently on the RTP
2552 * instance itself.
2553 */
2554 ast_rtp_instance_set_timeout(session_media->rtp, 0);
2555 if (session->endpoint->media.rtp.timeout && !session_media->remotely_held && !session_media->locally_held) {
2556 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout);
2557 } else if (session->endpoint->media.rtp.timeout_hold && (session_media->remotely_held || session_media->locally_held)) {
2558 ast_rtp_instance_set_timeout(session_media->rtp, session->endpoint->media.rtp.timeout_hold);
2559 }
2560
2561 rtp_timeout = ast_rtp_instance_get_timeout(session_media->rtp);
2562
2563 if (rtp_timeout) {
2564 session_media->timeout_sched_id = ast_sched_add_variable(sched, rtp_timeout*1000, rtp_check_timeout,
2565 session_media, 1);
2566 }
2567
2568 SCOPE_EXIT_RTN_VALUE(1, "Handled\n");
2569}
2570
2571/*! \brief Function which updates the media stream with external media address, if applicable */
2572static void change_outgoing_sdp_stream_media_address(pjsip_tx_data *tdata, struct pjmedia_sdp_media *stream, struct ast_sip_transport *transport)
2573{
2575 char host[NI_MAXHOST];
2576 struct ast_sockaddr our_sdp_addr = { { 0, } };
2577
2578 /* If the stream has been rejected there will be no connection line */
2579 if (!stream->conn || !transport_state) {
2580 return;
2581 }
2582
2583 ast_copy_pj_str(host, &stream->conn->addr, sizeof(host));
2584 ast_sockaddr_parse(&our_sdp_addr, host, PARSE_PORT_FORBID);
2585
2586 /* Reversed check here. We don't check the remote endpoint being
2587 * in our local net, but whether our outgoing session IP is
2588 * local. If it is not, we won't do rewriting. No localnet
2589 * configured? Always rewrite. */
2590 if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
2591 return;
2592 }
2593 ast_debug(5, "Setting media address to %s\n", ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2594 pj_strdup2(tdata->pool, &stream->conn->addr, ast_sockaddr_stringify_addr_remote(&transport_state->external_media_address));
2595}
2596
2597/*! \brief Function which stops the RTP instance */
2598static void stream_stop(struct ast_sip_session_media *session_media)
2599{
2600 if (!session_media->rtp) {
2601 return;
2602 }
2603
2604 AST_SCHED_DEL(sched, session_media->keepalive_sched_id);
2605 AST_SCHED_DEL(sched, session_media->timeout_sched_id);
2606 ast_rtp_instance_stop(session_media->rtp);
2607}
2608
2609/*! \brief Function which destroys the RTP instance when session ends */
2610static void stream_destroy(struct ast_sip_session_media *session_media)
2611{
2612 if (session_media->rtp) {
2613 stream_stop(session_media);
2614 ast_rtp_instance_destroy(session_media->rtp);
2615 }
2616 session_media->rtp = NULL;
2617}
2618
2619/*! \brief SDP handler for 'audio' media stream */
2621 .id = STR_AUDIO,
2622 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
2623 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
2624 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
2625 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
2626 .stream_stop = stream_stop,
2627 .stream_destroy = stream_destroy,
2628};
2629
2630/*! \brief SDP handler for 'video' media stream */
2632 .id = STR_VIDEO,
2633 .negotiate_incoming_sdp_stream = negotiate_incoming_sdp_stream,
2634 .create_outgoing_sdp_stream = create_outgoing_sdp_stream,
2635 .apply_negotiated_sdp_stream = apply_negotiated_sdp_stream,
2636 .change_outgoing_sdp_stream_media_address = change_outgoing_sdp_stream_media_address,
2637 .stream_stop = stream_stop,
2638 .stream_destroy = stream_destroy,
2639};
2640
2641static int video_info_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata)
2642{
2643 struct pjsip_transaction *tsx;
2644 pjsip_tx_data *tdata;
2645
2646 if (!session->channel
2647 || !ast_sip_are_media_types_equal(&rdata->msg_info.msg->body->content_type,
2649 return 0;
2650 }
2651
2652 tsx = pjsip_rdata_get_tsx(rdata);
2653
2655
2656 if (pjsip_dlg_create_response(session->inv_session->dlg, rdata, 200, NULL, &tdata) == PJ_SUCCESS) {
2657 pjsip_dlg_send_response(session->inv_session->dlg, tsx, tdata);
2658 }
2659
2660 return 0;
2661}
2662
2664 .method = "INFO",
2665 .incoming_request = video_info_incoming_request,
2666};
2667
2668/*! \brief Unloads the sdp RTP/AVP module from Asterisk */
2681
2682/*!
2683 * \brief Load the module
2684 *
2685 * Module loading including tests for configuration or dependencies.
2686 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
2687 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
2688 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
2689 * configuration file or other non-critical problem return
2690 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
2691 */
2692static int load_module(void)
2693{
2694 if (ast_check_ipv6()) {
2696 } else {
2697 ast_sockaddr_parse(&address_rtp, "0.0.0.0", 0);
2698 }
2699
2700 if (!(sched = ast_sched_context_create())) {
2701 ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
2702 goto end;
2703 }
2704
2706 ast_log(LOG_ERROR, "Unable to create scheduler context thread.\n");
2707 goto end;
2708 }
2709
2711 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_AUDIO);
2712 goto end;
2713 }
2714
2716 ast_log(LOG_ERROR, "Unable to register SDP handler for %s stream type\n", STR_VIDEO);
2717 goto end;
2718 }
2719
2721
2723end:
2724 unload_module();
2725
2727}
2728
2729AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP SDP RTP/AVP stream handler",
2730 .support_level = AST_MODULE_SUPPORT_CORE,
2731 .load = load_module,
2732 .unload = unload_module,
2733 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
2734 .requires = "res_pjsip,res_pjsip_session",
Access Control of various sorts.
enum queue_result id
Definition app_queue.c:1790
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.
Internal Asterisk hangup causes.
#define AST_CAUSE_REQUESTED_CHAN_UNAVAIL
Definition causes.h:125
static const char type[]
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:2983
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:1289
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:1171
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1417
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition channel.c:5785
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition channel.c:10725
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
Definition channel.c:1274
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Definition channel.c:1249
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3019
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition channel.c:5826
@ AST_SOFTHANGUP_DEV
Definition channel.h:1141
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_unlock(chan)
Definition channel.h:2984
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
ast_channel_state
ast_channel states
@ AST_STATE_UP
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:1968
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
Definition dsp.c:1962
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition dsp.c:1953
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
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition format.c:201
@ AST_FORMAT_CMP_EQUAL
Definition format.h:36
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:752
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:408
unsigned int ast_format_cap_get_framing(const struct ast_format_cap *cap)
Get the global framing.
Definition format_cap.c:446
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:425
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:636
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:531
@ 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:742
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:621
#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:403
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.
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
#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
@ AST_AF_UNSPEC
Definition netsock2.h:54
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:2513
pjsip_media_type pjsip_media_type_application_media_control_xml
Definition res_pjsip.c:3950
ast_sip_session_media_encryption
Definition res_pjsip.h:735
@ AST_SIP_MEDIA_ENCRYPT_SDES
Definition res_pjsip.h:741
@ AST_SIP_MEDIA_TRANSPORT_INVALID
Definition res_pjsip.h:737
@ AST_SIP_MEDIA_ENCRYPT_NONE
Definition res_pjsip.h:739
@ AST_SIP_MEDIA_ENCRYPT_DTLS
Definition res_pjsip.h:743
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:2221
int ast_sip_are_media_types_equal(pjsip_media_type *a, pjsip_media_type *b)
Compare pjsip media types.
Definition res_pjsip.c:2239
@ AST_SIP_DTMF_AUTO_INFO
Definition res_pjsip.h:560
@ AST_SIP_DTMF_AUTO
Definition res_pjsip.h:558
@ AST_SIP_DTMF_INBAND
Definition res_pjsip.h:554
@ AST_SIP_DTMF_RFC_4733
Definition res_pjsip.h:552
#define ast_sip_transport_is_nonlocal(transport_state, addr)
Definition res_pjsip.h:210
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 int assign_unique_bundle_payload(struct ast_sip_session *session, struct ast_sip_session_media *session_media, struct ast_sip_session_media *session_media_transport, const pjmedia_sdp_session *sdp, const pjmedia_sdp_media *media, struct ast_format *format)
Assign a payload type that is unique across the generated BUNDLE group.
static int bundle_payload_type_used(struct ast_sip_session *session, const pjmedia_sdp_session *sdp, const pjmedia_sdp_media *media, int bundle_group, int payload)
Determine whether a payload type is already advertised in a BUNDLE group.
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 int generating_local_offer(const struct ast_sip_session *session)
Determine whether the SDP currently being generated is a local offer.
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 int ensure_payload_type_mapping(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
Ensure an RTP codecs structure can receive a format using a payload type.
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 payload_type_compatible(struct ast_rtp_codecs *codecs, int payload, struct ast_format *format)
Check whether a payload slot is either free or already mapped to the requested format.
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.
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.
@ 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.
void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
Destroy the contents of an RTP codecs structure (but not the structure itself)
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition rtp_engine.c:468
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
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.
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:497
struct ast_rtp_payload_type * ast_rtp_codecs_get_payload(struct ast_rtp_codecs *codecs, int payload)
Retrieve rx payload mapped information by payload type.
void ast_rtp_instance_set_last_rx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP reception time.
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.
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
#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.
size_t ast_rtp_instance_extmap_count(struct ast_rtp_instance *instance)
Get the number of known unique identifiers.
Definition rtp_engine.c:950
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:783
@ 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.
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
Get the RTP keepalive interval.
const char * ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp)
Retrieve the CNAME used in RTCP SDES items.
int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
Get the RTP timeout value.
#define AST_RTP_MAX_PT
Definition rtp_engine.h:83
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.
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition rtp_engine.c:629
int ast_rtp_instance_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
Request that an RTP instance be bundled with another.
void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
Set the framing used for a set of codecs.
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp)
Get the last RTP transmission time.
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.
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:756
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:694
struct ast_rtp_instance * ast_rtp_instance_new_with_options(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data, const struct ast_rtp_instance_options *options)
Create a new RTP instance with additional options.
Definition rtp_engine.c:505
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.
@ 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 ...
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:961
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition rtp_engine.c:619
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.
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
Send a comfort noise packet to the RTP instance.
#define AST_RTP_PT_FIRST_DYNAMIC
Definition rtp_engine.h:92
void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc)
Set the remote SSRC for an RTP instance.
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.
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
void ast_rtp_codecs_payloads_merge(struct ast_rtp_codecs *src, struct ast_rtp_codecs *dest, struct ast_rtp_instance *instance)
Merge payload information from one RTP instance into another.
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
@ 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.
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.
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.
time_t ast_rtp_instance_get_last_rx(const struct ast_rtp_instance *rtp)
Get the last RTP reception time.
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.
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:604
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.
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:997
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.
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.
#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:937
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.
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:869
void ast_rtp_instance_extmap_clear(struct ast_rtp_instance *instance)
Clear negotiated RTP extension information.
Definition rtp_engine.c:913
#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:778
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:599
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int timeout)
Set the RTP keepalive interval.
unsigned int ast_rtp_instance_get_ssrc(struct ast_rtp_instance *rtp)
Retrieve the local SSRC value that we will be using.
#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.
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:981
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.
void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
Set the RTP timeout value.
int ast_rtp_codecs_set_preferred_format(struct ast_rtp_codecs *codecs, struct ast_format *format)
Set the preferred format.
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:2381
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:1917
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:1080
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
Definition stream.c:316
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
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition strings.h:730
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
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
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
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
Options for creating a new RTP instance.
Definition rtp_engine.h:994
unsigned int remote_ssrc
Definition rtp_engine.h:454
struct ast_format * format
Definition rtp_engine.h:306
structure for secure RTP audio
Definition sdp_srtp.h:38
struct ast_sdp_srtp::@297 sdp_srtp_list
struct ast_sdp_crypto * crypto
Definition sdp_srtp.h:40
struct ast_sip_media_rtp_configuration rtp
Definition res_pjsip.h:1019
An entity with which Asterisk communicates.
Definition res_pjsip.h:1067
struct ast_sip_endpoint_media_configuration media
Definition res_pjsip.h:1100
enum ast_sip_session_media_encryption encryption
Definition res_pjsip.h:958
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.
char * mid
Media identifier for this stream (may be shared across multiple streams)
A handler for SDPs in SIP sessions.
A supplement to SIP message processing.
struct ast_module *const char * method
A structure describing a SIP session.
Structure for SIP transport information.
Definition res_pjsip.h:117
struct pjsip_transport * transport
Transport itself.
Definition res_pjsip.h:119
Transport to bind to.
Definition res_pjsip.h:219
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:981
#define ast_assert(a)
Definition utils.h:779
#define ast_set_flag(p, flag)
Definition utils.h:71
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
Definition utils.c:2826
#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:637
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267
#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:708