Sun Oct 16 2011 08:43:08

Asterisk developer's documentation


sig_pri.h File Reference

Interface header for PRI signaling module. More...

#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/event.h"
#include "asterisk/ccss.h"
#include <libpri.h>
#include <dahdi/user.h>
Include dependency graph for sig_pri.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  sig_pri_callback
struct  sig_pri_chan
struct  sig_pri_span

Defines

#define DAHDI_CHAN_MAPPING_LOGICAL   1
#define DAHDI_CHAN_MAPPING_PHYSICAL   0
#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
#define DAHDI_OVERLAPDIAL_INCOMING   2
#define DAHDI_OVERLAPDIAL_NONE   0
#define DAHDI_OVERLAPDIAL_OUTGOING   1
#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)
#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_PRI_AOC_GRANT_D   (1 << 1)
#define SIG_PRI_AOC_GRANT_E   (1 << 2)
#define SIG_PRI_AOC_GRANT_S   (1 << 0)
#define SIG_PRI_DEBUG_DEFAULT   0
#define SIG_PRI_DEBUG_INTENSE
#define SIG_PRI_DEBUG_NORMAL   (PRI_DEBUG_APDU | PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q921_STATE)
#define SIG_PRI_MAX_CHANNELS   672
#define SIG_PRI_NUM_DCHANS   4

Enumerations

enum  sig_pri_call_level {
  SIG_PRI_CALL_LEVEL_IDLE, SIG_PRI_CALL_LEVEL_SETUP, SIG_PRI_CALL_LEVEL_OVERLAP, SIG_PRI_CALL_LEVEL_PROCEEDING,
  SIG_PRI_CALL_LEVEL_ALERTING, SIG_PRI_CALL_LEVEL_CONNECT
}
enum  sig_pri_law { SIG_PRI_DEFLAW = 0, SIG_PRI_ULAW, SIG_PRI_ALAW }
enum  sig_pri_tone {
  SIG_PRI_TONE_RINGTONE = 0, SIG_PRI_TONE_STUTTER, SIG_PRI_TONE_CONGESTION, SIG_PRI_TONE_DIALTONE,
  SIG_PRI_TONE_DIALRECALL, SIG_PRI_TONE_INFO, SIG_PRI_TONE_BUSY
}

Functions

void pri_event_alarm (struct sig_pri_span *pri, int index, int before_start_pri)
void pri_event_noalarm (struct sig_pri_span *pri, int index, int before_start_pri)
int pri_is_up (struct sig_pri_span *pri)
int pri_send_callrerouting_facility_exec (struct sig_pri_chan *p, enum ast_channel_state chanstate, const char *destination, const char *original, const char *reason)
int pri_send_keypad_facility_exec (struct sig_pri_chan *p, const char *digits)
int sig_pri_answer (struct sig_pri_chan *p, struct ast_channel *ast)
int sig_pri_available (struct sig_pri_chan **pvt, int is_specific_channel)
int sig_pri_call (struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, int timeout, int layer1)
int sig_pri_cc_agent_callee_available (struct ast_cc_agent *agent)
void sig_pri_cc_agent_destructor (struct ast_cc_agent *agent)
int sig_pri_cc_agent_init (struct ast_cc_agent *agent, struct sig_pri_chan *pvt_chan)
int sig_pri_cc_agent_party_b_free (struct ast_cc_agent *agent)
void sig_pri_cc_agent_req_rsp (struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
int sig_pri_cc_agent_start_monitoring (struct ast_cc_agent *agent)
int sig_pri_cc_agent_start_offer_timer (struct ast_cc_agent *agent)
int sig_pri_cc_agent_status_req (struct ast_cc_agent *agent)
int sig_pri_cc_agent_stop_offer_timer (struct ast_cc_agent *agent)
int sig_pri_cc_agent_stop_ringing (struct ast_cc_agent *agent)
int sig_pri_cc_monitor_cancel_available_timer (struct ast_cc_monitor *monitor, int *sched_id)
void sig_pri_cc_monitor_destructor (void *monitor_pvt)
int sig_pri_cc_monitor_req_cc (struct ast_cc_monitor *monitor, int *available_timer_id)
int sig_pri_cc_monitor_status_rsp (struct ast_cc_monitor *monitor, enum ast_device_state devstate)
int sig_pri_cc_monitor_suspend (struct ast_cc_monitor *monitor)
int sig_pri_cc_monitor_unsuspend (struct ast_cc_monitor *monitor)
void sig_pri_chan_alarm_notify (struct sig_pri_chan *p, int noalarm)
 Notify new alarm status.
void sig_pri_chan_delete (struct sig_pri_chan *doomed)
 Delete the sig_pri private channel structure.
struct sig_pri_chansig_pri_chan_new (void *pvt_data, struct sig_pri_callback *callback, struct sig_pri_span *pri, int logicalspan, int channo, int trunkgroup)
void sig_pri_cli_show_channels (int fd, struct sig_pri_span *pri)
void sig_pri_cli_show_channels_header (int fd)
void sig_pri_cli_show_span (int fd, int *dchannels, struct sig_pri_span *pri)
void sig_pri_cli_show_spans (int fd, int span, struct sig_pri_span *pri)
int sig_pri_digit_begin (struct sig_pri_chan *pvt, struct ast_channel *ast, char digit)
void sig_pri_extract_called_num_subaddr (struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
 Extract the called number and subaddress from the dial string.
void sig_pri_fixup (struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan)
int sig_pri_hangup (struct sig_pri_chan *p, struct ast_channel *ast)
int sig_pri_indicate (struct sig_pri_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
void sig_pri_init_pri (struct sig_pri_span *pri)
int sig_pri_is_chan_available (struct sig_pri_chan *pvt)
 Determine if a private channel structure is available.
int sig_pri_load (const char *cc_type_name)
 Load the sig_pri submodule.
struct ast_channelsig_pri_request (struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_channel *requestor, int transfercapability)
void sig_pri_set_alarm (struct sig_pri_chan *p, int in_alarm)
int sig_pri_start_pri (struct sig_pri_span *pri)
void sig_pri_stop_pri (struct sig_pri_span *pri)
 Stop PRI span.
void sig_pri_unload (void)
 Unload the sig_pri submodule.

Detailed Description

Interface header for PRI signaling module.

Author:
Matthew Fredrickson <creslin@digium.com>

Definition in file sig_pri.h.


Define Documentation

#define DAHDI_CHAN_MAPPING_LOGICAL   1

Definition at line 167 of file sig_pri.h.

Referenced by process_dahdi(), and sig_pri_start_pri().

#define DAHDI_CHAN_MAPPING_PHYSICAL   0

Definition at line 166 of file sig_pri.h.

Referenced by dahdi_chan_conf_default(), and process_dahdi().

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

Definition at line 173 of file sig_pri.h.

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_INCOMING   2
#define DAHDI_OVERLAPDIAL_NONE   0

Definition at line 170 of file sig_pri.h.

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_OUTGOING   1

Definition at line 171 of file sig_pri.h.

Referenced by dahdi_read(), process_dahdi(), pri_dchannel(), and sig_pri_start_pri().

#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)

Definition at line 162 of file sig_pri.h.

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 163 of file sig_pri.h.

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 161 of file sig_pri.h.

#define SIG_PRI_AOC_GRANT_D   (1 << 1)

Definition at line 67 of file sig_pri.h.

Referenced by process_dahdi(), sig_pri_handle_subcmds(), and sig_pri_indicate().

#define SIG_PRI_AOC_GRANT_E   (1 << 2)

Definition at line 68 of file sig_pri.h.

Referenced by process_dahdi(), sig_pri_handle_subcmds(), and sig_pri_indicate().

#define SIG_PRI_AOC_GRANT_S   (1 << 0)

Definition at line 66 of file sig_pri.h.

Referenced by process_dahdi(), sig_pri_handle_subcmds(), and sig_pri_indicate().

#define SIG_PRI_DEBUG_DEFAULT   0

PRI debug message flags set on initial startup.

Definition at line 63 of file sig_pri.h.

Referenced by sig_pri_start_pri().

#define SIG_PRI_DEBUG_INTENSE
Value:
(PRI_DEBUG_APDU | PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q921_STATE \
   | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP)

PRI debug message flags when intense PRI debugging is turned on at the command line.

Definition at line 53 of file sig_pri.h.

Referenced by handle_pri_debug().

#define SIG_PRI_DEBUG_NORMAL   (PRI_DEBUG_APDU | PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q921_STATE)

PRI debug message flags when normal PRI debugging is turned on at the command line.

Definition at line 49 of file sig_pri.h.

Referenced by handle_pri_debug().

#define SIG_PRI_MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 159 of file sig_pri.h.


Enumeration Type Documentation

Call establishment life cycle level for simple comparisons.

Enumerator:
SIG_PRI_CALL_LEVEL_IDLE 

Call does not exist.

SIG_PRI_CALL_LEVEL_SETUP 

Call is present but has no response yet. (SETUP)

SIG_PRI_CALL_LEVEL_OVERLAP 

Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE)

SIG_PRI_CALL_LEVEL_PROCEEDING 

Call routing is happening. (PROCEEDING)

SIG_PRI_CALL_LEVEL_ALERTING 

Called party is being alerted of the call. (ALERTING)

SIG_PRI_CALL_LEVEL_CONNECT 

Call is connected/answered. (CONNECT)

Definition at line 87 of file sig_pri.h.

                        {
   /*! Call does not exist. */
   SIG_PRI_CALL_LEVEL_IDLE,
   /*! Call is present but has no response yet. (SETUP) */
   SIG_PRI_CALL_LEVEL_SETUP,
   /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */
   SIG_PRI_CALL_LEVEL_OVERLAP,
   /*! Call routing is happening. (PROCEEDING) */
   SIG_PRI_CALL_LEVEL_PROCEEDING,
   /*! Called party is being alerted of the call. (ALERTING) */
   SIG_PRI_CALL_LEVEL_ALERTING,
   /*! Call is connected/answered. (CONNECT) */
   SIG_PRI_CALL_LEVEL_CONNECT,
};
Enumerator:
SIG_PRI_DEFLAW 
SIG_PRI_ULAW 
SIG_PRI_ALAW 

Definition at line 80 of file sig_pri.h.

Enumerator:
SIG_PRI_TONE_RINGTONE 
SIG_PRI_TONE_STUTTER 
SIG_PRI_TONE_CONGESTION 
SIG_PRI_TONE_DIALTONE 
SIG_PRI_TONE_DIALRECALL 
SIG_PRI_TONE_INFO 
SIG_PRI_TONE_BUSY 

Definition at line 70 of file sig_pri.h.


Function Documentation

void pri_event_alarm ( struct sig_pri_span pri,
int  index,
int  before_start_pri 
)

Definition at line 1897 of file sig_pri.c.

References sig_pri_span::dchanavail, DCHAN_NOTINALARM, DCHAN_UP, and pri_find_dchan().

Referenced by my_handle_dchan_exception(), and prepare_pri().

{
   pri->dchanavail[index] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
   if (!before_start_pri)
      pri_find_dchan(pri);
}
void pri_event_noalarm ( struct sig_pri_span pri,
int  index,
int  before_start_pri 
)

Definition at line 1904 of file sig_pri.c.

References sig_pri_span::dchanavail, DCHAN_NOTINALARM, and sig_pri_span::dchans.

Referenced by my_handle_dchan_exception(), and prepare_pri().

{
   pri->dchanavail[index] |= DCHAN_NOTINALARM;
   if (!before_start_pri)
      pri_restart(pri->dchans[index]);
}
int pri_is_up ( struct sig_pri_span pri)

Definition at line 995 of file sig_pri.c.

References SIG_PRI_NUM_DCHANS, sig_pri_span::dchanavail, and DCHAN_AVAILABLE.

Referenced by pri_dchannel().

{
   int x;
   for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
      if (pri->dchanavail[x] == DCHAN_AVAILABLE)
         return 1;
   }
   return 0;
}
int pri_send_callrerouting_facility_exec ( struct sig_pri_chan p,
enum ast_channel_state  chanstate,
const char *  destination,
const char *  original,
const char *  reason 
)

Definition at line 7804 of file sig_pri.c.

References sig_pri_lock_private(), sig_pri_chan::pri, sig_pri_chan::call, ast_log(), LOG_DEBUG, sig_pri_unlock_private(), pri_grab(), sig_pri_span::pri, pri_rel(), and sig_pri_span::span.

{
   int res = -1;

   sig_pri_lock_private(p);

   if (!p->pri || !p->call) {
      ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
      sig_pri_unlock_private(p);
      return -1;
   }

   if (!pri_grab(p, p->pri)) {
      res = pri_callrerouting_facility(p->pri->pri, p->call, destination, original, reason);
      pri_rel(p->pri);
   } else {
      ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->pri->span);
   }

   sig_pri_unlock_private(p);

   return res;
}
int pri_send_keypad_facility_exec ( struct sig_pri_chan p,
const char *  digits 
)

Definition at line 7780 of file sig_pri.c.

References sig_pri_lock_private(), sig_pri_chan::pri, sig_pri_chan::call, ast_debug, sig_pri_unlock_private(), pri_grab(), sig_pri_span::pri, and pri_rel().

Referenced by dahdi_send_keypad_facility_exec().

{
   sig_pri_lock_private(p);

   if (!p->pri || !p->call) {
      ast_debug(1, "Unable to find pri or call on channel!\n");
      sig_pri_unlock_private(p);
      return -1;
   }

   if (!pri_grab(p, p->pri)) {
      pri_keypad_facility(p->pri->pri, p->call, digits);
      pri_rel(p->pri);
   } else {
      ast_debug(1, "Unable to grab pri to send keypad facility!\n");
      sig_pri_unlock_private(p);
      return -1;
   }

   sig_pri_unlock_private(p);

   return 0;
}
int sig_pri_answer ( struct sig_pri_chan p,
struct ast_channel ast 
)

Definition at line 7070 of file sig_pri.c.

References pri_grab(), sig_pri_chan::pri, sig_pri_span::pri, sig_pri_chan::call, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_CONNECT, sig_pri_set_dialing(), sig_pri_open_media(), sig_pri_chan::digital, pri_rel(), ast_setstate(), and AST_STATE_UP.

Referenced by dahdi_answer().

{
   int res = 0;
   /* Send a pri acknowledge */
   if (!pri_grab(p, p->pri)) {
#if defined(HAVE_PRI_AOC_EVENTS)
      if (p->aoc_s_request_invoke_id_valid) {
         /* if AOC-S was requested and the invoke id is still present on answer.  That means
          * no AOC-S rate list was provided, so send a NULL response which will indicate that
          * AOC-S is not available */
         pri_aoc_s_request_response_send(p->pri->pri, p->call,
            p->aoc_s_request_invoke_id, NULL);
         p->aoc_s_request_invoke_id_valid = 0;
      }
#endif   /* defined(HAVE_PRI_AOC_EVENTS) */
      if (p->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
         p->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
      }
      sig_pri_set_dialing(p, 0);
      sig_pri_open_media(p);
      res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
      pri_rel(p->pri);
   } else {
      res = -1;
   }
   ast_setstate(ast, AST_STATE_UP);
   return res;
}
int sig_pri_available ( struct sig_pri_chan **  pvt,
int  is_specific_channel 
)

Definition at line 7167 of file sig_pri.c.

References sig_pri_span::pri, sig_pri_chan::pri, ast_mutex_lock, sig_pri_span::lock, sig_pri_available_check(), sig_pri_chan::allocated, and ast_mutex_unlock.

Referenced by available().

{
   struct sig_pri_chan *p = *pvt;
   struct sig_pri_span *pri;

   if (!p->pri) {
      /* Something is wrong here.  A PRI channel without the pri pointer? */
      return 0;
   }
   pri = p->pri;

   ast_mutex_lock(&pri->lock);
   if (
#if defined(HAVE_PRI_CALL_WAITING)
      /*
       * Only do call waiting calls if we have any
       * call waiting call outstanding.  We do not
       * want new calls to steal a B channel
       * freed for an earlier call waiting call.
       */
      !pri->num_call_waiting_calls &&
#endif   /* defined(HAVE_PRI_CALL_WAITING) */
      sig_pri_available_check(p)) {
      p->allocated = 1;
      ast_mutex_unlock(&pri->lock);
      return 1;
   }

#if defined(HAVE_PRI_CALL_WAITING)
   if (!is_specific_channel) {
      struct sig_pri_chan *cw;

      cw = sig_pri_cw_available(pri);
      if (cw) {
         /* We have a call waiting interface to use instead. */
         cw->allocated = 1;
         *pvt = cw;
         ast_mutex_unlock(&pri->lock);
         return 1;
      }
   }
#endif   /* defined(HAVE_PRI_CALL_WAITING) */
   ast_mutex_unlock(&pri->lock);
   return 0;
}
int sig_pri_call ( struct sig_pri_chan p,
struct ast_channel ast,
char *  rdest,
int  timeout,
int  layer1 
)
Note:
Parsing must remain in sync with sig_pri_extract_called_num_subaddr().

Definition at line 6400 of file sig_pri.c.

References AST_DECLARE_APP_ARGS, args, AST_APP_ARG, ext, OPT_ARG_ARRAY_SIZE, ast_log(), LOG_DEBUG, S_COR, ast_channel::connected, ast_party_connected_line::id, ast_party_id::name, ast_party_name::valid, ast_party_name::str, ast_party_id::number, ast_party_number::valid, ast_party_number::str, sig_pri_chan::pri, LOG_ERROR, sig_pri_chan::channel, ast_channel::_state, AST_STATE_DOWN, AST_STATE_RESERVED, LOG_WARNING, ast_channel::name, sig_pri_chan::dialdest, sig_pri_chan::outgoing, ast_copy_string(), AST_NONSTANDARD_APP_ARGS, ast_app_parse_options(), sig_pri_call_opts, ast_party_subaddress_init(), ast_party_subaddress::type, ast_party_subaddress::str, ast_party_subaddress::valid, sig_pri_chan::hidecallerid, sig_pri_chan::hidecalleridname, sig_pri_chan::stripmsd, pri_grab(), sig_pri_chan::call, sig_pri_span::pri, pri_rel(), sig_pri_set_digital(), IS_DIGITAL, ast_channel::transfercapability, sig_pri_chan::priexclusive, sig_pri_span::nodetype, PVT_TO_CHANNEL(), sig_pri_chan::digital, PRI_TRANS_CAP_DIGITAL, sig_pri_span::facilityenable, ast_verb, ast_transfercapability2str(), sig_pri_span::dialplan, sig_pri_span::internationalprefix, sig_pri_span::nationalprefix, ast_test_flag, OPT_KEYPAD, ast_strlen_zero(), OPT_ARG_KEYPAD, OPT_REVERSE_CHARGE, OPT_AOC_REQUEST, OPT_ARG_AOC_REQUEST, sig_pri_span::append_msn_to_user_tag, sig_pri_chan::user_tag, sig_pri_span::initial_user_tag, ast_free, ast_channel::caller, ast_party_caller::id, ast_party_id::tag, ast_strdup, sig_pri_span::localdialplan, sig_pri_chan::use_callingpres, ast_party_number::presentation, ast_party_id::subaddress, sig_pri_redirecting_update(), pbx_builtin_getvar_helper(), sig_pri_chan::owner, ast_cc_is_recall(), monitor, AST_CHANNEL_NAME, ast_channel_get_device_name(), ast_cc_get_monitor_by_recall_core_id(), ast_cc_monitor::private_data, ast_assert, ao2_ref, dialplan2str(), sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_SETUP, ast_setstate(), AST_STATE_DIALING, and sig_pri_set_dialing().

Referenced by dahdi_call().

{
   char dest[256]; /* must be same length as p->dialdest */
   struct ast_party_subaddress dialed_subaddress; /* Called subaddress */
   struct pri_sr *sr;
   char *c, *l, *n, *s;
#ifdef SUPPORT_USERUSER
   const char *useruser;
#endif
   int core_id;
   int pridialplan;
   int dp_strip;
   int prilocaldialplan;
   int ldp_strip;
   int exclusive;
#if defined(HAVE_PRI_SETUP_KEYPAD)
   const char *keypad;
#endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(group);  /* channel/group token */
      AST_APP_ARG(ext); /* extension token */
      AST_APP_ARG(opts);   /* options token */
      AST_APP_ARG(other);  /* Any remining unused arguments */
   );
   struct ast_flags opts;
   char *opt_args[OPT_ARG_ARRAY_SIZE];

   ast_log(LOG_DEBUG, "CALLER NAME: %s NUM: %s\n",
      S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
      S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));

   if (!p->pri) {
      ast_log(LOG_ERROR, "Could not find pri on channel %d\n", p->channel);
      return -1;
   }

   if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
      ast_log(LOG_WARNING, "sig_pri_call called on %s, neither down nor reserved\n", ast->name);
      return -1;
   }

   p->dialdest[0] = '\0';
   p->outgoing = 1;

   ast_copy_string(dest, rdest, sizeof(dest));
   AST_NONSTANDARD_APP_ARGS(args, dest, '/');
   if (ast_app_parse_options(sig_pri_call_opts, &opts, opt_args, args.opts)) {
      /* General invalid option syntax. */
      return -1;
   }

   c = args.ext;
   if (!c) {
      c = "";
   }

   /* setup dialed_subaddress if found */
   ast_party_subaddress_init(&dialed_subaddress);
   s = strchr(c, ':');
   if (s) {
      *s = '\0';
      s++;
      /* prefix */
      /* 'n' = NSAP */
      /* 'u' = User Specified */
      /* Default = NSAP */
      switch (*s) {
      case 'U':
      case 'u':
         s++;
         dialed_subaddress.type = 2;
         break;
      case 'N':
      case 'n':
         s++;
         /* default already covered with ast_party_subaddress_init */
         break;
      }
      dialed_subaddress.str = s;
      dialed_subaddress.valid = 1;
      s = NULL;
   }

   l = NULL;
   n = NULL;
   if (!p->hidecallerid) {
      if (ast->connected.id.number.valid) {
         /* If we get to the end of this loop without breaking, there's no
          * calleridnum.  This is done instead of testing for "unknown" or
          * the thousands of other ways that the calleridnum could be
          * invalid. */
         for (l = ast->connected.id.number.str; l && *l; l++) {
            if (strchr("0123456789", *l)) {
               l = ast->connected.id.number.str;
               break;
            }
         }
      } else {
         l = NULL;
      }
      if (!p->hidecalleridname) {
         n = ast->connected.id.name.valid ? ast->connected.id.name.str : NULL;
      }
   }

   if (strlen(c) < p->stripmsd) {
      ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
      return -1;
   }
   if (pri_grab(p, p->pri)) {
      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
      return -1;
   }
   if (!(p->call = pri_new_call(p->pri->pri))) {
      ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
      pri_rel(p->pri);
      return -1;
   }
   if (!(sr = pri_sr_new())) {
      ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
      pri_destroycall(p->pri->pri, p->call);
      p->call = NULL;
      pri_rel(p->pri);
      return -1;
   }

   sig_pri_set_digital(p, IS_DIGITAL(ast->transfercapability));   /* push up to parent for EC */

#if defined(HAVE_PRI_CALL_WAITING)
   if (p->is_call_waiting) {
      /*
       * Indicate that this is a call waiting call.
       * i.e., Normal call but with no B channel.
       */
      pri_sr_set_channel(sr, 0, 0, 1);
   } else
#endif   /* defined(HAVE_PRI_CALL_WAITING) */
   {
      /* Should the picked channel be used exclusively? */
      if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
         exclusive = 1;
      } else {
         exclusive = 0;
      }
      pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
   }

   pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
      (p->digital ? -1 : layer1));

   if (p->pri->facilityenable)
      pri_facility_enable(p->pri->pri);

   ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
   dp_strip = 0;
   pridialplan = p->pri->dialplan - 1;
   if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
      if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
         if (pridialplan == -2) {
            dp_strip = strlen(p->pri->internationalprefix);
         }
         pridialplan = PRI_INTERNATIONAL_ISDN;
      } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
         if (pridialplan == -2) {
            dp_strip = strlen(p->pri->nationalprefix);
         }
         pridialplan = PRI_NATIONAL_ISDN;
      } else {
         pridialplan = PRI_LOCAL_ISDN;
      }
   }
   while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
      switch (c[p->stripmsd]) {
      case 'U':
         pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
         break;
      case 'I':
         pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
         break;
      case 'N':
         pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
         break;
      case 'L':
         pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
         break;
      case 'S':
         pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
         break;
      case 'V':
         pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
         break;
      case 'R':
         pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
         break;
      case 'u':
         pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
         break;
      case 'e':
         pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
         break;
      case 'x':
         pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
         break;
      case 'f':
         pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
         break;
      case 'n':
         pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
         break;
      case 'p':
         pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
         break;
      case 'r':
         pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
         break;
      default:
         if (isalpha(c[p->stripmsd])) {
            ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
               c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
         }
         break;
      }
      c++;
   }
#if defined(HAVE_PRI_SETUP_KEYPAD)
   if (ast_test_flag(&opts, OPT_KEYPAD)
      && !ast_strlen_zero(opt_args[OPT_ARG_KEYPAD])) {
      /* We have a keypad facility digits option with digits. */
      keypad = opt_args[OPT_ARG_KEYPAD];
      pri_sr_set_keypad_digits(sr, keypad);
   } else {
      keypad = NULL;
   }
   if (!keypad || !ast_strlen_zero(c + p->stripmsd + dp_strip))
#endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
   {
      pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
   }

#if defined(HAVE_PRI_SUBADDR)
   if (dialed_subaddress.valid) {
      struct pri_party_subaddress subaddress;

      memset(&subaddress, 0, sizeof(subaddress));
      sig_pri_party_subaddress_from_ast(&subaddress, &dialed_subaddress);
      pri_sr_set_called_subaddress(sr, &subaddress);
   }
#endif   /* defined(HAVE_PRI_SUBADDR) */
#if defined(HAVE_PRI_REVERSE_CHARGE)
   if (ast_test_flag(&opts, OPT_REVERSE_CHARGE)) {
      pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
   }
#endif   /* defined(HAVE_PRI_REVERSE_CHARGE) */
#if defined(HAVE_PRI_AOC_EVENTS)
   if (ast_test_flag(&opts, OPT_AOC_REQUEST)
      && !ast_strlen_zero(opt_args[OPT_ARG_AOC_REQUEST])) {
      if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 's')) {
         pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_S);
      }
      if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'd')) {
         pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_D);
      }
      if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'e')) {
         pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_E);
      }
   }
#endif   /* defined(HAVE_PRI_AOC_EVENTS) */

   /* Setup the user tag for party id's from this device for this call. */
   if (p->pri->append_msn_to_user_tag) {
      snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
         p->pri->nodetype == PRI_NETWORK
            ? c + p->stripmsd + dp_strip
            : S_COR(ast->connected.id.number.valid,
               ast->connected.id.number.str, ""));
   } else {
      ast_copy_string(p->user_tag, p->pri->initial_user_tag, sizeof(p->user_tag));
   }

   /*
    * Replace the caller id tag from the channel creation
    * with the actual tag value.
    */
   ast_free(ast->caller.id.tag);
   ast->caller.id.tag = ast_strdup(p->user_tag);

   ldp_strip = 0;
   prilocaldialplan = p->pri->localdialplan - 1;
   if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
      if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
         if (prilocaldialplan == -2) {
            ldp_strip = strlen(p->pri->internationalprefix);
         }
         prilocaldialplan = PRI_INTERNATIONAL_ISDN;
      } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
         if (prilocaldialplan == -2) {
            ldp_strip = strlen(p->pri->nationalprefix);
         }
         prilocaldialplan = PRI_NATIONAL_ISDN;
      } else {
         prilocaldialplan = PRI_LOCAL_ISDN;
      }
   }
   if (l != NULL) {
      while (*l > '9' && *l != '*' && *l != '#') {
         switch (*l) {
         case 'U':
            prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
            break;
         case 'I':
            prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
            break;
         case 'N':
            prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
            break;
         case 'L':
            prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
            break;
         case 'S':
            prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
            break;
         case 'V':
            prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
            break;
         case 'R':
            prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
            break;
         case 'u':
            prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
            break;
         case 'e':
            prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
            break;
         case 'x':
            prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
            break;
         case 'f':
            prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
            break;
         case 'n':
            prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
            break;
         case 'p':
            prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
            break;
         case 'r':
            prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
            break;
         default:
            if (isalpha(*l)) {
               ast_log(LOG_WARNING,
                  "Unrecognized prilocaldialplan %s modifier: %c\n",
                  *l > 'Z' ? "NPI" : "TON", *l);
            }
            break;
         }
         l++;
      }
   }
   pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
      p->use_callingpres ? ast->connected.id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));

#if defined(HAVE_PRI_SUBADDR)
   if (ast->connected.id.subaddress.valid) {
      struct pri_party_subaddress subaddress;

      memset(&subaddress, 0, sizeof(subaddress));
      sig_pri_party_subaddress_from_ast(&subaddress, &ast->connected.id.subaddress);
      pri_sr_set_caller_subaddress(sr, &subaddress);
   }
#endif   /* defined(HAVE_PRI_SUBADDR) */

   sig_pri_redirecting_update(p, ast);

#ifdef SUPPORT_USERUSER
   /* User-user info */
   useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
   if (useruser)
      pri_sr_set_useruser(sr, useruser);
#endif

#if defined(HAVE_PRI_CCSS)
   if (ast_cc_is_recall(ast, &core_id, sig_pri_cc_type_name)) {
      struct ast_cc_monitor *monitor;
      char device_name[AST_CHANNEL_NAME];

      /* This is a CC recall call. */
      ast_channel_get_device_name(ast, device_name, sizeof(device_name));
      monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
      if (monitor) {
         struct sig_pri_cc_monitor_instance *instance;

         instance = monitor->private_data;

         /* If this fails then we have monitor instance ambiguity. */
         ast_assert(p->pri == instance->pri);

         if (pri_cc_call(p->pri->pri, instance->cc_id, p->call, sr)) {
            /* The CC recall call failed for some reason. */
            ast_log(LOG_WARNING, "Unable to setup CC recall call to device %s\n",
               device_name);
            ao2_ref(monitor, -1);
            pri_destroycall(p->pri->pri, p->call);
            p->call = NULL;
            pri_rel(p->pri);
            pri_sr_free(sr);
            return -1;
         }
         ao2_ref(monitor, -1);
      } else {
         core_id = -1;
      }
   } else
#endif   /* defined(HAVE_PRI_CCSS) */
   {
      core_id = -1;
   }
   if (core_id == -1 && pri_setup(p->pri->pri, p->call, sr)) {
      ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
         c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
      pri_destroycall(p->pri->pri, p->call);
      p->call = NULL;
      pri_rel(p->pri);
      pri_sr_free(sr);
      return -1;
   }
   p->call_level = SIG_PRI_CALL_LEVEL_SETUP;
   pri_sr_free(sr);
   ast_setstate(ast, AST_STATE_DIALING);
   sig_pri_set_dialing(p, 1);
   pri_rel(p->pri);
   return 0;
}
int sig_pri_cc_agent_callee_available ( struct ast_cc_agent agent)
void sig_pri_cc_agent_destructor ( struct ast_cc_agent agent)
int sig_pri_cc_agent_init ( struct ast_cc_agent agent,
struct sig_pri_chan pvt_chan 
)
int sig_pri_cc_agent_party_b_free ( struct ast_cc_agent agent)
void sig_pri_cc_agent_req_rsp ( struct ast_cc_agent agent,
enum ast_cc_agent_response_reason  reason 
)
int sig_pri_cc_agent_start_monitoring ( struct ast_cc_agent agent)
int sig_pri_cc_agent_start_offer_timer ( struct ast_cc_agent agent)
int sig_pri_cc_agent_status_req ( struct ast_cc_agent agent)
int sig_pri_cc_agent_stop_offer_timer ( struct ast_cc_agent agent)
int sig_pri_cc_agent_stop_ringing ( struct ast_cc_agent agent)
int sig_pri_cc_monitor_cancel_available_timer ( struct ast_cc_monitor monitor,
int *  sched_id 
)
void sig_pri_cc_monitor_destructor ( void *  monitor_pvt)
int sig_pri_cc_monitor_req_cc ( struct ast_cc_monitor monitor,
int *  available_timer_id 
)
int sig_pri_cc_monitor_status_rsp ( struct ast_cc_monitor monitor,
enum ast_device_state  devstate 
)
int sig_pri_cc_monitor_suspend ( struct ast_cc_monitor monitor)
int sig_pri_cc_monitor_unsuspend ( struct ast_cc_monitor monitor)
void sig_pri_chan_alarm_notify ( struct sig_pri_chan p,
int  noalarm 
)

Notify new alarm status.

Parameters:
pChannel private pointer.
noalarmNon-zero if not in alarm mode.
Note:
Assumes the sig_pri_lock_private(p) is already obtained.
Returns:
Nothing

Definition at line 7618 of file sig_pri.c.

References pri_grab(), sig_pri_chan::pri, sig_pri_set_alarm(), sig_pri_span::pri, sig_pri_chan::call, sig_pri_chan::owner, ast_channel::_softhangup, AST_SOFTHANGUP_DEV, sig_pri_span_devstate_changed(), and pri_rel().

Referenced by dahdi_handle_event(), and handle_init_event().

{
   pri_grab(p, p->pri);
   sig_pri_set_alarm(p, !noalarm);
   if (!noalarm) {
      if (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
         /* T309 is not enabled : destroy calls when alarm occurs */
         if (p->call) {
            pri_destroycall(p->pri->pri, p->call);
            p->call = NULL;
         }
         if (p->owner)
            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
      }
   }
   sig_pri_span_devstate_changed(p->pri);
   pri_rel(p->pri);
}
void sig_pri_chan_delete ( struct sig_pri_chan doomed)

Delete the sig_pri private channel structure.

Since:
1.8
Parameters:
doomedsig_pri private channel structure to delete.
Returns:
Nothing

Definition at line 7665 of file sig_pri.c.

References ast_free.

Referenced by destroy_dahdi_pvt().

{
   ast_free(doomed);
}
struct sig_pri_chan* sig_pri_chan_new ( void *  pvt_data,
struct sig_pri_callback callback,
struct sig_pri_span pri,
int  logicalspan,
int  channo,
int  trunkgroup 
) [read]

Definition at line 7637 of file sig_pri.c.

References ast_calloc, sig_pri_chan::logicalspan, sig_pri_chan::prioffset, sig_pri_chan::mastertrunkgroup, sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_chan::pri.

Referenced by mkintf(), and dahdi_new_pri_nobch_channel().

{
   struct sig_pri_chan *p;

   p = ast_calloc(1, sizeof(*p));
   if (!p)
      return p;

   p->logicalspan = logicalspan;
   p->prioffset = channo;
   p->mastertrunkgroup = trunkgroup;

   p->calls = callback;
   p->chan_pvt = pvt_data;

   p->pri = pri;

   return p;
}
void sig_pri_cli_show_channels ( int  fd,
struct sig_pri_span pri 
)

Definition at line 7678 of file sig_pri.c.

References ast_mutex_lock, sig_pri_span::lock, sig_pri_span::numchans, sig_pri_span::pvts, sig_pri_lock_private(), sig_pri_lock_owner(), sig_pri_chan::no_b_channel, sig_pri_is_chan_available(), sig_pri_unlock_private(), SIG_PRI_SC_LINE, sig_pri_span::span, sig_pri_chan::channel, sig_pri_call_level2str(), sig_pri_chan::call_level, sig_pri_chan::call, sig_pri_chan::owner, ast_channel::name, ast_channel_unlock, ast_mutex_unlock, and ast_cli().

Referenced by handle_pri_show_channels().

{
   char line[256];
   int idx;
   struct sig_pri_chan *pvt;

   ast_mutex_lock(&pri->lock);
   for (idx = 0; idx < pri->numchans; ++idx) {
      if (!pri->pvts[idx]) {
         continue;
      }
      pvt = pri->pvts[idx];
      sig_pri_lock_private(pvt);
      sig_pri_lock_owner(pri, idx);
      if (pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
         /* Don't show held/call-waiting channels if they are not in use. */
         sig_pri_unlock_private(pvt);
         continue;
      }

      snprintf(line, sizeof(line), SIG_PRI_SC_LINE,
         pri->span,
         pvt->channel,
         pvt->no_b_channel ? "No" : "Yes",/* Has media */
         sig_pri_is_chan_available(pvt) ? "Yes" : "No",
         sig_pri_call_level2str(pvt->call_level),
         pvt->call ? "Yes" : "No",
         pvt->owner ? pvt->owner->name : "");

      if (pvt->owner) {
         ast_channel_unlock(pvt->owner);
      }
      sig_pri_unlock_private(pvt);

      ast_mutex_unlock(&pri->lock);
      ast_cli(fd, "%s\n", line);
      ast_mutex_lock(&pri->lock);
   }
   ast_mutex_unlock(&pri->lock);
}
void sig_pri_cli_show_channels_header ( int  fd)

Definition at line 7672 of file sig_pri.c.

References ast_cli(), and SIG_PRI_SC_HEADER.

Referenced by handle_pri_show_channels().

{
   ast_cli(fd, SIG_PRI_SC_HEADER, "PRI",  "",     "B",    "Chan", "Call",  "PRI",  "Channel");
   ast_cli(fd, SIG_PRI_SC_HEADER, "Span", "Chan", "Chan", "Idle", "Level", "Call", "Name");
}
void sig_pri_cli_show_span ( int  fd,
int *  dchannels,
struct sig_pri_span pri 
)

Definition at line 7750 of file sig_pri.c.

References status, SIG_PRI_NUM_DCHANS, sig_pri_span::dchans, ast_cli(), pri_order(), build_status(), sig_pri_span::dchanavail, sig_pri_span::pri, ast_mutex_lock, sig_pri_span::lock, free, ast_mutex_unlock, sig_pri_span::overlapdial, and DAHDI_OVERLAPDIAL_INCOMING.

Referenced by handle_pri_show_span().

{
   int x;
   char status[256];

   for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
      if (pri->dchans[x]) {
#ifdef PRI_DUMP_INFO_STR
         char *info_str = NULL;
#endif
         ast_cli(fd, "%s D-channel: %d\n", pri_order(x), dchannels[x]);
         build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
         ast_cli(fd, "Status: %s\n", status);
         ast_mutex_lock(&pri->lock);
#ifdef PRI_DUMP_INFO_STR
         info_str = pri_dump_info_str(pri->pri);
         if (info_str) {
            ast_cli(fd, "%s", info_str);
            free(info_str);
         }
#else
         pri_dump_info(pri->pri);
#endif
         ast_mutex_unlock(&pri->lock);
         ast_cli(fd, "Overlap Recv: %s\n\n", (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
         ast_cli(fd, "\n");
      }
   }
}
void sig_pri_cli_show_spans ( int  fd,
int  span,
struct sig_pri_span pri 
)

Definition at line 7738 of file sig_pri.c.

References status, SIG_PRI_NUM_DCHANS, sig_pri_span::dchans, build_status(), sig_pri_span::dchanavail, sig_pri_span::pri, and ast_cli().

Referenced by handle_pri_show_spans().

{
   char status[256];
   int x;
   for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
      if (pri->dchans[x]) {
         build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
         ast_cli(fd, "PRI span %d/%d: %s\n", span, x, status);
      }
   }
}
int sig_pri_digit_begin ( struct sig_pri_chan pvt,
struct ast_channel ast,
char  digit 
)

Definition at line 7215 of file sig_pri.c.

References ast_channel::_state, AST_STATE_DIALING, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_OVERLAP, len(), sig_pri_chan::dialdest, ast_debug, ast_log(), LOG_WARNING, sig_pri_chan::pri, sig_pri_span::span, SIG_PRI_CALL_LEVEL_PROCEEDING, pri_grab(), sig_pri_span::pri, sig_pri_chan::call, pri_rel(), SIG_PRI_CALL_LEVEL_CONNECT, and sig_pri_call_level2str().

Referenced by dahdi_digit_begin().

{
   if (ast->_state == AST_STATE_DIALING) {
      if (pvt->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
         unsigned int len;

         len = strlen(pvt->dialdest);
         if (len < sizeof(pvt->dialdest) - 1) {
            ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
               digit);
            pvt->dialdest[len++] = digit;
            pvt->dialdest[len] = '\0';
         } else {
            ast_log(LOG_WARNING,
               "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
               pvt->pri->span, digit);
         }
         return 0;
      }
      if (pvt->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
         if (!pri_grab(pvt, pvt->pri)) {
            pri_information(pvt->pri->pri, pvt->call, digit);
            pri_rel(pvt->pri);
         } else {
            ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->pri->span);
         }
         return 0;
      }
      if (pvt->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
         ast_log(LOG_WARNING,
            "Span %d: Digit '%c' may be ignored by peer. (Call level:%d(%s))\n",
            pvt->pri->span, digit, pvt->call_level,
            sig_pri_call_level2str(pvt->call_level));
      }
   }
   return 1;
}
void sig_pri_extract_called_num_subaddr ( struct sig_pri_chan p,
const char *  rdest,
char *  called,
size_t  called_buff_size 
)

Extract the called number and subaddress from the dial string.

Since:
1.8
Parameters:
psig_pri channel structure.
rdestDial string buffer to extract called number and subaddress.
calledBuffer to fill with extracted <number>[:<subaddress>]
called_buff_sizeSize of buffer to fill.
Note:
Parsing must remain in sync with sig_pri_call().
Returns:
Nothing

Definition at line 6321 of file sig_pri.c.

References AST_DECLARE_APP_ARGS, args, AST_APP_ARG, ext, ast_strdupa, AST_NONSTANDARD_APP_ARGS, sig_pri_chan::stripmsd, and ast_strlen_zero().

Referenced by dahdi_request().

{
   char *dial;
   char *number;
   char *subaddr;
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(group);  /* channel/group token */
      AST_APP_ARG(ext); /* extension token */
      //AST_APP_ARG(opts); /* options token */
      AST_APP_ARG(other);  /* Any remining unused arguments */
   );

   /* Get private copy of dial string and break it up. */
   dial = ast_strdupa(rdest);
   AST_NONSTANDARD_APP_ARGS(args, dial, '/');

   number = args.ext;
   if (!number) {
      number = "";
   }

   /* Find and extract dialed_subaddress */
   subaddr = strchr(number, ':');
   if (subaddr) {
      *subaddr++ = '\0';

      /* Skip subaddress type prefix. */
      switch (*subaddr) {
      case 'U':
      case 'u':
      case 'N':
      case 'n':
         ++subaddr;
         break;
      default:
         break;
      }
   }

   /* Skip type-of-number/dial-plan prefix characters. */
   if (strlen(number) < p->stripmsd) {
      number = "";
   } else {
      number += p->stripmsd;
      while (isalpha(*number)) {
         ++number;
      }
   }

   /* Fill buffer with extracted number and subaddress. */
   if (ast_strlen_zero(subaddr)) {
      /* Put in called number only since there is no subaddress. */
      snprintf(called, called_buff_size, "%s", number);
   } else {
      /* Put in called number and subaddress. */
      snprintf(called, called_buff_size, "%s:%s", number, subaddr);
   }
}
void sig_pri_fixup ( struct ast_channel oldchan,
struct ast_channel newchan,
struct sig_pri_chan pchan 
)

Definition at line 7838 of file sig_pri.c.

References sig_pri_chan::owner.

Referenced by dahdi_fixup().

{
   if (pchan->owner == oldchan) {
      pchan->owner = newchan;
   }
}
int sig_pri_hangup ( struct sig_pri_chan p,
struct ast_channel ast 
)

Definition at line 6226 of file sig_pri.c.

References pbx_builtin_getvar_helper(), ast_log(), LOG_DEBUG, sig_pri_chan::channel, ast_channel::tech_pvt, LOG_WARNING, sig_pri_chan::outgoing, sig_pri_set_digital(), ast_atomic_fetchadd_int(), sig_pri_chan::pri, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_IDLE, sig_pri_chan::progress, sig_pri_chan::cid_num, sig_pri_chan::cid_subaddr, sig_pri_chan::cid_name, sig_pri_chan::user_tag, sig_pri_chan::exten, sig_pri_set_dialing(), pri_grab(), sig_pri_chan::call, sig_pri_chan::alreadyhungup, sig_pri_span::pri, cause, ast_channel::hangupcause, sig_pri_chan::allocated, sig_pri_chan::owner, sig_pri_span_devstate_changed(), and pri_rel().

Referenced by dahdi_hangup().

{
#ifdef SUPPORT_USERUSER
   const char *useruser = pbx_builtin_getvar_helper(ast, "USERUSERINFO");
#endif

   ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
   if (!ast->tech_pvt) {
      ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
      return 0;
   }

   p->outgoing = 0;
   sig_pri_set_digital(p, 0); /* push up to parent for EC*/
#if defined(HAVE_PRI_CALL_WAITING)
   if (p->is_call_waiting) {
      p->is_call_waiting = 0;
      ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
   }
#endif   /* defined(HAVE_PRI_CALL_WAITING) */
   p->call_level = SIG_PRI_CALL_LEVEL_IDLE;
   p->progress = 0;
   p->cid_num[0] = '\0';
   p->cid_subaddr[0] = '\0';
   p->cid_name[0] = '\0';
   p->user_tag[0] = '\0';
   p->exten[0] = '\0';
   sig_pri_set_dialing(p, 0);

   /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
   pri_grab(p, p->pri);
   if (p->call) {
      if (p->alreadyhungup) {
         ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");

#ifdef SUPPORT_USERUSER
         pri_call_set_useruser(p->call, useruser);
#endif

#if defined(HAVE_PRI_AOC_EVENTS)
         if (p->holding_aoce) {
            pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
         }
#endif   /* defined(HAVE_PRI_AOC_EVENTS) */
         pri_hangup(p->pri->pri, p->call, -1);
         p->call = NULL;
      } else {
         const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
         int icause = ast->hangupcause ? ast->hangupcause : -1;
         ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");

#ifdef SUPPORT_USERUSER
         pri_call_set_useruser(p->call, useruser);
#endif

         p->alreadyhungup = 1;
         if (cause) {
            if (atoi(cause))
               icause = atoi(cause);
         }
#if defined(HAVE_PRI_AOC_EVENTS)
         if (p->holding_aoce) {
            pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
         }
#endif   /* defined(HAVE_PRI_AOC_EVENTS) */
         pri_hangup(p->pri->pri, p->call, icause);
      }
   }
#if defined(HAVE_PRI_AOC_EVENTS)
   p->aoc_s_request_invoke_id_valid = 0;
   p->holding_aoce = 0;
   p->waiting_for_aoce = 0;
#endif   /* defined(HAVE_PRI_AOC_EVENTS) */

   p->allocated = 0;
   p->owner = NULL;

   sig_pri_span_devstate_changed(p->pri);
   pri_rel(p->pri);
   return 0;
}
int sig_pri_indicate ( struct sig_pri_chan p,
struct ast_channel chan,
int  condition,
const void *  data,
size_t  datalen 
)

Definition at line 6834 of file sig_pri.c.

References AST_CONTROL_BUSY, sig_pri_chan::priindication_oob, sig_pri_chan::no_b_channel, ast_channel::hangupcause, AST_CAUSE_USER_BUSY, ast_channel::_softhangup, AST_SOFTHANGUP_DEV, sig_pri_play_tone(), SIG_PRI_TONE_BUSY, sig_pri_chan::call_level, SIG_PRI_CALL_LEVEL_ALERTING, sig_pri_chan::outgoing, sig_pri_chan::progress, sig_pri_chan::pri, sig_pri_span::pri, pri_grab(), sig_pri_chan::call, PVT_TO_CHANNEL(), pri_rel(), ast_log(), LOG_WARNING, sig_pri_span::span, AST_CONTROL_RINGING, sig_pri_chan::digital, SIG_PRI_TONE_RINGTONE, ast_channel::_state, AST_STATE_UP, AST_STATE_RING, ast_setstate(), AST_STATE_RINGING, AST_CONTROL_PROCEEDING, ast_debug, ast_channel::name, SIG_PRI_CALL_LEVEL_PROCEEDING, sig_pri_set_dialing(), AST_CONTROL_PROGRESS, sig_pri_set_digital(), AST_CONTROL_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_SWITCH_CONGESTION, SIG_PRI_TONE_CONGESTION, AST_CONTROL_HOLD, sig_pri_chan::mohinterpret, sig_pri_chan::prioffset, ast_moh_start(), AST_CONTROL_UNHOLD, ast_moh_stop(), AST_CONTROL_SRCUPDATE, AST_CONTROL_CONNECTED_LINE, sig_pri_party_id_from_ast(), ast_channel::connected, ast_party_connected_line::id, AST_CONTROL_REDIRECTING, sig_pri_redirecting_update(), AST_CONTROL_AOC, ast_aoc_decode(), ast_aoc_get_msg_type(), AST_AOC_S, SIG_PRI_AOC_GRANT_S, AST_AOC_D, SIG_PRI_AOC_GRANT_D, AST_AOC_E, SIG_PRI_AOC_GRANT_E, LOG_DEBUG, ast_softhangup_nolock(), AST_AOC_REQUEST, ast_aoc_get_termination_request(), and ast_aoc_destroy_decoded().

Referenced by dahdi_indicate().

{
   int res = -1;

   switch (condition) {
   case AST_CONTROL_BUSY:
      if (p->priindication_oob || p->no_b_channel) {
         chan->hangupcause = AST_CAUSE_USER_BUSY;
         chan->_softhangup |= AST_SOFTHANGUP_DEV;
         res = 0;
         break;
      }
      res = sig_pri_play_tone(p, SIG_PRI_TONE_BUSY);
      if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
         chan->hangupcause = AST_CAUSE_USER_BUSY;
         p->progress = 1;/* No need to send plain PROGRESS after this. */
         if (p->pri && p->pri->pri) {
            if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
               pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
#else
               pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
               pri_rel(p->pri);
            } else {
               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
            }
         }
      }
      break;
   case AST_CONTROL_RINGING:
      if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
         p->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
         if (p->pri && p->pri->pri) {
            if (!pri_grab(p, p->pri)) {
               pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
                  p->no_b_channel || p->digital ? 0 : 1);
               pri_rel(p->pri);
            } else {
               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
            }
         }
      }
      res = sig_pri_play_tone(p, SIG_PRI_TONE_RINGTONE);
      if (chan->_state != AST_STATE_UP) {
         if (chan->_state != AST_STATE_RING)
            ast_setstate(chan, AST_STATE_RINGING);
      }
      break;
   case AST_CONTROL_PROCEEDING:
      ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
      if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
         p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
         if (p->pri && p->pri->pri) {
            if (!pri_grab(p, p->pri)) {
               pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
                  p->no_b_channel || p->digital ? 0 : 1);
               if (!p->no_b_channel && !p->digital) {
                  sig_pri_set_dialing(p, 0);
               }
               pri_rel(p->pri);
            } else {
               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
            }
         }
      }
      /* don't continue in ast_indicate */
      res = 0;
      break;
   case AST_CONTROL_PROGRESS:
      ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
      sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */
      if (!p->progress && p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing
         && !p->no_b_channel) {
         p->progress = 1;/* No need to send plain PROGRESS again. */
         if (p->pri && p->pri->pri) {
            if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
               pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
#else
               pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
               pri_rel(p->pri);
            } else {
               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
            }
         }
      }
      /* don't continue in ast_indicate */
      res = 0;
      break;
   case AST_CONTROL_CONGESTION:
      if (p->priindication_oob || p->no_b_channel) {
         /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
         switch (chan->hangupcause) {
         case AST_CAUSE_USER_BUSY:
         case AST_CAUSE_NORMAL_CLEARING:
         case 0:/* Cause has not been set. */
            /* Supply a more appropriate cause. */
            chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
            break;
         default:
            break;
         }
         chan->_softhangup |= AST_SOFTHANGUP_DEV;
         res = 0;
         break;
      }
      res = sig_pri_play_tone(p, SIG_PRI_TONE_CONGESTION);
      if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
         /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
         switch (chan->hangupcause) {
         case AST_CAUSE_USER_BUSY:
         case AST_CAUSE_NORMAL_CLEARING:
         case 0:/* Cause has not been set. */
            /* Supply a more appropriate cause. */
            chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
            break;
         default:
            break;
         }
         p->progress = 1;/* No need to send plain PROGRESS after this. */
         if (p->pri && p->pri->pri) {
            if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
               pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
#else
               pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
               pri_rel(p->pri);
            } else {
               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
            }
         }
      }
      break;
   case AST_CONTROL_HOLD:
      if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
         if (!pri_grab(p, p->pri)) {
            res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
            pri_rel(p->pri);
         } else {
            ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->pri->span);
         }
      } else
         ast_moh_start(chan, data, p->mohinterpret);
      break;
   case AST_CONTROL_UNHOLD:
      if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
         if (!pri_grab(p, p->pri)) {
            res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
            pri_rel(p->pri);
         }
      } else
         ast_moh_stop(chan);
      break;
   case AST_CONTROL_SRCUPDATE:
      res = 0;
      break;
   case -1:
      res = sig_pri_play_tone(p, -1);
      break;
   case AST_CONTROL_CONNECTED_LINE:
      ast_debug(1, "Received AST_CONTROL_CONNECTED_LINE on %s\n", chan->name);
      if (p->pri && !pri_grab(p, p->pri)) {
         struct pri_party_connected_line connected;

         memset(&connected, 0, sizeof(connected));
         sig_pri_party_id_from_ast(&connected.id, &chan->connected.id);

         pri_connected_line_update(p->pri->pri, p->call, &connected);
         pri_rel(p->pri);
      }
      break;
   case AST_CONTROL_REDIRECTING:
      ast_debug(1, "Received AST_CONTROL_REDIRECTING on %s\n", chan->name);
      if (p->pri && !pri_grab(p, p->pri)) {
         sig_pri_redirecting_update(p, chan);
         pri_rel(p->pri);
      }
      break;
   case AST_CONTROL_AOC:
#if defined(HAVE_PRI_AOC_EVENTS)
      {
         struct ast_aoc_decoded *decoded
            = ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, chan);
         ast_debug(1, "Received AST_CONTROL_AOC on %s\n", chan->name);
         if (decoded && p->pri && !pri_grab(p, p->pri)) {
            switch (ast_aoc_get_msg_type(decoded)) {
            case AST_AOC_S:
               if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
                  sig_pri_aoc_s_from_ast(p, decoded);
               }
               break;
            case AST_AOC_D:
               if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
                  sig_pri_aoc_d_from_ast(p, decoded);
               }
               break;
            case AST_AOC_E:
               if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
                  sig_pri_aoc_e_from_ast(p, decoded);
               }
               /* if hangup was delayed for this AOC-E msg, waiting_for_aoc
                * will be set.  A hangup is already occuring via a timeout during
                * this delay.  Instead of waiting for that timeout to occur, go ahead
                * and initiate the softhangup since the delay is no longer necessary */
               if (p->waiting_for_aoce) {
                  p->waiting_for_aoce = 0;
                  ast_log(LOG_DEBUG,
                     "Received final AOC-E msg, continue with hangup on %s\n",
                     chan->name);
                  ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
               }
               break;
            case AST_AOC_REQUEST:
               /* We do not pass through AOC requests, So unless this
                * is an AOC termination request it will be ignored */
               if (ast_aoc_get_termination_request(decoded)) {
                  pri_hangup(p->pri->pri, p->call, -1);
               }
               break;
            default:
               break;
            }
            pri_rel(p->pri);
         }
         ast_aoc_destroy_decoded(decoded);
      }
#endif   /* defined(HAVE_PRI_AOC_EVENTS) */
      break;
   }

   return res;
}
void sig_pri_init_pri ( struct sig_pri_span pri)

Definition at line 6213 of file sig_pri.c.

References ast_mutex_init, sig_pri_span::lock, sig_pri_span::master, AST_PTHREADT_NULL, SIG_PRI_NUM_DCHANS, and sig_pri_span::fds.

Referenced by dahdi_restart(), and load_module().

{
   int i;

   memset(pri, 0, sizeof(*pri));

   ast_mutex_init(&pri->lock);

   pri->master = AST_PTHREADT_NULL;
   for (i = 0; i < SIG_PRI_NUM_DCHANS; i++)
      pri->fds[i] = -1;
}
int sig_pri_is_chan_available ( struct sig_pri_chan pvt)

Determine if a private channel structure is available.

Since:
1.8
Parameters:
pvtChannel to determine if available.
Returns:
TRUE if the channel is available.

Definition at line 1090 of file sig_pri.c.

References sig_pri_is_chan_in_use().

Referenced by dahdi_pri_update_span_devstate(), pri_fixup_principle(), pri_find_empty_chan(), pri_dchannel(), sig_pri_available_check(), and sig_pri_cli_show_channels().

{
   return !sig_pri_is_chan_in_use(pvt)
#if defined(HAVE_PRI_SERVICE_MESSAGES)
      /* And not out-of-service */
      && !pvt->service_status
#endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
      ;
}
int sig_pri_load ( const char *  cc_type_name)

Load the sig_pri submodule.

Since:
1.8
Parameters:
cc_type_nameCC type name to use when looking up agent/monitor.
Return values:
0on success.
-1on error.

Definition at line 8450 of file sig_pri.c.

References ao2_container_alloc.

Referenced by load_module().

{
#if defined(HAVE_PRI_CCSS)
   sig_pri_cc_type_name = cc_type_name;
   sig_pri_cc_monitors = ao2_container_alloc(37, sig_pri_cc_monitor_instance_hash_fn,
      sig_pri_cc_monitor_instance_cmp_fn);
   if (!sig_pri_cc_monitors) {
      return -1;
   }
#endif   /* defined(HAVE_PRI_CCSS) */
   return 0;
}
struct ast_channel* sig_pri_request ( struct sig_pri_chan p,
enum sig_pri_law  law,
const struct ast_channel requestor,
int  transfercapability 
) [read]

Definition at line 981 of file sig_pri.c.

References ast_log(), LOG_DEBUG, sig_pri_chan::channel, sig_pri_chan::outgoing, sig_pri_new_ast_channel(), AST_STATE_RESERVED, and sig_pri_chan::exten.

Referenced by dahdi_request(), and pri_dchannel().

{
   struct ast_channel *ast;

   ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);

   p->outgoing = 1;
   ast = sig_pri_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
   if (!ast) {
      p->outgoing = 0;
   }
   return ast;
}
void sig_pri_set_alarm ( struct sig_pri_chan p,
int  in_alarm 
)

Definition at line 181 of file sig_pri.c.

References sig_pri_chan::resetting, sig_pri_chan::inalarm, sig_pri_chan::calls, sig_pri_callback::set_alarm, and sig_pri_chan::chan_pvt.

Referenced by mkintf(), pri_dchannel(), and sig_pri_chan_alarm_notify().

{
   /*
    * Clear the channel restart flag when the channel alarm changes
    * to prevent the flag from getting stuck when the link goes
    * down.
    */
   p->resetting = 0;

   p->inalarm = in_alarm;
   if (p->calls->set_alarm) {
      p->calls->set_alarm(p->chan_pvt, in_alarm);
   }
}
int sig_pri_start_pri ( struct sig_pri_span pri)

Definition at line 7427 of file sig_pri.c.

References ast_str_alloca, ARRAY_LEN, ast_event_unsubscribe(), ast_mutex_init, sig_pri_span::lock, sig_pri_sort_pri_chans(), strsep(), ast_strip(), ast_strlen_zero(), ast_str_set(), sig_pri_span::span, ast_event_subscribe(), AST_EVENT_MWI, ast_str_buffer(), AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, ast_log(), LOG_ERROR, SIG_PRI_NUM_DCHANS, sig_pri_span::fds, sig_pri_span::sig, SIG_BRI, sig_pri_span::dchans, sig_pri_span::nodetype, sig_pri_span::switchtype, SIG_BRI_PTMP, sig_pri_span::overlapdial, DAHDI_OVERLAPDIAL_OUTGOING, sig_pri_span::qsigchannelmapping, DAHDI_CHAN_MAPPING_LOGICAL, SIG_PRI_DEBUG_DEFAULT, sig_pri_span::nsf, sig_pri_span::pritimers, sig_pri_span::pri, sig_pri_span::resetpos, ast_pthread_create_background, sig_pri_span::master, pri_dchannel(), and errno.

Referenced by setup_dahdi_int().

{
   int x;
   int i;
#if defined(HAVE_PRI_MWI)
   char *saveptr;
   char *mbox_number;
   char *mbox_context;
   struct ast_str *mwi_description = ast_str_alloca(64);
#endif   /* defined(HAVE_PRI_MWI) */

#if defined(HAVE_PRI_MWI)
   /* Prepare the mbox[] for use. */
   for (i = 0; i < ARRAY_LEN(pri->mbox); ++i) {
      if (pri->mbox[i].sub) {
         pri->mbox[i].sub = ast_event_unsubscribe(pri->mbox[i].sub);
      }
   }
#endif   /* defined(HAVE_PRI_MWI) */

   ast_mutex_init(&pri->lock);
   sig_pri_sort_pri_chans(pri);

#if defined(HAVE_PRI_MWI)
   /*
    * Split the mwi_mailboxes configuration string into the mbox[]:
    * mailbox_number[@context]{,mailbox_number[@context]}
    */
   i = 0;
   saveptr = pri->mwi_mailboxes;
   while (i < ARRAY_LEN(pri->mbox)) {
      mbox_number = strsep(&saveptr, ",");
      if (!mbox_number) {
         break;
      }
      /* Split the mailbox_number and context */
      mbox_context = strchr(mbox_number, '@');
      if (mbox_context) {
         *mbox_context++ = '\0';
         mbox_context = ast_strip(mbox_context);
      }
      mbox_number = ast_strip(mbox_number);
      if (ast_strlen_zero(mbox_number)) {
         /* There is no mailbox number.  Skip it. */
         continue;
      }
      if (ast_strlen_zero(mbox_context)) {
         /* There was no context so use the default. */
         mbox_context = "default";
      }

      /* Fill the mbox[] element. */
      ast_str_set(&mwi_description, -1, "%s span %d[%d] MWI mailbox %s@%s",
         sig_pri_cc_type_name, pri->span, i, mbox_number, mbox_context);
      pri->mbox[i].sub = ast_event_subscribe(AST_EVENT_MWI, sig_pri_mwi_event_cb,
         ast_str_buffer(mwi_description), pri,
         AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox_number,
         AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mbox_context,
         AST_EVENT_IE_END);
      if (!pri->mbox[i].sub) {
         ast_log(LOG_ERROR, "%s span %d could not subscribe to MWI events for %s@%s.",
            sig_pri_cc_type_name, pri->span, mbox_number, mbox_context);
         continue;
      }
      pri->mbox[i].number = mbox_number;
      pri->mbox[i].context = mbox_context;
      ++i;
   }
#endif   /* defined(HAVE_PRI_MWI) */

   for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
      if (pri->fds[i] == -1) {
         break;
      }

      switch (pri->sig) {
      case SIG_BRI:
         pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
         break;
      case SIG_BRI_PTMP:
         pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
         break;
      default:
         pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
#if defined(HAVE_PRI_SERVICE_MESSAGES)
         if (pri->enable_service_message_support) {
            pri_set_service_message_support(pri->dchans[i], 1);
         }
#endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
         break;
      }

      pri_set_overlapdial(pri->dchans[i], (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING) ? 1 : 0);
#ifdef HAVE_PRI_PROG_W_CAUSE
      pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
#endif
#ifdef HAVE_PRI_INBANDDISCONNECT
      pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
#endif
      /* Enslave to master if appropriate */
      if (i)
         pri_enslave(pri->dchans[0], pri->dchans[i]);
      if (!pri->dchans[i]) {
         if (pri->fds[i] > 0)
            close(pri->fds[i]);
         pri->fds[i] = -1;
         ast_log(LOG_ERROR, "Unable to create PRI structure\n");
         return -1;
      }
      pri_set_debug(pri->dchans[i], SIG_PRI_DEBUG_DEFAULT);
      pri_set_nsf(pri->dchans[i], pri->nsf);
#ifdef PRI_GETSET_TIMERS
      for (x = 0; x < PRI_MAX_TIMERS; x++) {
         if (pri->pritimers[x] != 0)
            pri_set_timer(pri->dchans[i], x, pri->pritimers[x]);
      }
#endif
   }

   /* Assume primary is the one we use */
   pri->pri = pri->dchans[0];

#if defined(HAVE_PRI_CALL_HOLD)
   pri_hold_enable(pri->pri, 1);
#endif   /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_REROUTING)
   pri_reroute_enable(pri->pri, 1);
#endif   /* defined(HAVE_PRI_CALL_REROUTING) */
#if defined(HAVE_PRI_HANGUP_FIX)
   pri_hangup_fix_enable(pri->pri, 1);
#endif   /* defined(HAVE_PRI_HANGUP_FIX) */
#if defined(HAVE_PRI_CCSS)
   pri_cc_enable(pri->pri, 1);
   pri_cc_recall_mode(pri->pri, pri->cc_ptmp_recall_mode);
   pri_cc_retain_signaling_req(pri->pri, pri->cc_qsig_signaling_link_req);
   pri_cc_retain_signaling_rsp(pri->pri, pri->cc_qsig_signaling_link_rsp);
#endif   /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_TRANSFER)
   pri_transfer_enable(pri->pri, 1);
#endif   /* defined(HAVE_PRI_TRANSFER) */
#if defined(HAVE_PRI_AOC_EVENTS)
   pri_aoc_events_enable(pri->pri, 1);
#endif   /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_CALL_WAITING)
   pri_connect_ack_enable(pri->pri, 1);
#endif   /* defined(HAVE_PRI_CALL_WAITING) */
#if defined(HAVE_PRI_MCID)
   pri_mcid_enable(pri->pri, 1);
#endif   /* defined(HAVE_PRI_MCID) */
#if defined(HAVE_PRI_L2_PERSISTENCE)
   pri_persistent_layer2_option(pri->pri, pri->l2_persistence);
#endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */

   pri->resetpos = -1;
   if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
      for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
         if (!pri->dchans[i])
            break;
         if (pri->fds[i] > 0)
            close(pri->fds[i]);
         pri->fds[i] = -1;
      }
      ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
      return -1;
   }

#if defined(HAVE_PRI_MWI)
   /*
    * Send the initial MWI indications from the event cache for this span.
    *
    * If we were loaded after app_voicemail the event would already be in
    * the cache.  If we were loaded before app_voicemail the event would not
    * be in the cache yet and app_voicemail will send the event when it
    * gets loaded.
    */
   sig_pri_mwi_cache_update(pri);
#endif   /* defined(HAVE_PRI_MWI) */

   return 0;
}
void sig_pri_stop_pri ( struct sig_pri_span pri)

Stop PRI span.

Since:
1.8
Parameters:
priPRI span control structure.
Returns:
Nothing

Definition at line 7362 of file sig_pri.c.

References ARRAY_LEN, and ast_event_unsubscribe().

Referenced by __unload_module().

{
#if defined(HAVE_PRI_MWI)
   int idx;
#endif   /* defined(HAVE_PRI_MWI) */

#if defined(HAVE_PRI_MWI)
   for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
      if (pri->mbox[idx].sub) {
         pri->mbox[idx].sub = ast_event_unsubscribe(pri->mbox[idx].sub);
      }
   }
#endif   /* defined(HAVE_PRI_MWI) */
}
void sig_pri_unload ( void  )

Unload the sig_pri submodule.

Since:
1.8
Returns:
Nothing

Definition at line 8469 of file sig_pri.c.

References ao2_ref.

Referenced by __unload_module().

{
#if defined(HAVE_PRI_CCSS)
   if (sig_pri_cc_monitors) {
      ao2_ref(sig_pri_cc_monitors, -1);
      sig_pri_cc_monitors = NULL;
   }
#endif   /* defined(HAVE_PRI_CCSS) */
}