48 #include "asterisk/res_pjsip.h"
49 #include "asterisk/res_pjsip_session.h"
57 [T38_DISABLED] =
"DISABLED",
58 [T38_LOCAL_REINVITE] =
"LOCAL_REINVITE",
59 [T38_PEER_REINVITE] =
"REMOTE_REINVITE",
60 [T38_ENABLED] =
"ENABLED",
61 [T38_REJECTED] =
"REJECTED",
67 static int channel_read_rtp(
struct ast_channel *chan,
const char *type,
const char *field,
char *buf,
size_t buflen)
75 ast_log(AST_LOG_WARNING,
"Channel %s has no pvt!\n", ast_channel_name(chan));
81 ast_log(AST_LOG_WARNING,
"Channel %s has no session!\n", ast_channel_name(chan));
85 if (ast_strlen_zero(type)) {
86 ast_log(AST_LOG_WARNING,
"You must supply a type field for 'rtp' information\n");
90 if (ast_strlen_zero(field) || !strcmp(field,
"audio")) {
92 }
else if (!strcmp(field,
"video")) {
95 ast_log(AST_LOG_WARNING,
"Unknown media type field '%s' for 'rtp' information\n", field);
99 if (!media || !media->
rtp) {
100 ast_log(AST_LOG_WARNING,
"Channel %s has no %s media/RTP session\n",
101 ast_channel_name(chan),
S_OR(field,
"audio"));
105 if (!strcmp(type,
"src")) {
108 }
else if (!strcmp(type,
"dest")) {
111 }
else if (!strcmp(type,
"direct")) {
113 }
else if (!strcmp(type,
"secure")) {
116 int flag = ast_test_flag(srtp, AST_SRTP_CRYPTO_OFFER_OK);
117 snprintf(buf, buflen,
"%d", flag ? 1 : 0);
119 snprintf(buf, buflen,
"%d", 0);
121 }
else if (!strcmp(type,
"hold")) {
124 ast_log(AST_LOG_WARNING,
"Unknown type field '%s' specified for 'rtp' information\n", type);
134 static int channel_read_rtcp(
struct ast_channel *chan,
const char *type,
const char *field,
char *buf,
size_t buflen)
141 ast_log(AST_LOG_WARNING,
"Channel %s has no pvt!\n", ast_channel_name(chan));
147 ast_log(AST_LOG_WARNING,
"Channel %s has no session!\n", ast_channel_name(chan));
151 if (ast_strlen_zero(type)) {
152 ast_log(AST_LOG_WARNING,
"You must supply a type field for 'rtcp' information\n");
156 if (ast_strlen_zero(field) || !strcmp(field,
"audio")) {
158 }
else if (!strcmp(field,
"video")) {
161 ast_log(AST_LOG_WARNING,
"Unknown media type field '%s' for 'rtcp' information\n", field);
165 if (!media || !media->
rtp) {
166 ast_log(AST_LOG_WARNING,
"Channel %s has no %s media/RTP session\n",
167 ast_channel_name(chan),
S_OR(field,
"audio"));
171 if (!strncasecmp(type,
"all", 3)) {
174 if (!strcasecmp(type,
"all_jitter")) {
176 }
else if (!strcasecmp(type,
"all_rtt")) {
178 }
else if (!strcasecmp(type,
"all_loss")) {
180 }
else if (!strcasecmp(type,
"all_mes")) {
185 ast_log(AST_LOG_WARNING,
"Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
193 enum { INT, DBL } type;
199 {
"txcount", INT, { .i4 = &stats.txcount, }, },
200 {
"rxcount", INT, { .i4 = &stats.rxcount, }, },
201 {
"txjitter", DBL, { .d8 = &stats.txjitter, }, },
202 {
"rxjitter", DBL, { .d8 = &stats.rxjitter, }, },
203 {
"remote_maxjitter", DBL, { .d8 = &stats.remote_maxjitter, }, },
204 {
"remote_minjitter", DBL, { .d8 = &stats.remote_minjitter, }, },
205 {
"remote_normdevjitter", DBL, { .d8 = &stats.remote_normdevjitter, }, },
206 {
"remote_stdevjitter", DBL, { .d8 = &stats.remote_stdevjitter, }, },
207 {
"local_maxjitter", DBL, { .d8 = &stats.local_maxjitter, }, },
208 {
"local_minjitter", DBL, { .d8 = &stats.local_minjitter, }, },
209 {
"local_normdevjitter", DBL, { .d8 = &stats.local_normdevjitter, }, },
210 {
"local_stdevjitter", DBL, { .d8 = &stats.local_stdevjitter, }, },
211 {
"txploss", INT, { .i4 = &stats.txploss, }, },
212 {
"rxploss", INT, { .i4 = &stats.rxploss, }, },
213 {
"remote_maxrxploss", DBL, { .d8 = &stats.remote_maxrxploss, }, },
214 {
"remote_minrxploss", DBL, { .d8 = &stats.remote_minrxploss, }, },
215 {
"remote_normdevrxploss", DBL, { .d8 = &stats.remote_normdevrxploss, }, },
216 {
"remote_stdevrxploss", DBL, { .d8 = &stats.remote_stdevrxploss, }, },
217 {
"local_maxrxploss", DBL, { .d8 = &stats.local_maxrxploss, }, },
218 {
"local_minrxploss", DBL, { .d8 = &stats.local_minrxploss, }, },
219 {
"local_normdevrxploss", DBL, { .d8 = &stats.local_normdevrxploss, }, },
220 {
"local_stdevrxploss", DBL, { .d8 = &stats.local_stdevrxploss, }, },
221 {
"rtt", DBL, { .d8 = &stats.rtt, }, },
222 {
"maxrtt", DBL, { .d8 = &stats.maxrtt, }, },
223 {
"minrtt", DBL, { .d8 = &stats.minrtt, }, },
224 {
"normdevrtt", DBL, { .d8 = &stats.normdevrtt, }, },
225 {
"stdevrtt", DBL, { .d8 = &stats.stdevrtt, }, },
226 {
"local_ssrc", INT, { .i4 = &stats.local_ssrc, }, },
227 {
"remote_ssrc", INT, { .i4 = &stats.remote_ssrc, }, },
228 {
"txmes", DBL, { .d8 = &stats.txmes, }, },
229 {
"rxmes", DBL, { .d8 = &stats.rxmes, }, },
230 {
"remote_maxmes", DBL, { .d8 = &stats.remote_maxmes, }, },
231 {
"remote_minmes", DBL, { .d8 = &stats.remote_minmes, }, },
232 {
"remote_normdevmes", DBL, { .d8 = &stats.remote_normdevmes, }, },
233 {
"remote_stdevmes", DBL, { .d8 = &stats.remote_stdevmes, }, },
234 {
"local_maxmes", DBL, { .d8 = &stats.local_maxmes, }, },
235 {
"local_minmes", DBL, { .d8 = &stats.local_minmes, }, },
236 {
"local_normdevmes", DBL, { .d8 = &stats.local_normdevmes, }, },
237 {
"local_stdevmes", DBL, { .d8 = &stats.local_stdevmes, }, },
242 ast_log(AST_LOG_WARNING,
"Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
246 for (i = 0; !ast_strlen_zero(lookup[i].name); i++) {
247 if (!strcasecmp(type, lookup[i].name)) {
248 if (lookup[i].type == INT) {
249 snprintf(buf, buflen,
"%u", *lookup[i].i4);
251 snprintf(buf, buflen,
"%f", *lookup[i].d8);
256 ast_log(AST_LOG_WARNING,
"Unrecognized argument '%s' for 'rtcp' information\n", type);
263 static int print_escaped_uri(
struct ast_channel *chan,
const char *type,
264 pjsip_uri_context_e context,
const void *uri,
char *buf,
size_t size)
269 res = pjsip_uri_print(context, uri, buf, size);
271 ast_log(LOG_ERROR,
"Channel %s: Unescaped %s too long for %d byte buffer\n",
272 ast_channel_name(chan), type, (
int) size);
287 static int channel_read_pjsip(
struct ast_channel *chan,
const char *type,
const char *field,
char *buf,
size_t buflen)
295 ast_log(AST_LOG_WARNING,
"Channel %s has no pvt!\n", ast_channel_name(chan));
301 if (ast_strlen_zero(type)) {
302 ast_log(LOG_WARNING,
"You must supply a type field for 'pjsip' information\n");
304 }
else if (!strcmp(type,
"call-id")) {
305 snprintf(buf, buflen,
"%.*s", (
int) pj_strlen(&dlg->call_id->id), pj_strbuf(&dlg->call_id->id));
306 }
else if (!strcmp(type,
"secure")) {
307 #ifdef HAVE_PJSIP_GET_DEST_INFO
308 pjsip_host_info dest;
309 pj_pool_t *
pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
"secure-check", 128, 128);
310 pjsip_get_dest_info(dlg->target, NULL, pool, &dest);
311 snprintf(buf, buflen,
"%d", dest.flag & PJSIP_TRANSPORT_SECURE ? 1 : 0);
312 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
314 ast_log(LOG_WARNING,
"Asterisk has been built against a version of pjproject which does not have the required functionality to support the 'secure' argument. Please upgrade to version 2.3 or later.\n");
317 }
else if (!strcmp(type,
"target_uri")) {
318 res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI, dlg->target, buf,
320 }
else if (!strcmp(type,
"local_uri")) {
321 res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri,
323 }
else if (!strcmp(type,
"local_tag")) {
324 ast_copy_pj_str(buf, &dlg->local.info->tag, buflen);
327 }
else if (!strcmp(type,
"remote_uri")) {
328 res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR,
329 dlg->remote.info->uri, buf, buflen);
330 }
else if (!strcmp(type,
"remote_tag")) {
331 ast_copy_pj_str(buf, &dlg->remote.info->tag, buflen);
334 }
else if (!strcmp(type,
"request_uri")) {
336 res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI,
339 }
else if (!strcmp(type,
"t38state")) {
341 }
else if (!strcmp(type,
"local_addr")) {
345 datastore = ast_sip_session_get_datastore(channel->
session,
"transport_info");
347 ast_log(AST_LOG_WARNING,
"No transport information for channel %s\n", ast_channel_name(chan));
350 transport_data = datastore->data;
352 if (pj_sockaddr_has_addr(&transport_data->
local_addr)) {
353 pj_sockaddr_print(&transport_data->
local_addr, buf, buflen, 3);
355 }
else if (!strcmp(type,
"remote_addr")) {
359 datastore = ast_sip_session_get_datastore(channel->
session,
"transport_info");
361 ast_log(AST_LOG_WARNING,
"No transport information for channel %s\n", ast_channel_name(chan));
364 transport_data = datastore->data;
366 if (pj_sockaddr_has_addr(&transport_data->
remote_addr)) {
367 pj_sockaddr_print(&transport_data->
remote_addr, buf, buflen, 3);
370 ast_log(AST_LOG_WARNING,
"Unrecognized argument '%s' for 'pjsip' information\n", type);
389 static int read_pjsip(
void *data)
393 if (!strcmp(func_args->param,
"rtp")) {
394 if (!func_args->session->
channel) {
398 func_args->ret = channel_read_rtp(func_args->session->
channel, func_args->type,
399 func_args->field, func_args->buf,
401 }
else if (!strcmp(func_args->param,
"rtcp")) {
402 if (!func_args->session->
channel) {
406 func_args->ret = channel_read_rtcp(func_args->session->
channel, func_args->type,
407 func_args->field, func_args->buf,
409 }
else if (!strcmp(func_args->param,
"endpoint")) {
410 if (!func_args->session->
endpoint) {
411 ast_log(AST_LOG_WARNING,
"Channel %s has no endpoint!\n", func_args->session->
channel ?
412 ast_channel_name(func_args->session->
channel) :
"<unknown>");
417 }
else if (!strcmp(func_args->param,
"contact")) {
418 if (!func_args->session->
contact) {
422 }
else if (!strcmp(func_args->param,
"aor")) {
423 if (!func_args->session->
aor) {
427 }
else if (!strcmp(func_args->param,
"pjsip")) {
428 if (!func_args->session->
channel) {
432 func_args->ret = channel_read_pjsip(func_args->session->
channel, func_args->type,
433 func_args->field, func_args->buf,
456 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
461 if (ast_strlen_zero(parse)) {
462 ast_log(LOG_ERROR,
"Cannot call %s without arguments\n", cmd);
468 ast_channel_lock(chan);
472 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
473 ast_channel_unlock(chan);
477 channel = ast_channel_tech_pvt(chan);
479 ast_log(LOG_WARNING,
"Channel %s has no pvt!\n", ast_channel_name(chan));
480 ast_channel_unlock(chan);
485 ast_log(LOG_WARNING,
"Channel %s has no session\n", ast_channel_name(chan));
486 ast_channel_unlock(chan);
491 ast_channel_unlock(chan);
495 func_args.param = args.param;
496 func_args.type = args.type;
497 func_args.field = args.field;
501 ast_log(LOG_WARNING,
"Unable to read properties of channel %s: failed to push task\n", ast_channel_name(chan));
502 ao2_ref(func_args.session, -1);
505 ao2_ref(func_args.session, -1);
507 return func_args.ret;
514 const char *aor_name;
525 if (ast_strlen_zero(args.endpoint_name)) {
526 ast_log(LOG_WARNING,
"An endpoint name must be specified when using the '%s' dialplan function\n", cmd);
529 ast_log(LOG_WARNING,
"Specified endpoint '%s' was not found\n", args.endpoint_name);
533 aor_name =
S_OR(args.aor_name, endpoint->aors);
535 if (ast_strlen_zero(aor_name)) {
536 ast_log(LOG_WARNING,
"No AOR has been provided and no AORs are configured on endpoint '%s'\n", args.endpoint_name);
539 ast_log(LOG_WARNING,
"Could not get enough buffer space for dialing contacts\n");
542 ast_log(LOG_WARNING,
"Could not duplicate provided AORs\n");
546 while ((aor_name =
ast_strip(strsep(&rest,
",")))) {
555 }
else if (!(contacts = ast_sip_location_retrieve_aor_contacts_filtered(
aor, AST_SIP_CONTACT_FILTER_REACHABLE))) {
564 for (; (contact = ao2_iterator_next(&it_contacts));
ao2_ref(contact, -1)) {
567 if (!ast_strlen_zero(args.request_user)) {
594 ast_sip_session_media_state_free(state->
media_state);
600 .
type =
"pjsip_session_refresh",
607 RAII_VAR(
struct ast_datastore *, datastore, ast_sip_session_get_datastore(session,
"pjsip_session_refresh"), ao2_cleanup);
612 return datastore->data;
615 if (!(datastore = ast_sip_session_alloc_datastore(&session_refresh_datastore,
"pjsip_session_refresh"))
617 || ast_sip_session_add_datastore(session, datastore)) {
621 state = datastore->data;
622 state->
media_state = ast_sip_session_media_state_alloc();
624 ast_sip_session_remove_datastore(session,
"pjsip_session_refresh");
629 ast_sip_session_remove_datastore(session,
"pjsip_session_refresh");
633 datastore->data = state;
648 static int parse_uri_cb(
void *data)
652 pjsip_name_addr *uri;
653 pjsip_sip_uri *sip_uri;
658 pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(),
"ParseUri", 128, 128);
660 ast_log(LOG_ERROR,
"Failed to allocate ParseUri endpoint pool.\n");
665 pj_strdup2_with_null(pool, &tmp, args->uri);
666 uri = (pjsip_name_addr *)pjsip_parse_uri(pool, tmp.ptr, tmp.slen, PJSIP_PARSE_URI_AS_NAMEADDR);
667 if (!uri || (!PJSIP_URI_SCHEME_IS_SIP(uri) && !PJSIP_URI_SCHEME_IS_SIPS(uri))) {
668 ast_log(LOG_WARNING,
"Failed to parse URI '%s'\n", args->uri);
669 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
674 if (!strcmp(args->type,
"scheme")) {
675 ast_copy_pj_str(args->buf, pjsip_uri_get_scheme(uri), args->buflen);
676 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
678 }
else if (!strcmp(args->type,
"display")) {
679 ast_copy_pj_str(args->buf, &uri->display, args->buflen);
680 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
684 sip_uri = pjsip_uri_get_uri(uri);
686 ast_log(LOG_ERROR,
"Failed to get an URI object for '%s'\n", args->uri);
687 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
692 if (!strcmp(args->type,
"user")) {
693 ast_copy_pj_str(args->buf, &sip_uri->user, args->buflen);
694 }
else if (!strcmp(args->type,
"passwd")) {
695 ast_copy_pj_str(args->buf, &sip_uri->passwd, args->buflen);
696 }
else if (!strcmp(args->type,
"host")) {
697 ast_copy_pj_str(args->buf, &sip_uri->host, args->buflen);
698 }
else if (!strcmp(args->type,
"port")) {
699 snprintf(args->buf, args->buflen,
"%d", sip_uri->port);
700 }
else if (!strcmp(args->type,
"user_param")) {
701 ast_copy_pj_str(args->buf, &sip_uri->user_param, args->buflen);
702 }
else if (!strcmp(args->type,
"method_param")) {
703 ast_copy_pj_str(args->buf, &sip_uri->method_param, args->buflen);
704 }
else if (!strcmp(args->type,
"transport_param")) {
705 ast_copy_pj_str(args->buf, &sip_uri->transport_param, args->buflen);
706 }
else if (!strcmp(args->type,
"ttl_param")) {
707 snprintf(args->buf, args->buflen,
"%d", sip_uri->ttl_param);
708 }
else if (!strcmp(args->type,
"lr_param")) {
709 snprintf(args->buf, args->buflen,
"%d", sip_uri->lr_param);
710 }
else if (!strcmp(args->type,
"maddr_param")) {
711 ast_copy_pj_str(args->buf, &sip_uri->maddr_param, args->buflen);
713 ast_log(AST_LOG_WARNING,
"Unknown type part '%s' specified\n", args->type);
714 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
719 pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
727 int reading_uri_from_var;
736 reading_uri_from_var = !strcasecmp(cmd,
"PJSIP_PARSE_URI_FROM");
738 if (reading_uri_from_var) {
741 if (ast_strlen_zero(args.uri_str)) {
742 ast_log(LOG_WARNING,
"The name of a variable containing a URI must be specified when using the '%s' dialplan function\n", cmd);
746 ast_channel_lock(chan);
750 ast_channel_unlock(chan);
753 if (ast_strlen_zero(args.uri_str)) {
754 if (reading_uri_from_var) {
755 ast_log(LOG_WARNING,
"The variable provided to the '%s' dialplan function must contain a URI\n", cmd);
757 ast_log(LOG_WARNING,
"A URI must be specified when using the '%s' dialplan function\n", cmd);
762 if (ast_strlen_zero(args.type)) {
763 ast_log(LOG_WARNING,
"A type part of the URI must be specified when using the '%s' dialplan function\n", cmd);
767 memset(buf, 0, buflen);
769 func_args.uri = args.uri_str;
770 func_args.type = args.type;
772 func_args.buflen = buflen;
774 ast_log(LOG_WARNING,
"Unable to parse URI: failed to push task\n");
778 return func_args.ret;
781 static int media_offer_read_av(
struct ast_sip_session *session,
char *buf,
790 if (session->
inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
853 buf[accum - 1] =
',';
857 buf[accum ? accum - 1 : 0] =
'\0';
867 static int media_offer_write_av(
void *obj)
874 if (data->session->
inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
911 AST_MEDIA_TYPE_UNKNOWN);
926 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
931 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
935 channel = ast_channel_tech_pvt(chan);
937 if (!strcmp(data,
"audio")) {
938 return media_offer_read_av(channel->
session, buf, len, AST_MEDIA_TYPE_AUDIO);
939 }
else if (!strcmp(data,
"video")) {
940 return media_offer_read_av(channel->
session, buf, len, AST_MEDIA_TYPE_VIDEO);
957 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
962 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
966 channel = ast_channel_tech_pvt(chan);
967 mdata.session = channel->
session;
969 if (!strcmp(data,
"audio")) {
970 mdata.media_type = AST_MEDIA_TYPE_AUDIO;
971 }
else if (!strcmp(data,
"video")) {
972 mdata.media_type = AST_MEDIA_TYPE_VIDEO;
983 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
987 ast_channel_lock(chan);
989 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
990 ast_channel_unlock(chan);
994 channel = ast_channel_tech_pvt(chan);
996 if (ast_sip_dtmf_to_str(channel->
session->
dtmf, buf, len) < 0) {
997 ast_log(LOG_WARNING,
"Unknown DTMF mode %d on PJSIP channel %s\n", channel->
session->
dtmf, ast_channel_name(chan));
998 ast_channel_unlock(chan);
1002 ast_channel_unlock(chan);
1011 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
1016 ast_log(LOG_WARNING,
"%s: buffer too small\n", cmd);
1020 ast_channel_lock(chan);
1022 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
1023 ast_channel_unlock(chan);
1027 channel = ast_channel_tech_pvt(chan);
1030 ast_channel_unlock(chan);
1036 enum ast_sip_session_refresh_method method;
1039 static int sip_session_response_cb(
struct ast_sip_session *session, pjsip_rx_data *rdata)
1053 ast_channel_set_writeformat(session->
channel, fmt);
1054 ast_channel_set_rawwriteformat(session->
channel, fmt);
1055 ast_channel_set_readformat(session->
channel, fmt);
1056 ast_channel_set_rawreadformat(session->
channel, fmt);
1062 static int dtmf_mode_refresh_cb(
void *obj)
1066 if (data->session->
inv_session->state == PJSIP_INV_STATE_CONFIRMED) {
1067 ast_debug(3,
"Changing DTMF mode on channel %s after OFFER/ANSWER completion. Sending session refresh\n", ast_channel_name(data->session->
channel));
1069 ast_sip_session_refresh(data->session, NULL, NULL,
1070 sip_session_response_cb, data->method, 1, NULL);
1071 }
else if (data->session->
inv_session->state == PJSIP_INV_STATE_INCOMING) {
1072 ast_debug(3,
"Changing DTMF mode on channel %s during OFFER/ANSWER exchange. Updating SDP answer\n", ast_channel_name(data->session->
channel));
1073 ast_sip_session_regenerate_answer(data->session, NULL);
1083 int dsp_features = 0;
1086 .method = AST_SIP_SESSION_REFRESH_METHOD_INVITE,
1090 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
1094 ast_channel_lock(chan);
1096 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
1097 ast_channel_unlock(chan);
1101 channel = ast_channel_tech_pvt(chan);
1102 rdata.session = channel->
session;
1104 dtmf = ast_sip_str_to_dtmf(value);
1107 ast_log(LOG_WARNING,
"Cannot set DTMF mode to '%s' on channel '%s' as value is invalid.\n", value,
1108 ast_channel_name(chan));
1109 ast_channel_unlock(chan);
1115 ast_channel_unlock(chan);
1123 if (media && media->
rtp) {
1124 if (channel->
session->
dtmf == AST_SIP_DTMF_RFC_4733) {
1127 }
else if (channel->
session->
dtmf == AST_SIP_DTMF_INFO) {
1130 }
else if (channel->
session->
dtmf == AST_SIP_DTMF_INBAND) {
1133 }
else if (channel->
session->
dtmf == AST_SIP_DTMF_NONE) {
1136 }
else if (channel->
session->
dtmf == AST_SIP_DTMF_AUTO) {
1141 }
else if (channel->
session->
dtmf == AST_SIP_DTMF_AUTO_INFO) {
1153 if (channel->
session->
dtmf == AST_SIP_DTMF_INBAND ||
1155 dsp_features |= DSP_FEATURE_DIGIT_DETECT;
1157 dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
1162 ast_channel_unlock(chan);
1172 ast_channel_unlock(chan);
1182 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
1186 ast_channel_lock(chan);
1188 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
1189 ast_channel_unlock(chan);
1193 channel = ast_channel_tech_pvt(chan);
1196 ast_channel_unlock(chan);
1201 static int refresh_write_cb(
void *obj)
1211 ast_sip_session_refresh(data->session, NULL, NULL,
1212 sip_session_response_cb, data->method, 1, state->
media_state);
1215 ast_sip_session_remove_datastore(data->session,
"pjsip_session_refresh");
1224 .method = AST_SIP_SESSION_REFRESH_METHOD_INVITE,
1228 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
1233 ast_log(LOG_WARNING,
"'%s' not allowed on unanswered channel '%s'.\n", cmd, ast_channel_name(chan));
1238 ast_log(LOG_WARNING,
"Cannot call %s on a non-PJSIP channel\n", cmd);
1242 channel = ast_channel_tech_pvt(chan);
1243 rdata.session = channel->
session;
1245 if (!strcmp(value,
"invite")) {
1246 rdata.method = AST_SIP_SESSION_REFRESH_METHOD_INVITE;
1247 }
else if (!strcmp(value,
"update")) {
1248 rdata.method = AST_SIP_SESSION_REFRESH_METHOD_UPDATE;
1265 pjsip_tx_data *packet = NULL;
1267 if ((hdata->session->
inv_session->state != PJSIP_INV_STATE_DISCONNECTED) &&
1268 (pjsip_inv_answer(hdata->session->
inv_session, hdata->response_code, NULL, NULL, &packet) == PJ_SUCCESS)) {
1269 ast_sip_session_send_response(hdata->session, packet);
1279 const char *response) {
1284 response_code = ast_sip_str2rc(response);
1285 if (response_code < 0) {
1286 ast_log(LOG_WARNING,
"%s: Unrecognized response code parameter '%s'."
1287 " Defaulting to 603 DECLINE\n",
1288 channel_name, response);
1289 return PJSIP_SC_DECLINE;
1293 if (response_code < 400 || response_code > 699) {
1294 ast_log(LOG_WARNING,
"%s: Response code %d is out of range 400 -> 699."
1295 " Defaulting to 603 DECLINE\n",
1296 channel_name, response_code);
1297 return PJSIP_SC_DECLINE;
1299 return response_code;
1310 const char *tag = ast_channel_name(chan);
1312 hdata.response_code = response_code;
1314 ast_channel_lock(chan);
1316 ast_log(LOG_WARNING,
"%s: Not a PJSIP channel\n", tag);
1317 ast_channel_unlock(chan);
1321 channel = ast_channel_tech_pvt(chan);
1322 hdata.session = channel->
session;
1324 if (hdata.session->
inv_session->role != PJSIP_ROLE_UAS || (
1325 hdata.session->
inv_session->state != PJSIP_INV_STATE_INCOMING &&
1326 hdata.session->
inv_session->state != PJSIP_INV_STATE_EARLY)) {
1327 ast_log(LOG_WARNING,
"%s: Not an incoming channel or invalid state '%s'\n",
1328 tag, pjsip_inv_state_name(hdata.session->
inv_session->state));
1329 ast_channel_unlock(chan);
1333 ast_channel_unlock(chan);
1337 ast_log(LOG_WARNING,
"%s: failed to push hangup task to serializer\n", tag);
1349 const char *tag = ast_channel_name(chan);
1351 if (ast_strlen_zero(data)) {
1352 ast_log(LOG_WARNING,
"%s: Missing response code parameter\n", tag);
structure for secure RTP audio
enum ast_sip_session_t38state t38state
Main Channel structure associated with a channel.
struct ast_sip_endpoint * endpoint
pj_sockaddr local_addr
Our address that received the request.
Asterisk main include file. File version handling, generic pbx functions.
PJSIP dialplan functions header file.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
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.
Struct used to push PJSIP_PARSE_URI function arguments to task processor.
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.
int pjsip_acf_moh_passthrough_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_MOH_PASSTHROUGH function read callback.
Convenient Signal Processing routines.
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
struct ast_sip_session_media_state * media_state
Created proposed media state.
static pj_pool_t * pool
Global memory pool for configuration and timers.
static void session_refresh_state_destroy(void *obj)
Destructor for session refresh information.
Set when the stream has been removed/declined.
Session refresh state information.
Structure for a data store type.
ast_channel_state
ast_channel states
A structure which contains a channel implementation and session.
struct ast_sip_session * session
Pointer to session.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static const char * t38state_to_string[T38_MAX_ENUM]
String representations of the T.38 state enum.
Structure for a data store object.
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
struct pjsip_inv_session * inv_session
Transport information stored in transport_info datastore.
void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
Set the current negotiated formats of a stream.
void ast_free_ptr(void *ptr)
free() wrapper
Socket address structure.
A structure describing a SIP session.
int ast_manager_hangup_helper(struct mansession *s, const struct message *m, manager_hangup_handler_t handler, manager_hangup_cause_validator_t cause_validator)
A manager helper function that hangs up a channel using a supplied channel type specific hangup funct...
int pjsip_action_hangup(struct mansession *s, const struct message *m)
PJSIPHangup Manager Action.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
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 pjsip_acf_moh_passthrough_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_MOH_PASSTHROUGH function write callback.
struct ast_sip_endpoint_media_configuration media
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_DTMF_MODE function write callback.
int pjsip_acf_channel_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
CHANNEL function read callback.
int ast_dsp_get_features(struct ast_dsp *dsp)
Get features.
struct ast_stream * ast_stream_topology_get_first_stream_by_type(const struct ast_stream_topology *topology, enum ast_media_type type)
Gets the first active stream of a specific type from the topology.
General Asterisk PBX channel definitions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int pjsip_acf_dial_contacts_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_DIAL_CONTACTS function read callback.
int ast_sip_push_task_wait_serializer(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Push a task to the serializer and wait for it to complete.
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with '\0' ...
Access Control of various sorts.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Conversion utility functions.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
struct ast_channel * channel
#define ast_debug(level,...)
Log a DEBUG message.
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.
char * ast_rtp_instance_get_quality(struct ast_rtp_instance *instance, enum ast_rtp_instance_stat_field field, char *buf, size_t size)
Retrieve quality statistics about an RTP instance.
int pjsip_acf_media_offer_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_MEDIA_OFFER function write callback.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
struct ast_taskprocessor * serializer
int ast_str_to_int(const char *str, int *res)
Convert the given string to a signed integer.
static void pjsip_app_hangup_handler(struct ast_channel *chan, int response_code)
Called by pjsip_app_hangup and pjsip_action_hangup to actually perform the hangup.
int pjsip_acf_parse_uri_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
PJSIP_PARSE_URI function read callback.
pj_sockaddr remote_addr
The address that sent the request.
int pjsip_acf_session_refresh_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
PJSIP_SEND_SESSION_REFRESH function write callback.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Support for dynamic strings.
enum ast_sip_dtmf_mode dtmf
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
PJSIP Channel Driver shared data structures.
static int pjsip_hangup(void *obj)
Serializer task to hangup channel.
#define ast_calloc(num, len)
A wrapper for calloc()
char * ast_escape_quoted(const char *string, char *outbuf, int buflen)
Escape characters found in a quoted string.
static struct session_refresh_state * session_refresh_state_get_or_alloc(struct ast_sip_session *session)
Helper function which retrieves or allocates a session refresh state information datastore.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
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.
struct ast_stream_topology * ast_stream_topology_clone(const struct ast_stream_topology *topology)
Create a deep clone of an existing stream topology.
int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_DTMF_MODE function read callback.
#define AST_YESNO(x)
return Yes or No depending on the argument.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
ast_rtp_instance_stat_field
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
Set a stream metadata value.
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 pjsip_app_hangup(struct ast_channel *chan, const char *data)
PJSIPHangup Dialplan App.
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 used to push function arguments to task processor.
struct ast_sip_contact * contact
static int response_code_validator(const char *channel_name, const char *response)
Callback that validates the response code.
Asterisk module definitions.
int pjsip_acf_media_offer_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
PJSIP_MEDIA_OFFER function read callback.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
static const struct ast_datastore_info session_refresh_datastore
Datastore for attaching session refresh state information.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
unsigned int moh_passthrough
#define AST_APP_ARG(name)
Define an application argument.