55 #include "asterisk/logger_category.h"
58 #include "asterisk/res_pjsip.h"
59 #include "asterisk/res_pjsip_session.h"
60 #include "asterisk/res_pjsip_session_caps.h"
68 static const char STR_AUDIO[] =
"audio";
69 static const char STR_VIDEO[] =
"video";
71 static int send_keepalive(
const void *data)
86 ast_debug_rtp(3,
"(%p) RTP not sending keepalive since direct media is in use\n", rtp);
87 return keepalive * 1000;
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");
98 return keepalive * 1000;
101 return (keepalive - interval) * 1000;
137 return timeout * 500;
141 if (elapsed < timeout) {
143 return (timeout - elapsed) * 1000;
146 ast_log(LOG_NOTICE,
"Disconnecting channel '%s' for lack of %s RTP activity in %d seconds\n",
149 ast_channel_lock(chan);
150 ast_channel_hangupcause_set(chan, AST_CAUSE_REQUESTED_CHAN_UNAVAIL);
151 ast_channel_unlock(chan);
163 const struct pjmedia_sdp_media *remote_media)
181 const pjmedia_sdp_session *sdp)
191 for (index = 0; index < sdp->media_count; ++index) {
205 if (other_id == -1) {
226 const pjmedia_sdp_session *sdp)
237 media_address = &temp_media_address;
239 ast_debug_rtp(1,
"Endpoint %s: RTP media address invalid: %s\n",
253 char hoststr[PJ_INET6_ADDRSTRLEN];
255 pj_sockaddr_print(&trans_state->
host, hoststr,
sizeof(hoststr), 0);
257 ast_debug_rtp(1,
"Transport %s bound to %s: Using it for RTP media.\n",
259 media_address = &temp_media_address;
261 ast_debug_rtp(1,
"Transport %s bound to %s: Invalid for RTP media.\n",
271 ast_log(LOG_ERROR,
"Unable to create RTP instance using RTP engine '%s'\n", session->
endpoint->
media.
rtp.
engine);
282 if (session->
dtmf == AST_SIP_DTMF_RFC_4733 || session->
dtmf == AST_SIP_DTMF_AUTO || session->
dtmf == AST_SIP_DTMF_AUTO_INFO) {
285 }
else if (session->
dtmf == AST_SIP_DTMF_INBAND) {
289 if (session_media->
type == AST_MEDIA_TYPE_AUDIO &&
293 }
else if (session_media->
type == AST_MEDIA_TYPE_VIDEO) {
315 pjmedia_sdp_attr *attr;
316 pjmedia_sdp_rtpmap *rtpmap;
317 pjmedia_sdp_fmtp fmtp;
319 int i, num = 0, tel_event = 0;
325 SCOPE_ENTER(1,
"%s\n", ast_sip_session_get_name(session));
332 for (i = 0; i < stream->desc.fmt_count; ++i) {
336 if (!(attr = pjmedia_sdp_media_find_attr2(stream,
"rtpmap", &stream->desc.fmt[i]))) {
341 if ((pjmedia_sdp_attr_to_rtpmap(session->
inv_session->pool_prov, attr, &rtpmap)) != PJ_SUCCESS) {
345 ast_copy_pj_str(name, &rtpmap->enc_name,
sizeof(name));
346 if (strcmp(name,
"telephone-event") == 0) {
350 ast_copy_pj_str(media, (pj_str_t*)&stream->desc.media,
sizeof(media));
352 pj_strtoul(&stream->desc.fmt[i]), media, name, options, rtpmap->clock_rate);
354 if (!(attr = pjmedia_sdp_media_find_attr2(stream,
"fmtp", &rtpmap->pt))) {
358 if ((pjmedia_sdp_attr_get_fmtp(attr, &fmtp)) == PJ_SUCCESS) {
359 ast_copy_pj_str(fmt_param, &fmtp.fmt,
sizeof(fmt_param));
360 if (sscanf(fmt_param,
"%30d", &num) != 1) {
367 ast_copy_pj_str(fmt_param, &fmtp.fmt_param,
sizeof(fmt_param));
380 for (i = 0; i < stream->desc.fmt_count; ++i) {
387 if (!tel_event && (session->
dtmf == AST_SIP_DTMF_AUTO)) {
392 if (session->
dtmf == AST_SIP_DTMF_AUTO_INFO) {
404 if ((attr = pjmedia_sdp_media_find_attr2(stream,
"ptime", NULL))) {
405 unsigned long framing = pj_strtoul(pj_strltrim(&attr->value));
426 if (session_media_transport != session_media && session_media->
bundled) {
448 const struct pjmedia_sdp_media *stream)
453 SCOPE_ENTER(1,
"%s\n", ast_sip_session_get_name(session));
458 ast_log(LOG_ERROR,
"Failed to allocate %s incoming remote capabilities\n",
460 SCOPE_EXIT_RTN_VALUE(NULL,
"Couldn't allocate caps\n");
464 get_codecs(session, stream, &codecs, session_media, remote);
466 incoming_call_offer_cap = ast_sip_session_create_joint_call_cap(
467 session, session_media->
type, remote);
472 ao2_cleanup(incoming_call_offer_cap);
474 SCOPE_EXIT_RTN_VALUE(NULL,
"No incoming call offer caps\n");
488 SCOPE_EXIT_RTN_VALUE(incoming_call_offer_cap);
494 const struct pjmedia_sdp_media *stream,
495 int is_offer,
struct ast_stream *asterisk_stream)
504 int dsp_features = 0;
505 SCOPE_ENTER(1,
"%s %s\n", ast_sip_session_get_name(session), is_offer ?
"OFFER" :
"ANSWER");
510 ast_log(LOG_ERROR,
"Failed to allocate %s capabilities\n",
512 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't create %s capabilities\n",
517 if (direct_media_enabled) {
524 get_codecs(session, stream, &codecs, session_media, peer);
533 ast_log(LOG_NOTICE,
"No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
537 SCOPE_EXIT_RTN_VALUE(-1,
"No joint capabilities for '%s' media stream between our configuration(%s) and incoming SDP(%s)\n",
555 apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
557 if (session->
channel && ast_sip_session_is_pending_stream_default(session, asterisk_stream)) {
558 ast_channel_lock(session->
channel);
561 AST_MEDIA_TYPE_UNKNOWN);
590 ast_channel_nativeformats_set(session->
channel, caps);
591 if (media_type == AST_MEDIA_TYPE_AUDIO) {
596 if ( ((session->
dtmf == AST_SIP_DTMF_AUTO) || (session->
dtmf == AST_SIP_DTMF_AUTO_INFO) )
600 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
604 ast_dsp_free(session->
dsp);
613 ast_channel_unlock(session->
channel);
617 SCOPE_EXIT_RTN_VALUE(0);
620 static pjmedia_sdp_attr* generate_rtpmap_attr(
struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *
pool,
621 int rtp_code,
int asterisk_format,
struct ast_format *format,
int code)
623 #ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
624 extern pj_bool_t pjsip_use_compact_form;
626 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
628 pjmedia_sdp_rtpmap rtpmap;
629 pjmedia_sdp_attr *attr = NULL;
634 snprintf(tmp,
sizeof(tmp),
"%d", rtp_code);
635 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
641 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
644 if (!pj_stricmp2(&rtpmap.enc_name,
"opus")) {
645 pj_cstr(&rtpmap.param,
"2");
647 pj_cstr(&rtpmap.param, NULL);
650 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
656 static pjmedia_sdp_attr* generate_rtpmap_attr2(
struct ast_sip_session *session, pjmedia_sdp_media *media, pj_pool_t *pool,
657 int rtp_code,
int asterisk_format,
struct ast_format *format,
int code,
int sample_rate)
659 #ifndef HAVE_PJSIP_ENDPOINT_COMPACT_FORM
660 extern pj_bool_t pjsip_use_compact_form;
662 pj_bool_t pjsip_use_compact_form = pjsip_cfg()->endpt.use_compact_form;
664 pjmedia_sdp_rtpmap rtpmap;
665 pjmedia_sdp_attr *attr = NULL;
670 snprintf(tmp,
sizeof(tmp),
"%d", rtp_code);
671 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++], tmp);
677 rtpmap.pt = media->desc.fmt[media->desc.fmt_count - 1];
678 rtpmap.clock_rate = sample_rate;
680 if (!pj_stricmp2(&rtpmap.enc_name,
"opus")) {
681 pj_cstr(&rtpmap.param,
"2");
683 pj_cstr(&rtpmap.param, NULL);
686 pjmedia_sdp_rtpmap_to_attr(pool, &rtpmap, &attr);
691 static pjmedia_sdp_attr* generate_fmtp_attr(pj_pool_t *pool,
struct ast_format *format,
int rtp_code)
693 struct ast_str *fmtp0 = ast_str_alloca(256);
695 pjmedia_sdp_attr *attr = NULL;
702 while (*tmp ==
'\r' || *tmp ==
'\n') --tmp;
706 if (tmp && tmp[1] !=
'\0') {
707 fmtp1 = pj_str(tmp + 1);
711 attr = pjmedia_sdp_attr_create(pool,
"fmtp", &fmtp1);
718 unsigned int include_candidates)
722 const char *username, *password;
724 pjmedia_sdp_attr *attr;
738 attr = pjmedia_sdp_attr_create(pool,
"ice-ufrag", pj_cstr(&stmp, username));
739 media->attr[media->attr_count++] = attr;
743 attr = pjmedia_sdp_attr_create(pool,
"ice-pwd", pj_cstr(&stmp, password));
744 media->attr[media->attr_count++] = attr;
747 if (!include_candidates) {
757 for (; (candidate = ao2_iterator_next(&it_candidates));
ao2_ref(candidate, -1)) {
764 switch (candidate->
type) {
781 attr = pjmedia_sdp_attr_create(pool,
"candidate", pj_cstr(&stmp,
ast_str_buffer(attr_candidate)));
782 media->attr[media->attr_count++] = attr;
784 ast_free(attr_candidate);
793 const struct pjmedia_sdp_media *remote_stream)
796 const pjmedia_sdp_attr *attr;
805 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
806 attr = remote_stream->attr[attr_i];
807 if (!pj_strcmp2(&attr->name,
"candidate")) {
813 if (attr_i == remote_stream->attr_count) {
819 const struct pjmedia_sdp_session *remote,
const struct pjmedia_sdp_media *remote_stream)
822 const pjmedia_sdp_attr *ufrag_attr, *passwd_attr;
823 char ufrag_attr_value[256];
824 char passwd_attr_value[256];
831 ufrag_attr = pjmedia_sdp_media_find_attr2(remote_stream,
"ice-ufrag", NULL);
833 ufrag_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr,
"ice-ufrag", NULL);
836 ast_copy_pj_str(ufrag_attr_value, (pj_str_t*)&ufrag_attr->value,
sizeof(ufrag_attr_value));
840 passwd_attr = pjmedia_sdp_media_find_attr2(remote_stream,
"ice-pwd", NULL);
842 passwd_attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr,
"ice-pwd", NULL);
845 ast_copy_pj_str(passwd_attr_value, (pj_str_t*)&passwd_attr->value,
sizeof(passwd_attr_value));
850 if (ufrag_attr && passwd_attr) {
857 const struct pjmedia_sdp_session *remote,
const struct pjmedia_sdp_media *remote_stream)
860 const pjmedia_sdp_attr *attr;
861 char attr_value[256];
871 attr = pjmedia_sdp_media_find_attr2(remote_stream,
"ice-ufrag", NULL);
873 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr,
"ice-ufrag", NULL);
876 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value,
sizeof(attr_value));
879 ast_debug_ice(2,
"(%p) ICE no, or invalid ice-ufrag\n", session_media->
rtp);
883 attr = pjmedia_sdp_media_find_attr2(remote_stream,
"ice-pwd", NULL);
885 attr = pjmedia_sdp_attr_find2(remote->attr_count, remote->attr,
"ice-pwd", NULL);
888 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value,
sizeof(attr_value));
895 if (pjmedia_sdp_media_find_attr2(remote_stream,
"ice-lite", NULL)) {
900 for (attr_i = 0; attr_i < remote_stream->attr_count; ++attr_i) {
901 char foundation[33], transport[32], address[PJ_INET6_ADDRSTRLEN + 1], cand_type[6], relay_address[PJ_INET6_ADDRSTRLEN + 1] =
"";
902 unsigned int port, relay_port = 0;
905 attr = remote_stream->attr[attr_i];
908 if (pj_strcmp2(&attr->name,
"candidate")) {
912 ast_copy_pj_str(attr_value, (pj_str_t*)&attr->value,
sizeof(attr_value));
914 if (sscanf(attr_value,
"%32s %30u %31s %30u %46s %30u typ %5s %*s %23s %*s %30u", foundation, &candidate.
id, transport,
915 (
unsigned *)&candidate.
priority, address, &port, cand_type, relay_address, &relay_port) < 7) {
933 if (!strcasecmp(cand_type,
"host")) {
935 }
else if (!strcasecmp(cand_type,
"srflx")) {
937 }
else if (!strcasecmp(cand_type,
"relay")) {
943 if (!ast_strlen_zero(relay_address)) {
954 ice->
set_role(session_media->
rtp, pjmedia_sdp_neg_was_answer_remote(session->
inv_session->neg) == PJ_TRUE ?
955 AST_RTP_ICE_ROLE_CONTROLLING : AST_RTP_ICE_ROLE_CONTROLLED);
964 for (i = 0; i < stream->attr_count; i++) {
965 pjmedia_sdp_attr *attr;
968 attr = stream->attr[i];
969 if (pj_strcmp2(&attr->name,
"crypto")) {
981 const struct pjmedia_sdp_media *stream,
unsigned int *optimistic)
987 if (!transport_str) {
988 return AST_SIP_MEDIA_TRANSPORT_INVALID;
990 if (strstr(transport_str,
"UDP/TLS")) {
991 return AST_SIP_MEDIA_ENCRYPT_DTLS;
992 }
else if (strstr(transport_str,
"SAVP")) {
993 return AST_SIP_MEDIA_ENCRYPT_SDES;
996 return AST_SIP_MEDIA_ENCRYPT_SDES;
998 return AST_SIP_MEDIA_ENCRYPT_NONE;
1014 const struct pjmedia_sdp_media *stream)
1016 enum ast_sip_session_media_encryption incoming_encryption;
1017 char transport_end = stream->desc.transport.ptr[stream->desc.transport.slen - 1];
1018 unsigned int optimistic;
1022 return AST_SIP_MEDIA_TRANSPORT_INVALID;
1028 return incoming_encryption;
1033 return incoming_encryption;
1040 return AST_SIP_MEDIA_ENCRYPT_NONE;
1043 return AST_SIP_MEDIA_TRANSPORT_INVALID;
1048 if (!session_media->
srtp) {
1050 if (!session_media->
srtp) {
1055 if (!session_media->
srtp->crypto) {
1057 if (!session_media->
srtp->crypto) {
1081 ast_log(LOG_ERROR,
"Attempted to set an invalid DTLS-SRTP configuration on RTP instance '%p'\n",
1082 session_media->
rtp);
1086 if (setup_srtp(session_media)) {
1093 pjmedia_sdp_attr *attr)
1098 if (!attr->value.ptr || !dtls) {
1102 value = pj_strtrim(&attr->value);
1104 if (!pj_strcmp2(&attr->name,
"setup")) {
1105 if (!pj_stricmp2(value,
"active")) {
1107 }
else if (!pj_stricmp2(value,
"passive")) {
1109 }
else if (!pj_stricmp2(value,
"actpass")) {
1111 }
else if (!pj_stricmp2(value,
"holdconn")) {
1114 ast_log(LOG_WARNING,
"Unsupported setup attribute value '%*s'\n", (
int)value->slen, value->ptr);
1116 }
else if (!pj_strcmp2(&attr->name,
"connection")) {
1117 if (!pj_stricmp2(value,
"new")) {
1119 }
else if (!pj_stricmp2(value,
"existing")) {
1122 ast_log(LOG_WARNING,
"Unsupported connection attribute value '%*s'\n", (
int)value->slen, value->ptr);
1124 }
else if (!pj_strcmp2(&attr->name,
"fingerprint")) {
1125 char hash_value[256], hash[32];
1126 char fingerprint_text[value->slen + 1];
1127 ast_copy_pj_str(fingerprint_text, value,
sizeof(fingerprint_text));
1128 if (sscanf(fingerprint_text,
"%31s %255s", hash, hash_value) == 2) {
1129 if (!strcasecmp(hash,
"sha-1")) {
1131 }
else if (!strcasecmp(hash,
"sha-256")) {
1134 ast_log(LOG_WARNING,
"Unsupported fingerprint hash type '%s'\n",
1142 const struct pjmedia_sdp_session *sdp,
1143 const struct pjmedia_sdp_media *stream)
1147 for (i = 0; i < sdp->attr_count; i++) {
1148 apply_dtls_attrib(session_media, sdp->attr[i]);
1151 for (i = 0; i < stream->attr_count; i++) {
1152 apply_dtls_attrib(session_media, stream->attr[i]);
1155 ast_set_flag(session_media->
srtp, AST_SRTP_CRYPTO_OFFER_OK);
1161 const struct pjmedia_sdp_media *stream)
1165 for (i = 0; i < stream->attr_count; i++) {
1166 pjmedia_sdp_attr *attr;
1167 RAII_VAR(
char *, crypto_str, NULL, ast_free);
1170 attr = stream->attr[i];
1171 if (pj_strcmp2(&attr->name,
"crypto")) {
1175 crypto_str =
ast_strndup(attr->value.ptr, attr->value.slen);
1180 if (setup_srtp(session_media)) {
1189 ast_debug(1,
"Ignoring crypto offer with unsupported parameters: %s\n", crypto_str);
1198 const struct pjmedia_sdp_session *sdp,
1199 const struct pjmedia_sdp_media *stream)
1202 case AST_SIP_MEDIA_ENCRYPT_SDES:
1203 if (setup_sdes_srtp(session_media, stream)) {
1207 case AST_SIP_MEDIA_ENCRYPT_DTLS:
1208 if (setup_dtls_srtp(session, session_media)) {
1211 if (parse_dtls_attrib(session_media, sdp, stream)) {
1215 case AST_SIP_MEDIA_TRANSPORT_INVALID:
1216 case AST_SIP_MEDIA_ENCRYPT_NONE:
1227 ast_assert(session_media->
rtp != NULL);
1247 pjmedia_sdp_attr *attr;
1255 attr = pjmedia_sdp_attr_create(pool,
"ssrc", pj_cstr(&stmp, tmp));
1256 media->attr[media->attr_count++] = attr;
1261 const struct pjmedia_sdp_media *remote_stream)
1269 for (index = 0; index < remote_stream->attr_count; ++index) {
1270 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1271 char attr_value[pj_strlen(&attr->value) + 1];
1272 char *ssrc_attribute_name, *ssrc_attribute_value = NULL;
1276 if (pj_strcmp2(&attr->name,
"ssrc")) {
1280 ast_copy_pj_str(attr_value, &attr->value,
sizeof(attr_value));
1282 if ((ssrc_attribute_name = strchr(attr_value,
' '))) {
1284 *ssrc_attribute_name++ =
'\0';
1285 ssrc_attribute_value = strchr(ssrc_attribute_name,
':');
1286 if (ssrc_attribute_value) {
1288 *ssrc_attribute_value++ =
'\0';
1292 if (sscanf(attr_value,
"%30u", &ssrc) < 1) {
1299 if (pjmedia_sdp_neg_get_state(session->
inv_session->neg) == PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
1319 pjmedia_sdp_attr *attr;
1320 char msid[(AST_UUID_STR_LEN * 2) + 2];
1327 if (ast_strlen_zero(session_media->
mslabel)) {
1335 if (ast_strlen_zero(session_media->
mslabel)) {
1340 if (ast_strlen_zero(session_media->
label)) {
1346 snprintf(msid,
sizeof(msid),
"%s %s", session_media->
mslabel, session_media->
label);
1347 ast_debug(3,
"Stream msid: %p %s %s\n", stream,
1349 attr = pjmedia_sdp_attr_create(pool,
"msid", pj_cstr(&stmp, msid));
1350 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1353 if (!ast_strlen_zero(stream_label)) {
1354 ast_debug(3,
"Stream Label: %p %s %s\n", stream,
1356 attr = pjmedia_sdp_attr_create(pool,
"label", pj_cstr(&stmp, stream_label));
1357 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1365 pjmedia_sdp_attr *attr;
1375 attr = pjmedia_sdp_attr_create(pool,
"rtcp-fb", pj_cstr(&stmp,
"* transport-cc"));
1376 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1378 if (session_media->
type != AST_MEDIA_TYPE_VIDEO) {
1386 attr = pjmedia_sdp_attr_create(pool,
"rtcp-fb", pj_cstr(&stmp,
"* ccm fir"));
1387 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1389 attr = pjmedia_sdp_attr_create(pool,
"rtcp-fb", pj_cstr(&stmp,
"* goog-remb"));
1390 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1392 attr = pjmedia_sdp_attr_create(pool,
"rtcp-fb", pj_cstr(&stmp,
"* nack"));
1393 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1400 char extmap_value[256];
1409 const char *direction_str =
"";
1411 pjmedia_sdp_attr *attr;
1424 direction_str =
"/sendonly";
1427 direction_str =
"/recvonly";
1434 direction_str =
"/inactive";
1438 snprintf(extmap_value,
sizeof(extmap_value),
"%d%s %s", idx, direction_str,
1440 attr = pjmedia_sdp_attr_create(pool,
"extmap", pj_cstr(&stmp, extmap_value));
1441 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
1447 const struct pjmedia_sdp_media *remote_stream)
1457 for (index = 0; index < remote_stream->attr_count; ++index) {
1458 pjmedia_sdp_attr *attr = remote_stream->attr[index];
1459 char attr_value[pj_strlen(&attr->value) + 1];
1462 char direction_str[10] =
"";
1467 if (pj_strcmp2(&attr->name,
"extmap")) {
1471 ast_copy_pj_str(attr_value, &attr->value,
sizeof(attr_value));
1474 uri = strchr(attr_value,
' ');
1475 if (ast_strlen_zero(uri)) {
1480 if ((sscanf(attr_value,
"%30d%9s", &
id, direction_str) < 1) || (
id < 1)) {
1486 if (!strcasecmp(direction_str,
"/sendonly")) {
1488 }
else if (!strcasecmp(direction_str,
"/recvonly")) {
1490 }
else if (!strcasecmp(direction_str,
"/inactive")) {
1494 attributes = strchr(uri,
' ');
1495 if (!ast_strlen_zero(attributes)) {
1496 *attributes++ =
'\0';
1505 const pjmedia_sdp_media *media,
1509 if (ast_sip_session_is_pending_stream_default(session, stream) &&
1510 (session_media->
type == AST_MEDIA_TYPE_AUDIO)) {
1513 pjmedia_sdp_media_find_attr2(media,
"sendonly", NULL) ||
1514 pjmedia_sdp_media_find_attr2(media,
"inactive", NULL)) {
1529 int index,
struct ast_stream *asterisk_stream)
1531 char host[NI_MAXHOST];
1533 pjmedia_sdp_media *stream = sdp->media[index];
1536 enum ast_sip_session_media_encryption
encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
1539 SCOPE_ENTER(1,
"%s\n", ast_sip_session_get_name(session));
1543 ast_debug(3,
"Endpoint has no codecs for media type '%s', declining stream\n",
1545 SCOPE_EXIT_RTN_VALUE(0,
"Endpoint has no codecs\n");
1552 if (encryption == AST_SIP_MEDIA_TRANSPORT_INVALID) {
1553 SCOPE_EXIT_RTN_VALUE(-1,
"Incompatible transport\n");
1557 ast_copy_pj_str(host, stream->conn ? &stream->conn->addr : &sdp->conn->addr,
sizeof(host));
1562 SCOPE_EXIT_RTN_VALUE(-1,
"Invalid host\n");
1566 if (!session_media->
rtp &&
create_rtp(session, session_media, sdp)) {
1567 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't create rtp\n");
1572 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1574 if (session_media_transport == session_media || !session_media->
bundled) {
1576 session_media->
remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(stream,
"rtcp-mux", NULL) != NULL);
1577 set_ice_components(session, session_media);
1581 res = setup_media_encryption(session, session_media, sdp, stream);
1584 !pj_strncmp2(&stream->desc.transport,
"RTP/SAVP", 8)) {
1589 SCOPE_EXIT_RTN_VALUE(-1,
"Incompatible crypto\n");
1592 session_media->
encryption = AST_SIP_MEDIA_ENCRYPT_NONE;
1601 ((encryption == AST_SIP_MEDIA_ENCRYPT_SDES) && !res)) {
1616 process_ice_auth_attrb(session, session_media, sdp, stream);
1620 set_session_media_remotely_held(session_media, session, stream, asterisk_stream, addrs);
1622 joint = set_incoming_call_offer_cap(session, session_media, stream);
1623 res = apply_cap_to_bundled(session_media, session_media_transport, asterisk_stream, joint);
1626 SCOPE_EXIT_RTN_VALUE(0,
"Something failed\n");
1629 SCOPE_EXIT_RTN_VALUE(1);
1634 pj_pool_t *pool, pjmedia_sdp_media *media)
1637 pjmedia_sdp_attr *attr;
1639 const char *crypto_attribute;
1642 static const pj_str_t STR_NEW = {
"new", 3 };
1643 static const pj_str_t STR_EXISTING = {
"existing", 8 };
1644 static const pj_str_t STR_ACTIVE = {
"active", 6 };
1645 static const pj_str_t STR_PASSIVE = {
"passive", 7 };
1646 static const pj_str_t STR_ACTPASS = {
"actpass", 7 };
1647 static const pj_str_t STR_HOLDCONN = {
"holdconn", 8 };
1648 static const pj_str_t STR_MEDSECREQ = {
"requested", 9 };
1652 case AST_SIP_MEDIA_ENCRYPT_NONE:
1653 case AST_SIP_MEDIA_TRANSPORT_INVALID:
1655 case AST_SIP_MEDIA_ENCRYPT_SDES:
1656 if (!session_media->
srtp) {
1658 if (!session_media->
srtp) {
1663 tmp = session_media->
srtp;
1669 if (!crypto_attribute) {
1674 attr = pjmedia_sdp_attr_create(pool,
"crypto",
1675 pj_cstr(&stmp, crypto_attribute));
1676 media->attr[media->attr_count++] = attr;
1680 attr = pjmedia_sdp_attr_create(pool,
"3ge2ae", &STR_MEDSECREQ);
1681 media->attr[media->attr_count++] = attr;
1685 case AST_SIP_MEDIA_ENCRYPT_DTLS:
1686 if (setup_dtls_srtp(session, session_media)) {
1697 attr = pjmedia_sdp_attr_create(pool,
"connection", &STR_NEW);
1698 media->attr[media->attr_count++] = attr;
1701 attr = pjmedia_sdp_attr_create(pool,
"connection", &STR_EXISTING);
1702 media->attr[media->attr_count++] = attr;
1712 && pjmedia_sdp_neg_get_state(session->
inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
1720 attr = pjmedia_sdp_attr_create(pool,
"setup", &STR_ACTIVE);
1721 media->attr[media->attr_count++] = attr;
1724 attr = pjmedia_sdp_attr_create(pool,
"setup", &STR_PASSIVE);
1725 media->attr[media->attr_count++] = attr;
1728 attr = pjmedia_sdp_attr_create(pool,
"setup", &STR_ACTPASS);
1729 media->attr[media->attr_count++] = attr;
1732 attr = pjmedia_sdp_attr_create(pool,
"setup", &STR_HOLDCONN);
1747 ast_str_set(&fingerprint, 0,
"SHA-1 %s", crypto_attribute);
1749 ast_str_set(&fingerprint, 0,
"SHA-256 %s", crypto_attribute);
1752 attr = pjmedia_sdp_attr_create(pool,
"fingerprint", pj_cstr(&stmp,
ast_str_buffer(fingerprint)));
1753 media->attr[media->attr_count++] = attr;
1763 struct pjmedia_sdp_session *sdp,
const struct pjmedia_sdp_session *remote,
struct ast_stream *stream)
1765 pj_pool_t *pool = session->
inv_session->pool_prov;
1766 static const pj_str_t STR_RTP_AVP = {
"RTP/AVP", 7 };
1767 static const pj_str_t STR_IN = {
"IN", 2 };
1768 static const pj_str_t STR_IP4 = {
"IP4", 3};
1769 static const pj_str_t STR_IP6 = {
"IP6", 3};
1770 static const pj_str_t STR_SENDRECV = {
"sendrecv", 8 };
1771 static const pj_str_t STR_SENDONLY = {
"sendonly", 8 };
1772 static const pj_str_t STR_INACTIVE = {
"inactive", 8 };
1773 static const pj_str_t STR_RECVONLY = {
"recvonly", 8 };
1774 pjmedia_sdp_media *media;
1775 const char *hostip = NULL;
1779 pjmedia_sdp_attr *attr;
1781 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;
1782 int min_packet_size = 0, max_packet_size = 0;
1795 int build_dtmf_sample_rates = 1;
1797 SCOPE_ENTER(1,
"%s Type: %s %s\n", ast_sip_session_get_name(session),
1800 media = pj_pool_zalloc(pool,
sizeof(
struct pjmedia_sdp_media));
1802 SCOPE_EXIT_RTN_VALUE(-1,
"Pool alloc failure\n");
1809 media->desc.port = 0;
1810 media->desc.port_count = 1;
1816 media->desc.transport = remote_media->desc.transport;
1819 for (index = 0; index < remote_media->desc.fmt_count; ++index) {
1820 media->desc.fmt[index] = remote_media->desc.fmt[index];
1822 media->desc.fmt_count = remote_media->desc.fmt_count;
1825 media->desc.transport = STR_RTP_AVP;
1826 pj_strdup2(pool, &media->desc.fmt[media->desc.fmt_count++],
"32");
1829 sdp->media[sdp->media_count++] = media;
1832 SCOPE_EXIT_RTN_VALUE(1,
"Stream removed or no formats\n");
1835 if (!session_media->
rtp &&
create_rtp(session, session_media, sdp)) {
1836 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't create rtp\n");
1841 for (index = 0; index < sdp->media_count; ++index) {
1858 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
1860 if (session_media_transport == session_media || !session_media->
bundled) {
1861 set_ice_components(session, session_media);
1867 if (add_crypto_to_stream(session, session_media, pool, media)) {
1868 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't add crypto\n");
1871 if (pj_strlen(&session_media->
transport)) {
1873 media->desc.transport = session_media->
transport;
1878 (session_media->
encryption == AST_SIP_MEDIA_ENCRYPT_SDES),
1883 media->conn = pj_pool_zalloc(pool,
sizeof(
struct pjmedia_sdp_conn));
1885 SCOPE_EXIT_RTN_VALUE(-1,
"Pool alloc failure\n");
1889 if (direct_media_enabled) {
1892 hostip = ast_sip_get_host_ip_string(session->
endpoint->
media.
rtp.
ipv6 ? pj_AF_INET6() : pj_AF_INET());
1897 if (ast_strlen_zero(hostip)) {
1898 ast_log(LOG_ERROR,
"No local host IP available for stream %s\n",
1900 SCOPE_EXIT_RTN_VALUE(-1,
"No local host ip\n");
1903 media->conn->net_type = STR_IN;
1905 media->conn->addr_type = STR_IP4;
1906 pj_strdup2(pool, &media->conn->addr, hostip);
1908 if ((pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &media->conn->addr, &ip) == PJ_SUCCESS) &&
1909 (ip.addr.sa_family == pj_AF_INET6())) {
1910 media->conn->addr_type = STR_IP6;
1918 media->desc.port_count = 1;
1920 pjmedia_sdp_media *bundle_group_stream = sdp->media[session_media_transport->
stream_num];
1923 media->desc.transport = bundle_group_stream->desc.transport;
1924 media->conn = bundle_group_stream->conn;
1925 media->desc.port = bundle_group_stream->desc.port;
1927 if (add_crypto_to_stream(session, session_media_transport, pool, media)) {
1928 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't add crypto\n");
1937 ast_log(LOG_ERROR,
"Failed to allocate %s capabilities\n",
1939 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't create caps\n");
1942 if (direct_media_enabled) {
1950 ast_log(LOG_ERROR,
"Unable to add dtmf formats to SDP!\n");
1951 build_dtmf_sample_rates = 0;
1966 ast_log(LOG_WARNING,
"Format '%s' can not be added to SDP, consider disallowing it on endpoint '%s'\n",
1975 if (session_media_transport != session_media) {
1977 ast_log(LOG_WARNING,
"Unable to get rtp codec payload code for %s\n",
ast_format_get_name(format));
1985 ast_log(LOG_WARNING,
"Unable to get rtp codec payload code for %s\n",
ast_format_get_name(format));
1991 if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 1, format, 0))) {
1994 if (build_dtmf_sample_rates) {
2008 media->attr[media->attr_count++] = attr;
2011 if ((attr = generate_fmtp_attr(pool, format, rtp_code))) {
2012 media->attr[media->attr_count++] = attr;
2021 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2027 if (ast_sip_session_is_pending_stream_default(session, stream) && media_type != AST_MEDIA_TYPE_VIDEO
2028 && media->desc.fmt_count < PJMEDIA_MAX_SDP_FMT) {
2029 for (index = 1LL; index <=
AST_RTP_MAX; index <<= 1) {
2030 if (!(noncodec & index)) {
2037 if (rtp_code == -1) {
2039 }
else if ((attr = generate_rtpmap_attr(session, media, pool, rtp_code, 0, NULL, index))) {
2040 media->attr[media->attr_count++] = attr;
2042 }
else if (build_dtmf_sample_rates) {
2047 int i, found_default_offer = 0;
2052 if (rtp_code == -1) {
2056 if (
AST_VECTOR_GET(&sample_rates, i) == DEFAULT_DTMF_SAMPLE_RATE_MS) {
2058 found_default_offer = 1;
2061 if ((attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index,
AST_VECTOR_GET(&sample_rates, i)))) {
2062 media->attr[media->attr_count++] = attr;
2063 snprintf(tmp,
sizeof(tmp),
"%d 0-16", (rtp_code));
2064 attr = pjmedia_sdp_attr_create(pool,
"fmtp", pj_cstr(&stmp, tmp));
2065 media->attr[media->attr_count++] = attr;
2072 if (!found_default_offer) {
2076 if (rtp_code != -1 && (attr = generate_rtpmap_attr2(session, media, pool, rtp_code, 0, NULL, index, DEFAULT_DTMF_SAMPLE_RATE_MS))) {
2077 media->attr[media->attr_count++] = attr;
2078 snprintf(tmp,
sizeof(tmp),
"%d 0-16", (rtp_code));
2079 attr = pjmedia_sdp_attr_create(pool,
"fmtp", pj_cstr(&stmp, tmp));
2080 media->attr[media->attr_count++] = attr;
2085 if (media->desc.fmt_count == PJMEDIA_MAX_SDP_FMT) {
2095 if (!media->desc.fmt_count) {
2096 SCOPE_EXIT_RTN_VALUE(1,
"No formats added to stream\n");
2101 if (!min_packet_size) {
2104 if (min_packet_size) {
2105 snprintf(tmp,
sizeof(tmp),
"%d", min_packet_size);
2106 attr = pjmedia_sdp_attr_create(pool,
"ptime", pj_cstr(&stmp, tmp));
2107 media->attr[media->attr_count++] = attr;
2110 if (max_packet_size) {
2111 snprintf(tmp,
sizeof(tmp),
"%d", max_packet_size);
2112 attr = pjmedia_sdp_attr_create(pool,
"maxptime", pj_cstr(&stmp, tmp));
2113 media->attr[media->attr_count++] = attr;
2116 attr = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_attr);
2119 attr->name = STR_INACTIVE;
2121 attr->name = STR_SENDONLY;
2125 attr->name = STR_RECVONLY;
2127 attr->name = STR_SENDONLY;
2129 attr->name = STR_RECVONLY;
2131 attr->name = STR_INACTIVE;
2133 attr->name = STR_SENDRECV;
2136 media->attr[media->attr_count++] = attr;
2140 attr = pjmedia_sdp_attr_create(pool,
"rtcp-mux", NULL);
2141 pjmedia_sdp_attr_add(&media->attr_count, media->attr, attr);
2145 add_msid_to_stream(session, session_media, pool, media, stream);
2146 add_rtcp_fb_to_stream(session, session_media, pool, media);
2147 add_extmap_to_stream(session, session_media, pool, media);
2150 sdp->media[sdp->media_count++] = media;
2152 SCOPE_EXIT_RTN_VALUE(1,
"RC: 1\n");
2159 if (!session_media->
rtp) {
2177 if (!session_media->
rtp) {
2193 if (!session_media->
rtp) {
2202 const struct pjmedia_sdp_session *remote,
int index,
struct ast_stream *asterisk_stream)
2205 struct pjmedia_sdp_media *remote_stream = remote->media[index];
2207 char host[NI_MAXHOST];
2211 SCOPE_ENTER(1,
"%s Stream: %s\n", ast_sip_session_get_name(session),
2215 SCOPE_EXIT_RTN_VALUE(1,
"No channel\n");
2221 SCOPE_EXIT_RTN_VALUE(-1,
"Incompatible transport\n");
2225 if (!session_media->
rtp &&
create_rtp(session, session_media, local)) {
2226 SCOPE_EXIT_RTN_VALUE(-1,
"Couldn't create rtp\n");
2232 session_media_transport = ast_sip_session_media_get_transport(session, session_media);
2234 if (session_media_transport == session_media || !session_media->
bundled) {
2235 session_media->
remote_rtcp_mux = (pjmedia_sdp_media_find_attr2(remote_stream,
"rtcp-mux", NULL) != NULL);
2236 set_ice_components(session, session_media);
2238 enable_rtcp(session, session_media, remote_stream);
2240 res = setup_media_encryption(session, session_media, remote, remote_stream);
2245 SCOPE_EXIT_RTN_VALUE(-1,
"Incompatible crypto\n");
2248 if (!remote_stream->conn && !remote->conn) {
2249 SCOPE_EXIT_RTN_VALUE(1,
"No connection info\n");
2252 ast_copy_pj_str(host, remote_stream->conn ? &remote_stream->conn->addr : &remote->conn->addr,
sizeof(host));
2257 SCOPE_EXIT_RTN_VALUE(-1,
"Host invalid\n");
2264 ast_sip_session_media_set_write_callback(session, session_media, media_session_rtp_write_callback);
2265 ast_sip_session_media_add_read_callback(session, session_media,
ast_rtp_instance_fd(session_media->
rtp, 0),
2266 media_session_rtp_read_callback);
2268 ast_sip_session_media_add_read_callback(session, session_media,
ast_rtp_instance_fd(session_media->
rtp, 1),
2269 media_session_rtcp_read_callback);
2277 ast_sip_session_media_set_write_callback(session, session_media, media_session_rtp_write_callback);
2278 enable_rtcp(session, session_media, remote_stream);
2281 if (set_caps(session, session_media, session_media_transport, remote_stream, 0, asterisk_stream)) {
2282 SCOPE_EXIT_RTN_VALUE(-1,
"set_caps failed\n");
2286 ast_channel_lock(session->
channel);
2288 ast_channel_unlock(session->
channel);
2295 if (media_type != AST_MEDIA_TYPE_AUDIO && media_type != AST_MEDIA_TYPE_VIDEO) {
2296 if ((pjmedia_sdp_neg_was_answer_remote(session->
inv_session->neg) == PJ_FALSE)
2297 && (session->
inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2300 SCOPE_EXIT_RTN_VALUE(1,
"moh\n");
2303 set_session_media_remotely_held(session_media, session, remote_stream, asterisk_stream, addrs);
2318 }
else if ((pjmedia_sdp_neg_was_answer_remote(session->
inv_session->neg) == PJ_FALSE)
2319 && (session->
inv_session->state == PJSIP_INV_STATE_CONFIRMED)) {
2327 (session_media->
type == AST_MEDIA_TYPE_AUDIO ||
2328 session_media->
type == AST_MEDIA_TYPE_VIDEO)) {
2362 SCOPE_EXIT_RTN_VALUE(1,
"Handled\n");
2369 char host[NI_MAXHOST];
2373 if (!stream->conn || !transport_state) {
2377 ast_copy_pj_str(host, &stream->conn->addr,
sizeof(host));
2384 if (ast_sip_transport_is_nonlocal(transport_state, &our_sdp_addr) && transport_state->localnet) {
2394 if (!session_media->
rtp) {
2406 if (session_media->
rtp) {
2410 session_media->
rtp = NULL;
2435 static int video_info_incoming_request(
struct ast_sip_session *session,
struct pjsip_rx_data *rdata)
2437 struct pjsip_transaction *tsx;
2438 pjsip_tx_data *tdata;
2441 || !ast_sip_are_media_types_equal(&rdata->msg_info.msg->body->content_type,
2442 &pjsip_media_type_application_media_control_xml)) {
2446 tsx = pjsip_rdata_get_tsx(rdata);
2450 if (pjsip_dlg_create_response(session->
inv_session->dlg, rdata, 200, NULL, &tdata) == PJ_SUCCESS) {
2451 pjsip_dlg_send_response(session->
inv_session->dlg, tsx, tdata);
2459 .incoming_request = video_info_incoming_request,
2465 ast_sip_session_unregister_supplement(&video_info_supplement);
2466 ast_sip_session_unregister_sdp_handler(&video_sdp_handler, STR_VIDEO);
2467 ast_sip_session_unregister_sdp_handler(&audio_sdp_handler, STR_AUDIO);
2495 ast_log(LOG_ERROR,
"Unable to create scheduler context.\n");
2500 ast_log(LOG_ERROR,
"Unable to create scheduler context thread.\n");
2504 if (ast_sip_session_register_sdp_handler(&audio_sdp_handler, STR_AUDIO)) {
2505 ast_log(LOG_ERROR,
"Unable to register SDP handler for %s stream type\n", STR_AUDIO);
2509 if (ast_sip_session_register_sdp_handler(&video_sdp_handler, STR_VIDEO)) {
2510 ast_log(LOG_ERROR,
"Unable to register SDP handler for %s stream type\n", STR_VIDEO);
2514 ast_sip_session_register_supplement(&video_info_supplement);
2523 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"PJSIP SDP RTP/AVP stream handler",
2524 .support_level = AST_MODULE_SUPPORT_CORE,
2528 .requires =
"res_pjsip,res_pjsip_session",
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
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...
structure for secure RTP audio
Main Channel structure associated with a channel.
struct ast_sip_endpoint * endpoint
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.
int(* set_configuration)(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg)
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.
Asterisk main include file. File version handling, generic pbx functions.
static char * ast_sockaddr_stringify_addr_remote(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
int ast_rtp_instance_extmap_get_id(struct ast_rtp_instance *instance, enum ast_rtp_extension extension)
Retrieve the id for an RTP extension.
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.
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
struct ast_sip_session_media_state * pending_media_state
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.
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.
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.
const char *(* get_password)(struct ast_rtp_instance *instance)
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.
const char *(* get_fingerprint)(struct ast_rtp_instance *instance)
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
int ast_stream_get_group(const struct ast_stream *stream)
Get the stream group that a stream is part of.
#define ast_channel_unref(c)
Decrease channel reference count.
int ast_rtp_instance_bundle(struct ast_rtp_instance *child, struct ast_rtp_instance *parent)
Request that an RTP instance be bundled with another.
const ast_string_field transport
size_t ast_rtp_instance_extmap_count(struct ast_rtp_instance *instance)
Get the number of known unique identifiers.
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 ...
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
Get the RTP timeout value.
Convenient Signal Processing routines.
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
#define AST_RTP_PT_LAST_STATIC
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
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.
A handler for SDPs in SIP sessions.
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)
Function which applies a negotiated stream.
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
static struct ast_sched_context * sched
Scheduler for RTCP purposes.
static int load_module(void)
Load the module.
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
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.
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
unsigned int asymmetric_rtp_codec
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
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.
Set when the stream has been removed/declined.
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...
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.
ast_channel_state
ast_channel states
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.
void(* change_components)(struct ast_rtp_instance *instance, int num_components)
void(* add_remote_candidate)(struct ast_rtp_instance *instance, const struct ast_rtp_engine_ice_candidate *candidate)
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
void ast_rtp_instance_extmap_clear(struct ast_rtp_instance *instance)
Clear negotiated RTP extension information.
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.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
ast_rtp_extension
Known RTP extensions.
void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout)
Set the RTP timeout value.
Set when the stream is not sending OR receiving media.
#define ast_debug_ice(sublevel,...)
Log debug level ICE information.
void ast_rtp_codecs_set_framing(struct ast_rtp_codecs *codecs, unsigned int framing)
Set the framing used for a set of codecs.
static void stream_destroy(struct ast_sip_session_media *session_media)
Function which destroys the RTP instance when session ends.
void(* stop)(struct ast_rtp_instance *instance)
struct pjsip_inv_session * inv_session
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
Structure for an ICE candidate.
Socket address structure.
void ast_rtp_instance_set_stream_num(struct ast_rtp_instance *instance, int stream_num)
Set the stream number for an RTP instance.
A structure describing a SIP session.
enum ast_rtp_dtls_hash(* get_fingerprint_hash)(struct ast_rtp_instance *instance)
static struct ast_sockaddr address_rtp
Address for RTP.
static void enable_rtp_extension(struct ast_sip_session *session, struct ast_sip_session_media *session_media, enum ast_rtp_extension extension, enum ast_rtp_extension_direction direction, const pjmedia_sdp_session *sdp)
Enable an RTP extension on an RTP session.
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
enum ast_rtp_dtls_setup(* get_setup)(struct ast_rtp_instance *instance)
struct ast_format_cap * direct_media_cap
static int unload_module(void)
Unloads the sdp RTP/AVP module from Asterisk.
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.
struct ast_sip_session_media_state * active_media_state
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
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.
struct ast_sip_endpoint_media_configuration media
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
enum ast_rtp_ice_candidate_type type
static struct ast_sip_session_sdp_handler video_sdp_handler
SDP handler for 'video' media stream.
enum ast_rtp_dtls_connection(* get_connection)(struct ast_rtp_instance *instance)
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
static char * ast_sockaddr_stringify_port(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return a port only.
#define ast_str_tmp(init_len, __expr)
Provides a temporary ast_str and returns a copy of its buffer.
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
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...
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Structure for SIP transport information.
static int rtp_check_timeout(const void *data)
Check whether RTP is being received or not.
General Asterisk PBX channel definitions.
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.
#define AST_SCHED_DEL(sched, id)
Remove a scheduler entry.
SRTP and SDP Security descriptions.
int ast_check_ipv6(void)
Test that an OS supports IPv6 Networking.
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
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...
void ast_rtp_instance_set_remote_ssrc(struct ast_rtp_instance *rtp, unsigned int ssrc)
Set the remote SSRC for an RTP instance.
Access Control of various sorts.
static struct ao2_container * codecs
Registered codecs.
void(* set_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint)
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Scheduler Routines (derived from cheops)
structure to hold extensions
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.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
struct ast_channel * channel
A set of macros to manage forward-linked lists.
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.
#define ast_debug(level,...)
Log a DEBUG message.
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
#define AST_VECTOR(name, type)
Define a vector structure.
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...
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.
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
An entity with which Asterisk communicates.
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
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.
struct ast_sockaddr relay_address
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Structure that represents the optional DTLS SRTP support within an RTP engine.
enum ast_sip_security_negotiation security_negotiation
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
ast_rtp_dtls_setup
DTLS setup types.
const char *(* get_ufrag)(struct ast_rtp_instance *instance)
enum ast_rtp_dtls_setup default_setup
time_t ast_rtp_instance_get_last_tx(const struct ast_rtp_instance *rtp)
Get the last RTP transmission time.
void(* set_authentication)(struct ast_rtp_instance *instance, const char *ufrag, const char *password)
struct ao2_container *(* get_local_candidates)(struct ast_rtp_instance *instance)
static void stream_stop(struct ast_sip_session_media *session_media)
Function which stops the RTP instance.
Support for dynamic strings.
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.
ast_rtp_extension_direction
Directions for RTP extensions.
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.
void(* set_role)(struct ast_rtp_instance *instance, enum ast_rtp_ice_role role)
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
Send a comfort noise packet to the RTP instance.
static struct ast_sip_session_sdp_handler audio_sdp_handler
SDP handler for 'audio' media stream.
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
enum ast_sip_dtmf_mode dtmf
enum ast_rtp_ice_component_type id
unsigned int ast_rtp_instance_get_ssrc(struct ast_rtp_instance *rtp)
Retrieve the local SSRC value that we will be using.
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.
#define ast_strndup(str, len)
A wrapper for strndup()
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
char * ast_sockaddr_stringify_fmt(const struct ast_sockaddr *addr, int format)
Convert a socket address to a string.
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(* reset)(struct ast_rtp_instance *instance)
ast_rtp_dtls_hash
DTLS fingerprint hashes.
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
unsigned int preferred_codec_only
Set when the stream is sending media only.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
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.
void(* start)(struct ast_rtp_instance *instance)
time_t ast_rtp_instance_get_last_rx(const struct ast_rtp_instance *rtp)
Get the last RTP reception time.
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.
void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
Set the state of a stream.
void(* set_setup)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_setup setup)
struct ast_sdp_srtp * ast_sdp_srtp_alloc(void)
allocate a ast_sdp_srtp structure
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
struct ast_sdp_crypto * ast_sdp_crypto_alloc(void)
Initialize an return an ast_sdp_crypto struct.
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
int ast_rtp_codecs_set_preferred_format(struct ast_rtp_codecs *codecs, struct ast_format *format)
Set the preferred format.
const char * ast_rtp_instance_extmap_get_uri(struct ast_rtp_instance *instance, int id)
Retrieve the URI for an RTP extension id.
Module has failed to load, may be in an inconsistent state.
void ast_rtp_codecs_payloads_destroy(struct ast_rtp_codecs *codecs)
Destroy the contents of an RTP codecs structure (but not the structure itself)
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.
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int timeout)
Set the RTP keepalive interval.
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.
A supplement to SIP message processing.
struct ast_frame ast_null_frame
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.
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.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
#define ast_debug_rtp(sublevel,...)
Log debug level RTP information.
int ast_rtp_codecs_payloads_initialize(struct ast_rtp_codecs *codecs)
Initialize an RTP codecs structure.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
const ast_string_field mohsuggest
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
const char * ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key)
Get a stream metadata value.
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...
enum ast_rtp_dtmf_mode ast_rtp_instance_dtmf_mode_get(struct ast_rtp_instance *instance)
Get the DTMF mode of an RTP instance.
Data structure associated with a single frame of data.
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
Get the RTP keepalive interval.
Internal Asterisk hangup causes.
enum ast_srtp_suite suite
Structure that represents the optional ICE support within an RTP engine.
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.
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.
ast_media_type
Types of media.
struct ast_sockaddr address
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.
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.
int ast_stream_get_position(const struct ast_stream *stream)
Get the position of the stream in the topology.
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Pluggable RTP Architecture.
Asterisk module definitions.
const char * ast_rtp_instance_get_cname(struct ast_rtp_instance *rtp)
Retrieve the CNAME used in RTCP SDES items.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
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.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Set when the stream is receiving media only.
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
void ast_rtp_instance_set_last_rx(struct ast_rtp_instance *rtp, time_t time)
Set the last RTP reception time.
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
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.
void(* ice_lite)(struct ast_rtp_instance *instance)
static int media_stream_has_crypto(const struct pjmedia_sdp_media *stream)
figure out if media stream has crypto lines for sdes
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.