Mon Oct 8 12:39:29 2012

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>

Go to the source code of this file.

Data Structures

struct  sig_pri_callback
struct  sig_pri_chan
struct  sig_pri_mbox
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
#define SIG_PRI_MAX_CHANNELS   672
#define SIG_PRI_MAX_MWI_CONTEXT_LEN   10
#define SIG_PRI_MAX_MWI_MAILBOX_STR
 Maximum mwi_mailbox string length.
#define SIG_PRI_MAX_MWI_MAILBOXES   8
#define SIG_PRI_MAX_MWI_MBOX_NUMBER_LEN   10
#define SIG_PRI_NUM_DCHANS   4
#define SRVST_BOTH   (SRVST_NEAREND | SRVST_FAREND)
 SRVST_BOTH is used to indicate that both sides of the channel are out-of-service.
#define SRVST_DBKEY   "service-state"
 Persistent Service State.
#define SRVST_FAREND   (1 << 1)
 SRVST_FAREND is used to indicate that the far end was taken out-of-service.
#define SRVST_INITIALIZED   0
 SRVST_INITIALIZED is used to indicate a channel being out-of-service The SRVST_INITIALIZED is mostly used maintain backwards compatibility but also may mean that the channel has not yet received a RESTART message. If a channel is out-of-service with this reason a RESTART message will result in the channel being put into service.
#define SRVST_NEAREND   (1 << 0)
 SRVST_NEAREND is used to indicate that the near end was put out-of-service.
#define SRVST_TYPE_OOS   "O"
 The out-of-service SERVICE state.

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_DEFER_DIAL, SIG_PRI_CALL_LEVEL_CONNECT
}
enum  sig_pri_law { SIG_PRI_DEFLAW = 0, SIG_PRI_ULAW, SIG_PRI_ALAW }
enum  sig_pri_reset_state { SIG_PRI_RESET_IDLE, SIG_PRI_RESET_ACTIVE, SIG_PRI_RESET_NO_ACK }
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_maintenance_bservice (struct pri *pri, struct sig_pri_chan *p, int changestatus)
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)
 Alert the caller that it is time to try recalling.
void sig_pri_cc_agent_destructor (struct ast_cc_agent *agent)
 Destroy private data on the agent.
int sig_pri_cc_agent_init (struct ast_cc_agent *agent, struct sig_pri_chan *pvt_chan)
 PRI CC agent initialization.
int sig_pri_cc_agent_party_b_free (struct ast_cc_agent *agent)
 Let the caller know that the callee has become free but that the caller cannot attempt to call back because he is either busy or there is congestion on his line.
void sig_pri_cc_agent_req_rsp (struct ast_cc_agent *agent, enum ast_cc_agent_response_reason reason)
 Response to a CC request.
int sig_pri_cc_agent_start_monitoring (struct ast_cc_agent *agent)
 Begin monitoring a busy device.
int sig_pri_cc_agent_start_offer_timer (struct ast_cc_agent *agent)
 Start the offer timer.
int sig_pri_cc_agent_status_req (struct ast_cc_agent *agent)
 Request the status of the agent's device.
int sig_pri_cc_agent_stop_offer_timer (struct ast_cc_agent *agent)
 Stop the offer timer.
int sig_pri_cc_agent_stop_ringing (struct ast_cc_agent *agent)
 Request for an agent's phone to stop ringing.
int sig_pri_cc_monitor_cancel_available_timer (struct ast_cc_monitor *monitor, int *sched_id)
 Cancel the running available timer.
void sig_pri_cc_monitor_destructor (void *monitor_pvt)
 Destroy PRI private data on the monitor.
int sig_pri_cc_monitor_req_cc (struct ast_cc_monitor *monitor, int *available_timer_id)
 Request CCSS.
int sig_pri_cc_monitor_status_rsp (struct ast_cc_monitor *monitor, enum ast_device_state devstate)
 Status response to an ast_cc_monitor_status_request().
int sig_pri_cc_monitor_suspend (struct ast_cc_monitor *monitor)
 Suspend monitoring.
int sig_pri_cc_monitor_unsuspend (struct ast_cc_monitor *monitor)
 Unsuspend monitoring.
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.
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)
void sig_pri_dial_complete (struct sig_pri_chan *pvt, struct ast_channel *ast)
 DTMF dial string complete.
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_alarm_ignored (struct sig_pri_span *pri)
 Determine if layer 1 alarms are ignored.
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.
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.

Variables

static const char dahdi_db [] = "dahdi/registry"
 The AstDB family.


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 192 of file sig_pri.h.

#define DAHDI_CHAN_MAPPING_PHYSICAL   0

Definition at line 191 of file sig_pri.h.

Referenced by dahdi_chan_conf_default().

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

Definition at line 198 of file sig_pri.h.

#define DAHDI_OVERLAPDIAL_INCOMING   2

Definition at line 197 of file sig_pri.h.

Referenced by dahdi_handle_event(), dahdi_read(), pri_ss_thread(), sig_pri_cli_show_span(), and sig_pri_indicate().

#define DAHDI_OVERLAPDIAL_NONE   0

Definition at line 195 of file sig_pri.h.

#define DAHDI_OVERLAPDIAL_OUTGOING   1

Definition at line 196 of file sig_pri.h.

Referenced by dahdi_read().

#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)

Definition at line 187 of file sig_pri.h.

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 188 of file sig_pri.h.

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 186 of file sig_pri.h.

#define SIG_PRI_AOC_GRANT_D   (1 << 1)

Definition at line 67 of file sig_pri.h.

Referenced by sig_pri_aoc_request_from_pri(), 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 sig_pri_aoc_request_from_pri(), 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 sig_pri_aoc_request_from_pri(), 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.

#define SIG_PRI_DEBUG_INTENSE

Value:

(PRI_DEBUG_APDU | PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q921_STATE \
   | PRI_DEBUG_CC | 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 42 of file sig_pri.h.

Referenced by handle_pri_debug().

#define SIG_PRI_DEBUG_NORMAL

Value:

(PRI_DEBUG_APDU | PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q921_STATE \
   | PRI_DEBUG_CC)
PRI debug message flags when normal PRI debugging is turned on at the command line.

Definition at line 37 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 184 of file sig_pri.h.

#define SIG_PRI_MAX_MWI_CONTEXT_LEN   10

Typical maximum length of mwi mailbox context

Definition at line 327 of file sig_pri.h.

#define SIG_PRI_MAX_MWI_MAILBOX_STR

Value:

Maximum mwi_mailbox string length.

max_length = mailboxes * (mbox_number + '@' + context + ',') The last ',' is a null terminator instead.

Definition at line 334 of file sig_pri.h.

#define SIG_PRI_MAX_MWI_MAILBOXES   8

Maximum number of mailboxes per span.

Definition at line 323 of file sig_pri.h.

#define SIG_PRI_MAX_MWI_MBOX_NUMBER_LEN   10

Typical maximum length of mwi mailbox number

Definition at line 325 of file sig_pri.h.

#define SIG_PRI_NUM_DCHANS   4

No more than 4 d-channels

Definition at line 183 of file sig_pri.h.

Referenced by pri_active_dchan_index(), pri_find_dchan(), pri_is_up(), sig_pri_init_pri(), and sig_pri_start_pri().

#define SRVST_BOTH   (SRVST_NEAREND | SRVST_FAREND)

SRVST_BOTH is used to indicate that both sides of the channel are out-of-service.

Definition at line 216 of file sig_pri.h.

#define SRVST_DBKEY   "service-state"

Persistent Service State.

Definition at line 202 of file sig_pri.h.

Referenced by destroy_all_channels().

#define SRVST_FAREND   (1 << 1)

SRVST_FAREND is used to indicate that the far end was taken out-of-service.

Definition at line 214 of file sig_pri.h.

Referenced by pri_check_restart().

#define SRVST_INITIALIZED   0

SRVST_INITIALIZED is used to indicate a channel being out-of-service The SRVST_INITIALIZED is mostly used maintain backwards compatibility but also may mean that the channel has not yet received a RESTART message. If a channel is out-of-service with this reason a RESTART message will result in the channel being put into service.

Definition at line 210 of file sig_pri.h.

#define SRVST_NEAREND   (1 << 0)

SRVST_NEAREND is used to indicate that the near end was put out-of-service.

Definition at line 212 of file sig_pri.h.

Referenced by pri_check_restart().

#define SRVST_TYPE_OOS   "O"

The out-of-service SERVICE state.

Definition at line 204 of file sig_pri.h.


Enumeration Type Documentation

enum sig_pri_call_level

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_DEFER_DIAL  Call is dialing 'w' deferred digits. (CONNECT)
SIG_PRI_CALL_LEVEL_CONNECT  Call is connected/answered. (CONNECT)

Definition at line 87 of file sig_pri.h.

00087                         {
00088    /*! Call does not exist. */
00089    SIG_PRI_CALL_LEVEL_IDLE,
00090    /*! Call is present but has no response yet. (SETUP) */
00091    SIG_PRI_CALL_LEVEL_SETUP,
00092    /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */
00093    SIG_PRI_CALL_LEVEL_OVERLAP,
00094    /*! Call routing is happening. (PROCEEDING) */
00095    SIG_PRI_CALL_LEVEL_PROCEEDING,
00096    /*! Called party is being alerted of the call. (ALERTING) */
00097    SIG_PRI_CALL_LEVEL_ALERTING,
00098    /*! Call is dialing 'w' deferred digits. (CONNECT) */
00099    SIG_PRI_CALL_LEVEL_DEFER_DIAL,
00100    /*! Call is connected/answered. (CONNECT) */
00101    SIG_PRI_CALL_LEVEL_CONNECT,
00102 };

enum sig_pri_law

Enumerator:
SIG_PRI_DEFLAW 
SIG_PRI_ULAW 
SIG_PRI_ALAW 

Definition at line 80 of file sig_pri.h.

00080                  {
00081    SIG_PRI_DEFLAW = 0,
00082    SIG_PRI_ULAW,
00083    SIG_PRI_ALAW
00084 };

enum sig_pri_reset_state

Enumerator:
SIG_PRI_RESET_IDLE  The channel is not being RESTARTed.
SIG_PRI_RESET_ACTIVE  The channel is being RESTARTed.

Note:
Waiting for a RESTART ACKNOWLEDGE from the peer.
SIG_PRI_RESET_NO_ACK  Peer may not be sending the expected RESTART ACKNOWLEDGE.

We have already received a SETUP on this channel. If another SETUP comes in on this channel then the peer considers this channel useable. Assume that the peer is never going to give us a RESTART ACKNOWLEDGE and assume that we have received one. This is not according to Q.931, but some peers occasionally fail to send a RESTART ACKNOWLEDGE.

Definition at line 104 of file sig_pri.h.

00104                          {
00105    /*! \brief The channel is not being RESTARTed. */
00106    SIG_PRI_RESET_IDLE,
00107    /*!
00108     * \brief The channel is being RESTARTed.
00109     * \note Waiting for a RESTART ACKNOWLEDGE from the peer.
00110     */
00111    SIG_PRI_RESET_ACTIVE,
00112    /*!
00113     * \brief Peer may not be sending the expected RESTART ACKNOWLEDGE.
00114     *
00115     * \details We have already received a SETUP on this channel.
00116     * If another SETUP comes in on this channel then the peer
00117     * considers this channel useable.  Assume that the peer is
00118     * never going to give us a RESTART ACKNOWLEDGE and assume that
00119     * we have received one.  This is not according to Q.931, but
00120     * some peers occasionally fail to send a RESTART ACKNOWLEDGE.
00121     */
00122    SIG_PRI_RESET_NO_ACK,
00123 };

enum sig_pri_tone

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 2001 of file sig_pri.c.

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

Referenced by my_handle_dchan_exception(), and prepare_pri().

02002 {
02003    pri->dchanavail[index] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
02004    if (!before_start_pri) {
02005       pri_find_dchan(pri);
02006    }
02007 }

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

Definition at line 2009 of file sig_pri.c.

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

Referenced by my_handle_dchan_exception(), and prepare_pri().

02010 {
02011    pri->dchanavail[index] |= DCHAN_NOTINALARM;
02012    if (!before_start_pri)
02013       pri_restart(pri->dchans[index]);
02014 }

int pri_is_up ( struct sig_pri_span pri  ) 

Definition at line 1026 of file sig_pri.c.

References DCHAN_AVAILABLE, sig_pri_span::dchanavail, and SIG_PRI_NUM_DCHANS.

Referenced by pri_dchannel().

01027 {
01028    int x;
01029    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
01030       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
01031          return 1;
01032    }
01033    return 0;
01034 }

int pri_maintenance_bservice ( struct pri *  pri,
struct sig_pri_chan p,
int  changestatus 
)

Definition at line 8031 of file sig_pri.c.

References sig_pri_chan::channel, PRI_SPAN, and PVT_TO_CHANNEL().

08032 {
08033    int channel = PVT_TO_CHANNEL(p);
08034    int span = PRI_SPAN(channel);
08035 
08036    return pri_maintenance_service(pri, span, channel, changestatus);
08037 }

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 8009 of file sig_pri.c.

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

Referenced by dahdi_send_callrerouting_facility_exec().

08010 {
08011    int res;
08012 
08013    sig_pri_lock_private(p);
08014 
08015    if (!p->pri || !p->call) {
08016       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
08017       sig_pri_unlock_private(p);
08018       return -1;
08019    }
08020 
08021    pri_grab(p, p->pri);
08022    res = pri_callrerouting_facility(p->pri->pri, p->call, destination, original, reason);
08023    pri_rel(p->pri);
08024 
08025    sig_pri_unlock_private(p);
08026 
08027    return res;
08028 }

int pri_send_keypad_facility_exec ( struct sig_pri_chan p,
const char *  digits 
)

Definition at line 7990 of file sig_pri.c.

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

Referenced by dahdi_send_keypad_facility_exec().

07991 {
07992    sig_pri_lock_private(p);
07993 
07994    if (!p->pri || !p->call) {
07995       ast_debug(1, "Unable to find pri or call on channel!\n");
07996       sig_pri_unlock_private(p);
07997       return -1;
07998    }
07999 
08000    pri_grab(p, p->pri);
08001    pri_keypad_facility(p->pri->pri, p->call, digits);
08002    pri_rel(p->pri);
08003 
08004    sig_pri_unlock_private(p);
08005 
08006    return 0;
08007 }

int sig_pri_answer ( struct sig_pri_chan p,
struct ast_channel ast 
)

Definition at line 7239 of file sig_pri.c.

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

Referenced by dahdi_answer().

07240 {
07241    int res;
07242 
07243    /* Send a pri acknowledge */
07244    pri_grab(p, p->pri);
07245 #if defined(HAVE_PRI_AOC_EVENTS)
07246    if (p->aoc_s_request_invoke_id_valid) {
07247       /* if AOC-S was requested and the invoke id is still present on answer.  That means
07248        * no AOC-S rate list was provided, so send a NULL response which will indicate that
07249        * AOC-S is not available */
07250       pri_aoc_s_request_response_send(p->pri->pri, p->call,
07251          p->aoc_s_request_invoke_id, NULL);
07252       p->aoc_s_request_invoke_id_valid = 0;
07253    }
07254 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
07255    if (p->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
07256       p->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
07257    }
07258    sig_pri_set_dialing(p, 0);
07259    sig_pri_open_media(p);
07260    res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
07261    pri_rel(p->pri);
07262    ast_setstate(ast, AST_STATE_UP);
07263    return res;
07264 }

int sig_pri_available ( struct sig_pri_chan **  pvt,
int  is_specific_channel 
)

Definition at line 7334 of file sig_pri.c.

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

Referenced by available().

07335 {
07336    struct sig_pri_chan *p = *pvt;
07337    struct sig_pri_span *pri;
07338 
07339    if (!p->pri) {
07340       /* Something is wrong here.  A PRI channel without the pri pointer? */
07341       return 0;
07342    }
07343    pri = p->pri;
07344 
07345    ast_mutex_lock(&pri->lock);
07346    if (
07347 #if defined(HAVE_PRI_CALL_WAITING)
07348       /*
07349        * Only do call waiting calls if we have any
07350        * call waiting call outstanding.  We do not
07351        * want new calls to steal a B channel
07352        * freed for an earlier call waiting call.
07353        */
07354       !pri->num_call_waiting_calls &&
07355 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
07356       sig_pri_available_check(p)) {
07357       p->allocated = 1;
07358       ast_mutex_unlock(&pri->lock);
07359       return 1;
07360    }
07361 
07362 #if defined(HAVE_PRI_CALL_WAITING)
07363    if (!is_specific_channel) {
07364       struct sig_pri_chan *cw;
07365 
07366       cw = sig_pri_cw_available(pri);
07367       if (cw) {
07368          /* We have a call waiting interface to use instead. */
07369          cw->allocated = 1;
07370          *pvt = cw;
07371          ast_mutex_unlock(&pri->lock);
07372          return 1;
07373       }
07374    }
07375 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
07376    ast_mutex_unlock(&pri->lock);
07377    return 0;
07378 }

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 6564 of file sig_pri.c.

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

Referenced by dahdi_call().

06565 {
06566    char dest[256]; /* must be same length as p->dialdest */
06567    struct ast_party_subaddress dialed_subaddress; /* Called subaddress */
06568    struct pri_sr *sr;
06569    char *c, *l, *n, *s;
06570 #ifdef SUPPORT_USERUSER
06571    const char *useruser;
06572 #endif
06573    int core_id;
06574    int pridialplan;
06575    int dp_strip;
06576    int prilocaldialplan;
06577    int ldp_strip;
06578    int exclusive;
06579 #if defined(HAVE_PRI_SETUP_KEYPAD)
06580    const char *keypad;
06581 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06582    AST_DECLARE_APP_ARGS(args,
06583       AST_APP_ARG(group);  /* channel/group token */
06584       AST_APP_ARG(ext); /* extension token */
06585       AST_APP_ARG(opts);   /* options token */
06586       AST_APP_ARG(other);  /* Any remining unused arguments */
06587    );
06588    struct ast_flags opts;
06589    char *opt_args[OPT_ARG_ARRAY_SIZE];
06590 
06591    ast_log(LOG_DEBUG, "CALLER NAME: %s NUM: %s\n",
06592       S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
06593       S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));
06594 
06595    if (!p->pri) {
06596       ast_log(LOG_ERROR, "Could not find pri on channel %d\n", p->channel);
06597       return -1;
06598    }
06599 
06600    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
06601       ast_log(LOG_WARNING, "sig_pri_call called on %s, neither down nor reserved\n", ast->name);
06602       return -1;
06603    }
06604 
06605    p->dialdest[0] = '\0';
06606    sig_pri_set_outgoing(p, 1);
06607 
06608    ast_copy_string(dest, rdest, sizeof(dest));
06609    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
06610    if (ast_app_parse_options(sig_pri_call_opts, &opts, opt_args, args.opts)) {
06611       /* General invalid option syntax. */
06612       return -1;
06613    }
06614 
06615    c = args.ext;
06616    if (!c) {
06617       c = "";
06618    }
06619 
06620    /* setup dialed_subaddress if found */
06621    ast_party_subaddress_init(&dialed_subaddress);
06622    s = strchr(c, ':');
06623    if (s) {
06624       *s = '\0';
06625       s++;
06626       /* prefix */
06627       /* 'n' = NSAP */
06628       /* 'u' = User Specified */
06629       /* Default = NSAP */
06630       switch (*s) {
06631       case 'U':
06632       case 'u':
06633          s++;
06634          dialed_subaddress.type = 2;
06635          break;
06636       case 'N':
06637       case 'n':
06638          s++;
06639          /* default already covered with ast_party_subaddress_init */
06640          break;
06641       }
06642       dialed_subaddress.str = s;
06643       dialed_subaddress.valid = 1;
06644    }
06645 
06646    l = NULL;
06647    n = NULL;
06648    if (!p->hidecallerid) {
06649       if (ast->connected.id.number.valid) {
06650          /* If we get to the end of this loop without breaking, there's no
06651           * calleridnum.  This is done instead of testing for "unknown" or
06652           * the thousands of other ways that the calleridnum could be
06653           * invalid. */
06654          for (l = ast->connected.id.number.str; l && *l; l++) {
06655             if (strchr("0123456789", *l)) {
06656                l = ast->connected.id.number.str;
06657                break;
06658             }
06659          }
06660       } else {
06661          l = NULL;
06662       }
06663       if (!p->hidecalleridname) {
06664          n = ast->connected.id.name.valid ? ast->connected.id.name.str : NULL;
06665       }
06666    }
06667 
06668    if (strlen(c) < p->stripmsd) {
06669       ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
06670       return -1;
06671    }
06672 
06673    /* Extract any 'w' deferred digits. */
06674    s = strchr(c + p->stripmsd, 'w');
06675    if (s) {
06676       *s++ = '\0';
06677       ast_copy_string(p->deferred_digits, s, sizeof(p->deferred_digits));
06678       /*
06679        * Since we have a 'w', this means that there will not be any
06680        * more normal dialed digits.  Therefore, the sending complete
06681        * ie needs to be sent with any normal digits.
06682        */
06683    } else {
06684       p->deferred_digits[0] = '\0';
06685    }
06686 
06687    pri_grab(p, p->pri);
06688    if (!(p->call = pri_new_call(p->pri->pri))) {
06689       ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
06690       pri_rel(p->pri);
06691       return -1;
06692    }
06693    if (!(sr = pri_sr_new())) {
06694       ast_log(LOG_WARNING, "Failed to allocate setup request on channel %d\n",
06695          p->channel);
06696       pri_destroycall(p->pri->pri, p->call);
06697       p->call = NULL;
06698       pri_rel(p->pri);
06699       return -1;
06700    }
06701 
06702    sig_pri_set_digital(p, IS_DIGITAL(ast->transfercapability));   /* push up to parent for EC */
06703 
06704 #if defined(HAVE_PRI_CALL_WAITING)
06705    if (p->is_call_waiting) {
06706       /*
06707        * Indicate that this is a call waiting call.
06708        * i.e., Normal call but with no B channel.
06709        */
06710       pri_sr_set_channel(sr, 0, 0, 1);
06711    } else
06712 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
06713    {
06714       /* Should the picked channel be used exclusively? */
06715       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
06716          exclusive = 1;
06717       } else {
06718          exclusive = 0;
06719       }
06720       pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
06721    }
06722 
06723    pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
06724       (p->digital ? -1 : layer1));
06725 
06726    if (p->pri->facilityenable)
06727       pri_facility_enable(p->pri->pri);
06728 
06729    ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
06730    dp_strip = 0;
06731    pridialplan = p->pri->dialplan - 1;
06732    if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
06733       if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
06734          if (pridialplan == -2) {
06735             dp_strip = strlen(p->pri->internationalprefix);
06736          }
06737          pridialplan = PRI_INTERNATIONAL_ISDN;
06738       } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
06739          if (pridialplan == -2) {
06740             dp_strip = strlen(p->pri->nationalprefix);
06741          }
06742          pridialplan = PRI_NATIONAL_ISDN;
06743       } else {
06744          pridialplan = PRI_LOCAL_ISDN;
06745       }
06746    }
06747    while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
06748       switch (c[p->stripmsd]) {
06749       case 'U':
06750          pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
06751          break;
06752       case 'I':
06753          pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
06754          break;
06755       case 'N':
06756          pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
06757          break;
06758       case 'L':
06759          pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
06760          break;
06761       case 'S':
06762          pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
06763          break;
06764       case 'V':
06765          pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
06766          break;
06767       case 'R':
06768          pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
06769          break;
06770       case 'u':
06771          pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
06772          break;
06773       case 'e':
06774          pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
06775          break;
06776       case 'x':
06777          pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
06778          break;
06779       case 'f':
06780          pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
06781          break;
06782       case 'n':
06783          pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
06784          break;
06785       case 'p':
06786          pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
06787          break;
06788       case 'r':
06789          pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
06790          break;
06791       default:
06792          if (isalpha(c[p->stripmsd])) {
06793             ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
06794                c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
06795          }
06796          break;
06797       }
06798       c++;
06799    }
06800 #if defined(HAVE_PRI_SETUP_KEYPAD)
06801    if (ast_test_flag(&opts, OPT_KEYPAD)
06802       && !ast_strlen_zero(opt_args[OPT_ARG_KEYPAD])) {
06803       /* We have a keypad facility digits option with digits. */
06804       keypad = opt_args[OPT_ARG_KEYPAD];
06805       pri_sr_set_keypad_digits(sr, keypad);
06806    } else {
06807       keypad = NULL;
06808    }
06809    if (!keypad || !ast_strlen_zero(c + p->stripmsd + dp_strip))
06810 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06811    {
06812       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
06813    }
06814 
06815 #if defined(HAVE_PRI_SUBADDR)
06816    if (dialed_subaddress.valid) {
06817       struct pri_party_subaddress subaddress;
06818 
06819       memset(&subaddress, 0, sizeof(subaddress));
06820       sig_pri_party_subaddress_from_ast(&subaddress, &dialed_subaddress);
06821       pri_sr_set_called_subaddress(sr, &subaddress);
06822    }
06823 #endif   /* defined(HAVE_PRI_SUBADDR) */
06824 #if defined(HAVE_PRI_REVERSE_CHARGE)
06825    if (ast_test_flag(&opts, OPT_REVERSE_CHARGE)) {
06826       pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
06827    }
06828 #endif   /* defined(HAVE_PRI_REVERSE_CHARGE) */
06829 #if defined(HAVE_PRI_AOC_EVENTS)
06830    if (ast_test_flag(&opts, OPT_AOC_REQUEST)
06831       && !ast_strlen_zero(opt_args[OPT_ARG_AOC_REQUEST])) {
06832       if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 's')) {
06833          pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_S);
06834       }
06835       if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'd')) {
06836          pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_D);
06837       }
06838       if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'e')) {
06839          pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_E);
06840       }
06841    }
06842 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
06843 
06844    /* Setup the user tag for party id's from this device for this call. */
06845    if (p->pri->append_msn_to_user_tag) {
06846       snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
06847          p->pri->nodetype == PRI_NETWORK
06848             ? c + p->stripmsd + dp_strip
06849             : S_COR(ast->connected.id.number.valid,
06850                ast->connected.id.number.str, ""));
06851    } else {
06852       ast_copy_string(p->user_tag, p->pri->initial_user_tag, sizeof(p->user_tag));
06853    }
06854 
06855    /*
06856     * Replace the caller id tag from the channel creation
06857     * with the actual tag value.
06858     */
06859    ast_free(ast->caller.id.tag);
06860    ast->caller.id.tag = ast_strdup(p->user_tag);
06861 
06862    ldp_strip = 0;
06863    prilocaldialplan = p->pri->localdialplan - 1;
06864    if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
06865       if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
06866          if (prilocaldialplan == -2) {
06867             ldp_strip = strlen(p->pri->internationalprefix);
06868          }
06869          prilocaldialplan = PRI_INTERNATIONAL_ISDN;
06870       } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
06871          if (prilocaldialplan == -2) {
06872             ldp_strip = strlen(p->pri->nationalprefix);
06873          }
06874          prilocaldialplan = PRI_NATIONAL_ISDN;
06875       } else {
06876          prilocaldialplan = PRI_LOCAL_ISDN;
06877       }
06878    }
06879    if (l != NULL) {
06880       while (*l > '9' && *l != '*' && *l != '#') {
06881          switch (*l) {
06882          case 'U':
06883             prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
06884             break;
06885          case 'I':
06886             prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
06887             break;
06888          case 'N':
06889             prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
06890             break;
06891          case 'L':
06892             prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
06893             break;
06894          case 'S':
06895             prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
06896             break;
06897          case 'V':
06898             prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
06899             break;
06900          case 'R':
06901             prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
06902             break;
06903          case 'u':
06904             prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
06905             break;
06906          case 'e':
06907             prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
06908             break;
06909          case 'x':
06910             prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
06911             break;
06912          case 'f':
06913             prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
06914             break;
06915          case 'n':
06916             prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
06917             break;
06918          case 'p':
06919             prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
06920             break;
06921          case 'r':
06922             prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
06923             break;
06924          default:
06925             if (isalpha(*l)) {
06926                ast_log(LOG_WARNING,
06927                   "Unrecognized prilocaldialplan %s modifier: %c\n",
06928                   *l > 'Z' ? "NPI" : "TON", *l);
06929             }
06930             break;
06931          }
06932          l++;
06933       }
06934    }
06935    pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
06936       p->use_callingpres ? ast->connected.id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
06937 
06938 #if defined(HAVE_PRI_SUBADDR)
06939    if (ast->connected.id.subaddress.valid) {
06940       struct pri_party_subaddress subaddress;
06941 
06942       memset(&subaddress, 0, sizeof(subaddress));
06943       sig_pri_party_subaddress_from_ast(&subaddress, &ast->connected.id.subaddress);
06944       pri_sr_set_caller_subaddress(sr, &subaddress);
06945    }
06946 #endif   /* defined(HAVE_PRI_SUBADDR) */
06947 
06948    sig_pri_redirecting_update(p, ast);
06949 
06950 #ifdef SUPPORT_USERUSER
06951    /* User-user info */
06952    useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
06953    if (useruser)
06954       pri_sr_set_useruser(sr, useruser);
06955 #endif
06956 
06957 #if defined(HAVE_PRI_CCSS)
06958    if (ast_cc_is_recall(ast, &core_id, sig_pri_cc_type_name)) {
06959       struct ast_cc_monitor *monitor;
06960       char device_name[AST_CHANNEL_NAME];
06961 
06962       /* This is a CC recall call. */
06963       ast_channel_get_device_name(ast, device_name, sizeof(device_name));
06964       monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
06965       if (monitor) {
06966          struct sig_pri_cc_monitor_instance *instance;
06967 
06968          instance = monitor->private_data;
06969 
06970          /* If this fails then we have monitor instance ambiguity. */
06971          ast_assert(p->pri == instance->pri);
06972 
06973          if (pri_cc_call(p->pri->pri, instance->cc_id, p->call, sr)) {
06974             /* The CC recall call failed for some reason. */
06975             ast_log(LOG_WARNING, "Unable to setup CC recall call to device %s\n",
06976                device_name);
06977             ao2_ref(monitor, -1);
06978             pri_destroycall(p->pri->pri, p->call);
06979             p->call = NULL;
06980             pri_rel(p->pri);
06981             pri_sr_free(sr);
06982             return -1;
06983          }
06984          ao2_ref(monitor, -1);
06985       } else {
06986          core_id = -1;
06987       }
06988    } else
06989 #endif   /* defined(HAVE_PRI_CCSS) */
06990    {
06991       core_id = -1;
06992    }
06993    if (core_id == -1 && pri_setup(p->pri->pri, p->call, sr)) {
06994       ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
06995          c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
06996       pri_destroycall(p->pri->pri, p->call);
06997       p->call = NULL;
06998       pri_rel(p->pri);
06999       pri_sr_free(sr);
07000       return -1;
07001    }
07002    p->call_level = SIG_PRI_CALL_LEVEL_SETUP;
07003    pri_sr_free(sr);
07004    ast_setstate(ast, AST_STATE_DIALING);
07005    sig_pri_set_dialing(p, 1);
07006    pri_rel(p->pri);
07007    return 0;
07008 }

int sig_pri_cc_agent_callee_available ( struct ast_cc_agent agent  ) 

Alert the caller that it is time to try recalling.

Since:
1.8
Parameters:
agent CC core agent control.
The core will call this function when it receives notice that a monitored party has become available.

The agent's job is to send a message to the caller to notify it of such a change. If the agent is able to discern that the caller is currently unavailable, then the agent should react by calling the ast_cc_caller_unavailable function.

Return values:
0 on success.
-1 on error.

Definition at line 8352 of file sig_pri.c.

References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_agent_prv::cc_id, sig_pri_span::lock, sig_pri_span::pri, sig_pri_cc_agent_prv::pri, and ast_cc_agent::private_data.

08353 {
08354    struct sig_pri_cc_agent_prv *cc_pvt;
08355 
08356    cc_pvt = agent->private_data;
08357    ast_mutex_lock(&cc_pvt->pri->lock);
08358    pri_cc_remote_user_free(cc_pvt->pri->pri, cc_pvt->cc_id);
08359    ast_mutex_unlock(&cc_pvt->pri->lock);
08360    return 0;
08361 }

void sig_pri_cc_agent_destructor ( struct ast_cc_agent agent  ) 

Destroy private data on the agent.

Since:
1.8
Parameters:
agent CC core agent control.
The core will call this function upon completion or failure of CC.

Note:
The agent private_data pointer may be NULL if the agent constructor failed.
Returns:
Nothing

Definition at line 8381 of file sig_pri.c.

References ast_free, ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_agent_prv::cc_id, sig_pri_cc_agent_prv::cc_request_response_pending, sig_pri_span::lock, sig_pri_span::pri, sig_pri_cc_agent_prv::pri, and ast_cc_agent::private_data.

Referenced by dahdi_pri_cc_agent_destructor().

08382 {
08383    struct sig_pri_cc_agent_prv *cc_pvt;
08384    int res;
08385 
08386    cc_pvt = agent->private_data;
08387    if (!cc_pvt) {
08388       /* The agent constructor probably failed. */
08389       return;
08390    }
08391    ast_mutex_lock(&cc_pvt->pri->lock);
08392    res = -1;
08393    if (cc_pvt->cc_request_response_pending) {
08394       res = pri_cc_req_rsp(cc_pvt->pri->pri, cc_pvt->cc_id, 2/* short_term_denial */);
08395    }
08396    if (res) {
08397       pri_cc_cancel(cc_pvt->pri->pri, cc_pvt->cc_id);
08398    }
08399    ast_mutex_unlock(&cc_pvt->pri->lock);
08400    ast_free(cc_pvt);
08401 }

int sig_pri_cc_agent_init ( struct ast_cc_agent agent,
struct sig_pri_chan pvt_chan 
)

PRI CC agent initialization.

Since:
1.8
Parameters:
agent CC core agent control.
pvt_chan Original channel the agent will attempt to recall.
This callback is called when the CC core is initialized. Agents should allocate any private data necessary for the call and assign it to the private_data on the agent. Additionally, if any ast_cc_agent_flags are pertinent to the specific agent type, they should be set in this function as well.

Return values:
0 on success.
-1 on error.

Definition at line 8064 of file sig_pri.c.

References ast_calloc, ast_free, ast_mutex_lock, ast_mutex_unlock, sig_pri_chan::call, sig_pri_span::lock, sig_pri_span::pri, sig_pri_chan::pri, and ast_cc_agent::private_data.

Referenced by dahdi_pri_cc_agent_init().

08065 {
08066    struct sig_pri_cc_agent_prv *cc_pvt;
08067 
08068    cc_pvt = ast_calloc(1, sizeof(*cc_pvt));
08069    if (!cc_pvt) {
08070       return -1;
08071    }
08072 
08073    ast_mutex_lock(&pvt_chan->pri->lock);
08074    cc_pvt->pri = pvt_chan->pri;
08075    cc_pvt->cc_id = pri_cc_available(pvt_chan->pri->pri, pvt_chan->call);
08076    ast_mutex_unlock(&pvt_chan->pri->lock);
08077    if (cc_pvt->cc_id == -1) {
08078       ast_free(cc_pvt);
08079       return -1;
08080    }
08081    agent->private_data = cc_pvt;
08082    return 0;
08083 }

int sig_pri_cc_agent_party_b_free ( struct ast_cc_agent agent  ) 

Let the caller know that the callee has become free but that the caller cannot attempt to call back because he is either busy or there is congestion on his line.

Since:
1.8
Parameters:
agent CC core agent control.
This is something that really only affects a scenario where a phone places a call over ISDN PTMP to Asterisk, who then connects over PTMP again to the ISDN network. For most agent types, there is no need to implement this callback at all because they don't really need to actually do anything in this situation. If you're having trouble understanding what the purpose of this callback is, then you can be safe simply not implementing it.

Return values:
0 on success.
-1 on error.

Definition at line 8296 of file sig_pri.c.

References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_agent_prv::cc_id, sig_pri_span::lock, sig_pri_span::pri, sig_pri_cc_agent_prv::pri, and ast_cc_agent::private_data.

08297 {
08298    struct sig_pri_cc_agent_prv *cc_pvt;
08299 
08300    cc_pvt = agent->private_data;
08301    ast_mutex_lock(&cc_pvt->pri->lock);
08302    pri_cc_b_free(cc_pvt->pri->pri, cc_pvt->cc_id);
08303    ast_mutex_unlock(&cc_pvt->pri->lock);
08304    return 0;
08305 }

void sig_pri_cc_agent_req_rsp ( struct ast_cc_agent agent,
enum ast_cc_agent_response_reason  reason 
)

Response to a CC request.

Since:
1.8
Parameters:
agent CC core agent control.
reason CC request response status.
When the core receives knowledge that a called party has accepted a CC request, it will call this callback. The core may also call this if there is some error when attempting to process the incoming CC request.

The duty of this is to issue a propper response to a CC request from the caller by acknowledging receipt of that request or rejecting it.

Returns:
Nothing

Definition at line 8157 of file sig_pri.c.

References AST_CC_AGENT_RESPONSE_FAILURE_INVALID, AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY, AST_CC_AGENT_RESPONSE_SUCCESS, ast_cc_failed(), ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_agent_prv::cc_id, sig_pri_cc_agent_prv::cc_request_response_pending, ast_cc_agent::core_id, sig_pri_span::lock, sig_pri_span::pri, sig_pri_cc_agent_prv::pri, ast_cc_agent::private_data, sig_pri_cc_type_name, and status.

08158 {
08159    struct sig_pri_cc_agent_prv *cc_pvt;
08160    int res;
08161    int status;
08162    const char *failed_msg;
08163    static const char *failed_to_send = "Failed to send the CC request response.";
08164    static const char *not_accepted = "The core declined the CC request.";
08165 
08166    cc_pvt = agent->private_data;
08167    ast_mutex_lock(&cc_pvt->pri->lock);
08168    if (cc_pvt->cc_request_response_pending) {
08169       cc_pvt->cc_request_response_pending = 0;
08170 
08171       /* Convert core response reason to ISDN response status. */
08172       status = 2;/* short_term_denial */
08173       switch (reason) {
08174       case AST_CC_AGENT_RESPONSE_SUCCESS:
08175          status = 0;/* success */
08176          break;
08177       case AST_CC_AGENT_RESPONSE_FAILURE_INVALID:
08178          status = 2;/* short_term_denial */
08179          break;
08180       case AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY:
08181          status = 5;/* queue_full */
08182          break;
08183       }
08184 
08185       res = pri_cc_req_rsp(cc_pvt->pri->pri, cc_pvt->cc_id, status);
08186       if (!status) {
08187          /* CC core request was accepted. */
08188          if (res) {
08189             failed_msg = failed_to_send;
08190          } else {
08191             failed_msg = NULL;
08192          }
08193       } else {
08194          /* CC core request was declined. */
08195          if (res) {
08196             failed_msg = failed_to_send;
08197          } else {
08198             failed_msg = not_accepted;
08199          }
08200       }
08201    } else {
08202       failed_msg = NULL;
08203    }
08204    ast_mutex_unlock(&cc_pvt->pri->lock);
08205    if (failed_msg) {
08206       ast_cc_failed(agent->core_id, "%s agent: %s", sig_pri_cc_type_name, failed_msg);
08207    }
08208 }

int sig_pri_cc_agent_start_monitoring ( struct ast_cc_agent agent  ) 

Begin monitoring a busy device.

Since:
1.8
Parameters:
agent CC core agent control.
The core will call this callback if the callee becomes available but the caller has reported that he is busy. The agent should begin monitoring the caller's device. When the caller becomes available again, the agent should call ast_cc_agent_caller_available.

Return values:
0 on success.
-1 on error.

Definition at line 8325 of file sig_pri.c.

08326 {
08327    /* libpri already knows when and how it needs to monitor Party A. */
08328    return 0;
08329 }

int sig_pri_cc_agent_start_offer_timer ( struct ast_cc_agent agent  ) 

Start the offer timer.

Since:
1.8
Parameters:
agent CC core agent control.
This is called by the core when the caller hangs up after a call for which CC may be requested. The agent should begin the timer as configured.

The primary reason why this functionality is left to the specific agent implementations is due to the differing use of schedulers throughout the code. Some channel drivers may already have a scheduler context they wish to use, and amongst those, some may use the ast_sched API while others may use the ast_sched_thread API, which are incompatible.

Return values:
0 on success.
-1 on error.

Definition at line 8108 of file sig_pri.c.

08109 {
08110    /* libpri maintains it's own offer timer in the form of T_RETENTION. */
08111    return 0;
08112 }

int sig_pri_cc_agent_status_req ( struct ast_cc_agent agent  ) 

Request the status of the agent's device.

Since:
1.8
Parameters:
agent CC core agent control.
Asynchronous request for the status of any caller which may be a valid caller for the CC transaction. Status responses should be made using the ast_cc_status_response function.

Return values:
0 on success.
-1 on error.

Definition at line 8227 of file sig_pri.c.

References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_agent_prv::cc_id, sig_pri_span::lock, sig_pri_span::pri, sig_pri_cc_agent_prv::pri, and ast_cc_agent::private_data.

08228 {
08229    struct sig_pri_cc_agent_prv *cc_pvt;
08230 
08231    cc_pvt = agent->private_data;
08232    ast_mutex_lock(&cc_pvt->pri->lock);
08233    pri_cc_status_req(cc_pvt->pri->pri, cc_pvt->cc_id);
08234    ast_mutex_unlock(&cc_pvt->pri->lock);
08235    return 0;
08236 }

int sig_pri_cc_agent_stop_offer_timer ( struct ast_cc_agent agent  ) 

Stop the offer timer.

Since:
1.8
Parameters:
agent CC core agent control.
This callback is called by the CC core when the caller has requested CC.

Return values:
0 on success.
-1 on error.

Definition at line 8129 of file sig_pri.c.

08130 {
08131    /* libpri maintains it's own offer timer in the form of T_RETENTION. */
08132    return 0;
08133 }

int sig_pri_cc_agent_stop_ringing ( struct ast_cc_agent agent  ) 

Request for an agent's phone to stop ringing.

Since:
1.8
Parameters:
agent CC core agent control.
The usefulness of this is quite limited. The only specific known case for this is if Asterisk requests CC over an ISDN PTMP link as the TE side. If other phones are in the same recall group as the Asterisk server, and one of those phones picks up the recall notice, then Asterisk will receive a "stop ringing" notification from the NT side of the PTMP link. This indication needs to be passed to the phone on the other side of the Asterisk server which originally placed the call so that it will stop ringing. Since the phone may be of any type, it is necessary to have a callback that the core can know about.

Return values:
0 on success.
-1 on error.

Definition at line 8262 of file sig_pri.c.

References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_agent_prv::cc_id, sig_pri_span::lock, sig_pri_span::pri, sig_pri_cc_agent_prv::pri, and ast_cc_agent::private_data.

08263 {
08264    struct sig_pri_cc_agent_prv *cc_pvt;
08265 
08266    cc_pvt = agent->private_data;
08267    ast_mutex_lock(&cc_pvt->pri->lock);
08268    pri_cc_stop_alerting(cc_pvt->pri->pri, cc_pvt->cc_id);
08269    ast_mutex_unlock(&cc_pvt->pri->lock);
08270    return 0;
08271 }

int sig_pri_cc_monitor_cancel_available_timer ( struct ast_cc_monitor monitor,
int *  sched_id 
)

Cancel the running available timer.

Since:
1.8
Parameters:
monitor CC core monitor control.
sched_id Available timer scheduler id to cancel. Will never be NULL for a device monitor.
In most cases, this function will likely consist of just a call to AST_SCHED_DEL. It might have been possible to do this within the core, but unfortunately the mixture of sched_thread and sched usage in Asterisk prevents such usage.

Return values:
0 on success
-1 on failure.

Definition at line 8607 of file sig_pri.c.

08608 {
08609    /*
08610     * libpri maintains it's own available timer as one of:
08611     * T_CCBS2/T_CCBS5/T_CCBS6/QSIG_CCBS_T2
08612     * T_CCNR2/T_CCNR5/T_CCNR6/QSIG_CCNR_T2
08613     */
08614    return 0;
08615 }

void sig_pri_cc_monitor_destructor ( void *  monitor_pvt  ) 

Destroy PRI private data on the monitor.

Since:
1.8
Parameters:
monitor_pvt CC device monitor private data pointer.
Implementers of this callback are responsible for destroying all heap-allocated data in the monitor's private_data pointer, including the private_data itself.

Definition at line 8630 of file sig_pri.c.

References ao2_ref, ao2_unlink, and sig_pri_cc_monitors.

08631 {
08632    struct sig_pri_cc_monitor_instance *instance;
08633 
08634    instance = monitor_pvt;
08635    if (!instance) {
08636       return;
08637    }
08638    ao2_unlink(sig_pri_cc_monitors, instance);
08639    ao2_ref(instance, -1);
08640 }

int sig_pri_cc_monitor_req_cc ( struct ast_cc_monitor monitor,
int *  available_timer_id 
)

Request CCSS.

Since:
1.8
Parameters:
monitor CC core monitor control.
available_timer_id Where to put the available timer scheduler id. Will never be NULL for a device monitor.
Perform whatever steps are necessary in order to request CC. In addition, the monitor implementation is responsible for starting the available timer in this callback. The scheduler ID for the callback must be stored in the parent_link's child_avail_id field.

Return values:
0 on success
-1 on failure.

Definition at line 8463 of file sig_pri.c.

References AST_CC_CCBS, AST_CC_CCNR, ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, monitor, sig_pri_span::pri, and sig_pri_cc_monitor_instance::pri.

08464 {
08465    struct sig_pri_cc_monitor_instance *instance;
08466    int cc_mode;
08467    int res;
08468 
08469    switch (monitor->service_offered) {
08470    case AST_CC_CCBS:
08471       cc_mode = 0;/* CCBS */
08472       break;
08473    case AST_CC_CCNR:
08474       cc_mode = 1;/* CCNR */
08475       break;
08476    default:
08477       /* CC service not supported by ISDN. */
08478       return -1;
08479    }
08480 
08481    instance = monitor->private_data;
08482 
08483    /* libpri handles it's own available timer. */
08484    ast_mutex_lock(&instance->pri->lock);
08485    res = pri_cc_req(instance->pri->pri, instance->cc_id, cc_mode);
08486    ast_mutex_unlock(&instance->pri->lock);
08487 
08488    return res;
08489 }

int sig_pri_cc_monitor_status_rsp ( struct ast_cc_monitor monitor,
enum ast_device_state  devstate 
)

Status response to an ast_cc_monitor_status_request().

Since:
1.8
Parameters:
monitor CC core monitor control.
devstate Current status of a Party A device.
Alert a monitor as to the status of the agent for which the monitor had previously requested a status request.

Note:
Zero or more responses may come as a result.
Return values:
0 on success
-1 on failure.

Definition at line 8562 of file sig_pri.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNKNOWN, ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, monitor, sig_pri_span::pri, and sig_pri_cc_monitor_instance::pri.

08563 {
08564    struct sig_pri_cc_monitor_instance *instance;
08565    int cc_status;
08566 
08567    switch (devstate) {
08568    case AST_DEVICE_UNKNOWN:
08569    case AST_DEVICE_NOT_INUSE:
08570       cc_status = 0;/* free */
08571       break;
08572    case AST_DEVICE_BUSY:
08573    case AST_DEVICE_INUSE:
08574       cc_status = 1;/* busy */
08575       break;
08576    default:
08577       /* Don't know how to interpret this device state into free/busy status. */
08578       return 0;
08579    }
08580    instance = monitor->private_data;
08581    ast_mutex_lock(&instance->pri->lock);
08582    pri_cc_status_req_rsp(instance->pri->pri, instance->cc_id, cc_status);
08583    ast_mutex_unlock(&instance->pri->lock);
08584 
08585    return 0;
08586 }

int sig_pri_cc_monitor_suspend ( struct ast_cc_monitor monitor  ) 

Suspend monitoring.

Since:
1.8
Parameters:
monitor CC core monitor control.
Implementers must perform the necessary steps to suspend monitoring.

Return values:
0 on success
-1 on failure.

Definition at line 8506 of file sig_pri.c.

References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, monitor, sig_pri_span::pri, and sig_pri_cc_monitor_instance::pri.

08507 {
08508    struct sig_pri_cc_monitor_instance *instance;
08509 
08510    instance = monitor->private_data;
08511    ast_mutex_lock(&instance->pri->lock);
08512    pri_cc_status(instance->pri->pri, instance->cc_id, 1/* busy */);
08513    ast_mutex_unlock(&instance->pri->lock);
08514 
08515    return 0;
08516 }

int sig_pri_cc_monitor_unsuspend ( struct ast_cc_monitor monitor  ) 

Unsuspend monitoring.

Since:
1.8
Parameters:
monitor CC core monitor control.
Perform the necessary steps to unsuspend monitoring.

Return values:
0 on success
-1 on failure.

Definition at line 8532 of file sig_pri.c.

References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, monitor, sig_pri_span::pri, and sig_pri_cc_monitor_instance::pri.

08533 {
08534    struct sig_pri_cc_monitor_instance *instance;
08535 
08536    instance = monitor->private_data;
08537    ast_mutex_lock(&instance->pri->lock);
08538    pri_cc_status(instance->pri->pri, instance->cc_id, 0/* free */);
08539    ast_mutex_unlock(&instance->pri->lock);
08540 
08541    return 0;
08542 }

void sig_pri_chan_alarm_notify ( struct sig_pri_chan p,
int  noalarm 
)

Notify new alarm status.

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

Definition at line 7816 of file sig_pri.c.

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

Referenced by dahdi_handle_event(), and handle_init_event().

07817 {
07818    pri_grab(p, p->pri);
07819    sig_pri_set_alarm(p, !noalarm);
07820    if (!noalarm) {
07821       if (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07822          /* T309 is not enabled : destroy calls when alarm occurs */
07823          if (p->call) {
07824             pri_destroycall(p->pri->pri, p->call);
07825             p->call = NULL;
07826          }
07827          if (p->owner)
07828             p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
07829       }
07830    }
07831    sig_pri_span_devstate_changed(p->pri);
07832    pri_rel(p->pri);
07833 }

void sig_pri_chan_delete ( struct sig_pri_chan doomed  ) 

Delete the sig_pri private channel structure.

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

Definition at line 7875 of file sig_pri.c.

References ast_free.

Referenced by destroy_dahdi_pvt().

07876 {
07877    ast_free(doomed);
07878 }

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 
)

Definition at line 7847 of file sig_pri.c.

References ast_calloc, and sig_pri_chan::pri.

07848 {
07849    struct sig_pri_chan *p;
07850 
07851    p = ast_calloc(1, sizeof(*p));
07852    if (!p)
07853       return p;
07854 
07855    p->logicalspan = logicalspan;
07856    p->prioffset = channo;
07857    p->mastertrunkgroup = trunkgroup;
07858 
07859    p->calls = callback;
07860    p->chan_pvt = pvt_data;
07861 
07862    p->pri = pri;
07863 
07864    return p;
07865 }

void sig_pri_cli_show_channels ( int  fd,
struct sig_pri_span pri 
)

Definition at line 7888 of file sig_pri.c.

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

Referenced by handle_pri_show_channels().

07889 {
07890    char line[256];
07891    int idx;
07892    struct sig_pri_chan *pvt;
07893 
07894    ast_mutex_lock(&pri->lock);
07895    for (idx = 0; idx < pri->numchans; ++idx) {
07896       if (!pri->pvts[idx]) {
07897          continue;
07898       }
07899       pvt = pri->pvts[idx];
07900       sig_pri_lock_private(pvt);
07901       sig_pri_lock_owner(pri, idx);
07902       if (pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
07903          /* Don't show held/call-waiting channels if they are not in use. */
07904          sig_pri_unlock_private(pvt);
07905          continue;
07906       }
07907 
07908       snprintf(line, sizeof(line), SIG_PRI_SC_LINE,
07909          pri->span,
07910          pvt->channel,
07911          pvt->no_b_channel ? "No" : "Yes",/* Has media */
07912          sig_pri_is_chan_available(pvt) ? "Yes" : "No",
07913          sig_pri_call_level2str(pvt->call_level),
07914          pvt->call ? "Yes" : "No",
07915          pvt->owner ? pvt->owner->name : "");
07916 
07917       if (pvt->owner) {
07918          ast_channel_unlock(pvt->owner);
07919       }
07920       sig_pri_unlock_private(pvt);
07921 
07922       ast_mutex_unlock(&pri->lock);
07923       ast_cli(fd, "%s\n", line);
07924       ast_mutex_lock(&pri->lock);
07925    }
07926    ast_mutex_unlock(&pri->lock);
07927 }

void sig_pri_cli_show_channels_header ( int  fd  ) 

Definition at line 7882 of file sig_pri.c.

References ast_cli(), and SIG_PRI_SC_HEADER.

Referenced by handle_pri_show_channels().

07883 {
07884    ast_cli(fd, SIG_PRI_SC_HEADER, "PRI",  "",     "B",    "Chan", "Call",  "PRI",  "Channel");
07885    ast_cli(fd, SIG_PRI_SC_HEADER, "Span", "Chan", "Chan", "Idle", "Level", "Call", "Name");
07886 }

void sig_pri_cli_show_span ( int  fd,
int *  dchannels,
struct sig_pri_span pri 
)

Definition at line 7960 of file sig_pri.c.

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

Referenced by handle_pri_show_span().

07961 {
07962    int x;
07963    char status[256];
07964 
07965    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
07966       if (pri->dchans[x]) {
07967 #ifdef PRI_DUMP_INFO_STR
07968          char *info_str = NULL;
07969 #endif
07970          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), dchannels[x]);
07971          build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
07972          ast_cli(fd, "Status: %s\n", status);
07973          ast_mutex_lock(&pri->lock);
07974 #ifdef PRI_DUMP_INFO_STR
07975          info_str = pri_dump_info_str(pri->pri);
07976          if (info_str) {
07977             ast_cli(fd, "%s", info_str);
07978             free(info_str);
07979          }
07980 #else
07981          pri_dump_info(pri->pri);
07982 #endif
07983          ast_mutex_unlock(&pri->lock);
07984          ast_cli(fd, "Overlap Recv: %s\n\n", (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
07985          ast_cli(fd, "\n");
07986       }
07987    }
07988 }

void sig_pri_cli_show_spans ( int  fd,
int  span,
struct sig_pri_span pri 
)

Definition at line 7948 of file sig_pri.c.

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

Referenced by handle_pri_show_spans().

07949 {
07950    char status[256];
07951    int x;
07952    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
07953       if (pri->dchans[x]) {
07954          build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
07955          ast_cli(fd, "PRI span %d/%d: %s\n", span, x, status);
07956       }
07957    }
07958 }

void sig_pri_dial_complete ( struct sig_pri_chan pvt,
struct ast_channel ast 
)

DTMF dial string complete.

Since:
1.8.11
Parameters:
pvt sig_pri private channel structure.
ast Asterisk channel
Note:
Channel and private lock are already held.
Returns:
Nothing

Definition at line 7428 of file sig_pri.c.

References AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), sig_pri_chan::call_level, sig_pri_chan::calls, sig_pri_chan::chan_pvt, f, sig_pri_callback::queue_control, SIG_PRI_CALL_LEVEL_CONNECT, SIG_PRI_CALL_LEVEL_DEFER_DIAL, sig_pri_open_media(), sig_pri_set_dialing(), and sig_pri_set_echocanceller().

Referenced by dahdi_handle_event().

07429 {
07430    /* If we just completed 'w' deferred dialing digits, we need to answer now. */
07431    if (pvt->call_level == SIG_PRI_CALL_LEVEL_DEFER_DIAL) {
07432       pvt->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
07433 
07434       sig_pri_open_media(pvt);
07435       {
07436          struct ast_frame f = {AST_FRAME_CONTROL, };
07437 
07438          if (pvt->calls->queue_control) {
07439             pvt->calls->queue_control(pvt->chan_pvt, AST_CONTROL_ANSWER);
07440          }
07441 
07442          f.subclass.integer = AST_CONTROL_ANSWER;
07443          ast_queue_frame(ast, &f);
07444       }
07445       sig_pri_set_dialing(pvt, 0);
07446       /* Enable echo cancellation if it's not on already */
07447       sig_pri_set_echocanceller(pvt, 1);
07448    }
07449 }

int sig_pri_digit_begin ( struct sig_pri_chan pvt,
struct ast_channel ast,
char  digit 
)

Definition at line 7382 of file sig_pri.c.

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

Referenced by dahdi_digit_begin().

07383 {
07384    if (ast->_state == AST_STATE_DIALING) {
07385       if (pvt->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
07386          unsigned int len;
07387 
07388          len = strlen(pvt->dialdest);
07389          if (len < sizeof(pvt->dialdest) - 1) {
07390             ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
07391                digit);
07392             pvt->dialdest[len++] = digit;
07393             pvt->dialdest[len] = '\0';
07394          } else {
07395             ast_log(LOG_WARNING,
07396                "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
07397                pvt->pri->span, digit);
07398          }
07399          return 0;
07400       }
07401       if (pvt->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
07402          pri_grab(pvt, pvt->pri);
07403          pri_information(pvt->pri->pri, pvt->call, digit);
07404          pri_rel(pvt->pri);
07405          return 0;
07406       }
07407       if (pvt->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
07408          ast_log(LOG_WARNING,
07409             "Span %d: Digit '%c' may be ignored by peer. (Call level:%d(%s))\n",
07410             pvt->pri->span, digit, pvt->call_level,
07411             sig_pri_call_level2str(pvt->call_level));
07412       }
07413    }
07414    return 1;
07415 }

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:
p sig_pri channel structure.
rdest Dial string buffer to extract called number and subaddress.
called Buffer to fill with extracted <number>[:<subaddress>]
called_buff_size Size of buffer to fill.
Note:
Parsing must remain in sync with sig_pri_call().
Returns:
Nothing

Definition at line 6478 of file sig_pri.c.

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

Referenced by dahdi_request().

06479 {
06480    char *dial;
06481    char *number;
06482    char *subaddr;
06483    AST_DECLARE_APP_ARGS(args,
06484       AST_APP_ARG(group);  /* channel/group token */
06485       AST_APP_ARG(ext); /* extension token */
06486       //AST_APP_ARG(opts); /* options token */
06487       AST_APP_ARG(other);  /* Any remining unused arguments */
06488    );
06489 
06490    /* Get private copy of dial string and break it up. */
06491    dial = ast_strdupa(rdest);
06492    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
06493 
06494    number = args.ext;
06495    if (!number) {
06496       number = "";
06497    }
06498 
06499    /* Find and extract dialed_subaddress */
06500    subaddr = strchr(number, ':');
06501    if (subaddr) {
06502       *subaddr++ = '\0';
06503 
06504       /* Skip subaddress type prefix. */
06505       switch (*subaddr) {
06506       case 'U':
06507       case 'u':
06508       case 'N':
06509       case 'n':
06510          ++subaddr;
06511          break;
06512       default:
06513          break;
06514       }
06515    }
06516 
06517    /* Skip type-of-number/dial-plan prefix characters. */
06518    if (strlen(number) < p->stripmsd) {
06519       number = "";
06520    } else {
06521       char *deferred;
06522 
06523       number += p->stripmsd;
06524       deferred = strchr(number, 'w');
06525       if (deferred) {
06526          /* Remove any 'w' deferred digits. */
06527          *deferred = '\0';
06528       }
06529       while (isalpha(*number)) {
06530          ++number;
06531       }
06532    }
06533 
06534    /* Fill buffer with extracted number and subaddress. */
06535    if (ast_strlen_zero(subaddr)) {
06536       /* Put in called number only since there is no subaddress. */
06537       snprintf(called, called_buff_size, "%s", number);
06538    } else {
06539       /* Put in called number and subaddress. */
06540       snprintf(called, called_buff_size, "%s:%s", number, subaddr);
06541    }
06542 }

void sig_pri_fixup ( struct ast_channel oldchan,
struct ast_channel newchan,
struct sig_pri_chan pchan 
)

Definition at line 8040 of file sig_pri.c.

References sig_pri_chan::owner.

08041 {
08042    if (pchan->owner == oldchan) {
08043       pchan->owner = newchan;
08044    }
08045 }

int sig_pri_hangup ( struct sig_pri_chan p,
struct ast_channel ast 
)

Definition at line 6387 of file sig_pri.c.

References sig_pri_chan::allocated, sig_pri_chan::alreadyhungup, sig_pri_chan::aoc_e, sig_pri_chan::aoc_s_request_invoke_id_valid, ast_atomic_fetchadd_int(), ast_debug, ast_log(), ast_strlen_zero(), sig_pri_chan::call, sig_pri_chan::call_level, cause, sig_pri_chan::channel, sig_pri_chan::cid_name, sig_pri_chan::cid_num, sig_pri_chan::cid_subaddr, sig_pri_chan::exten, ast_channel::hangupcause, sig_pri_chan::holding_aoce, sig_pri_chan::is_call_waiting, LOG_WARNING, sig_pri_span::num_call_waiting_calls, sig_pri_chan::owner, pbx_builtin_getvar_helper(), sig_pri_span::pri, sig_pri_chan::pri, pri_grab(), pri_rel(), sig_pri_chan::progress, SIG_PRI_CALL_LEVEL_IDLE, sig_pri_set_dialing(), sig_pri_set_digital(), sig_pri_set_outgoing(), sig_pri_span_devstate_changed(), ast_channel::tech_pvt, sig_pri_chan::user_tag, and sig_pri_chan::waiting_for_aoce.

Referenced by dahdi_hangup().

06388 {
06389    ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
06390    if (!ast->tech_pvt) {
06391       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06392       return 0;
06393    }
06394 
06395    sig_pri_set_outgoing(p, 0);
06396    sig_pri_set_digital(p, 0); /* push up to parent for EC*/
06397 #if defined(HAVE_PRI_CALL_WAITING)
06398    if (p->is_call_waiting) {
06399       p->is_call_waiting = 0;
06400       ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
06401    }
06402 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
06403    p->call_level = SIG_PRI_CALL_LEVEL_IDLE;
06404    p->progress = 0;
06405    p->cid_num[0] = '\0';
06406    p->cid_subaddr[0] = '\0';
06407    p->cid_name[0] = '\0';
06408    p->user_tag[0] = '\0';
06409    p->exten[0] = '\0';
06410    sig_pri_set_dialing(p, 0);
06411 
06412    /* Make sure we really have a call */
06413    pri_grab(p, p->pri);
06414    if (p->call) {
06415 #if defined(SUPPORT_USERUSER)
06416       const char *useruser = pbx_builtin_getvar_helper(ast, "USERUSERINFO");
06417 
06418       if (!ast_strlen_zero(useruser)) {
06419          pri_call_set_useruser(p->call, useruser);
06420       }
06421 #endif   /* defined(SUPPORT_USERUSER) */
06422 
06423 #if defined(HAVE_PRI_AOC_EVENTS)
06424       if (p->holding_aoce) {
06425          pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
06426       }
06427 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
06428 
06429       if (p->alreadyhungup) {
06430          ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
06431 
06432          pri_hangup(p->pri->pri, p->call, -1);
06433          p->call = NULL;
06434       } else {
06435          const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
06436          int icause = ast->hangupcause ? ast->hangupcause : -1;
06437 
06438          p->alreadyhungup = 1;
06439          if (!ast_strlen_zero(cause)) {
06440             if (atoi(cause)) {
06441                icause = atoi(cause);
06442             }
06443          }
06444          ast_debug(1,
06445             "Not yet hungup...  Calling hangup with cause %d, and clearing call\n",
06446             icause);
06447 
06448          pri_hangup(p->pri->pri, p->call, icause);
06449       }
06450    }
06451 #if defined(HAVE_PRI_AOC_EVENTS)
06452    p->aoc_s_request_invoke_id_valid = 0;
06453    p->holding_aoce = 0;
06454    p->waiting_for_aoce = 0;
06455 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
06456 
06457    p->allocated = 0;
06458    p->owner = NULL;
06459 
06460    sig_pri_span_devstate_changed(p->pri);
06461    pri_rel(p->pri);
06462    return 0;
06463 }

int sig_pri_indicate ( struct sig_pri_chan p,
struct ast_channel chan,
int  condition,
const void *  data,
size_t  datalen 
)

Definition at line 7010 of file sig_pri.c.

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

Referenced by dahdi_indicate().

07011 {
07012    int res = -1;
07013 
07014    switch (condition) {
07015    case AST_CONTROL_BUSY:
07016       if (p->priindication_oob || p->no_b_channel) {
07017          chan->hangupcause = AST_CAUSE_USER_BUSY;
07018          chan->_softhangup |= AST_SOFTHANGUP_DEV;
07019          res = 0;
07020          break;
07021       }
07022       res = sig_pri_play_tone(p, SIG_PRI_TONE_BUSY);
07023       if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
07024          chan->hangupcause = AST_CAUSE_USER_BUSY;
07025          p->progress = 1;/* No need to send plain PROGRESS after this. */
07026          if (p->pri && p->pri->pri) {
07027             pri_grab(p, p->pri);
07028 #ifdef HAVE_PRI_PROG_W_CAUSE
07029             pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07030 #else
07031             pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07032 #endif
07033             pri_rel(p->pri);
07034          }
07035       }
07036       break;
07037    case AST_CONTROL_RINGING:
07038       if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
07039          p->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
07040          if (p->pri && p->pri->pri) {
07041             pri_grab(p, p->pri);
07042             pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
07043                p->no_b_channel || p->digital ? 0 : 1);
07044             pri_rel(p->pri);
07045          }
07046       }
07047       res = sig_pri_play_tone(p, SIG_PRI_TONE_RINGTONE);
07048       if (chan->_state != AST_STATE_UP) {
07049          if (chan->_state != AST_STATE_RING)
07050             ast_setstate(chan, AST_STATE_RINGING);
07051       }
07052       break;
07053    case AST_CONTROL_PROCEEDING:
07054       ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07055       if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
07056          p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
07057          if (p->pri && p->pri->pri) {
07058             pri_grab(p, p->pri);
07059             pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
07060                p->no_b_channel || p->digital ? 0 : 1);
07061             if (!p->no_b_channel && !p->digital) {
07062                sig_pri_set_dialing(p, 0);
07063             }
07064             pri_rel(p->pri);
07065          }
07066       }
07067       /* don't continue in ast_indicate */
07068       res = 0;
07069       break;
07070    case AST_CONTROL_PROGRESS:
07071       ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07072       sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */
07073       if (!p->progress && p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing
07074          && !p->no_b_channel) {
07075          p->progress = 1;/* No need to send plain PROGRESS again. */
07076          if (p->pri && p->pri->pri) {
07077             pri_grab(p, p->pri);
07078 #ifdef HAVE_PRI_PROG_W_CAUSE
07079             pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
07080 #else
07081             pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07082 #endif
07083             pri_rel(p->pri);
07084          }
07085       }
07086       /* don't continue in ast_indicate */
07087       res = 0;
07088       break;
07089    case AST_CONTROL_INCOMPLETE:
07090       /* If we are connected or if we support overlap dialing, wait for additional digits */
07091       if (p->call_level == SIG_PRI_CALL_LEVEL_CONNECT || (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
07092          res = 0;
07093          break;
07094       }
07095       /* Otherwise, treat as congestion */
07096       chan->hangupcause = AST_CAUSE_INVALID_NUMBER_FORMAT;
07097       /* Falls through */
07098    case AST_CONTROL_CONGESTION:
07099       if (p->priindication_oob || p->no_b_channel) {
07100          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07101          switch (chan->hangupcause) {
07102          case AST_CAUSE_USER_BUSY:
07103          case AST_CAUSE_NORMAL_CLEARING:
07104          case 0:/* Cause has not been set. */
07105             /* Supply a more appropriate cause. */
07106             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07107             break;
07108          default:
07109             break;
07110          }
07111          chan->_softhangup |= AST_SOFTHANGUP_DEV;
07112          res = 0;
07113          break;
07114       }
07115       res = sig_pri_play_tone(p, SIG_PRI_TONE_CONGESTION);
07116       if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
07117          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07118          switch (chan->hangupcause) {
07119          case AST_CAUSE_USER_BUSY:
07120          case AST_CAUSE_NORMAL_CLEARING:
07121          case 0:/* Cause has not been set. */
07122             /* Supply a more appropriate cause. */
07123             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07124             break;
07125          default:
07126             break;
07127          }
07128          p->progress = 1;/* No need to send plain PROGRESS after this. */
07129          if (p->pri && p->pri->pri) {
07130             pri_grab(p, p->pri);
07131 #ifdef HAVE_PRI_PROG_W_CAUSE
07132             pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07133 #else
07134             pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07135 #endif
07136             pri_rel(p->pri);
07137          }
07138       }
07139       break;
07140    case AST_CONTROL_HOLD:
07141       if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07142          pri_grab(p, p->pri);
07143          res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07144          pri_rel(p->pri);
07145       } else
07146          ast_moh_start(chan, data, p->mohinterpret);
07147       break;
07148    case AST_CONTROL_UNHOLD:
07149       if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07150          pri_grab(p, p->pri);
07151          res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07152          pri_rel(p->pri);
07153       } else
07154          ast_moh_stop(chan);
07155       break;
07156    case AST_CONTROL_SRCUPDATE:
07157       res = 0;
07158       break;
07159    case -1:
07160       res = sig_pri_play_tone(p, -1);
07161       break;
07162    case AST_CONTROL_CONNECTED_LINE:
07163       ast_debug(1, "Received AST_CONTROL_CONNECTED_LINE on %s\n", chan->name);
07164       if (p->pri) {
07165          struct pri_party_connected_line connected;
07166 
07167          pri_grab(p, p->pri);
07168          memset(&connected, 0, sizeof(connected));
07169          sig_pri_party_id_from_ast(&connected.id, &chan->connected.id);
07170 
07171          pri_connected_line_update(p->pri->pri, p->call, &connected);
07172          pri_rel(p->pri);
07173       }
07174       break;
07175    case AST_CONTROL_REDIRECTING:
07176       ast_debug(1, "Received AST_CONTROL_REDIRECTING on %s\n", chan->name);
07177       if (p->pri) {
07178          pri_grab(p, p->pri);
07179          sig_pri_redirecting_update(p, chan);
07180          pri_rel(p->pri);
07181       }
07182       break;
07183    case AST_CONTROL_AOC:
07184 #if defined(HAVE_PRI_AOC_EVENTS)
07185       {
07186          struct ast_aoc_decoded *decoded
07187             = ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, chan);
07188          ast_debug(1, "Received AST_CONTROL_AOC on %s\n", chan->name);
07189          if (decoded && p->pri) {
07190             pri_grab(p, p->pri);
07191             switch (ast_aoc_get_msg_type(decoded)) {
07192             case AST_AOC_S:
07193                if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
07194                   sig_pri_aoc_s_from_ast(p, decoded);
07195                }
07196                break;
07197             case AST_AOC_D:
07198                if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
07199                   sig_pri_aoc_d_from_ast(p, decoded);
07200                }
07201                break;
07202             case AST_AOC_E:
07203                if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
07204                   sig_pri_aoc_e_from_ast(p, decoded);
07205                }
07206                /* if hangup was delayed for this AOC-E msg, waiting_for_aoc
07207                 * will be set.  A hangup is already occuring via a timeout during
07208                 * this delay.  Instead of waiting for that timeout to occur, go ahead
07209                 * and initiate the softhangup since the delay is no longer necessary */
07210                if (p->waiting_for_aoce) {
07211                   p->waiting_for_aoce = 0;
07212                   ast_log(LOG_DEBUG,
07213                      "Received final AOC-E msg, continue with hangup on %s\n",
07214                      chan->name);
07215                   ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
07216                }
07217                break;
07218             case AST_AOC_REQUEST:
07219                /* We do not pass through AOC requests, So unless this
07220                 * is an AOC termination request it will be ignored */
07221                if (ast_aoc_get_termination_request(decoded)) {
07222                   pri_hangup(p->pri->pri, p->call, -1);
07223                }
07224                break;
07225             default:
07226                break;
07227             }
07228             pri_rel(p->pri);
07229          }
07230          ast_aoc_destroy_decoded(decoded);
07231       }
07232 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
07233       break;
07234    }
07235 
07236    return res;
07237 }

void sig_pri_init_pri ( struct sig_pri_span pri  ) 

Definition at line 6374 of file sig_pri.c.

References ast_mutex_init, AST_PTHREADT_NULL, and SIG_PRI_NUM_DCHANS.

Referenced by load_module().

06375 {
06376    int i;
06377 
06378    memset(pri, 0, sizeof(*pri));
06379 
06380    ast_mutex_init(&pri->lock);
06381 
06382    pri->master = AST_PTHREADT_NULL;
06383    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++)
06384       pri->fds[i] = -1;
06385 }

int sig_pri_is_alarm_ignored ( struct sig_pri_span pri  ) 

Determine if layer 1 alarms are ignored.

Parameters:
p Channel private pointer.
Returns:
TRUE if the alarm is ignored.

Definition at line 7842 of file sig_pri.c.

References sig_pri_span::layer1_ignored.

Referenced by handle_alarms(), handle_clear_alarms(), my_handle_dchan_exception(), and sig_pri_set_alarm().

07843 {
07844    return pri->layer1_ignored;
07845 }

int sig_pri_is_chan_available ( struct sig_pri_chan pvt  ) 

Determine if a private channel structure is available.

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

Definition at line 1159 of file sig_pri.c.

References sig_pri_chan::service_status, and sig_pri_is_chan_in_use().

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

01160 {
01161    return !sig_pri_is_chan_in_use(pvt)
01162 #if defined(HAVE_PRI_SERVICE_MESSAGES)
01163       /* And not out-of-service */
01164       && !pvt->service_status
01165 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
01166       ;
01167 }

int sig_pri_load ( const char *  cc_type_name  ) 

Load the sig_pri submodule.

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

Definition at line 8652 of file sig_pri.c.

References ao2_container_alloc, sig_pri_cc_monitor_instance_cmp_fn(), sig_pri_cc_monitor_instance_hash_fn(), sig_pri_cc_monitors, and sig_pri_cc_type_name.

Referenced by load_module().

08653 {
08654 #if defined(HAVE_PRI_CCSS)
08655    sig_pri_cc_type_name = cc_type_name;
08656    sig_pri_cc_monitors = ao2_container_alloc(37, sig_pri_cc_monitor_instance_hash_fn,
08657       sig_pri_cc_monitor_instance_cmp_fn);
08658    if (!sig_pri_cc_monitors) {
08659       return -1;
08660    }
08661 #endif   /* defined(HAVE_PRI_CCSS) */
08662    return 0;
08663 }

struct ast_channel* sig_pri_request ( struct sig_pri_chan p,
enum sig_pri_law  law,
const struct ast_channel requestor,
int  transfercapability 
)

Definition at line 1012 of file sig_pri.c.

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

Referenced by dahdi_request(), and pri_dchannel().

01013 {
01014    struct ast_channel *ast;
01015 
01016    ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
01017 
01018    sig_pri_set_outgoing(p, 1);
01019    ast = sig_pri_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
01020    if (!ast) {
01021       sig_pri_set_outgoing(p, 0);
01022    }
01023    return ast;
01024 }

void sig_pri_set_alarm ( struct sig_pri_chan p,
int  in_alarm 
)

Definition at line 187 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, sig_pri_chan::inalarm, sig_pri_chan::pri, sig_pri_chan::resetting, sig_pri_callback::set_alarm, sig_pri_is_alarm_ignored(), and SIG_PRI_RESET_IDLE.

Referenced by sig_pri_chan_alarm_notify().

00188 {
00189    if (sig_pri_is_alarm_ignored(p->pri)) {
00190       /* Always set not in alarm */
00191       in_alarm = 0;
00192    }
00193 
00194    /*
00195     * Clear the channel restart state when the channel alarm
00196     * changes to prevent the state from getting stuck when the link
00197     * goes down.
00198     */
00199    p->resetting = SIG_PRI_RESET_IDLE;
00200 
00201    p->inalarm = in_alarm;
00202    if (p->calls->set_alarm) {
00203       p->calls->set_alarm(p->chan_pvt, in_alarm);
00204    }
00205 }

int sig_pri_start_pri ( struct sig_pri_span pri  ) 

Definition at line 7625 of file sig_pri.c.

References ARRAY_LEN, AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), ast_event_unsubscribe(), ast_log(), ast_mutex_init, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strip(), ast_strlen_zero(), sig_pri_mbox::context, sig_pri_span::dchans, sig_pri_span::enable_service_message_support, sig_pri_span::fds, HAVE_PRI_SERVICE_MESSAGES, sig_pri_span::lock, LOG_ERROR, sig_pri_span::mbox, sig_pri_span::mwi_mailboxes, sig_pri_span::nodetype, sig_pri_mbox::number, sig_pri_span::sig, SIG_BRI, SIG_BRI_PTMP, sig_pri_cc_type_name, sig_pri_mwi_event_cb(), SIG_PRI_NUM_DCHANS, sig_pri_sort_pri_chans(), sig_pri_span::span, strsep(), sig_pri_mbox::sub, and sig_pri_span::switchtype.

Referenced by setup_dahdi_int().

07626 {
07627    int x;
07628    int i;
07629 #if defined(HAVE_PRI_MWI)
07630    char *saveptr;
07631    char *mbox_number;
07632    char *mbox_context;
07633    struct ast_str *mwi_description = ast_str_alloca(64);
07634 #endif   /* defined(HAVE_PRI_MWI) */
07635 
07636 #if defined(HAVE_PRI_MWI)
07637    /* Prepare the mbox[] for use. */
07638    for (i = 0; i < ARRAY_LEN(pri->mbox); ++i) {
07639       if (pri->mbox[i].sub) {
07640          pri->mbox[i].sub = ast_event_unsubscribe(pri->mbox[i].sub);
07641       }
07642    }
07643 #endif   /* defined(HAVE_PRI_MWI) */
07644 
07645    ast_mutex_init(&pri->lock);
07646    sig_pri_sort_pri_chans(pri);
07647 
07648 #if defined(HAVE_PRI_MWI)
07649    /*
07650     * Split the mwi_mailboxes configuration string into the mbox[]:
07651     * mailbox_number[@context]{,mailbox_number[@context]}
07652     */
07653    i = 0;
07654    saveptr = pri->mwi_mailboxes;
07655    while (i < ARRAY_LEN(pri->mbox)) {
07656       mbox_number = strsep(&saveptr, ",");
07657       if (!mbox_number) {
07658          break;
07659       }
07660       /* Split the mailbox_number and context */
07661       mbox_context = strchr(mbox_number, '@');
07662       if (mbox_context) {
07663          *mbox_context++ = '\0';
07664          mbox_context = ast_strip(mbox_context);
07665       }
07666       mbox_number = ast_strip(mbox_number);
07667       if (ast_strlen_zero(mbox_number)) {
07668          /* There is no mailbox number.  Skip it. */
07669          continue;
07670       }
07671       if (ast_strlen_zero(mbox_context)) {
07672          /* There was no context so use the default. */
07673          mbox_context = "default";
07674       }
07675 
07676       /* Fill the mbox[] element. */
07677       ast_str_set(&mwi_description, -1, "%s span %d[%d] MWI mailbox %s@%s",
07678          sig_pri_cc_type_name, pri->span, i, mbox_number, mbox_context);
07679       pri->mbox[i].sub = ast_event_subscribe(AST_EVENT_MWI, sig_pri_mwi_event_cb,
07680          ast_str_buffer(mwi_description), pri,
07681          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox_number,
07682          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mbox_context,
07683          AST_EVENT_IE_END);
07684       if (!pri->mbox[i].sub) {
07685          ast_log(LOG_ERROR, "%s span %d could not subscribe to MWI events for %s@%s.",
07686             sig_pri_cc_type_name, pri->span, mbox_number, mbox_context);
07687          continue;
07688       }
07689       pri->mbox[i].number = mbox_number;
07690       pri->mbox[i].context = mbox_context;
07691       ++i;
07692    }
07693 #endif   /* defined(HAVE_PRI_MWI) */
07694 
07695    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
07696       if (pri->fds[i] == -1) {
07697          break;
07698       }
07699 
07700       switch (pri->sig) {
07701       case SIG_BRI:
07702          pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
07703          break;
07704       case SIG_BRI_PTMP:
07705          pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
07706          break;
07707       default:
07708          pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
07709 #if defined(HAVE_PRI_SERVICE_MESSAGES)
07710          if (pri->enable_service_message_support) {
07711             pri_set_service_message_support(pri->dchans[i], 1);
07712          }
07713 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
07714          break;
07715       }
07716 
07717       pri_set_overlapdial(pri->dchans[i], (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING) ? 1 : 0);
07718 #ifdef HAVE_PRI_PROG_W_CAUSE
07719       pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
07720 #endif
07721 #ifdef HAVE_PRI_INBANDDISCONNECT
07722       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
07723 #endif
07724       /* Enslave to master if appropriate */
07725       if (i)
07726          pri_enslave(pri->dchans[0], pri->dchans[i]);
07727       if (!pri->dchans[i]) {
07728          if (pri->fds[i] > 0)
07729             close(pri->fds[i]);
07730          pri->fds[i] = -1;
07731          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
07732          return -1;
07733       }
07734       pri_set_debug(pri->dchans[i], SIG_PRI_DEBUG_DEFAULT);
07735       pri_set_nsf(pri->dchans[i], pri->nsf);
07736 #ifdef PRI_GETSET_TIMERS
07737       for (x = 0; x < PRI_MAX_TIMERS; x++) {
07738          if (pri->pritimers[x] != 0)
07739             pri_set_timer(pri->dchans[i], x, pri->pritimers[x]);
07740       }
07741 #endif
07742    }
07743 
07744    /* Assume primary is the one we use */
07745    pri->pri = pri->dchans[0];
07746 
07747 #if defined(HAVE_PRI_CALL_HOLD)
07748    pri_hold_enable(pri->pri, 1);
07749 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
07750 #if defined(HAVE_PRI_CALL_REROUTING)
07751    pri_reroute_enable(pri->pri, 1);
07752 #endif   /* defined(HAVE_PRI_CALL_REROUTING) */
07753 #if defined(HAVE_PRI_HANGUP_FIX)
07754    pri_hangup_fix_enable(pri->pri, 1);
07755 #endif   /* defined(HAVE_PRI_HANGUP_FIX) */
07756 #if defined(HAVE_PRI_CCSS)
07757    pri_cc_enable(pri->pri, 1);
07758    pri_cc_recall_mode(pri->pri, pri->cc_ptmp_recall_mode);
07759    pri_cc_retain_signaling_req(pri->pri, pri->cc_qsig_signaling_link_req);
07760    pri_cc_retain_signaling_rsp(pri->pri, pri->cc_qsig_signaling_link_rsp);
07761 #endif   /* defined(HAVE_PRI_CCSS) */
07762 #if defined(HAVE_PRI_TRANSFER)
07763    pri_transfer_enable(pri->pri, 1);
07764 #endif   /* defined(HAVE_PRI_TRANSFER) */
07765 #if defined(HAVE_PRI_AOC_EVENTS)
07766    pri_aoc_events_enable(pri->pri, 1);
07767 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
07768 #if defined(HAVE_PRI_CALL_WAITING)
07769    pri_connect_ack_enable(pri->pri, 1);
07770 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
07771 #if defined(HAVE_PRI_MCID)
07772    pri_mcid_enable(pri->pri, 1);
07773 #endif   /* defined(HAVE_PRI_MCID) */
07774 #if defined(HAVE_PRI_L2_PERSISTENCE)
07775    pri_persistent_layer2_option(pri->pri, pri->l2_persistence);
07776 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
07777 
07778    pri->resetpos = -1;
07779    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
07780       for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
07781          if (!pri->dchans[i])
07782             break;
07783          if (pri->fds[i] > 0)
07784             close(pri->fds[i]);
07785          pri->fds[i] = -1;
07786       }
07787       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
07788       return -1;
07789    }
07790 
07791 #if defined(HAVE_PRI_MWI)
07792    /*
07793     * Send the initial MWI indications from the event cache for this span.
07794     *
07795     * If we were loaded after app_voicemail the event would already be in
07796     * the cache.  If we were loaded before app_voicemail the event would not
07797     * be in the cache yet and app_voicemail will send the event when it
07798     * gets loaded.
07799     */
07800    sig_pri_mwi_cache_update(pri);
07801 #endif   /* defined(HAVE_PRI_MWI) */
07802 
07803    return 0;
07804 }

void sig_pri_stop_pri ( struct sig_pri_span pri  ) 

Stop PRI span.

Since:
1.8
Parameters:
pri PRI span control structure.
Returns:
Nothing

Definition at line 7560 of file sig_pri.c.

References ARRAY_LEN, ast_event_unsubscribe(), sig_pri_span::mbox, and sig_pri_mbox::sub.

Referenced by __unload_module().

07561 {
07562 #if defined(HAVE_PRI_MWI)
07563    int idx;
07564 #endif   /* defined(HAVE_PRI_MWI) */
07565 
07566 #if defined(HAVE_PRI_MWI)
07567    for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
07568       if (pri->mbox[idx].sub) {
07569          pri->mbox[idx].sub = ast_event_unsubscribe(pri->mbox[idx].sub);
07570       }
07571    }
07572 #endif   /* defined(HAVE_PRI_MWI) */
07573 }

void sig_pri_unload ( void   ) 

Unload the sig_pri submodule.

Since:
1.8
Returns:
Nothing

Definition at line 8671 of file sig_pri.c.

References ao2_ref, and sig_pri_cc_monitors.

Referenced by __unload_module().

08672 {
08673 #if defined(HAVE_PRI_CCSS)
08674    if (sig_pri_cc_monitors) {
08675       ao2_ref(sig_pri_cc_monitors, -1);
08676       sig_pri_cc_monitors = NULL;
08677    }
08678 #endif   /* defined(HAVE_PRI_CCSS) */
08679 }


Variable Documentation

const char dahdi_db[] = "dahdi/registry" [static]

The AstDB family.

Definition at line 219 of file sig_pri.h.

Referenced by destroy_all_channels().


Generated on Mon Oct 8 12:39:29 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7