pjsip/dialplan_functions.c File Reference

PJSIP channel dialplan functions. More...

#include "asterisk.h"
#include <pjsip.h>
#include <pjlib.h>
#include <pjsip_ua.h>
#include "asterisk/astobj2.h"
#include "asterisk/module.h"
#include "asterisk/acl.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/format.h"
#include "asterisk/pbx.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/res_pjsip_session.h"
#include "include/chan_pjsip.h"
#include "include/dialplan_functions.h"

Include dependency graph for pjsip/dialplan_functions.c:

Go to the source code of this file.

Data Structures

struct  media_offer_data
struct  pjsip_func_args
 Struct used to push function arguments to task processor. More...

Functions

static int channel_read_pjsip (struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
static int channel_read_rtcp (struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
static int channel_read_rtp (struct ast_channel *chan, const char *type, const char *field, char *buf, size_t buflen)
static int media_offer_read_av (struct ast_sip_session *session, char *buf, size_t len, enum ast_media_type media_type)
static int media_offer_write_av (void *obj)
int pjsip_acf_channel_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 CHANNEL function read callback.
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 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.
int pjsip_acf_media_offer_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 PJSIP_MEDIA_OFFER function write callback.
static int read_pjsip (void *data)

Variables

static const char * t38state_to_string [T38_MAX_ENUM]
 String representations of the T.38 state enum.


Detailed Description

PJSIP channel dialplan functions.

Author:
Joshua Colp <jcolp@digium.com> 

Matt Jordan <mjordan@digium.com> 

Definition in file pjsip/dialplan_functions.c.


Function Documentation

static int channel_read_pjsip ( struct ast_channel chan,
const char *  type,
const char *  field,
char *  buf,
size_t  buflen 
) [static]

Definition at line 581 of file pjsip/dialplan_functions.c.

References ao2_cleanup, ast_channel_name(), ast_channel_tech_pvt(), ast_copy_string(), ast_escape_quoted(), ast_log, AST_LOG_WARNING, ast_sip_get_pjsip_endpoint(), ast_sip_session_get_datastore(), ast_strdupa, ast_strlen_zero, ast_sip_session::inv_session, transport_info_data::local_addr, LOG_WARNING, NULL, pool, RAII_VAR, transport_info_data::remote_addr, ast_sip_channel_pvt::session, and ast_sip_session::t38state.

Referenced by read_pjsip().

00582 {
00583    struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
00584    char *buf_copy;
00585    pjsip_dialog *dlg;
00586 
00587    if (!channel) {
00588       ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
00589       return -1;
00590    }
00591 
00592    dlg = channel->session->inv_session->dlg;
00593 
00594    if (ast_strlen_zero(type)) {
00595       ast_log(LOG_WARNING, "You must supply a type field for 'pjsip' information\n");
00596       return -1;
00597    } else if (!strcmp(type, "secure")) {
00598 #ifdef HAVE_PJSIP_GET_DEST_INFO
00599       pjsip_host_info dest;
00600       pj_pool_t *pool = pjsip_endpt_create_pool(ast_sip_get_pjsip_endpoint(), "secure-check", 128, 128);
00601       pjsip_get_dest_info(dlg->target, NULL, pool, &dest);
00602       snprintf(buf, buflen, "%d", dest.flag & PJSIP_TRANSPORT_SECURE ? 1 : 0);
00603       pjsip_endpt_release_pool(ast_sip_get_pjsip_endpoint(), pool);
00604 #else
00605       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");
00606       return -1;
00607 #endif
00608    } else if (!strcmp(type, "target_uri")) {
00609       pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->target, buf, buflen);
00610       buf_copy = ast_strdupa(buf);
00611       ast_escape_quoted(buf_copy, buf, buflen);
00612    } else if (!strcmp(type, "local_uri")) {
00613       pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri, buf, buflen);
00614       buf_copy = ast_strdupa(buf);
00615       ast_escape_quoted(buf_copy, buf, buflen);
00616    } else if (!strcmp(type, "remote_uri")) {
00617       pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->remote.info->uri, buf, buflen);
00618       buf_copy = ast_strdupa(buf);
00619       ast_escape_quoted(buf_copy, buf, buflen);
00620    } else if (!strcmp(type, "t38state")) {
00621       ast_copy_string(buf, t38state_to_string[channel->session->t38state], buflen);
00622    } else if (!strcmp(type, "local_addr")) {
00623       RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
00624       struct transport_info_data *transport_data;
00625 
00626       datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
00627       if (!datastore) {
00628          ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
00629          return -1;
00630       }
00631       transport_data = datastore->data;
00632 
00633       if (pj_sockaddr_has_addr(&transport_data->local_addr)) {
00634          pj_sockaddr_print(&transport_data->local_addr, buf, buflen, 3);
00635       }
00636    } else if (!strcmp(type, "remote_addr")) {
00637       RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
00638       struct transport_info_data *transport_data;
00639 
00640       datastore = ast_sip_session_get_datastore(channel->session, "transport_info");
00641       if (!datastore) {
00642          ast_log(AST_LOG_WARNING, "No transport information for channel %s\n", ast_channel_name(chan));
00643          return -1;
00644       }
00645       transport_data = datastore->data;
00646 
00647       if (pj_sockaddr_has_addr(&transport_data->remote_addr)) {
00648          pj_sockaddr_print(&transport_data->remote_addr, buf, buflen, 3);
00649       }
00650    } else {
00651       ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'pjsip' information\n", type);
00652       return -1;
00653    }
00654 
00655    return 0;
00656 }

static int channel_read_rtcp ( struct ast_channel chan,
const char *  type,
const char *  field,
char *  buf,
size_t  buflen 
) [static]

Definition at line 461 of file pjsip/dialplan_functions.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_log, AST_LOG_WARNING, ast_rtp_instance_get_quality(), ast_rtp_instance_get_stats(), AST_RTP_INSTANCE_STAT_ALL, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS, AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT, ast_strlen_zero, ast_rtp_instance_stats::local_maxjitter, ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minjitter, ast_rtp_instance_stats::local_minrxploss, ast_rtp_instance_stats::local_normdevjitter, ast_rtp_instance_stats::local_normdevrxploss, ast_rtp_instance_stats::local_ssrc, ast_rtp_instance_stats::local_stdevjitter, ast_rtp_instance_stats::local_stdevrxploss, ast_rtp_instance_stats::maxrtt, chan_pjsip_pvt::media, ast_rtp_instance_stats::minrtt, name, ast_rtp_instance_stats::normdevrtt, NULL, ast_sip_channel_pvt::pvt, ast_rtp_instance_stats::remote_maxjitter, ast_rtp_instance_stats::remote_maxrxploss, ast_rtp_instance_stats::remote_minjitter, ast_rtp_instance_stats::remote_minrxploss, ast_rtp_instance_stats::remote_normdevjitter, ast_rtp_instance_stats::remote_normdevrxploss, ast_rtp_instance_stats::remote_ssrc, ast_rtp_instance_stats::remote_stdevjitter, ast_rtp_instance_stats::remote_stdevrxploss, ast_sip_session_media::rtp, ast_rtp_instance_stats::rtt, ast_rtp_instance_stats::rxcount, ast_rtp_instance_stats::rxjitter, ast_rtp_instance_stats::rxploss, S_OR, SIP_MEDIA_AUDIO, SIP_MEDIA_VIDEO, ast_rtp_instance_stats::stdevrtt, ast_rtp_instance_stats::txcount, ast_rtp_instance_stats::txjitter, and ast_rtp_instance_stats::txploss.

Referenced by read_pjsip().

00462 {
00463    struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
00464    struct chan_pjsip_pvt *pvt;
00465    struct ast_sip_session_media *media = NULL;
00466 
00467    if (!channel) {
00468       ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
00469       return -1;
00470    }
00471 
00472    pvt = channel->pvt;
00473    if (!pvt) {
00474       ast_log(AST_LOG_WARNING, "Channel %s has no chan_pjsip pvt!\n", ast_channel_name(chan));
00475       return -1;
00476    }
00477 
00478    if (ast_strlen_zero(type)) {
00479       ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtcp' information\n");
00480       return -1;
00481    }
00482 
00483    if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
00484       media = pvt->media[SIP_MEDIA_AUDIO];
00485    } else if (!strcmp(field, "video")) {
00486       media = pvt->media[SIP_MEDIA_VIDEO];
00487    } else {
00488       ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtcp' information\n", field);
00489       return -1;
00490    }
00491 
00492    if (!media || !media->rtp) {
00493       ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
00494          ast_channel_name(chan), S_OR(field, "audio"));
00495       return -1;
00496    }
00497 
00498    if (!strncasecmp(type, "all", 3)) {
00499       enum ast_rtp_instance_stat_field stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY;
00500 
00501       if (!strcasecmp(type, "all_jitter")) {
00502          stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY_JITTER;
00503       } else if (!strcasecmp(type, "all_rtt")) {
00504          stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY_RTT;
00505       } else if (!strcasecmp(type, "all_loss")) {
00506          stat_field = AST_RTP_INSTANCE_STAT_FIELD_QUALITY_LOSS;
00507       }
00508 
00509       if (!ast_rtp_instance_get_quality(media->rtp, stat_field, buf, buflen)) {
00510          ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
00511          return -1;
00512       }
00513    } else {
00514       struct ast_rtp_instance_stats stats;
00515       int i;
00516       struct {
00517          const char *name;
00518          enum { INT, DBL } type;
00519          union {
00520             unsigned int *i4;
00521             double *d8;
00522          };
00523       } lookup[] = {
00524          { "txcount",               INT, { .i4 = &stats.txcount, }, },
00525          { "rxcount",               INT, { .i4 = &stats.rxcount, }, },
00526          { "txjitter",              DBL, { .d8 = &stats.txjitter, }, },
00527          { "rxjitter",              DBL, { .d8 = &stats.rxjitter, }, },
00528          { "remote_maxjitter",      DBL, { .d8 = &stats.remote_maxjitter, }, },
00529          { "remote_minjitter",      DBL, { .d8 = &stats.remote_minjitter, }, },
00530          { "remote_normdevjitter",  DBL, { .d8 = &stats.remote_normdevjitter, }, },
00531          { "remote_stdevjitter",    DBL, { .d8 = &stats.remote_stdevjitter, }, },
00532          { "local_maxjitter",       DBL, { .d8 = &stats.local_maxjitter, }, },
00533          { "local_minjitter",       DBL, { .d8 = &stats.local_minjitter, }, },
00534          { "local_normdevjitter",   DBL, { .d8 = &stats.local_normdevjitter, }, },
00535          { "local_stdevjitter",     DBL, { .d8 = &stats.local_stdevjitter, }, },
00536          { "txploss",               INT, { .i4 = &stats.txploss, }, },
00537          { "rxploss",               INT, { .i4 = &stats.rxploss, }, },
00538          { "remote_maxrxploss",     DBL, { .d8 = &stats.remote_maxrxploss, }, },
00539          { "remote_minrxploss",     DBL, { .d8 = &stats.remote_minrxploss, }, },
00540          { "remote_normdevrxploss", DBL, { .d8 = &stats.remote_normdevrxploss, }, },
00541          { "remote_stdevrxploss",   DBL, { .d8 = &stats.remote_stdevrxploss, }, },
00542          { "local_maxrxploss",      DBL, { .d8 = &stats.local_maxrxploss, }, },
00543          { "local_minrxploss",      DBL, { .d8 = &stats.local_minrxploss, }, },
00544          { "local_normdevrxploss",  DBL, { .d8 = &stats.local_normdevrxploss, }, },
00545          { "local_stdevrxploss",    DBL, { .d8 = &stats.local_stdevrxploss, }, },
00546          { "rtt",                   DBL, { .d8 = &stats.rtt, }, },
00547          { "maxrtt",                DBL, { .d8 = &stats.maxrtt, }, },
00548          { "minrtt",                DBL, { .d8 = &stats.minrtt, }, },
00549          { "normdevrtt",            DBL, { .d8 = &stats.normdevrtt, }, },
00550          { "stdevrtt",              DBL, { .d8 = &stats.stdevrtt, }, },
00551          { "local_ssrc",            INT, { .i4 = &stats.local_ssrc, }, },
00552          { "remote_ssrc",           INT, { .i4 = &stats.remote_ssrc, }, },
00553          { NULL, },
00554       };
00555 
00556       if (ast_rtp_instance_get_stats(media->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
00557          ast_log(AST_LOG_WARNING, "Unable to retrieve 'rtcp' statistics for %s\n", ast_channel_name(chan));
00558          return -1;
00559       }
00560 
00561       for (i = 0; !ast_strlen_zero(lookup[i].name); i++) {
00562          if (!strcasecmp(type, lookup[i].name)) {
00563             if (lookup[i].type == INT) {
00564                snprintf(buf, buflen, "%u", *lookup[i].i4);
00565             } else {
00566                snprintf(buf, buflen, "%f", *lookup[i].d8);
00567             }
00568             return 0;
00569          }
00570       }
00571       ast_log(AST_LOG_WARNING, "Unrecognized argument '%s' for 'rtcp' information\n", type);
00572       return -1;
00573    }
00574 
00575    return 0;
00576 }

static int channel_read_rtp ( struct ast_channel chan,
const char *  type,
const char *  field,
char *  buf,
size_t  buflen 
) [static]

Definition at line 400 of file pjsip/dialplan_functions.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_copy_string(), ast_log, AST_LOG_WARNING, ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address, ast_sockaddr_stringify(), ast_strlen_zero, ast_sip_session_media::direct_media_addr, chan_pjsip_pvt::media, NULL, ast_sip_channel_pvt::pvt, ast_sip_session_media::remotely_held, ast_sip_session_media::rtp, S_OR, SIP_MEDIA_AUDIO, SIP_MEDIA_VIDEO, and ast_sip_session_media::srtp.

Referenced by read_pjsip().

00401 {
00402    struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
00403    struct chan_pjsip_pvt *pvt;
00404    struct ast_sip_session_media *media = NULL;
00405    struct ast_sockaddr addr;
00406 
00407    if (!channel) {
00408       ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
00409       return -1;
00410    }
00411 
00412    pvt = channel->pvt;
00413    if (!pvt) {
00414       ast_log(AST_LOG_WARNING, "Channel %s has no chan_pjsip pvt!\n", ast_channel_name(chan));
00415       return -1;
00416    }
00417 
00418    if (ast_strlen_zero(type)) {
00419       ast_log(AST_LOG_WARNING, "You must supply a type field for 'rtp' information\n");
00420       return -1;
00421    }
00422 
00423    if (ast_strlen_zero(field) || !strcmp(field, "audio")) {
00424       media = pvt->media[SIP_MEDIA_AUDIO];
00425    } else if (!strcmp(field, "video")) {
00426       media = pvt->media[SIP_MEDIA_VIDEO];
00427    } else {
00428       ast_log(AST_LOG_WARNING, "Unknown media type field '%s' for 'rtp' information\n", field);
00429       return -1;
00430    }
00431 
00432    if (!media || !media->rtp) {
00433       ast_log(AST_LOG_WARNING, "Channel %s has no %s media/RTP session\n",
00434          ast_channel_name(chan), S_OR(field, "audio"));
00435       return -1;
00436    }
00437 
00438    if (!strcmp(type, "src")) {
00439       ast_rtp_instance_get_local_address(media->rtp, &addr);
00440       ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
00441    } else if (!strcmp(type, "dest")) {
00442       ast_rtp_instance_get_remote_address(media->rtp, &addr);
00443       ast_copy_string(buf, ast_sockaddr_stringify(&addr), buflen);
00444    } else if (!strcmp(type, "direct")) {
00445       ast_copy_string(buf, ast_sockaddr_stringify(&media->direct_media_addr), buflen);
00446    } else if (!strcmp(type, "secure")) {
00447       snprintf(buf, buflen, "%d", media->srtp ? 1 : 0);
00448    } else if (!strcmp(type, "hold")) {
00449       snprintf(buf, buflen, "%d", media->remotely_held ? 1 : 0);
00450    } else {
00451       ast_log(AST_LOG_WARNING, "Unknown type field '%s' specified for 'rtp' information\n", type);
00452       return -1;
00453    }
00454 
00455    return 0;
00456 }

static int media_offer_read_av ( struct ast_sip_session session,
char *  buf,
size_t  len,
enum ast_media_type  media_type 
) [static]

Definition at line 854 of file pjsip/dialplan_functions.c.

References ao2_ref, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_get_name(), ast_format_get_type(), and ast_sip_session::req_caps.

Referenced by pjsip_acf_media_offer_read().

00856 {
00857    int i, size = 0;
00858 
00859    for (i = 0; i < ast_format_cap_count(session->req_caps); i++) {
00860       struct ast_format *fmt = ast_format_cap_get_format(session->req_caps, i);
00861 
00862       if (ast_format_get_type(fmt) != media_type) {
00863          ao2_ref(fmt, -1);
00864          continue;
00865       }
00866 
00867       /* add one since we'll include a comma */
00868       size = strlen(ast_format_get_name(fmt)) + 1;
00869       if (len < size) {
00870          ao2_ref(fmt, -1);
00871          break;
00872       }
00873       len -= size;
00874 
00875       /* no reason to use strncat here since we have already ensured buf has
00876                    enough space, so strcat can be safely used */
00877       strcat(buf, ast_format_get_name(fmt));
00878       strcat(buf, ",");
00879 
00880       ao2_ref(fmt, -1);
00881    }
00882 
00883    if (size) {
00884       /* remove the extra comma */
00885       buf[strlen(buf) - 1] = '\0';
00886    }
00887    return 0;
00888 }

static int media_offer_write_av ( void *  obj  )  [static]

int pjsip_acf_channel_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)

CHANNEL function read callback.

Parameters:
chan The channel the function is called on
cmd The name of the function
data Arguments passed to the function
buf Out buffer that should be populated with the data
len Size of the buffer
Return values:
0 on success
-1 on failure

Definition at line 728 of file pjsip/dialplan_functions.c.

References args, AST_APP_ARG, ast_channel_name(), ast_channel_tech(), ast_channel_tech_pvt(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_WARNING, ast_sip_push_task_synchronous(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, pjsip_func_args::buf, pjsip_func_args::chan, pjsip_func_args::field, pjsip_func_args::len, LOG_ERROR, LOG_WARNING, pjsip_func_args::param, parse(), read_pjsip(), pjsip_func_args::ret, ast_sip_session::serializer, ast_sip_channel_pvt::session, pjsip_func_args::type, and type.

00729 {
00730    struct pjsip_func_args func_args = { 0, };
00731    struct ast_sip_channel_pvt *channel;
00732    char *parse = ast_strdupa(data);
00733 
00734    AST_DECLARE_APP_ARGS(args,
00735       AST_APP_ARG(param);
00736       AST_APP_ARG(type);
00737       AST_APP_ARG(field);
00738    );
00739 
00740    if (!chan) {
00741       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
00742       return -1;
00743    }
00744    channel = ast_channel_tech_pvt(chan);
00745 
00746    /* Check for zero arguments */
00747    if (ast_strlen_zero(parse)) {
00748       ast_log(LOG_ERROR, "Cannot call %s without arguments\n", cmd);
00749       return -1;
00750    }
00751 
00752    AST_STANDARD_APP_ARGS(args, parse);
00753 
00754    /* Sanity check */
00755    if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
00756       ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
00757       return 0;
00758    }
00759 
00760    if (!channel) {
00761       ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
00762       return -1;
00763    }
00764 
00765    memset(buf, 0, len);
00766 
00767    func_args.chan = chan;
00768    func_args.param = args.param;
00769    func_args.type = args.type;
00770    func_args.field = args.field;
00771    func_args.buf = buf;
00772    func_args.len = len;
00773    if (ast_sip_push_task_synchronous(channel->session->serializer, read_pjsip, &func_args)) {
00774       ast_log(LOG_WARNING, "Unable to read properties of channel %s: failed to push task\n", ast_channel_name(chan));
00775       return -1;
00776    }
00777 
00778    return func_args.ret;
00779 }

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.

Parameters:
chan The channel the function is called on
cmd The name of the function
data Arguments passed to the function
buf Out buffer that should be populated with the data
len Size of the buffer
Return values:
0 on success
-1 on failure

Definition at line 781 of file pjsip/dialplan_functions.c.

References ao2_cleanup, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_free_ptr, ast_log, ast_sip_get_sorcery(), ast_sip_location_retrieve_aor(), ast_sip_location_retrieve_aor_contacts(), ast_sorcery_retrieve_by_id(), AST_STANDARD_APP_ARGS, ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_strlen(), ast_str_truncate(), ast_strdupa, ast_strlen_zero, LOG_WARNING, NULL, RAII_VAR, S_OR, strsep(), and ast_sip_contact::uri.

00782 {
00783    RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);
00784    RAII_VAR(struct ast_str *, dial, NULL, ast_free_ptr);
00785    const char *aor_name;
00786    char *rest;
00787 
00788    AST_DECLARE_APP_ARGS(args,
00789       AST_APP_ARG(endpoint_name);
00790       AST_APP_ARG(aor_name);
00791       AST_APP_ARG(request_user);
00792    );
00793 
00794    AST_STANDARD_APP_ARGS(args, data);
00795 
00796    if (ast_strlen_zero(args.endpoint_name)) {
00797       ast_log(LOG_WARNING, "An endpoint name must be specified when using the '%s' dialplan function\n", cmd);
00798       return -1;
00799    } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", args.endpoint_name))) {
00800       ast_log(LOG_WARNING, "Specified endpoint '%s' was not found\n", args.endpoint_name);
00801       return -1;
00802    }
00803 
00804    aor_name = S_OR(args.aor_name, endpoint->aors);
00805 
00806    if (ast_strlen_zero(aor_name)) {
00807       ast_log(LOG_WARNING, "No AOR has been provided and no AORs are configured on endpoint '%s'\n", args.endpoint_name);
00808       return -1;
00809    } else if (!(dial = ast_str_create(len))) {
00810       ast_log(LOG_WARNING, "Could not get enough buffer space for dialing contacts\n");
00811       return -1;
00812    } else if (!(rest = ast_strdupa(aor_name))) {
00813       ast_log(LOG_WARNING, "Could not duplicate provided AORs\n");
00814       return -1;
00815    }
00816 
00817    while ((aor_name = strsep(&rest, ","))) {
00818       RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup);
00819       RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup);
00820       struct ao2_iterator it_contacts;
00821       struct ast_sip_contact *contact;
00822 
00823       if (!aor) {
00824          /* If the AOR provided is not found skip it, there may be more */
00825          continue;
00826       } else if (!(contacts = ast_sip_location_retrieve_aor_contacts(aor))) {
00827          /* No contacts are available, skip it as well */
00828          continue;
00829       } else if (!ao2_container_count(contacts)) {
00830          /* We were given a container but no contacts are in it... */
00831          continue;
00832       }
00833 
00834       it_contacts = ao2_iterator_init(contacts, 0);
00835       for (; (contact = ao2_iterator_next(&it_contacts)); ao2_ref(contact, -1)) {
00836          ast_str_append(&dial, -1, "PJSIP/");
00837 
00838          if (!ast_strlen_zero(args.request_user)) {
00839             ast_str_append(&dial, -1, "%s@", args.request_user);
00840          }
00841          ast_str_append(&dial, -1, "%s/%s&", args.endpoint_name, contact->uri);
00842       }
00843       ao2_iterator_destroy(&it_contacts);
00844    }
00845 
00846    /* Trim the '&' at the end off */
00847    ast_str_truncate(dial, ast_str_strlen(dial) - 1);
00848 
00849    ast_copy_string(buf, ast_str_buffer(dial), len);
00850 
00851    return 0;
00852 }

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.

Parameters:
chan The channel the function is called on
cmd The name of the function
data Arguments passed to the function
buf Out buffer that should be populated with the data
len Size of the buffer
Return values:
0 on success
-1 on failure

Definition at line 906 of file pjsip/dialplan_functions.c.

References ast_channel_tech(), ast_channel_tech_pvt(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, LOG_WARNING, media_offer_read_av(), ast_sip_channel_pvt::session, and type.

00907 {
00908    struct ast_sip_channel_pvt *channel;
00909 
00910    if (!chan) {
00911       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
00912       return -1;
00913    }
00914 
00915    if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
00916       ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
00917       return -1;
00918    }
00919 
00920    channel = ast_channel_tech_pvt(chan);
00921 
00922    if (!strcmp(data, "audio")) {
00923       return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_AUDIO);
00924    } else if (!strcmp(data, "video")) {
00925       return media_offer_read_av(channel->session, buf, len, AST_MEDIA_TYPE_VIDEO);
00926    }
00927 
00928    return 0;
00929 }

int pjsip_acf_media_offer_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)

PJSIP_MEDIA_OFFER function write callback.

Parameters:
chan The channel the function is called on
cmd The name of the function
data Arguments passed to the function
value Value to be set by the function
Return values:
0 on success
-1 on failure

Definition at line 931 of file pjsip/dialplan_functions.c.

References ast_channel_tech(), ast_channel_tech_pvt(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_sip_push_task_synchronous(), LOG_WARNING, media_offer_write_av(), media_offer_data::media_type, ast_sip_session::serializer, ast_sip_channel_pvt::session, media_offer_data::session, type, and media_offer_data::value.

00932 {
00933    struct ast_sip_channel_pvt *channel;
00934    struct media_offer_data mdata = {
00935       .value = value
00936    };
00937 
00938    if (!chan) {
00939       ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
00940       return -1;
00941    }
00942 
00943    if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
00944       ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
00945       return -1;
00946    }
00947 
00948    channel = ast_channel_tech_pvt(chan);
00949    mdata.session = channel->session;
00950 
00951    if (!strcmp(data, "audio")) {
00952       mdata.media_type = AST_MEDIA_TYPE_AUDIO;
00953    } else if (!strcmp(data, "video")) {
00954       mdata.media_type = AST_MEDIA_TYPE_VIDEO;
00955    }
00956 
00957    return ast_sip_push_task_synchronous(channel->session->serializer, media_offer_write_av, &mdata);
00958 }

static int read_pjsip ( void *  data  )  [static]

Definition at line 670 of file pjsip/dialplan_functions.c.

References ast_sip_session::aor, ast_channel_name(), ast_channel_tech_pvt(), ast_log, AST_LOG_WARNING, ast_sorcery_object_get_id(), pjsip_func_args::buf, pjsip_func_args::chan, channel_read_pjsip(), channel_read_rtcp(), channel_read_rtp(), ast_sip_session::contact, ast_sip_session::endpoint, pjsip_func_args::field, func_args(), pjsip_func_args::len, pjsip_func_args::param, ast_sip_channel_pvt::pvt, pjsip_func_args::ret, ast_sip_channel_pvt::session, and pjsip_func_args::type.

Referenced by pjsip_acf_channel_read().

00671 {
00672    struct pjsip_func_args *func_args = data;
00673 
00674    if (!strcmp(func_args->param, "rtp")) {
00675       func_args->ret = channel_read_rtp(func_args->chan, func_args->type,
00676                                         func_args->field, func_args->buf,
00677                                         func_args->len);
00678    } else if (!strcmp(func_args->param, "rtcp")) {
00679       func_args->ret = channel_read_rtcp(func_args->chan, func_args->type,
00680                                          func_args->field, func_args->buf,
00681                                          func_args->len);
00682    } else if (!strcmp(func_args->param, "endpoint")) {
00683       struct ast_sip_channel_pvt *pvt = ast_channel_tech_pvt(func_args->chan);
00684 
00685       if (!pvt) {
00686          ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(func_args->chan));
00687          return -1;
00688       }
00689       if (!pvt->session || !pvt->session->endpoint) {
00690          ast_log(AST_LOG_WARNING, "Channel %s has no endpoint!\n", ast_channel_name(func_args->chan));
00691          return -1;
00692       }
00693       snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(pvt->session->endpoint));
00694    } else if (!strcmp(func_args->param, "contact")) {
00695       struct ast_sip_channel_pvt *pvt = ast_channel_tech_pvt(func_args->chan);
00696 
00697       if (!pvt) {
00698          ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(func_args->chan));
00699          return -1;
00700       }
00701       if (!pvt->session || !pvt->session->contact) {
00702          return 0;
00703       }
00704       snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(pvt->session->contact));
00705    } else if (!strcmp(func_args->param, "aor")) {
00706       struct ast_sip_channel_pvt *pvt = ast_channel_tech_pvt(func_args->chan);
00707 
00708       if (!pvt) {
00709          ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(func_args->chan));
00710          return -1;
00711       }
00712       if (!pvt->session || !pvt->session->aor) {
00713          return 0;
00714       }
00715       snprintf(func_args->buf, func_args->len, "%s", ast_sorcery_object_get_id(pvt->session->aor));
00716    } else if (!strcmp(func_args->param, "pjsip")) {
00717       func_args->ret = channel_read_pjsip(func_args->chan, func_args->type,
00718                                           func_args->field, func_args->buf,
00719                                           func_args->len);
00720    } else {
00721       func_args->ret = -1;
00722    }
00723 
00724    return 0;
00725 }


Variable Documentation

const char* t38state_to_string[T38_MAX_ENUM] [static]

String representations of the T.38 state enum.

Definition at line 389 of file pjsip/dialplan_functions.c.


Generated on Thu Apr 16 06:30:40 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6