Mon Oct 8 12:39:29 2012

Asterisk developer's documentation


sig_pri.c File Reference

PRI signaling module. More...

#include "asterisk.h"
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/say.h"
#include "asterisk/manager.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/cli.h"
#include "asterisk/transcap.h"
#include "asterisk/features.h"
#include "asterisk/aoc.h"
#include "sig_pri.h"

Go to the source code of this file.

Data Structures

struct  sig_pri_cc_agent_prv
struct  sig_pri_cc_monitor_instance
struct  xfer_rsp_data

Defines

#define DCHAN_AVAILABLE   (DCHAN_NOTINALARM | DCHAN_UP)
#define DCHAN_NOTINALARM   (1 << 0)
#define DCHAN_UP   (1 << 1)
#define FORCE_RESTART_UNAVAIL_CHANS   1
#define PRI_CHANNEL(p)   ((p) & 0xff)
#define PRI_CIS_CALL   (1 << 17)
#define PRI_EXPLICIT   (1 << 16)
#define PRI_HELD_CALL   (1 << 18)
#define PRI_SPAN(p)   (((p) >> 8) & 0xff)
#define SIG_PRI_SC_HEADER   "%-4s %4s %-4s %-4s %-10s %-4s %s\n"
#define SIG_PRI_SC_LINE   "%4d %4d %-4s %-4s %-10s %-4s %s"

Typedefs

typedef void(*) xfer_rsp_callback (void *data, int is_successful)
 Protocol callback to indicate if transfer will happen.

Enumerations

enum  SIG_PRI_CALL_OPT_ARGS { OPT_ARG_KEYPAD = 0, OPT_ARG_AOC_REQUEST, OPT_ARG_ARRAY_SIZE }
enum  SIG_PRI_CALL_OPT_FLAGS { OPT_KEYPAD = (1 << 0), OPT_REVERSE_CHARGE = (1 << 1), OPT_AOC_REQUEST = (1 << 2) }

Functions

static void apply_plan_to_existing_number (char *buf, size_t size, const struct sig_pri_span *pri, const char *number, int plan)
static void apply_plan_to_number (char *buf, size_t size, const struct sig_pri_span *pri, const char *number, int plan)
static unsigned char ast_pri_pack_hex_char (char c)
static int ast_pri_pack_hex_string (unsigned char *dst, char *src, int maxlen)
static int ast_to_pri_char_set (enum AST_PARTY_CHAR_SET ast_char_set)
static int ast_to_pri_presentation (int ast_presentation)
static int ast_to_pri_reason (enum AST_REDIRECTING_REASON ast_reason)
static void build_status (char *s, size_t len, int status, int active)
static int detect_aoc_e_subcmd (const struct pri_subcommands *subcmds)
static char * dialplan2str (int dialplan)
static void * do_idle_thread (void *v_pvt)
static int pri_active_dchan_index (struct sig_pri_span *pri)
static void pri_check_restart (struct sig_pri_span *pri)
static void * pri_dchannel (void *vpri)
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)
static void pri_find_dchan (struct sig_pri_span *pri)
static int pri_find_empty_chan (struct sig_pri_span *pri, int backwards)
static int pri_find_empty_nobch (struct sig_pri_span *pri)
static int pri_find_fixup_principle (struct sig_pri_span *pri, int channel, q931_call *call)
static int pri_find_principle (struct sig_pri_span *pri, int channel, q931_call *call)
static int pri_find_principle_by_call (struct sig_pri_span *pri, q931_call *call)
static int pri_fixup_principle (struct sig_pri_span *pri, int principle, q931_call *call)
static int pri_grab (struct sig_pri_chan *p, struct sig_pri_span *pri)
int pri_is_up (struct sig_pri_span *pri)
int pri_maintenance_bservice (struct pri *pri, struct sig_pri_chan *p, int changestatus)
static const char * pri_order (int level)
static void pri_queue_control (struct sig_pri_span *pri, int chanpos, int subclass)
static void pri_queue_frame (struct sig_pri_span *pri, int chanpos, struct ast_frame *frame)
static void pri_rel (struct sig_pri_span *pri)
int pri_send_callrerouting_facility_exec (struct sig_pri_chan *p, enum ast_channel_state chanstate, const char *destination, const char *original, const char *reason)
int pri_send_keypad_facility_exec (struct sig_pri_chan *p, const char *digits)
static void * pri_ss_thread (void *data)
static enum AST_PARTY_CHAR_SET pri_to_ast_char_set (int pri_char_set)
static int pri_to_ast_presentation (int pri_presentation)
static enum AST_REDIRECTING_REASON pri_to_ast_reason (int pri_reason)
static unsigned int PVT_TO_CHANNEL (struct sig_pri_chan *p)
static char * redirectingreason2str (int redirectingreason)
static void sig_pri_ami_channel_event (struct sig_pri_chan *p)
int sig_pri_answer (struct sig_pri_chan *p, struct ast_channel *ast)
static enum ast_aoc_s_charged_item sig_pri_aoc_charged_item_to_ast (enum PRI_AOC_CHARGED_ITEM value)
static enum PRI_AOC_CHARGED_ITEM sig_pri_aoc_charged_item_to_pri (enum PRI_AOC_CHARGED_ITEM value)
static void sig_pri_aoc_d_from_ast (struct sig_pri_chan *pvt, struct ast_aoc_decoded *decoded)
static void sig_pri_aoc_d_from_pri (const struct pri_subcmd_aoc_d *aoc_d, struct ast_channel *owner, int passthrough)
static void sig_pri_aoc_e_from_ast (struct sig_pri_chan *pvt, struct ast_aoc_decoded *decoded)
static void sig_pri_aoc_e_from_pri (const struct pri_subcmd_aoc_e *aoc_e, struct ast_channel *owner, int passthrough)
static int sig_pri_aoc_multiplier_from_ast (enum ast_aoc_currency_multiplier mult)
static int sig_pri_aoc_multiplier_from_pri (const int mult)
static void sig_pri_aoc_request_from_pri (const struct pri_subcmd_aoc_request *aoc_request, struct sig_pri_chan *pvt, q931_call *call)
static void sig_pri_aoc_s_from_ast (struct sig_pri_chan *pvt, struct ast_aoc_decoded *decoded)
static void sig_pri_aoc_s_from_pri (const struct pri_subcmd_aoc_s *aoc_s, struct ast_channel *owner, int passthrough)
static enum ast_aoc_time_scale sig_pri_aoc_scale_to_ast (enum PRI_AOC_TIME_SCALE value)
static enum PRI_AOC_TIME_SCALE sig_pri_aoc_scale_to_pri (enum ast_aoc_time_scale value)
static int sig_pri_attempt_transfer (struct sig_pri_span *pri, q931_call *call_1_pri, int call_1_held, q931_call *call_2_pri, int call_2_held, xfer_rsp_callback rsp_callback, void *data)
int sig_pri_available (struct sig_pri_chan **pvt, int is_specific_channel)
static int sig_pri_available_check (struct sig_pri_chan *pvt)
int sig_pri_call (struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, int timeout, int layer1)
static const char * sig_pri_call_level2str (enum sig_pri_call_level level)
int sig_pri_cc_agent_callee_available (struct ast_cc_agent *agent)
 Alert the caller that it is time to try recalling.
static int sig_pri_cc_agent_cmp_cc_id (void *obj, void *arg, int flags)
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.
static int sig_pri_cc_available (struct sig_pri_span *pri, int chanpos, long cc_id, enum ast_cc_service_type service)
static void sig_pri_cc_generic_check (struct sig_pri_span *pri, int chanpos, enum ast_cc_service_type service)
static void sig_pri_cc_link_canceled (struct sig_pri_span *pri, long cc_id, int is_agent)
int sig_pri_cc_monitor_cancel_available_timer (struct ast_cc_monitor *monitor, int *sched_id)
 Cancel the running available timer.
static int sig_pri_cc_monitor_cmp_cc_id (void *obj, void *arg, int flags)
void sig_pri_cc_monitor_destructor (void *monitor_pvt)
 Destroy PRI private data on the monitor.
static int sig_pri_cc_monitor_instance_cmp_fn (void *obj, void *arg, int flags)
static void sig_pri_cc_monitor_instance_destroy (void *data)
static int sig_pri_cc_monitor_instance_hash_fn (const void *obj, const int flags)
static struct sig_pri_cc_monitor_instancesig_pri_cc_monitor_instance_init (int core_id, struct sig_pri_span *pri, long cc_id, const char *device_name)
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)
static int sig_pri_cmp_pri_chans (const void *left, const void *right)
static struct sig_pri_chansig_pri_cw_available (struct sig_pri_span *pri)
void sig_pri_dial_complete (struct sig_pri_chan *pvt, struct ast_channel *ast)
 DTMF dial string complete.
static void sig_pri_dial_digits (struct sig_pri_chan *p, const char *dial_string)
int sig_pri_digit_begin (struct sig_pri_chan *pvt, struct ast_channel *ast, char digit)
static void sig_pri_dsp_reset_and_flush_digits (struct sig_pri_chan *p)
static void sig_pri_event_party_id (struct ast_str **msg, const char *prefix, struct ast_party_id *party)
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.
static struct ast_cc_agentsig_pri_find_cc_agent_by_cc_id (struct sig_pri_span *pri, long cc_id)
static struct sig_pri_cc_monitor_instancesig_pri_find_cc_monitor_by_cc_id (struct sig_pri_span *pri, long cc_id)
void sig_pri_fixup (struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_pri_chan *pchan)
static void sig_pri_fixup_chans (struct sig_pri_chan *old_chan, struct sig_pri_chan *new_chan)
static const char * sig_pri_get_orig_dialstring (struct sig_pri_chan *p)
static void sig_pri_handle_cis_subcmds (struct sig_pri_span *pri, int event_id, const struct pri_subcommands *subcmds, q931_call *call_rsp)
static void sig_pri_handle_dchan_exception (struct sig_pri_span *pri, int index)
static int sig_pri_handle_hold (struct sig_pri_span *pri, pri_event *ev)
static void sig_pri_handle_retrieve (struct sig_pri_span *pri, pri_event *ev)
static void sig_pri_handle_subcmds (struct sig_pri_span *pri, int chanpos, int event_id, int channel, const struct pri_subcommands *subcmds, q931_call *call_rsp)
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)
static void sig_pri_init_config (struct sig_pri_chan *pvt, struct sig_pri_span *pri)
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.
static int sig_pri_is_chan_in_use (struct sig_pri_chan *pvt)
static int sig_pri_is_cis_call (int channel)
static void sig_pri_kill_call (struct sig_pri_span *pri, q931_call *call, int cause)
int sig_pri_load (const char *cc_type_name)
 Load the sig_pri submodule.
static void sig_pri_lock_owner (struct sig_pri_span *pri, int chanpos)
static void sig_pri_lock_private (struct sig_pri_chan *p)
static void sig_pri_make_cc_dialstring (struct sig_pri_chan *p, char *buf, size_t buf_size)
static void sig_pri_mcid_event (struct sig_pri_span *pri, const struct pri_subcmd_mcid_req *mcid, struct ast_channel *owner)
static int sig_pri_msn_match (const char *msn_patterns, const char *exten)
static void sig_pri_mwi_cache_update (struct sig_pri_span *pri)
static void sig_pri_mwi_event_cb (const struct ast_event *event, void *userdata)
static struct ast_channelsig_pri_new_ast_channel (struct sig_pri_chan *p, int state, int ulaw, int transfercapability, char *exten, const struct ast_channel *requestor)
static void sig_pri_open_media (struct sig_pri_chan *p)
static void sig_pri_party_id_convert (struct ast_party_id *ast_id, const struct pri_party_id *pri_id, struct sig_pri_span *pri)
static void sig_pri_party_id_from_ast (struct pri_party_id *pri_id, const struct ast_party_id *ast_id)
static void sig_pri_party_name_convert (struct ast_party_name *ast_name, const struct pri_party_name *pri_name)
static void sig_pri_party_name_from_ast (struct pri_party_name *pri_name, const struct ast_party_name *ast_name)
static void sig_pri_party_number_convert (struct ast_party_number *ast_number, const struct pri_party_number *pri_number, struct sig_pri_span *pri)
static void sig_pri_party_number_from_ast (struct pri_party_number *pri_number, const struct ast_party_number *ast_number)
static void sig_pri_party_subaddress_from_ast (struct pri_party_subaddress *pri_subaddress, const struct ast_party_subaddress *ast_subaddress)
static int sig_pri_play_tone (struct sig_pri_chan *p, enum sig_pri_tone tone)
static void sig_pri_redirecting_convert (struct ast_party_redirecting *ast_redirecting, const struct pri_party_redirecting *pri_redirecting, const struct ast_party_redirecting *ast_guide, struct sig_pri_span *pri)
static void sig_pri_redirecting_update (struct sig_pri_chan *pvt, struct ast_channel *ast)
ast_channelsig_pri_request (struct sig_pri_chan *p, enum sig_pri_law law, const struct ast_channel *requestor, int transfercapability)
static void sig_pri_send_aoce_termination_request (struct sig_pri_span *pri, int chanpos, unsigned int ms)
static void sig_pri_send_mwi_indication (struct sig_pri_span *pri, const char *mbox_number, const char *mbox_context, int num_messages)
void sig_pri_set_alarm (struct sig_pri_chan *p, int in_alarm)
static void sig_pri_set_caller_id (struct sig_pri_chan *p)
static void sig_pri_set_dialing (struct sig_pri_chan *p, int is_dialing)
static void sig_pri_set_digital (struct sig_pri_chan *p, int is_digital)
static void sig_pri_set_dnid (struct sig_pri_chan *p, const char *dnid)
static int sig_pri_set_echocanceller (struct sig_pri_chan *p, int enable)
static void sig_pri_set_outgoing (struct sig_pri_chan *p, int is_outgoing)
static void sig_pri_set_rdnis (struct sig_pri_chan *p, const char *rdnis)
static void sig_pri_set_subaddress (struct ast_party_subaddress *ast_subaddress, const struct pri_party_subaddress *pri_subaddress)
static void sig_pri_sort_pri_chans (struct sig_pri_span *pri)
static void sig_pri_span_devstate_changed (struct sig_pri_span *pri)
int sig_pri_start_pri (struct sig_pri_span *pri)
void sig_pri_stop_pri (struct sig_pri_span *pri)
 Stop PRI span.
static void sig_pri_transfer_rsp (void *data, int is_successful)
void sig_pri_unload (void)
 Unload the sig_pri submodule.
static void sig_pri_unlock_private (struct sig_pri_chan *p)

Variables

static int pri_gendigittimeout = 8000
static int pri_matchdigittimeout = 3000
static struct ast_app_option sig_pri_call_opts [128] = { [ 'K' ] = { .flag = OPT_KEYPAD , .arg_index = OPT_ARG_KEYPAD + 1 }, [ 'R' ] = { .flag = OPT_REVERSE_CHARGE }, [ 'A' ] = { .flag = OPT_AOC_REQUEST , .arg_index = OPT_ARG_AOC_REQUEST + 1 }, }
static struct ao2_containersig_pri_cc_monitors
static const char * sig_pri_cc_type_name


Detailed Description

PRI signaling module.

Author:
Matthew Fredrickson <creslin@digium.com>

Definition in file sig_pri.c.


Define Documentation

#define DCHAN_AVAILABLE   (DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 119 of file sig_pri.c.

Referenced by pri_is_up().

#define DCHAN_NOTINALARM   (1 << 0)

Definition at line 108 of file sig_pri.c.

Referenced by build_status(), pri_event_alarm(), and pri_event_noalarm().

#define DCHAN_UP   (1 << 1)

Definition at line 109 of file sig_pri.c.

Referenced by pri_dchannel(), and pri_event_alarm().

#define FORCE_RESTART_UNAVAIL_CHANS   1

Define to force a RESTART on a channel that returns a cause code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause is because of a stuck channel on the peer and the channel is always the next channel we pick for an outgoing call then this can help.

Definition at line 75 of file sig_pri.c.

#define PRI_CHANNEL (  )     ((p) & 0xff)

Definition at line 112 of file sig_pri.c.

Referenced by pri_find_fixup_principle(), pri_find_principle(), sig_pri_handle_retrieve(), and sig_pri_handle_subcmds().

#define PRI_CIS_CALL   (1 << 17)

Definition at line 115 of file sig_pri.c.

Referenced by sig_pri_is_cis_call().

#define PRI_EXPLICIT   (1 << 16)

Definition at line 114 of file sig_pri.c.

Referenced by PVT_TO_CHANNEL().

#define PRI_HELD_CALL   (1 << 18)

Definition at line 116 of file sig_pri.c.

Referenced by pri_find_principle(), and sig_pri_handle_retrieve().

#define PRI_SPAN (  )     (((p) >> 8) & 0xff)

Definition at line 113 of file sig_pri.c.

Referenced by pri_find_fixup_principle(), pri_maintenance_bservice(), and sig_pri_handle_subcmds().

#define SIG_PRI_SC_HEADER   "%-4s %4s %-4s %-4s %-10s %-4s %s\n"

Definition at line 7880 of file sig_pri.c.

Referenced by sig_pri_cli_show_channels_header().

#define SIG_PRI_SC_LINE   "%4d %4d %-4s %-4s %-10s %-4s %s"

Definition at line 7881 of file sig_pri.c.

Referenced by sig_pri_cli_show_channels().


Typedef Documentation

typedef void(*) xfer_rsp_callback(void *data, int is_successful)

Protocol callback to indicate if transfer will happen.

Since:
1.8
Parameters:
data Callback user data pointer
is_successful TRUE if the transfer will happen.
Returns:
Nothing

Definition at line 2312 of file sig_pri.c.


Enumeration Type Documentation

enum SIG_PRI_CALL_OPT_ARGS

Enumerator:
OPT_ARG_KEYPAD 
OPT_ARG_AOC_REQUEST 
OPT_ARG_ARRAY_SIZE 

Definition at line 6549 of file sig_pri.c.

06549                            {
06550    OPT_ARG_KEYPAD = 0,
06551    OPT_ARG_AOC_REQUEST,
06552 
06553    /* note: this entry _MUST_ be the last one in the enum */
06554    OPT_ARG_ARRAY_SIZE,
06555 };

enum SIG_PRI_CALL_OPT_FLAGS

Enumerator:
OPT_KEYPAD 
OPT_REVERSE_CHARGE 
OPT_AOC_REQUEST 

Definition at line 6544 of file sig_pri.c.

06544                             {
06545    OPT_KEYPAD =         (1 << 0),
06546    OPT_REVERSE_CHARGE = (1 << 1),   /* Collect call */
06547    OPT_AOC_REQUEST =    (1 << 2),   /* AOC Request */
06548 };


Function Documentation

static void apply_plan_to_existing_number ( char *  buf,
size_t  size,
const struct sig_pri_span pri,
const char *  number,
int  plan 
) [static]

Definition at line 1663 of file sig_pri.c.

References apply_plan_to_number(), ast_strlen_zero(), and sig_pri_chan::pri.

Referenced by sig_pri_party_number_convert().

01664 {
01665    /* Make sure a number exists so the prefix isn't placed on an empty string. */
01666    if (ast_strlen_zero(number)) {
01667       if (size) {
01668          *buf = '\0';
01669       }
01670       return;
01671    }
01672    apply_plan_to_number(buf, size, pri, number, plan);
01673 }

static void apply_plan_to_number ( char *  buf,
size_t  size,
const struct sig_pri_span pri,
const char *  number,
int  plan 
) [static]

Definition at line 1627 of file sig_pri.c.

References sig_pri_span::internationalprefix, sig_pri_span::localprefix, sig_pri_span::nationalprefix, sig_pri_chan::pri, sig_pri_span::privateprefix, and sig_pri_span::unknownprefix.

Referenced by apply_plan_to_existing_number().

01628 {
01629    switch (plan) {
01630    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
01631       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
01632       break;
01633    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
01634       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
01635       break;
01636    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
01637       snprintf(buf, size, "%s%s", pri->localprefix, number);
01638       break;
01639    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
01640       snprintf(buf, size, "%s%s", pri->privateprefix, number);
01641       break;
01642    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
01643       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
01644       break;
01645    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
01646       snprintf(buf, size, "%s", number);
01647       break;
01648    }
01649 }

static unsigned char ast_pri_pack_hex_char ( char  c  )  [static]

Definition at line 695 of file sig_pri.c.

Referenced by ast_pri_pack_hex_string().

00696 {
00697    unsigned char res;
00698 
00699    if (c < '0') {
00700       res = 0;
00701    } else if (c < ('9' + 1)) {
00702       res = c - '0';
00703    } else if (c < 'A') {
00704       res = 0;
00705    } else if (c < ('F' + 1)) {
00706       res = c - 'A' + 10;
00707    } else if (c < 'a') {
00708       res = 0;
00709    } else if (c < ('f' + 1)) {
00710       res = c - 'a' + 10;
00711    } else {
00712       res = 0;
00713    }
00714    return res;
00715 }

static int ast_pri_pack_hex_string ( unsigned char *  dst,
char *  src,
int  maxlen 
) [static]

Definition at line 734 of file sig_pri.c.

References ast_pri_pack_hex_char(), and len().

Referenced by sig_pri_party_subaddress_from_ast().

00735 {
00736    int res = 0;
00737    int len = strlen(src);
00738 
00739    if (len > (2 * maxlen)) {
00740       len = 2 * maxlen;
00741    }
00742 
00743    res = len / 2 + len % 2;
00744 
00745    while (len > 1) {
00746       *dst = ast_pri_pack_hex_char(*src) << 4;
00747       src++;
00748       *dst |= ast_pri_pack_hex_char(*src);
00749       dst++, src++;
00750       len -= 2;
00751    }
00752    if (len) { /* 1 left */
00753       *dst = ast_pri_pack_hex_char(*src) << 4;
00754    }
00755    return res;
00756 }

static int ast_to_pri_char_set ( enum AST_PARTY_CHAR_SET  ast_char_set  )  [static]

Definition at line 597 of file sig_pri.c.

References AST_PARTY_CHAR_SET_ISO10646_BMPSTRING, AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING, AST_PARTY_CHAR_SET_ISO8859_1, AST_PARTY_CHAR_SET_ISO8859_2, AST_PARTY_CHAR_SET_ISO8859_3, AST_PARTY_CHAR_SET_ISO8859_4, AST_PARTY_CHAR_SET_ISO8859_5, AST_PARTY_CHAR_SET_ISO8859_7, AST_PARTY_CHAR_SET_UNKNOWN, and AST_PARTY_CHAR_SET_WITHDRAWN.

Referenced by sig_pri_party_name_from_ast().

00598 {
00599    int pri_char_set;
00600 
00601    switch (ast_char_set) {
00602    default:
00603    case AST_PARTY_CHAR_SET_UNKNOWN:
00604       pri_char_set = PRI_CHAR_SET_UNKNOWN;
00605       break;
00606    case AST_PARTY_CHAR_SET_ISO8859_1:
00607       pri_char_set = PRI_CHAR_SET_ISO8859_1;
00608       break;
00609    case AST_PARTY_CHAR_SET_WITHDRAWN:
00610       pri_char_set = PRI_CHAR_SET_WITHDRAWN;
00611       break;
00612    case AST_PARTY_CHAR_SET_ISO8859_2:
00613       pri_char_set = PRI_CHAR_SET_ISO8859_2;
00614       break;
00615    case AST_PARTY_CHAR_SET_ISO8859_3:
00616       pri_char_set = PRI_CHAR_SET_ISO8859_3;
00617       break;
00618    case AST_PARTY_CHAR_SET_ISO8859_4:
00619       pri_char_set = PRI_CHAR_SET_ISO8859_4;
00620       break;
00621    case AST_PARTY_CHAR_SET_ISO8859_5:
00622       pri_char_set = PRI_CHAR_SET_ISO8859_5;
00623       break;
00624    case AST_PARTY_CHAR_SET_ISO8859_7:
00625       pri_char_set = PRI_CHAR_SET_ISO8859_7;
00626       break;
00627    case AST_PARTY_CHAR_SET_ISO10646_BMPSTRING:
00628       pri_char_set = PRI_CHAR_SET_ISO10646_BMPSTRING;
00629       break;
00630    case AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING:
00631       pri_char_set = PRI_CHAR_SET_ISO10646_UTF_8STRING;
00632       break;
00633    }
00634 
00635    return pri_char_set;
00636 }

static int ast_to_pri_presentation ( int  ast_presentation  )  [static]

Definition at line 492 of file sig_pri.c.

References AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.

Referenced by sig_pri_party_name_from_ast(), and sig_pri_party_number_from_ast().

00493 {
00494    int pri_presentation;
00495 
00496    switch (ast_presentation) {
00497    case AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED:
00498       pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
00499       break;
00500    case AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN:
00501       pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN;
00502       break;
00503    case AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN:
00504       pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN;
00505       break;
00506    case AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER:
00507       pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER;
00508       break;
00509 
00510    case AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED:
00511       pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
00512       break;
00513    case AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN:
00514       pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN;
00515       break;
00516    case AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN:
00517       pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN;
00518       break;
00519    case AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER:
00520       pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER;
00521       break;
00522 
00523    case AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED:
00524    case AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN:
00525    case AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN:
00526    case AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER:
00527       pri_presentation = PRES_NUMBER_NOT_AVAILABLE;
00528       break;
00529 
00530    default:
00531       pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
00532       break;
00533    }
00534 
00535    return pri_presentation;
00536 }

static int ast_to_pri_reason ( enum AST_REDIRECTING_REASON  ast_reason  )  [static]

Definition at line 402 of file sig_pri.c.

References AST_REDIRECTING_REASON_DEFLECTION, AST_REDIRECTING_REASON_NO_ANSWER, AST_REDIRECTING_REASON_UNCONDITIONAL, AST_REDIRECTING_REASON_UNKNOWN, and AST_REDIRECTING_REASON_USER_BUSY.

Referenced by sig_pri_redirecting_update().

00403 {
00404    int pri_reason;
00405 
00406    switch (ast_reason) {
00407    case AST_REDIRECTING_REASON_USER_BUSY:
00408       pri_reason = PRI_REDIR_FORWARD_ON_BUSY;
00409       break;
00410    case AST_REDIRECTING_REASON_NO_ANSWER:
00411       pri_reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
00412       break;
00413    case AST_REDIRECTING_REASON_UNCONDITIONAL:
00414       pri_reason = PRI_REDIR_UNCONDITIONAL;
00415       break;
00416    case AST_REDIRECTING_REASON_DEFLECTION:
00417       pri_reason = PRI_REDIR_DEFLECTION;
00418       break;
00419    case AST_REDIRECTING_REASON_UNKNOWN:
00420    default:
00421       pri_reason = PRI_REDIR_UNKNOWN;
00422       break;
00423    }
00424 
00425    return pri_reason;
00426 }

static void build_status ( char *  s,
size_t  len,
int  status,
int  active 
) [static]

Definition at line 7929 of file sig_pri.c.

References DCHAN_NOTINALARM.

Referenced by sig_pri_cli_show_span(), and sig_pri_cli_show_spans().

07930 {
07931    if (!s || len < 1) {
07932       return;
07933    }
07934    s[0] = '\0';
07935    if (!(status & DCHAN_NOTINALARM))
07936       strncat(s, "In Alarm, ", len - strlen(s) - 1);
07937    if (status & DCHAN_UP)
07938       strncat(s, "Up", len - strlen(s) - 1);
07939    else
07940       strncat(s, "Down", len - strlen(s) - 1);
07941    if (active)
07942       strncat(s, ", Active", len - strlen(s) - 1);
07943    else
07944       strncat(s, ", Standby", len - strlen(s) - 1);
07945    s[len - 1] = '\0';
07946 }

static int detect_aoc_e_subcmd ( const struct pri_subcommands *  subcmds  )  [static]

Definition at line 4057 of file sig_pri.c.

04058 {
04059    int i;
04060 
04061    if (!subcmds) {
04062       return 0;
04063    }
04064    for (i = 0; i < subcmds->counter_subcmd; ++i) {
04065       const struct pri_subcommand *subcmd = &subcmds->subcmd[i];
04066       if (subcmd->cmd == PRI_SUBCMD_AOC_E) {
04067          return 1;
04068       }
04069    }
04070    return 0;
04071 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 1607 of file sig_pri.c.

Referenced by sig_pri_call().

01608 {
01609    if (dialplan == -1) {
01610       return("Dynamically set dialplan in ISDN");
01611    }
01612    return (pri_plan2str(dialplan));
01613 }

static void* do_idle_thread ( void *  v_pvt  )  [static]

Definition at line 1827 of file sig_pri.c.

References ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_verb, ast_waitfor(), sig_pri_chan::channel, ast_channel::context, ast_channel::exten, f, sig_pri_span::idlecontext, sig_pri_span::idledial, sig_pri_span::idleext, LOG_WARNING, ast_channel::name, sig_pri_chan::owner, sig_pri_chan::pri, and ast_channel::priority.

Referenced by pri_dchannel().

01828 {
01829    struct sig_pri_chan *pvt = v_pvt;
01830    struct ast_channel *chan = pvt->owner;
01831    struct ast_frame *f;
01832    char ex[80];
01833    /* Wait up to 30 seconds for an answer */
01834    int newms, ms = 30000;
01835 
01836    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
01837    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
01838    if (ast_call(chan, ex, 0)) {
01839       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
01840       ast_hangup(chan);
01841       return NULL;
01842    }
01843    while ((newms = ast_waitfor(chan, ms)) > 0) {
01844       f = ast_read(chan);
01845       if (!f) {
01846          /* Got hangup */
01847          break;
01848       }
01849       if (f->frametype == AST_FRAME_CONTROL) {
01850          switch (f->subclass.integer) {
01851          case AST_CONTROL_ANSWER:
01852             /* Launch the PBX */
01853             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
01854             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
01855             chan->priority = 1;
01856             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
01857             ast_pbx_run(chan);
01858             /* It's already hungup, return immediately */
01859             return NULL;
01860          case AST_CONTROL_BUSY:
01861             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
01862             break;
01863          case AST_CONTROL_CONGESTION:
01864             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
01865             break;
01866          };
01867       }
01868       ast_frfree(f);
01869       ms = newms;
01870    }
01871    /* Hangup the channel since nothing happend */
01872    ast_hangup(chan);
01873    return NULL;
01874 }

static int pri_active_dchan_index ( struct sig_pri_span pri  )  [static]

Definition at line 1053 of file sig_pri.c.

References ast_log(), sig_pri_span::dchans, LOG_WARNING, sig_pri_span::pri, and SIG_PRI_NUM_DCHANS.

01054 {
01055    int x;
01056 
01057    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
01058       if ((pri->dchans[x] == pri->pri))
01059          return x;
01060    }
01061 
01062    ast_log(LOG_WARNING, "No active dchan found!\n");
01063    return -1;
01064 }

static void pri_check_restart ( struct sig_pri_span pri  )  [static]

Definition at line 1685 of file sig_pri.c.

References ast_log(), sig_pri_span::lastreset, LOG_NOTICE, sig_pri_span::numchans, sig_pri_span::pri, sig_pri_chan::pri, PVT_TO_CHANNEL(), sig_pri_span::pvts, sig_pri_span::resetpos, sig_pri_span::resetting, sig_pri_chan::resetting, sig_pri_chan::service_status, sig_pri_is_chan_in_use(), SIG_PRI_RESET_ACTIVE, sig_pri_span_devstate_changed(), sig_pri_span::span, SRVST_FAREND, and SRVST_NEAREND.

Referenced by pri_dchannel().

01686 {
01687 #if defined(HAVE_PRI_SERVICE_MESSAGES)
01688    unsigned why;
01689 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
01690 
01691    for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
01692       if (!pri->pvts[pri->resetpos]
01693          || pri->pvts[pri->resetpos]->no_b_channel
01694          || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
01695          continue;
01696       }
01697 #if defined(HAVE_PRI_SERVICE_MESSAGES)
01698       why = pri->pvts[pri->resetpos]->service_status;
01699       if (why) {
01700          ast_log(LOG_NOTICE,
01701             "Span %d: channel %d out-of-service (reason: %s), not sending RESTART\n",
01702             pri->span, pri->pvts[pri->resetpos]->channel,
01703             (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
01704          continue;
01705       }
01706 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
01707       break;
01708    }
01709    if (pri->resetpos < pri->numchans) {
01710       /* Mark the channel as resetting and restart it */
01711       pri->pvts[pri->resetpos]->resetting = SIG_PRI_RESET_ACTIVE;
01712       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
01713    } else {
01714       pri->resetting = 0;
01715       time(&pri->lastreset);
01716       sig_pri_span_devstate_changed(pri);
01717    }
01718 }

static void* pri_dchannel ( void *  vpri  )  [static]

Definition at line 4585 of file sig_pri.c.

References ast_channel::_softhangup, sig_pri_chan::allocated, ast_copy_string(), ast_exists_extension(), AST_FORMAT_ULAW, ast_hangup(), ast_log(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tv(), ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_verb, ast_verbose, sig_pri_chan::channel, DCHAN_UP, sig_pri_span::dchanavail, sig_pri_span::dchans, sig_pri_span::debug, do_idle_thread(), errno, sig_pri_span::fds, sig_pri_span::idlecontext, sig_pri_span::idledial, sig_pri_span::idleext, sig_pri_chan::isidlecall, sig_pri_span::lastreset, len(), sig_pri_span::lock, LOG_WARNING, sig_pri_span::minidle, sig_pri_span::minunused, ast_channel::name, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_chan::owner, sig_pri_span::pri, pri_check_restart(), pri_is_up(), pri_order(), sig_pri_span::pvts, sig_pri_span::resetinterval, sig_pri_span::resetpos, sig_pri_span::resetting, sig_pri_span::sig, SIG_BRI_PTMP, sig_pri_handle_dchan_exception(), sig_pri_is_chan_available(), sig_pri_lock_private(), sig_pri_request(), sig_pri_span_devstate_changed(), sig_pri_unlock_private(), sig_pri_span::span, and sig_pri_span::switchtype.

04586 {
04587    struct sig_pri_span *pri = vpri;
04588    pri_event *e;
04589    struct pollfd fds[SIG_PRI_NUM_DCHANS];
04590    int res;
04591    int chanpos = 0;
04592    int x;
04593    int law;
04594    struct ast_channel *c;
04595    struct timeval tv, lowest, *next;
04596    int doidling=0;
04597    char *cc;
04598    time_t t;
04599    int i, which=-1;
04600    int numdchans;
04601    pthread_t threadid;
04602    char ani2str[6];
04603    char plancallingnum[AST_MAX_EXTENSION];
04604    char plancallingani[AST_MAX_EXTENSION];
04605    char calledtonstr[10];
04606    struct timeval lastidle = { 0, 0 };
04607    pthread_t p;
04608    struct ast_channel *idle;
04609    char idlen[80];
04610    int nextidle = -1;
04611    int haveidles;
04612    int activeidles;
04613    unsigned int len;
04614 
04615    gettimeofday(&lastidle, NULL);
04616    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
04617 
04618    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
04619       /* Need to do idle dialing, check to be sure though */
04620       cc = strchr(pri->idleext, '@');
04621       if (cc) {
04622          *cc = '\0';
04623          cc++;
04624          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
04625 #if 0
04626          /* Extensions may not be loaded yet */
04627          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
04628             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
04629          else
04630 #endif
04631             doidling = 1;
04632       } else
04633          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
04634    }
04635    for (;;) {
04636       for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
04637          if (!pri->dchans[i])
04638             break;
04639          fds[i].fd = pri->fds[i];
04640          fds[i].events = POLLIN | POLLPRI;
04641          fds[i].revents = 0;
04642       }
04643       numdchans = i;
04644       time(&t);
04645       ast_mutex_lock(&pri->lock);
04646       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
04647          if (pri->resetting && pri_is_up(pri)) {
04648             if (pri->resetpos < 0) {
04649                pri_check_restart(pri);
04650                if (pri->resetting) {
04651                   sig_pri_span_devstate_changed(pri);
04652                }
04653             }
04654          } else {
04655             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
04656                pri->resetting = 1;
04657                pri->resetpos = -1;
04658             }
04659          }
04660       }
04661       /* Look for any idle channels if appropriate */
04662       if (doidling && pri_is_up(pri)) {
04663          nextidle = -1;
04664          haveidles = 0;
04665          activeidles = 0;
04666          for (x = pri->numchans; x >= 0; x--) {
04667             if (pri->pvts[x] && !pri->pvts[x]->no_b_channel) {
04668                if (sig_pri_is_chan_available(pri->pvts[x])) {
04669                   if (haveidles < pri->minunused) {
04670                      haveidles++;
04671                   } else {
04672                      nextidle = x;
04673                      break;
04674                   }
04675                } else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
04676                   activeidles++;
04677                }
04678             }
04679          }
04680          if (nextidle > -1) {
04681             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
04682                /* Don't create a new idle call more than once per second */
04683                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
04684                pri->pvts[nextidle]->allocated = 1;
04685                /*
04686                 * Release the PRI lock while we create the channel so other
04687                 * threads can send D channel messages.
04688                 */
04689                ast_mutex_unlock(&pri->lock);
04690                /*
04691                 * We already have the B channel reserved for this call.  We
04692                 * just need to make sure that sig_pri_hangup() has completed
04693                 * cleaning up before continuing.
04694                 */
04695                sig_pri_lock_private(pri->pvts[nextidle]);
04696                sig_pri_unlock_private(pri->pvts[nextidle]);
04697                idle = sig_pri_request(pri->pvts[nextidle], AST_FORMAT_ULAW, NULL, 0);
04698                ast_mutex_lock(&pri->lock);
04699                if (idle) {
04700                   pri->pvts[nextidle]->isidlecall = 1;
04701                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, pri->pvts[nextidle])) {
04702                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
04703                      ast_mutex_unlock(&pri->lock);
04704                      ast_hangup(idle);
04705                      ast_mutex_lock(&pri->lock);
04706                   }
04707                } else {
04708                   pri->pvts[nextidle]->allocated = 0;
04709                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
04710                }
04711                gettimeofday(&lastidle, NULL);
04712             }
04713          } else if ((haveidles < pri->minunused) &&
04714             (activeidles > pri->minidle)) {
04715             /* Mark something for hangup if there is something
04716                that can be hungup */
04717             for (x = pri->numchans; x >= 0; x--) {
04718                /* find a candidate channel */
04719                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
04720                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04721                   haveidles++;
04722                   /* Stop if we have enough idle channels or
04723                     can't spare any more active idle ones */
04724                   if ((haveidles >= pri->minunused) ||
04725                      (activeidles <= pri->minidle))
04726                      break;
04727                }
04728             }
04729          }
04730       }
04731       /* Start with reasonable max */
04732       if (doidling || pri->resetting) {
04733          /*
04734           * Make sure we stop at least once per second if we're
04735           * monitoring idle channels
04736           */
04737          lowest = ast_tv(1, 0);
04738       } else {
04739          /* Don't poll for more than 60 seconds */
04740          lowest = ast_tv(60, 0);
04741       }
04742       for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
04743          if (!pri->dchans[i]) {
04744             /* We scanned all D channels on this span. */
04745             break;
04746          }
04747          next = pri_schedule_next(pri->dchans[i]);
04748          if (next) {
04749             /* We need relative time here */
04750             tv = ast_tvsub(*next, ast_tvnow());
04751             if (tv.tv_sec < 0) {
04752                /*
04753                 * A timer has already expired.
04754                 * By definition zero time is the lowest so we can quit early.
04755                 */
04756                lowest = ast_tv(0, 0);
04757                break;
04758             }
04759             if (ast_tvcmp(tv, lowest) < 0) {
04760                lowest = tv;
04761             }
04762          }
04763       }
04764       ast_mutex_unlock(&pri->lock);
04765 
04766       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
04767       pthread_testcancel();
04768       e = NULL;
04769       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
04770       pthread_testcancel();
04771       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
04772 
04773       ast_mutex_lock(&pri->lock);
04774       if (!res) {
04775          for (which = 0; which < SIG_PRI_NUM_DCHANS; which++) {
04776             if (!pri->dchans[which])
04777                break;
04778             /* Just a timeout, run the scheduler */
04779             e = pri_schedule_run(pri->dchans[which]);
04780             if (e)
04781                break;
04782          }
04783       } else if (res > -1) {
04784          for (which = 0; which < SIG_PRI_NUM_DCHANS; which++) {
04785             if (!pri->dchans[which])
04786                break;
04787             if (fds[which].revents & POLLPRI) {
04788                sig_pri_handle_dchan_exception(pri, which);
04789             } else if (fds[which].revents & POLLIN) {
04790                e = pri_check_event(pri->dchans[which]);
04791             }
04792             if (e)
04793                break;
04794          }
04795       } else if (errno != EINTR)
04796          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
04797 
04798       if (e) {
04799          if (pri->debug) {
04800             ast_verbose("Span %d: Processing event %s\n",
04801                pri->span, pri_event2str(e->e));
04802          }
04803 
04804          if (e->e != PRI_EVENT_DCHAN_DOWN) {
04805             if (!(pri->dchanavail[which] & DCHAN_UP)) {
04806                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
04807             }
04808             pri->dchanavail[which] |= DCHAN_UP;
04809          } else {
04810             if (pri->dchanavail[which] & DCHAN_UP) {
04811                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
04812             }
04813             pri->dchanavail[which] &= ~DCHAN_UP;
04814          }
04815 
04816          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
04817             /* Must be an NFAS group that has the secondary dchan active */
04818             pri->pri = pri->dchans[which];
04819 
04820          switch (e->e) {
04821          case PRI_EVENT_DCHAN_UP:
04822             pri->no_d_channels = 0;
04823             if (!pri->pri) {
04824                pri_find_dchan(pri);
04825             }
04826 
04827             /* Note presense of D-channel */
04828             time(&pri->lastreset);
04829 
04830             /* Restart in 5 seconds */
04831             if (pri->resetinterval > -1) {
04832                pri->lastreset -= pri->resetinterval;
04833                pri->lastreset += 5;
04834             }
04835             /* Take the channels from inalarm condition */
04836             pri->resetting = 0;
04837             for (i = 0; i < pri->numchans; i++) {
04838                if (pri->pvts[i]) {
04839                   sig_pri_set_alarm(pri->pvts[i], 0);
04840                }
04841             }
04842             sig_pri_span_devstate_changed(pri);
04843             break;
04844          case PRI_EVENT_DCHAN_DOWN:
04845             pri_find_dchan(pri);
04846             if (!pri_is_up(pri)) {
04847                if (pri->sig == SIG_BRI_PTMP) {
04848                   /*
04849                    * For PTMP connections with non-persistent layer 2 we want to
04850                    * *not* declare inalarm unless there actually is an alarm.
04851                    */
04852                   break;
04853                }
04854                /* Hangup active channels and put them in alarm mode */
04855                pri->resetting = 0;
04856                for (i = 0; i < pri->numchans; i++) {
04857                   struct sig_pri_chan *p = pri->pvts[i];
04858 
04859                   if (p) {
04860                      if (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04861                         /* T309 is not enabled : destroy calls when alarm occurs */
04862                         if (p->call) {
04863                            pri_destroycall(p->pri->pri, p->call);
04864                            p->call = NULL;
04865                         }
04866                         if (p->owner)
04867                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04868                      }
04869                      sig_pri_set_alarm(p, 1);
04870                   }
04871                }
04872                sig_pri_span_devstate_changed(pri);
04873             }
04874             break;
04875          case PRI_EVENT_RESTART:
04876             if (e->restart.channel > -1 && PRI_CHANNEL(e->restart.channel) != 0xFF) {
04877                chanpos = pri_find_principle(pri, e->restart.channel, NULL);
04878                if (chanpos < 0)
04879                   ast_log(LOG_WARNING,
04880                      "Span %d: Restart requested on odd/unavailable channel number %d/%d\n",
04881                      pri->span, PRI_SPAN(e->restart.channel),
04882                      PRI_CHANNEL(e->restart.channel));
04883                else {
04884                   int skipit = 0;
04885 #if defined(HAVE_PRI_SERVICE_MESSAGES)
04886                   unsigned why;
04887 
04888                   why = pri->pvts[chanpos]->service_status;
04889                   if (why) {
04890                      ast_log(LOG_NOTICE,
04891                         "Span %d: Channel %d/%d out-of-service (reason: %s), ignoring RESTART\n",
04892                         pri->span, PRI_SPAN(e->restart.channel),
04893                         PRI_CHANNEL(e->restart.channel),
04894                         (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
04895                      skipit = 1;
04896                   }
04897 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
04898                   sig_pri_lock_private(pri->pvts[chanpos]);
04899                   if (!skipit) {
04900                      ast_verb(3, "Span %d: Channel %d/%d restarted\n", pri->span,
04901                         PRI_SPAN(e->restart.channel),
04902                         PRI_CHANNEL(e->restart.channel));
04903                      if (pri->pvts[chanpos]->call) {
04904                         pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
04905                         pri->pvts[chanpos]->call = NULL;
04906                      }
04907                   }
04908                   /* Force soft hangup if appropriate */
04909                   if (pri->pvts[chanpos]->owner)
04910                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04911                   sig_pri_unlock_private(pri->pvts[chanpos]);
04912                }
04913             } else {
04914                ast_verb(3, "Restart requested on entire span %d\n", pri->span);
04915                for (x = 0; x < pri->numchans; x++)
04916                   if (pri->pvts[x]) {
04917                      sig_pri_lock_private(pri->pvts[x]);
04918                      if (pri->pvts[x]->call) {
04919                         pri_destroycall(pri->pri, pri->pvts[x]->call);
04920                         pri->pvts[x]->call = NULL;
04921                      }
04922                      if (pri->pvts[x]->owner)
04923                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04924                      sig_pri_unlock_private(pri->pvts[x]);
04925                   }
04926             }
04927             sig_pri_span_devstate_changed(pri);
04928             break;
04929          case PRI_EVENT_KEYPAD_DIGIT:
04930             if (sig_pri_is_cis_call(e->digit.channel)) {
04931                sig_pri_handle_cis_subcmds(pri, e->e, e->digit.subcmds,
04932                   e->digit.call);
04933                break;
04934             }
04935             chanpos = pri_find_principle_by_call(pri, e->digit.call);
04936             if (chanpos < 0) {
04937                ast_log(LOG_WARNING,
04938                   "Span %d: Received keypad digits for unknown call.\n", pri->span);
04939                break;
04940             }
04941             sig_pri_lock_private(pri->pvts[chanpos]);
04942             sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.channel,
04943                e->digit.subcmds, e->digit.call);
04944             /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
04945             if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
04946                && pri->pvts[chanpos]->owner) {
04947                /* how to do that */
04948                int digitlen = strlen(e->digit.digits);
04949                int i;
04950 
04951                for (i = 0; i < digitlen; i++) {
04952                   struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
04953 
04954                   pri_queue_frame(pri, chanpos, &f);
04955                }
04956             }
04957             sig_pri_unlock_private(pri->pvts[chanpos]);
04958             break;
04959 
04960          case PRI_EVENT_INFO_RECEIVED:
04961             if (sig_pri_is_cis_call(e->ring.channel)) {
04962                sig_pri_handle_cis_subcmds(pri, e->e, e->ring.subcmds,
04963                   e->ring.call);
04964                break;
04965             }
04966             chanpos = pri_find_principle_by_call(pri, e->ring.call);
04967             if (chanpos < 0) {
04968                ast_log(LOG_WARNING,
04969                   "Span %d: Received INFORMATION for unknown call.\n", pri->span);
04970                break;
04971             }
04972             sig_pri_lock_private(pri->pvts[chanpos]);
04973             sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
04974                e->ring.subcmds, e->ring.call);
04975             /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
04976             if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
04977                && pri->pvts[chanpos]->owner) {
04978                /* how to do that */
04979                int digitlen = strlen(e->ring.callednum);
04980                int i;
04981 
04982                for (i = 0; i < digitlen; i++) {
04983                   struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
04984 
04985                   pri_queue_frame(pri, chanpos, &f);
04986                }
04987             }
04988             sig_pri_unlock_private(pri->pvts[chanpos]);
04989             break;
04990 #if defined(HAVE_PRI_SERVICE_MESSAGES)
04991          case PRI_EVENT_SERVICE:
04992             chanpos = pri_find_principle(pri, e->service.channel, NULL);
04993             if (chanpos < 0) {
04994                ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n",
04995                   e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
04996             } else {
04997                char db_chan_name[20];
04998                char db_answer[5];
04999                int ch;
05000                unsigned *why;
05001 
05002                ch = pri->pvts[chanpos]->channel;
05003                snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->span, ch);
05004                why = &pri->pvts[chanpos]->service_status;
05005                switch (e->service.changestatus) {
05006                case 0: /* in-service */
05007                   /* Far end wants to be in service now. */
05008                   ast_db_del(db_chan_name, SRVST_DBKEY);
05009                   *why &= ~SRVST_FAREND;
05010                   if (*why) {
05011                      snprintf(db_answer, sizeof(db_answer), "%s:%u",
05012                         SRVST_TYPE_OOS, *why);
05013                      ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
05014                   } else {
05015                      sig_pri_span_devstate_changed(pri);
05016                   }
05017                   break;
05018                case 2: /* out-of-service */
05019                   /* Far end wants to be out-of-service now. */
05020                   ast_db_del(db_chan_name, SRVST_DBKEY);
05021                   *why |= SRVST_FAREND;
05022                   snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS,
05023                      *why);
05024                   ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
05025                   sig_pri_span_devstate_changed(pri);
05026                   break;
05027                default:
05028                   ast_log(LOG_ERROR, "Huh?  changestatus is: %d\n", e->service.changestatus);
05029                   break;
05030                }
05031                ast_log(LOG_NOTICE, "Channel %d/%d span %d (logical: %d) received a change of service message, status '%d'\n",
05032                   PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span, ch, e->service.changestatus);
05033             }
05034             break;
05035          case PRI_EVENT_SERVICE_ACK:
05036             chanpos = pri_find_principle(pri, e->service_ack.channel, NULL);
05037             if (chanpos < 0) {
05038                ast_log(LOG_WARNING, "Received service acknowledge change status '%d' on unconfigured channel %d/%d span %d\n",
05039                   e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
05040             } else {
05041                ast_debug(2, "Channel %d/%d span %d received a change os service acknowledgement message, status '%d'\n",
05042                   PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span, e->service_ack.changestatus);
05043             }
05044             break;
05045 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
05046          case PRI_EVENT_RING:
05047             if (!ast_strlen_zero(pri->msn_list)
05048                && !sig_pri_msn_match(pri->msn_list, e->ring.callednum)) {
05049                /* The call is not for us so ignore it. */
05050                ast_verb(3,
05051                   "Ignoring call to '%s' on span %d.  Its not in the MSN list: %s\n",
05052                   e->ring.callednum, pri->span, pri->msn_list);
05053                pri_destroycall(pri->pri, e->ring.call);
05054                break;
05055             }
05056             if (sig_pri_is_cis_call(e->ring.channel)) {
05057                sig_pri_handle_cis_subcmds(pri, e->e, e->ring.subcmds,
05058                   e->ring.call);
05059                break;
05060             }
05061             chanpos = pri_find_principle_by_call(pri, e->ring.call);
05062             if (-1 < chanpos) {
05063                /* Libpri has already filtered out duplicate SETUPs. */
05064                ast_log(LOG_WARNING,
05065                   "Span %d: Got SETUP with duplicate call ptr (%p).  Dropping call.\n",
05066                   pri->span, e->ring.call);
05067                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
05068                break;
05069             }
05070             if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
05071                /* Any channel requested. */
05072                chanpos = pri_find_empty_chan(pri, 1);
05073             } else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
05074                /* No channel specified. */
05075 #if defined(HAVE_PRI_CALL_WAITING)
05076                if (!pri->allow_call_waiting_calls)
05077 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
05078                {
05079                   /* We will not accept incoming call waiting calls. */
05080                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
05081                   break;
05082                }
05083 #if defined(HAVE_PRI_CALL_WAITING)
05084                chanpos = pri_find_empty_nobch(pri);
05085                if (chanpos < 0) {
05086                   /* We could not find/create a call interface. */
05087                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
05088                   break;
05089                }
05090                /* Setup the call interface to use. */
05091                sig_pri_init_config(pri->pvts[chanpos], pri);
05092 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
05093             } else {
05094                /* A channel is specified. */
05095                chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
05096                if (chanpos < 0) {
05097                   ast_log(LOG_WARNING,
05098                      "Span %d: SETUP on unconfigured channel %d/%d\n",
05099                      pri->span, PRI_SPAN(e->ring.channel),
05100                      PRI_CHANNEL(e->ring.channel));
05101                } else {
05102                   switch (pri->pvts[chanpos]->resetting) {
05103                   case SIG_PRI_RESET_IDLE:
05104                      break;
05105                   case SIG_PRI_RESET_ACTIVE:
05106                      /*
05107                       * The peer may have lost the expected ack or not received the
05108                       * RESTART yet.
05109                       */
05110                      pri->pvts[chanpos]->resetting = SIG_PRI_RESET_NO_ACK;
05111                      break;
05112                   case SIG_PRI_RESET_NO_ACK:
05113                      /* The peer likely is not going to ack the RESTART. */
05114                      ast_debug(1,
05115                         "Span %d: Second SETUP while waiting for RESTART ACKNOWLEDGE on channel %d/%d\n",
05116                         pri->span, PRI_SPAN(e->ring.channel),
05117                         PRI_CHANNEL(e->ring.channel));
05118 
05119                      /* Assume we got the ack. */
05120                      pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
05121                      if (pri->resetting) {
05122                         /* Go on to the next idle channel to RESTART. */
05123                         pri_check_restart(pri);
05124                      }
05125                      break;
05126                   }
05127                   if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
05128                      /* This is where we handle initial glare */
05129                      ast_debug(1,
05130                         "Span %d: SETUP requested unavailable channel %d/%d.  Attempting to renegotiate.\n",
05131                         pri->span, PRI_SPAN(e->ring.channel),
05132                         PRI_CHANNEL(e->ring.channel));
05133                      chanpos = -1;
05134                   }
05135                }
05136 #if defined(ALWAYS_PICK_CHANNEL)
05137                if (e->ring.flexible) {
05138                   chanpos = -1;
05139                }
05140 #endif   /* defined(ALWAYS_PICK_CHANNEL) */
05141                if (chanpos < 0 && e->ring.flexible) {
05142                   /* We can try to pick another channel. */
05143                   chanpos = pri_find_empty_chan(pri, 1);
05144                }
05145             }
05146             if (chanpos < 0) {
05147                if (e->ring.flexible) {
05148                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
05149                } else {
05150                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
05151                }
05152                break;
05153             }
05154 
05155             sig_pri_lock_private(pri->pvts[chanpos]);
05156 
05157             /* Mark channel as in use so noone else will steal it. */
05158             pri->pvts[chanpos]->call = e->ring.call;
05159 
05160             /* Use plancallingnum as a scratch buffer since it is initialized next. */
05161             apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri,
05162                e->ring.redirectingnum, e->ring.callingplanrdnis);
05163             sig_pri_set_rdnis(pri->pvts[chanpos], plancallingnum);
05164 
05165             /* Setup caller-id info */
05166             apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri,
05167                e->ring.callingnum, e->ring.callingplan);
05168             pri->pvts[chanpos]->cid_ani2 = 0;
05169             if (pri->pvts[chanpos]->use_callerid) {
05170                ast_shrink_phone_number(plancallingnum);
05171                ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
05172 #ifdef PRI_ANI
05173                apply_plan_to_existing_number(plancallingani, sizeof(plancallingani),
05174                   pri, e->ring.callingani, e->ring.callingplanani);
05175                ast_shrink_phone_number(plancallingani);
05176                ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani,
05177                   sizeof(pri->pvts[chanpos]->cid_ani));
05178 #endif
05179                pri->pvts[chanpos]->cid_subaddr[0] = '\0';
05180 #if defined(HAVE_PRI_SUBADDR)
05181                if (e->ring.calling.subaddress.valid) {
05182                   struct ast_party_subaddress calling_subaddress;
05183 
05184                   ast_party_subaddress_init(&calling_subaddress);
05185                   sig_pri_set_subaddress(&calling_subaddress,
05186                      &e->ring.calling.subaddress);
05187                   if (calling_subaddress.str) {
05188                      ast_copy_string(pri->pvts[chanpos]->cid_subaddr,
05189                         calling_subaddress.str,
05190                         sizeof(pri->pvts[chanpos]->cid_subaddr));
05191                   }
05192                   ast_party_subaddress_free(&calling_subaddress);
05193                }
05194 #endif /* defined(HAVE_PRI_SUBADDR) */
05195                ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
05196                pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
05197                pri->pvts[chanpos]->callingpres = e->ring.callingpres;
05198                if (e->ring.ani2 >= 0) {
05199                   pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
05200                }
05201             } else {
05202                pri->pvts[chanpos]->cid_num[0] = '\0';
05203                pri->pvts[chanpos]->cid_subaddr[0] = '\0';
05204                pri->pvts[chanpos]->cid_ani[0] = '\0';
05205                pri->pvts[chanpos]->cid_name[0] = '\0';
05206                pri->pvts[chanpos]->cid_ton = 0;
05207                pri->pvts[chanpos]->callingpres = 0;
05208             }
05209 
05210             /* Setup the user tag for party id's from this device for this call. */
05211             if (pri->append_msn_to_user_tag) {
05212                snprintf(pri->pvts[chanpos]->user_tag,
05213                   sizeof(pri->pvts[chanpos]->user_tag), "%s_%s",
05214                   pri->initial_user_tag,
05215                   pri->nodetype == PRI_NETWORK
05216                      ? plancallingnum : e->ring.callednum);
05217             } else {
05218                ast_copy_string(pri->pvts[chanpos]->user_tag,
05219                   pri->initial_user_tag, sizeof(pri->pvts[chanpos]->user_tag));
05220             }
05221 
05222             sig_pri_set_caller_id(pri->pvts[chanpos]);
05223 
05224             /* Set DNID on all incoming calls -- even immediate */
05225             sig_pri_set_dnid(pri->pvts[chanpos], e->ring.callednum);
05226 
05227             /* If immediate=yes go to s|1 */
05228             if (pri->pvts[chanpos]->immediate) {
05229                ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
05230                pri->pvts[chanpos]->exten[0] = 's';
05231                pri->pvts[chanpos]->exten[1] = '\0';
05232             }
05233             /* Get called number */
05234             else if (!ast_strlen_zero(e->ring.callednum)) {
05235                ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
05236             } else if (pri->overlapdial)
05237                pri->pvts[chanpos]->exten[0] = '\0';
05238             else {
05239                /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
05240                pri->pvts[chanpos]->exten[0] = 's';
05241                pri->pvts[chanpos]->exten[1] = '\0';
05242             }
05243             /* No number yet, but received "sending complete"? */
05244             if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
05245                ast_verb(3, "Going to extension s|1 because of Complete received\n");
05246                pri->pvts[chanpos]->exten[0] = 's';
05247                pri->pvts[chanpos]->exten[1] = '\0';
05248             }
05249 
05250             /* Make sure extension exists (or in overlap dial mode, can exist) */
05251             if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
05252                ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
05253                /* Select audio companding mode. */
05254                switch (e->ring.layer1) {
05255                case PRI_LAYER_1_ALAW:
05256                   law = SIG_PRI_ALAW;
05257                   break;
05258                case PRI_LAYER_1_ULAW:
05259                   law = SIG_PRI_ULAW;
05260                   break;
05261                default:
05262                   /* This is a data call to us. */
05263                   law = SIG_PRI_DEFLAW;
05264                   break;
05265                }
05266 
05267                if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05268                   /* Just announce proceeding */
05269                   pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
05270                   pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
05271                } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
05272                   pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
05273                   pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
05274                } else {
05275                   pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP;
05276                   pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
05277                }
05278 
05279                /* Start PBX */
05280                if (!e->ring.complete
05281                   && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
05282                   && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
05283                   /*
05284                    * Release the PRI lock while we create the channel so other
05285                    * threads can send D channel messages.  We must also release
05286                    * the private lock to prevent deadlock while creating the
05287                    * channel.
05288                    */
05289                   sig_pri_unlock_private(pri->pvts[chanpos]);
05290                   ast_mutex_unlock(&pri->lock);
05291                   c = sig_pri_new_ast_channel(pri->pvts[chanpos],
05292                      AST_STATE_RESERVED, law, e->ring.ctype,
05293                      pri->pvts[chanpos]->exten, NULL);
05294                   ast_mutex_lock(&pri->lock);
05295                   sig_pri_lock_private(pri->pvts[chanpos]);
05296                   if (c) {
05297 #if defined(HAVE_PRI_SUBADDR)
05298                      if (e->ring.calling.subaddress.valid) {
05299                         /* Set Calling Subaddress */
05300                         sig_pri_lock_owner(pri, chanpos);
05301                         sig_pri_set_subaddress(
05302                            &pri->pvts[chanpos]->owner->caller.id.subaddress,
05303                            &e->ring.calling.subaddress);
05304                         if (!e->ring.calling.subaddress.type
05305                            && !ast_strlen_zero(
05306                               (char *) e->ring.calling.subaddress.data)) {
05307                            /* NSAP */
05308                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
05309                               (char *) e->ring.calling.subaddress.data);
05310                         }
05311                         ast_channel_unlock(c);
05312                      }
05313                      if (e->ring.called_subaddress.valid) {
05314                         /* Set Called Subaddress */
05315                         sig_pri_lock_owner(pri, chanpos);
05316                         sig_pri_set_subaddress(
05317                            &pri->pvts[chanpos]->owner->dialed.subaddress,
05318                            &e->ring.called_subaddress);
05319                         if (!e->ring.called_subaddress.type
05320                            && !ast_strlen_zero(
05321                               (char *) e->ring.called_subaddress.data)) {
05322                            /* NSAP */
05323                            pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
05324                               (char *) e->ring.called_subaddress.data);
05325                         }
05326                         ast_channel_unlock(c);
05327                      }
05328 #else
05329                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
05330                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
05331                      }
05332 #endif /* !defined(HAVE_PRI_SUBADDR) */
05333                      if (e->ring.ani2 >= 0) {
05334                         snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
05335                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
05336                      }
05337 
05338 #ifdef SUPPORT_USERUSER
05339                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
05340                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
05341                      }
05342 #endif
05343 
05344                      snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
05345                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
05346                      if (e->ring.redirectingreason >= 0) {
05347                         /* This is now just a status variable.  Use REDIRECTING() dialplan function. */
05348                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
05349                      }
05350 #if defined(HAVE_PRI_REVERSE_CHARGE)
05351                      pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge;
05352 #endif
05353 #if defined(HAVE_PRI_SETUP_KEYPAD)
05354                      ast_copy_string(pri->pvts[chanpos]->keypad_digits,
05355                         e->ring.keypad_digits,
05356                         sizeof(pri->pvts[chanpos]->keypad_digits));
05357 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
05358 
05359                      sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
05360                         e->ring.subcmds, e->ring.call);
05361 
05362                      if (!pri->pvts[chanpos]->digital
05363                         && !pri->pvts[chanpos]->no_b_channel) {
05364                         /*
05365                          * Call has a channel.
05366                          * Indicate that we are providing dialtone.
05367                          */
05368                         pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */
05369 #ifdef HAVE_PRI_PROG_W_CAUSE
05370                         pri_progress_with_cause(pri->pri, e->ring.call,
05371                            PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */
05372 #else
05373                         pri_progress(pri->pri, e->ring.call,
05374                            PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
05375 #endif
05376                      }
05377                   }
05378                   if (c && !ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, pri->pvts[chanpos])) {
05379                      ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
05380                         plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
05381                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
05382                   } else {
05383                      ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
05384                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
05385                      if (c) {
05386                         /* Avoid deadlock while destroying channel */
05387                         sig_pri_unlock_private(pri->pvts[chanpos]);
05388                         ast_mutex_unlock(&pri->lock);
05389                         ast_hangup(c);
05390                         ast_mutex_lock(&pri->lock);
05391                      } else {
05392                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
05393                         pri->pvts[chanpos]->call = NULL;
05394                         sig_pri_unlock_private(pri->pvts[chanpos]);
05395                         sig_pri_span_devstate_changed(pri);
05396                      }
05397                      break;
05398                   }
05399                } else {
05400                   /*
05401                    * Release the PRI lock while we create the channel so other
05402                    * threads can send D channel messages.  We must also release
05403                    * the private lock to prevent deadlock while creating the
05404                    * channel.
05405                    */
05406                   sig_pri_unlock_private(pri->pvts[chanpos]);
05407                   ast_mutex_unlock(&pri->lock);
05408                   c = sig_pri_new_ast_channel(pri->pvts[chanpos],
05409                      AST_STATE_RING, law, e->ring.ctype,
05410                      pri->pvts[chanpos]->exten, NULL);
05411                   ast_mutex_lock(&pri->lock);
05412                   sig_pri_lock_private(pri->pvts[chanpos]);
05413                   if (c) {
05414                      /*
05415                       * It is reasonably safe to set the following
05416                       * channel variables while the PRI and DAHDI private
05417                       * structures are locked.  The PBX has not been
05418                       * started yet and it is unlikely that any other task
05419                       * will do anything with the channel we have just
05420                       * created.
05421                       */
05422 #if defined(HAVE_PRI_SUBADDR)
05423                      if (e->ring.calling.subaddress.valid) {
05424                         /* Set Calling Subaddress */
05425                         sig_pri_lock_owner(pri, chanpos);
05426                         sig_pri_set_subaddress(
05427                            &pri->pvts[chanpos]->owner->caller.id.subaddress,
05428                            &e->ring.calling.subaddress);
05429                         if (!e->ring.calling.subaddress.type
05430                            && !ast_strlen_zero(
05431                               (char *) e->ring.calling.subaddress.data)) {
05432                            /* NSAP */
05433                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
05434                               (char *) e->ring.calling.subaddress.data);
05435                         }
05436                         ast_channel_unlock(c);
05437                      }
05438                      if (e->ring.called_subaddress.valid) {
05439                         /* Set Called Subaddress */
05440                         sig_pri_lock_owner(pri, chanpos);
05441                         sig_pri_set_subaddress(
05442                            &pri->pvts[chanpos]->owner->dialed.subaddress,
05443                            &e->ring.called_subaddress);
05444                         if (!e->ring.called_subaddress.type
05445                            && !ast_strlen_zero(
05446                               (char *) e->ring.called_subaddress.data)) {
05447                            /* NSAP */
05448                            pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
05449                               (char *) e->ring.called_subaddress.data);
05450                         }
05451                         ast_channel_unlock(c);
05452                      }
05453 #else
05454                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
05455                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
05456                      }
05457 #endif /* !defined(HAVE_PRI_SUBADDR) */
05458                      if (e->ring.ani2 >= 0) {
05459                         snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
05460                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
05461                      }
05462 
05463 #ifdef SUPPORT_USERUSER
05464                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
05465                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
05466                      }
05467 #endif
05468 
05469                      if (e->ring.redirectingreason >= 0) {
05470                         /* This is now just a status variable.  Use REDIRECTING() dialplan function. */
05471                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
05472                      }
05473 #if defined(HAVE_PRI_REVERSE_CHARGE)
05474                      pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge;
05475 #endif
05476 #if defined(HAVE_PRI_SETUP_KEYPAD)
05477                      ast_copy_string(pri->pvts[chanpos]->keypad_digits,
05478                         e->ring.keypad_digits,
05479                         sizeof(pri->pvts[chanpos]->keypad_digits));
05480 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
05481 
05482                      snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
05483                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
05484 
05485                      sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
05486                         e->ring.subcmds, e->ring.call);
05487 
05488                   }
05489                   if (c && !ast_pbx_start(c)) {
05490                      ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
05491                         plancallingnum, pri->pvts[chanpos]->exten,
05492                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
05493                      sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
05494                   } else {
05495                      ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
05496                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
05497                      if (c) {
05498                         /* Avoid deadlock while destroying channel */
05499                         sig_pri_unlock_private(pri->pvts[chanpos]);
05500                         ast_mutex_unlock(&pri->lock);
05501                         ast_hangup(c);
05502                         ast_mutex_lock(&pri->lock);
05503                      } else {
05504                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
05505                         pri->pvts[chanpos]->call = NULL;
05506                         sig_pri_unlock_private(pri->pvts[chanpos]);
05507                         sig_pri_span_devstate_changed(pri);
05508                      }
05509                      break;
05510                   }
05511                }
05512             } else {
05513                ast_verb(3,
05514                   "Span %d: Extension %s@%s does not exist.  Rejecting call from '%s'.\n",
05515                   pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
05516                   pri->pvts[chanpos]->cid_num);
05517                pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
05518                pri->pvts[chanpos]->call = NULL;
05519                pri->pvts[chanpos]->exten[0] = '\0';
05520                sig_pri_unlock_private(pri->pvts[chanpos]);
05521                sig_pri_span_devstate_changed(pri);
05522                break;
05523             }
05524             sig_pri_unlock_private(pri->pvts[chanpos]);
05525             break;
05526          case PRI_EVENT_RINGING:
05527             if (sig_pri_is_cis_call(e->ringing.channel)) {
05528                sig_pri_handle_cis_subcmds(pri, e->e, e->ringing.subcmds,
05529                   e->ringing.call);
05530                break;
05531             }
05532             chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
05533                e->ringing.call);
05534             if (chanpos < 0) {
05535                break;
05536             }
05537             sig_pri_lock_private(pri->pvts[chanpos]);
05538 
05539             sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.channel,
05540                e->ringing.subcmds, e->ringing.call);
05541             sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
05542             sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
05543             sig_pri_lock_owner(pri, chanpos);
05544             if (pri->pvts[chanpos]->owner) {
05545                ast_setstate(pri->pvts[chanpos]->owner, AST_STATE_RINGING);
05546                ast_channel_unlock(pri->pvts[chanpos]->owner);
05547             }
05548             pri_queue_control(pri, chanpos, AST_CONTROL_RINGING);
05549             if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_ALERTING) {
05550                pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
05551             }
05552 
05553             if (!pri->pvts[chanpos]->progress
05554                && !pri->pvts[chanpos]->no_b_channel
05555 #ifdef PRI_PROGRESS_MASK
05556                && (e->ringing.progressmask
05557                   & (PRI_PROG_CALL_NOT_E2E_ISDN | PRI_PROG_INBAND_AVAILABLE))
05558 #else
05559                && e->ringing.progress == 8
05560 #endif
05561                ) {
05562                /* Bring voice path up */
05563                pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
05564                pri->pvts[chanpos]->progress = 1;
05565                sig_pri_set_dialing(pri->pvts[chanpos], 0);
05566                sig_pri_open_media(pri->pvts[chanpos]);
05567             }
05568 
05569 #ifdef SUPPORT_USERUSER
05570             if (!ast_strlen_zero(e->ringing.useruserinfo)) {
05571                struct ast_channel *owner;
05572 
05573                sig_pri_lock_owner(pri, chanpos);
05574                owner = pri->pvts[chanpos]->owner;
05575                if (owner) {
05576                   pbx_builtin_setvar_helper(owner, "USERUSERINFO",
05577                      e->ringing.useruserinfo);
05578                   ast_channel_unlock(owner);
05579                }
05580             }
05581 #endif
05582 
05583             sig_pri_unlock_private(pri->pvts[chanpos]);
05584             break;
05585          case PRI_EVENT_PROGRESS:
05586             if (sig_pri_is_cis_call(e->proceeding.channel)) {
05587                sig_pri_handle_cis_subcmds(pri, e->e, e->proceeding.subcmds,
05588                   e->proceeding.call);
05589                break;
05590             }
05591             chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
05592                e->proceeding.call);
05593             if (chanpos < 0) {
05594                break;
05595             }
05596             sig_pri_lock_private(pri->pvts[chanpos]);
05597             sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
05598                e->proceeding.subcmds, e->proceeding.call);
05599 
05600             if (e->proceeding.cause > -1) {
05601                ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
05602 
05603                /* Work around broken, out of spec USER_BUSY cause in a progress message */
05604                if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
05605                   if (pri->pvts[chanpos]->owner) {
05606                      ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
05607 
05608                      pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
05609                      pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
05610                   }
05611                }
05612             }
05613 
05614             if (!pri->pvts[chanpos]->progress
05615                && !pri->pvts[chanpos]->no_b_channel
05616 #ifdef PRI_PROGRESS_MASK
05617                && (e->proceeding.progressmask
05618                   & (PRI_PROG_CALL_NOT_E2E_ISDN | PRI_PROG_INBAND_AVAILABLE))
05619 #else
05620                && e->proceeding.progress == 8
05621 #endif
05622                ) {
05623                /* Bring voice path up */
05624                ast_debug(1,
05625                   "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
05626                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,
05627                   pri->span);
05628                pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
05629                pri->pvts[chanpos]->progress = 1;
05630                sig_pri_set_dialing(pri->pvts[chanpos], 0);
05631                sig_pri_open_media(pri->pvts[chanpos]);
05632             }
05633             sig_pri_unlock_private(pri->pvts[chanpos]);
05634             break;
05635          case PRI_EVENT_PROCEEDING:
05636             if (sig_pri_is_cis_call(e->proceeding.channel)) {
05637                sig_pri_handle_cis_subcmds(pri, e->e, e->proceeding.subcmds,
05638                   e->proceeding.call);
05639                break;
05640             }
05641             chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
05642                e->proceeding.call);
05643             if (chanpos < 0) {
05644                break;
05645             }
05646             sig_pri_lock_private(pri->pvts[chanpos]);
05647             sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
05648                e->proceeding.subcmds, e->proceeding.call);
05649             if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
05650                pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
05651                ast_debug(1,
05652                   "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
05653                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,
05654                   pri->span);
05655                pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
05656             }
05657             if (!pri->pvts[chanpos]->progress
05658                && !pri->pvts[chanpos]->no_b_channel
05659 #ifdef PRI_PROGRESS_MASK
05660                && (e->proceeding.progressmask
05661                   & (PRI_PROG_CALL_NOT_E2E_ISDN | PRI_PROG_INBAND_AVAILABLE))
05662 #else
05663                && e->proceeding.progress == 8
05664 #endif
05665                ) {
05666                /* Bring voice path up */
05667                pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
05668                pri->pvts[chanpos]->progress = 1;
05669                sig_pri_open_media(pri->pvts[chanpos]);
05670             }
05671             sig_pri_set_dialing(pri->pvts[chanpos], 0);
05672             sig_pri_unlock_private(pri->pvts[chanpos]);
05673             break;
05674          case PRI_EVENT_FACILITY:
05675             if (!e->facility.call || sig_pri_is_cis_call(e->facility.channel)) {
05676                /* Event came in on the dummy channel or a CIS call. */
05677 #if defined(HAVE_PRI_CALL_REROUTING)
05678                sig_pri_handle_cis_subcmds(pri, e->e, e->facility.subcmds,
05679                   e->facility.subcall);
05680 #else
05681                sig_pri_handle_cis_subcmds(pri, e->e, e->facility.subcmds,
05682                   e->facility.call);
05683 #endif   /* !defined(HAVE_PRI_CALL_REROUTING) */
05684                break;
05685             }
05686             chanpos = pri_find_principle_by_call(pri, e->facility.call);
05687             if (chanpos < 0) {
05688                ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
05689                   pri->span);
05690                break;
05691             }
05692             sig_pri_lock_private(pri->pvts[chanpos]);
05693 #if defined(HAVE_PRI_CALL_REROUTING)
05694             sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
05695                e->facility.subcmds, e->facility.subcall);
05696 #else
05697             sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
05698                e->facility.subcmds, e->facility.call);
05699 #endif   /* !defined(HAVE_PRI_CALL_REROUTING) */
05700             sig_pri_unlock_private(pri->pvts[chanpos]);
05701             break;
05702          case PRI_EVENT_ANSWER:
05703             if (sig_pri_is_cis_call(e->answer.channel)) {
05704 #if defined(HAVE_PRI_CALL_WAITING)
05705                /* Call is CIS so do normal CONNECT_ACKNOWLEDGE. */
05706                pri_connect_ack(pri->pri, e->answer.call, 0);
05707 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
05708                sig_pri_handle_cis_subcmds(pri, e->e, e->answer.subcmds,
05709                   e->answer.call);
05710                break;
05711             }
05712             chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
05713             if (chanpos < 0) {
05714                break;
05715             }
05716 #if defined(HAVE_PRI_CALL_WAITING)
05717             if (pri->pvts[chanpos]->is_call_waiting) {
05718                if (pri->pvts[chanpos]->no_b_channel) {
05719                   int new_chanpos;
05720 
05721                   /*
05722                    * Need to find a free channel now or
05723                    * kill the call with PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION.
05724                    */
05725                   new_chanpos = pri_find_empty_chan(pri, 1);
05726                   if (0 <= new_chanpos) {
05727                      new_chanpos = pri_fixup_principle(pri, new_chanpos,
05728                         e->answer.call);
05729                   }
05730                   if (new_chanpos < 0) {
05731                      /*
05732                       * Either no channel was available or someone stole
05733                       * the channel!
05734                       */
05735                      ast_verb(3,
05736                         "Span %d: Channel not available for call waiting call.\n",
05737                         pri->span);
05738                      sig_pri_lock_private(pri->pvts[chanpos]);
05739                      sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
05740                         e->answer.subcmds, e->answer.call);
05741                      sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
05742                      sig_pri_lock_owner(pri, chanpos);
05743                      if (pri->pvts[chanpos]->owner) {
05744                         pri->pvts[chanpos]->owner->hangupcause = PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION;
05745                         switch (pri->pvts[chanpos]->owner->_state) {
05746                         case AST_STATE_BUSY:
05747                         case AST_STATE_UP:
05748                            ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
05749                            break;
05750                         default:
05751                            pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
05752                            break;
05753                         }
05754                         ast_channel_unlock(pri->pvts[chanpos]->owner);
05755                      } else {
05756                         pri->pvts[chanpos]->is_call_waiting = 0;
05757                         ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
05758                         pri_hangup(pri->pri, e->answer.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
05759                         pri->pvts[chanpos]->call = NULL;
05760                      }
05761                      sig_pri_unlock_private(pri->pvts[chanpos]);
05762                      sig_pri_span_devstate_changed(pri);
05763                      break;
05764                   }
05765                   chanpos = new_chanpos;
05766                }
05767                pri_connect_ack(pri->pri, e->answer.call, PVT_TO_CHANNEL(pri->pvts[chanpos]));
05768                sig_pri_span_devstate_changed(pri);
05769             } else {
05770                /* Call is normal so do normal CONNECT_ACKNOWLEDGE. */
05771                pri_connect_ack(pri->pri, e->answer.call, 0);
05772             }
05773 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
05774             sig_pri_lock_private(pri->pvts[chanpos]);
05775 
05776 #if defined(HAVE_PRI_CALL_WAITING)
05777             if (pri->pvts[chanpos]->is_call_waiting) {
05778                pri->pvts[chanpos]->is_call_waiting = 0;
05779                ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
05780             }
05781 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
05782             sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
05783                e->answer.subcmds, e->answer.call);
05784             if (!ast_strlen_zero(pri->pvts[chanpos]->deferred_digits)) {
05785                /* We have some 'w' deferred digits to dial now. */
05786                ast_verb(3,
05787                   "Span %d: Channel %d/%d dialing deferred digit string: %s\n",
05788                   pri->span, pri->pvts[chanpos]->logicalspan,
05789                   pri->pvts[chanpos]->prioffset,
05790                   pri->pvts[chanpos]->deferred_digits);
05791                if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_DEFER_DIAL) {
05792                   pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_DEFER_DIAL;
05793                }
05794                sig_pri_dial_digits(pri->pvts[chanpos],
05795                   pri->pvts[chanpos]->deferred_digits);
05796             } else {
05797                if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
05798                   pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
05799                }
05800                sig_pri_open_media(pri->pvts[chanpos]);
05801                pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER);
05802                sig_pri_set_dialing(pri->pvts[chanpos], 0);
05803                /* Enable echo cancellation if it's not on already */
05804                sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
05805             }
05806 
05807 #ifdef SUPPORT_USERUSER
05808             if (!ast_strlen_zero(e->answer.useruserinfo)) {
05809                struct ast_channel *owner;
05810 
05811                sig_pri_lock_owner(pri, chanpos);
05812                owner = pri->pvts[chanpos]->owner;
05813                if (owner) {
05814                   pbx_builtin_setvar_helper(owner, "USERUSERINFO",
05815                      e->answer.useruserinfo);
05816                   ast_channel_unlock(owner);
05817                }
05818             }
05819 #endif
05820 
05821             sig_pri_unlock_private(pri->pvts[chanpos]);
05822             break;
05823 #if defined(HAVE_PRI_CALL_WAITING)
05824          case PRI_EVENT_CONNECT_ACK:
05825             if (sig_pri_is_cis_call(e->connect_ack.channel)) {
05826                sig_pri_handle_cis_subcmds(pri, e->e, e->connect_ack.subcmds,
05827                   e->connect_ack.call);
05828                break;
05829             }
05830             chanpos = pri_find_fixup_principle(pri, e->connect_ack.channel,
05831                e->connect_ack.call);
05832             if (chanpos < 0) {
05833                break;
05834             }
05835 
05836             sig_pri_lock_private(pri->pvts[chanpos]);
05837             sig_pri_handle_subcmds(pri, chanpos, e->e, e->connect_ack.channel,
05838                e->connect_ack.subcmds, e->connect_ack.call);
05839             sig_pri_open_media(pri->pvts[chanpos]);
05840             sig_pri_unlock_private(pri->pvts[chanpos]);
05841             sig_pri_span_devstate_changed(pri);
05842             break;
05843 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
05844          case PRI_EVENT_HANGUP:
05845             if (sig_pri_is_cis_call(e->hangup.channel)) {
05846                sig_pri_handle_cis_subcmds(pri, e->e, e->hangup.subcmds,
05847                   e->hangup.call);
05848                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
05849                break;
05850             }
05851             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
05852             if (chanpos < 0) {
05853                /*
05854                 * Continue hanging up the call even though
05855                 * we do not remember it (if we ever did).
05856                 */
05857                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
05858                break;
05859             }
05860             sig_pri_lock_private(pri->pvts[chanpos]);
05861             sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
05862                e->hangup.subcmds, e->hangup.call);
05863             switch (e->hangup.cause) {
05864             case PRI_CAUSE_INVALID_CALL_REFERENCE:
05865                /*
05866                 * The peer denies the existence of this call so we must
05867                 * continue hanging it up and forget about it.
05868                 */
05869                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
05870                pri->pvts[chanpos]->call = NULL;
05871                break;
05872             default:
05873                break;
05874             }
05875             if (!pri->pvts[chanpos]->alreadyhungup) {
05876                /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
05877                pri->pvts[chanpos]->alreadyhungup = 1;
05878                switch (e->hangup.cause) {
05879                case PRI_CAUSE_USER_BUSY:
05880                case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05881                   sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
05882                   break;
05883                default:
05884                   break;
05885                }
05886                if (pri->pvts[chanpos]->owner) {
05887                   int do_hangup = 0;
05888 
05889                   /* Queue a BUSY instead of a hangup if our cause is appropriate */
05890                   pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
05891                   switch (pri->pvts[chanpos]->owner->_state) {
05892                   case AST_STATE_BUSY:
05893                   case AST_STATE_UP:
05894                      do_hangup = 1;
05895                      break;
05896                   default:
05897                      if (!pri->pvts[chanpos]->outgoing) {
05898                         /*
05899                          * The incoming call leg hung up before getting
05900                          * connected so just hangup the call.
05901                          */
05902                         do_hangup = 1;
05903                         break;
05904                      }
05905                      switch (e->hangup.cause) {
05906                      case PRI_CAUSE_USER_BUSY:
05907                         pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
05908                         break;
05909                      case PRI_CAUSE_CALL_REJECTED:
05910                      case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
05911                      case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
05912                      case PRI_CAUSE_SWITCH_CONGESTION:
05913                      case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
05914                      case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
05915                         pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
05916                         break;
05917                      default:
05918                         do_hangup = 1;
05919                         break;
05920                      }
05921                      break;
05922                   }
05923 
05924                   if (do_hangup) {
05925 #if defined(HAVE_PRI_AOC_EVENTS)
05926                      if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
05927                         /* If a AOC-E msg was sent during the release, we must use a
05928                          * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
05929                         pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
05930                      } else {
05931                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05932                      }
05933 #else
05934                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05935 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
05936                   }
05937                } else {
05938                   /*
05939                    * Continue hanging up the call even though
05940                    * we do not have an owner.
05941                    */
05942                   pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
05943                   pri->pvts[chanpos]->call = NULL;
05944                }
05945                ast_verb(3, "Span %d: Channel %d/%d got hangup, cause %d\n",
05946                   pri->span, pri->pvts[chanpos]->logicalspan,
05947                   pri->pvts[chanpos]->prioffset, e->hangup.cause);
05948             } else {
05949                /* Continue hanging up the call. */
05950                pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
05951                pri->pvts[chanpos]->call = NULL;
05952             }
05953 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
05954             if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
05955                && pri->sig != SIG_BRI_PTMP && !pri->resetting
05956                && pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
05957                ast_verb(3,
05958                   "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
05959                   pri->span, pri->pvts[chanpos]->logicalspan,
05960                   pri->pvts[chanpos]->prioffset);
05961                pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
05962                pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
05963             }
05964 #endif   /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
05965             if (e->hangup.aoc_units > -1)
05966                ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
05967                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
05968 
05969 #ifdef SUPPORT_USERUSER
05970             if (!ast_strlen_zero(e->hangup.useruserinfo)) {
05971                struct ast_channel *owner;
05972 
05973                sig_pri_lock_owner(pri, chanpos);
05974                owner = pri->pvts[chanpos]->owner;
05975                if (owner) {
05976                   pbx_builtin_setvar_helper(owner, "USERUSERINFO",
05977                      e->hangup.useruserinfo);
05978                   ast_channel_unlock(owner);
05979                }
05980             }
05981 #endif
05982 
05983             sig_pri_unlock_private(pri->pvts[chanpos]);
05984             sig_pri_span_devstate_changed(pri);
05985             break;
05986          case PRI_EVENT_HANGUP_REQ:
05987             if (sig_pri_is_cis_call(e->hangup.channel)) {
05988                sig_pri_handle_cis_subcmds(pri, e->e, e->hangup.subcmds,
05989                   e->hangup.call);
05990                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
05991                break;
05992             }
05993             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
05994             if (chanpos < 0) {
05995                /*
05996                 * Continue hanging up the call even though
05997                 * we do not remember it (if we ever did).
05998                 */
05999                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
06000                break;
06001             }
06002             sig_pri_lock_private(pri->pvts[chanpos]);
06003             sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
06004                e->hangup.subcmds, e->hangup.call);
06005 #if defined(HAVE_PRI_CALL_HOLD)
06006             if (e->hangup.call_active && e->hangup.call_held
06007                && pri->hold_disconnect_transfer) {
06008                /* We are to transfer the call instead of simply hanging up. */
06009                sig_pri_unlock_private(pri->pvts[chanpos]);
06010                if (!sig_pri_attempt_transfer(pri, e->hangup.call_held, 1,
06011                   e->hangup.call_active, 0, NULL, NULL)) {
06012                   break;
06013                }
06014                sig_pri_lock_private(pri->pvts[chanpos]);
06015             }
06016 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
06017             switch (e->hangup.cause) {
06018             case PRI_CAUSE_USER_BUSY:
06019             case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06020                sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
06021                break;
06022             case PRI_CAUSE_INVALID_CALL_REFERENCE:
06023                /*
06024                 * The peer denies the existence of this call so we must
06025                 * continue hanging it up and forget about it.  We should not
06026                 * get this cause here, but for completeness we will handle it
06027                 * anyway.
06028                 */
06029                pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
06030                pri->pvts[chanpos]->call = NULL;
06031                break;
06032             default:
06033                break;
06034             }
06035             if (pri->pvts[chanpos]->owner) {
06036                int do_hangup = 0;
06037 
06038                pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
06039                switch (pri->pvts[chanpos]->owner->_state) {
06040                case AST_STATE_BUSY:
06041                case AST_STATE_UP:
06042                   do_hangup = 1;
06043                   break;
06044                default:
06045                   if (!pri->pvts[chanpos]->outgoing) {
06046                      /*
06047                       * The incoming call leg hung up before getting
06048                       * connected so just hangup the call.
06049                       */
06050                      do_hangup = 1;
06051                      break;
06052                   }
06053                   switch (e->hangup.cause) {
06054                   case PRI_CAUSE_USER_BUSY:
06055                      pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
06056                      break;
06057                   case PRI_CAUSE_CALL_REJECTED:
06058                   case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
06059                   case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
06060                   case PRI_CAUSE_SWITCH_CONGESTION:
06061                   case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
06062                   case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
06063                      pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
06064                      break;
06065                   default:
06066                      do_hangup = 1;
06067                      break;
06068                   }
06069                   break;
06070                }
06071 
06072                if (do_hangup) {
06073 #if defined(HAVE_PRI_AOC_EVENTS)
06074                   if (!pri->pvts[chanpos]->holding_aoce
06075                      && pri->aoce_delayhangup
06076                      && ast_bridged_channel(pri->pvts[chanpos]->owner)) {
06077                      sig_pri_send_aoce_termination_request(pri, chanpos,
06078                         pri_get_timer(pri->pri, PRI_TIMER_T305) / 2);
06079                   } else if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
06080                      /* If a AOC-E msg was sent during the Disconnect, we must use a AST_CONTROL_HANGUP frame
06081                       * to guarantee that frame gets read before hangup */
06082                      pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
06083                   } else {
06084                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06085                   }
06086 #else
06087                   pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06088 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
06089                }
06090                ast_verb(3, "Span %d: Channel %d/%d got hangup request, cause %d\n",
06091                   pri->span, pri->pvts[chanpos]->logicalspan,
06092                   pri->pvts[chanpos]->prioffset, e->hangup.cause);
06093             } else {
06094                /*
06095                 * Continue hanging up the call even though
06096                 * we do not have an owner.
06097                 */
06098                pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
06099                pri->pvts[chanpos]->call = NULL;
06100             }
06101 #if defined(FORCE_RESTART_UNAVAIL_CHANS)
06102             if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
06103                && pri->sig != SIG_BRI_PTMP && !pri->resetting
06104                && pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
06105                ast_verb(3,
06106                   "Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
06107                   pri->span, pri->pvts[chanpos]->logicalspan,
06108                   pri->pvts[chanpos]->prioffset);
06109                pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
06110                pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
06111             }
06112 #endif   /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
06113 
06114 #ifdef SUPPORT_USERUSER
06115             if (!ast_strlen_zero(e->hangup.useruserinfo)) {
06116                struct ast_channel *owner;
06117 
06118                sig_pri_lock_owner(pri, chanpos);
06119                owner = pri->pvts[chanpos]->owner;
06120                if (owner) {
06121                   pbx_builtin_setvar_helper(owner, "USERUSERINFO",
06122                      e->hangup.useruserinfo);
06123                   ast_channel_unlock(owner);
06124                }
06125             }
06126 #endif
06127 
06128             sig_pri_unlock_private(pri->pvts[chanpos]);
06129             sig_pri_span_devstate_changed(pri);
06130             break;
06131          case PRI_EVENT_HANGUP_ACK:
06132             if (sig_pri_is_cis_call(e->hangup.channel)) {
06133                sig_pri_handle_cis_subcmds(pri, e->e, e->hangup.subcmds,
06134                   e->hangup.call);
06135                break;
06136             }
06137             chanpos = pri_find_principle_by_call(pri, e->hangup.call);
06138             if (chanpos < 0) {
06139                break;
06140             }
06141             sig_pri_lock_private(pri->pvts[chanpos]);
06142             pri->pvts[chanpos]->call = NULL;
06143             if (pri->pvts[chanpos]->owner) {
06144                ast_verb(3, "Span %d: Channel %d/%d got hangup ACK\n", pri->span,
06145                   pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset);
06146             }
06147 #ifdef SUPPORT_USERUSER
06148             if (!ast_strlen_zero(e->hangup.useruserinfo)) {
06149                struct ast_channel *owner;
06150 
06151                sig_pri_lock_owner(pri, chanpos);
06152                owner = pri->pvts[chanpos]->owner;
06153                if (owner) {
06154                   pbx_builtin_setvar_helper(owner, "USERUSERINFO",
06155                      e->hangup.useruserinfo);
06156                   ast_channel_unlock(owner);
06157                }
06158             }
06159 #endif
06160             sig_pri_unlock_private(pri->pvts[chanpos]);
06161             sig_pri_span_devstate_changed(pri);
06162             break;
06163          case PRI_EVENT_CONFIG_ERR:
06164             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
06165             break;
06166          case PRI_EVENT_RESTART_ACK:
06167             chanpos = pri_find_principle(pri, e->restartack.channel, NULL);
06168             if (chanpos < 0) {
06169                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
06170                   channel number, so we have to figure it out...  This must be why
06171                   everybody resets exactly a channel at a time. */
06172                for (x = 0; x < pri->numchans; x++) {
06173                   if (pri->pvts[x]
06174                      && pri->pvts[x]->resetting != SIG_PRI_RESET_IDLE) {
06175                      chanpos = x;
06176                      sig_pri_lock_private(pri->pvts[chanpos]);
06177                      ast_debug(1,
06178                         "Span %d: Assuming restart ack is for channel %d/%d\n",
06179                         pri->span, pri->pvts[chanpos]->logicalspan,
06180                         pri->pvts[chanpos]->prioffset);
06181                      if (pri->pvts[chanpos]->owner) {
06182                         ast_log(LOG_WARNING,
06183                            "Span %d: Got restart ack on channel %d/%d with owner\n",
06184                            pri->span, pri->pvts[chanpos]->logicalspan,
06185                            pri->pvts[chanpos]->prioffset);
06186                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06187                      }
06188                      pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
06189                      ast_verb(3,
06190                         "Span %d: Channel %d/%d successfully restarted\n",
06191                         pri->span, pri->pvts[chanpos]->logicalspan,
06192                         pri->pvts[chanpos]->prioffset);
06193                      sig_pri_unlock_private(pri->pvts[chanpos]);
06194                      if (pri->resetting)
06195                         pri_check_restart(pri);
06196                      break;
06197                   }
06198                }
06199                if (chanpos < 0) {
06200                   ast_log(LOG_WARNING,
06201                      "Span %d: Restart ACK on strange channel %d/%d\n",
06202                      pri->span, PRI_SPAN(e->restartack.channel),
06203                      PRI_CHANNEL(e->restartack.channel));
06204                }
06205             } else {
06206                sig_pri_lock_private(pri->pvts[chanpos]);
06207                if (pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
06208                   /* The channel is not in the resetting state. */
06209                   ast_debug(1,
06210                      "Span %d: Unexpected or late restart ack on channel %d/%d (Ignoring)\n",
06211                      pri->span, pri->pvts[chanpos]->logicalspan,
06212                      pri->pvts[chanpos]->prioffset);
06213                   sig_pri_unlock_private(pri->pvts[chanpos]);
06214                   break;
06215                }
06216                if (pri->pvts[chanpos]->owner) {
06217                   ast_log(LOG_WARNING,
06218                      "Span %d: Got restart ack on channel %d/%d with owner\n",
06219                      pri->span, pri->pvts[chanpos]->logicalspan,
06220                      pri->pvts[chanpos]->prioffset);
06221                   pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
06222                }
06223                pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
06224                ast_verb(3,
06225                   "Span %d: Channel %d/%d successfully restarted\n",
06226                   pri->span, pri->pvts[chanpos]->logicalspan,
06227                   pri->pvts[chanpos]->prioffset);
06228                sig_pri_unlock_private(pri->pvts[chanpos]);
06229                if (pri->resetting)
06230                   pri_check_restart(pri);
06231             }
06232             break;
06233          case PRI_EVENT_SETUP_ACK:
06234             if (sig_pri_is_cis_call(e->setup_ack.channel)) {
06235                sig_pri_handle_cis_subcmds(pri, e->e, e->setup_ack.subcmds,
06236                   e->setup_ack.call);
06237                break;
06238             }
06239             chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel,
06240                e->setup_ack.call);
06241             if (chanpos < 0) {
06242                break;
06243             }
06244             sig_pri_lock_private(pri->pvts[chanpos]);
06245             sig_pri_handle_subcmds(pri, chanpos, e->e, e->setup_ack.channel,
06246                e->setup_ack.subcmds, e->setup_ack.call);
06247             if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
06248                pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP;
06249             }
06250 
06251             /* Send any queued digits */
06252             len = strlen(pri->pvts[chanpos]->dialdest);
06253             for (x = 0; x < len; ++x) {
06254                ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
06255                pri_information(pri->pri, pri->pvts[chanpos]->call,
06256                   pri->pvts[chanpos]->dialdest[x]);
06257             }
06258 
06259             if (!pri->pvts[chanpos]->progress
06260                && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
06261                && !pri->pvts[chanpos]->digital
06262                && !pri->pvts[chanpos]->no_b_channel) {
06263                /*
06264                 * Call has a channel.
06265                 * Indicate for overlap dialing that dialtone may be present.
06266                 */
06267                pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
06268                pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */
06269                sig_pri_set_dialing(pri->pvts[chanpos], 0);
06270                sig_pri_open_media(pri->pvts[chanpos]);
06271             }
06272             sig_pri_unlock_private(pri->pvts[chanpos]);
06273             break;
06274          case PRI_EVENT_NOTIFY:
06275             if (sig_pri_is_cis_call(e->notify.channel)) {
06276 #if defined(HAVE_PRI_CALL_HOLD)
06277                sig_pri_handle_cis_subcmds(pri, e->e, e->notify.subcmds,
06278                   e->notify.call);
06279 #else
06280                sig_pri_handle_cis_subcmds(pri, e->e, e->notify.subcmds, NULL);
06281 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
06282                break;
06283             }
06284 #if defined(HAVE_PRI_CALL_HOLD)
06285             chanpos = pri_find_principle_by_call(pri, e->notify.call);
06286             if (chanpos < 0) {
06287                ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n",
06288                   pri->span);
06289                break;
06290             }
06291 #else
06292             /*
06293              * This version of libpri does not supply a call pointer for
06294              * this message.  We are just going to have to trust that the
06295              * correct principle is found.
06296              */
06297             chanpos = pri_find_principle(pri, e->notify.channel, NULL);
06298             if (chanpos < 0) {
06299                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
06300                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
06301                break;
06302             }
06303 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
06304             sig_pri_lock_private(pri->pvts[chanpos]);
06305 #if defined(HAVE_PRI_CALL_HOLD)
06306             sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.channel,
06307                e->notify.subcmds, e->notify.call);
06308 #else
06309             sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.channel,
06310                e->notify.subcmds, NULL);
06311 #endif   /* !defined(HAVE_PRI_CALL_HOLD) */
06312             switch (e->notify.info) {
06313             case PRI_NOTIFY_REMOTE_HOLD:
06314                if (!pri->discardremoteholdretrieval) {
06315                   pri_queue_control(pri, chanpos, AST_CONTROL_HOLD);
06316                }
06317                break;
06318             case PRI_NOTIFY_REMOTE_RETRIEVAL:
06319                if (!pri->discardremoteholdretrieval) {
06320                   pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
06321                }
06322                break;
06323             }
06324             sig_pri_unlock_private(pri->pvts[chanpos]);
06325             break;
06326 #if defined(HAVE_PRI_CALL_HOLD)
06327          case PRI_EVENT_HOLD:
06328             /* We should not be getting any CIS calls with this message type. */
06329             if (sig_pri_handle_hold(pri, e)) {
06330                pri_hold_rej(pri->pri, e->hold.call,
06331                   PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
06332             } else {
06333                pri_hold_ack(pri->pri, e->hold.call);
06334             }
06335             break;
06336 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
06337 #if defined(HAVE_PRI_CALL_HOLD)
06338          case PRI_EVENT_HOLD_ACK:
06339             ast_debug(1, "Event: HOLD_ACK\n");
06340             break;
06341 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
06342 #if defined(HAVE_PRI_CALL_HOLD)
06343          case PRI_EVENT_HOLD_REJ:
06344             ast_debug(1, "Event: HOLD_REJ\n");
06345             break;
06346 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
06347 #if defined(HAVE_PRI_CALL_HOLD)
06348          case PRI_EVENT_RETRIEVE:
06349             /* We should not be getting any CIS calls with this message type. */
06350             sig_pri_handle_retrieve(pri, e);
06351             break;
06352 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
06353 #if defined(HAVE_PRI_CALL_HOLD)
06354          case PRI_EVENT_RETRIEVE_ACK:
06355             ast_debug(1, "Event: RETRIEVE_ACK\n");
06356             break;
06357 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
06358 #if defined(HAVE_PRI_CALL_HOLD)
06359          case PRI_EVENT_RETRIEVE_REJ:
06360             ast_debug(1, "Event: RETRIEVE_REJ\n");
06361             break;
06362 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
06363          default:
06364             ast_debug(1, "Event: %d\n", e->e);
06365             break;
06366          }
06367       }
06368       ast_mutex_unlock(&pri->lock);
06369    }
06370    /* Never reached */
06371    return NULL;
06372 }

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 }

static void pri_find_dchan ( struct sig_pri_span pri  )  [static]

Definition at line 1066 of file sig_pri.c.

References sig_pri_span::dchans, sig_pri_span::pri, and SIG_PRI_NUM_DCHANS.

Referenced by pri_event_alarm().

01067 {
01068    struct pri *old;
01069    int oldslot = -1;
01070    int newslot = -1;
01071    int idx;
01072 
01073    old = pri->pri;
01074    for (idx = 0; idx < SIG_PRI_NUM_DCHANS; ++idx) {
01075       if (!pri->dchans[idx]) {
01076          /* No more D channels defined on the span. */
01077          break;
01078       }
01079       if (pri->dchans[idx] == old) {
01080          oldslot = idx;
01081       }
01082       if (newslot < 0 && pri->dchanavail[idx] == DCHAN_AVAILABLE) {
01083          newslot = idx;
01084       }
01085    }
01086    /* At this point, idx is a count of how many D-channels are defined on the span. */
01087 
01088    if (1 < idx) {
01089       /* We have several D-channels defined on the span.  (NFAS PRI setup) */
01090       if (newslot < 0) {
01091          /* No D-channels available.  Default to the primary D-channel. */
01092          newslot = 0;
01093 
01094          if (!pri->no_d_channels) {
01095             pri->no_d_channels = 1;
01096             if (old && oldslot != newslot) {
01097                ast_log(LOG_WARNING,
01098                   "Span %d: No D-channels up!  Switching selected D-channel from %s to %s.\n",
01099                   pri->span, pri_order(oldslot), pri_order(newslot));
01100             } else {
01101                ast_log(LOG_WARNING, "Span %d: No D-channels up!\n", pri->span);
01102             }
01103          }
01104       } else {
01105          pri->no_d_channels = 0;
01106       }
01107       if (old && oldslot != newslot) {
01108          ast_log(LOG_NOTICE,
01109             "Switching selected D-channel from %s (fd %d) to %s (fd %d)!\n",
01110             pri_order(oldslot), pri->fds[oldslot],
01111             pri_order(newslot), pri->fds[newslot]);
01112       }
01113    } else {
01114       if (newslot < 0) {
01115          /* The only D-channel is not up. */
01116          newslot = 0;
01117 
01118          if (!pri->no_d_channels) {
01119             pri->no_d_channels = 1;
01120 
01121             /*
01122              * This is annoying to see on non-persistent layer 2
01123              * connections.  Let's not complain in that case.
01124              */
01125             if (pri->sig != SIG_BRI_PTMP) {
01126                ast_log(LOG_WARNING, "Span %d: D-channel is down!\n", pri->span);
01127             }
01128          }
01129       } else {
01130          pri->no_d_channels = 0;
01131       }
01132    }
01133    pri->pri = pri->dchans[newslot];
01134 }

static int pri_find_empty_chan ( struct sig_pri_span pri,
int  backwards 
) [static]

Definition at line 1764 of file sig_pri.c.

References ast_debug, sig_pri_chan::logicalspan, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_chan::pri, sig_pri_chan::prioffset, sig_pri_span::pvts, and sig_pri_is_chan_available().

Referenced by sig_pri_handle_retrieve().

01765 {
01766    int x;
01767    if (backwards)
01768       x = pri->numchans;
01769    else
01770       x = 0;
01771    for (;;) {
01772       if (backwards && (x < 0))
01773          break;
01774       if (!backwards && (x >= pri->numchans))
01775          break;
01776       if (pri->pvts[x]
01777          && !pri->pvts[x]->no_b_channel
01778          && sig_pri_is_chan_available(pri->pvts[x])) {
01779          ast_debug(1, "Found empty available channel %d/%d\n",
01780             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
01781          return x;
01782       }
01783       if (backwards)
01784          x--;
01785       else
01786          x++;
01787    }
01788    return -1;
01789 }

static int pri_find_empty_nobch ( struct sig_pri_span pri  )  [static]

Definition at line 1804 of file sig_pri.c.

References ast_debug, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_chan::pri, sig_pri_span::pvts, and sig_pri_is_chan_available().

Referenced by sig_pri_cw_available(), and sig_pri_handle_hold().

01805 {
01806    int idx;
01807 
01808    for (idx = 0; idx < pri->numchans; ++idx) {
01809       if (pri->pvts[idx]
01810          && pri->pvts[idx]->no_b_channel
01811          && sig_pri_is_chan_available(pri->pvts[idx])) {
01812          ast_debug(1, "Found empty available no B channel interface\n");
01813          return idx;
01814       }
01815    }
01816 
01817    /* Need to create a new interface. */
01818    if (pri->calls->new_nobch_intf) {
01819       idx = pri->calls->new_nobch_intf(pri);
01820    } else {
01821       idx = -1;
01822    }
01823    return idx;
01824 }

static int pri_find_fixup_principle ( struct sig_pri_span pri,
int  channel,
q931_call *  call 
) [static]

Definition at line 1563 of file sig_pri.c.

References ast_log(), LOG_WARNING, sig_pri_chan::pri, PRI_CHANNEL, pri_find_principle(), pri_fixup_principle(), PRI_SPAN, sig_pri_kill_call(), and sig_pri_span::span.

01564 {
01565    int chanpos;
01566 
01567    chanpos = pri_find_principle(pri, channel, call);
01568    if (chanpos < 0) {
01569       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
01570          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
01571       sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
01572       return -1;
01573    }
01574    chanpos = pri_fixup_principle(pri, chanpos, call);
01575    if (chanpos < 0) {
01576       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
01577          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
01578       /*
01579        * Using Q.931 section 5.2.3.1 b) as the reason for picking
01580        * PRI_CAUSE_CHANNEL_UNACCEPTABLE.  Receiving a
01581        * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
01582        * that channel (which is not specified by Q.931) and kill some
01583        * other call which would be bad.
01584        */
01585       sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
01586       return -1;
01587    }
01588    return chanpos;
01589 }

static int pri_find_principle ( struct sig_pri_span pri,
int  channel,
q931_call *  call 
) [static]

Definition at line 1329 of file sig_pri.c.

References sig_pri_chan::call, sig_pri_span::numchans, sig_pri_chan::pri, PRI_CHANNEL, PRI_HELD_CALL, sig_pri_chan::prioffset, and sig_pri_span::pvts.

Referenced by pri_find_fixup_principle(), and sig_pri_handle_retrieve().

01330 {
01331    int x;
01332    int span;
01333    int principle;
01334    int prioffset;
01335 
01336    if (channel < 0) {
01337       /* Channel is not picked yet. */
01338       return -1;
01339    }
01340 
01341    prioffset = PRI_CHANNEL(channel);
01342    if (!prioffset || (channel & PRI_HELD_CALL)) {
01343       if (!call) {
01344          /* Cannot find a call waiting call or held call without a call. */
01345          return -1;
01346       }
01347       principle = -1;
01348       for (x = 0; x < pri->numchans; ++x) {
01349          if (pri->pvts[x]
01350             && pri->pvts[x]->call == call) {
01351             principle = x;
01352             break;
01353          }
01354       }
01355       return principle;
01356    }
01357 
01358    span = PRI_SPAN(channel);
01359    if (!(channel & PRI_EXPLICIT)) {
01360       int index;
01361 
01362       index = pri_active_dchan_index(pri);
01363       if (index == -1) {
01364          return -1;
01365       }
01366       span = pri->dchan_logical_span[index];
01367    }
01368 
01369    principle = -1;
01370    for (x = 0; x < pri->numchans; x++) {
01371       if (pri->pvts[x]
01372          && pri->pvts[x]->prioffset == prioffset
01373          && pri->pvts[x]->logicalspan == span
01374          && !pri->pvts[x]->no_b_channel) {
01375          principle = x;
01376          break;
01377       }
01378    }
01379 
01380    return principle;
01381 }

static int pri_find_principle_by_call ( struct sig_pri_span pri,
q931_call *  call 
) [static]

Definition at line 1264 of file sig_pri.c.

References sig_pri_chan::call, sig_pri_span::numchans, sig_pri_chan::pri, and sig_pri_span::pvts.

Referenced by sig_pri_attempt_transfer(), sig_pri_handle_hold(), sig_pri_handle_retrieve(), and sig_pri_kill_call().

01265 {
01266    int idx;
01267 
01268    if (!call) {
01269       /* Cannot find a call without a call. */
01270       return -1;
01271    }
01272    for (idx = 0; idx < pri->numchans; ++idx) {
01273       if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
01274          /* Found the principle */
01275          return idx;
01276       }
01277    }
01278    return -1;
01279 }

static int pri_fixup_principle ( struct sig_pri_span pri,
int  principle,
q931_call *  call 
) [static]

Definition at line 1396 of file sig_pri.c.

References ast_channel_unlock, ast_log(), ast_verb, sig_pri_chan::call, LOG_WARNING, sig_pri_span::numchans, sig_pri_chan::pri, sig_pri_span::pvts, sig_pri_ami_channel_event(), SIG_PRI_CALL_LEVEL_IDLE, sig_pri_fixup_chans(), sig_pri_is_chan_available(), sig_pri_lock_owner(), sig_pri_lock_private(), sig_pri_open_media(), and sig_pri_unlock_private().

Referenced by pri_find_fixup_principle(), sig_pri_handle_hold(), and sig_pri_handle_retrieve().

01397 {
01398    int x;
01399 
01400    if (principle < 0 || pri->numchans <= principle) {
01401       /* Out of rannge */
01402       return -1;
01403    }
01404    if (!call) {
01405       /* No call */
01406       return principle;
01407    }
01408    if (pri->pvts[principle] && pri->pvts[principle]->call == call) {
01409       /* Call is already on the specified principle. */
01410       return principle;
01411    }
01412 
01413    /* Find the old principle location. */
01414    for (x = 0; x < pri->numchans; x++) {
01415       struct sig_pri_chan *new_chan;
01416       struct sig_pri_chan *old_chan;
01417 
01418       if (!pri->pvts[x] || pri->pvts[x]->call != call) {
01419          continue;
01420       }
01421 
01422       /* Found our call */
01423       new_chan = pri->pvts[principle];
01424       old_chan = pri->pvts[x];
01425 
01426       /* Get locks to safely move to the new private structure. */
01427       sig_pri_lock_private(old_chan);
01428       sig_pri_lock_owner(pri, x);
01429       sig_pri_lock_private(new_chan);
01430 
01431       ast_verb(3, "Moving call (%s) from channel %d to %d.\n",
01432          old_chan->owner ? old_chan->owner->name : "",
01433          old_chan->channel, new_chan->channel);
01434       if (!sig_pri_is_chan_available(new_chan)) {
01435          ast_log(LOG_WARNING,
01436             "Can't move call (%s) from channel %d to %d.  It is already in use.\n",
01437             old_chan->owner ? old_chan->owner->name : "",
01438             old_chan->channel, new_chan->channel);
01439          sig_pri_unlock_private(new_chan);
01440          if (old_chan->owner) {
01441             ast_channel_unlock(old_chan->owner);
01442          }
01443          sig_pri_unlock_private(old_chan);
01444          return -1;
01445       }
01446 
01447       sig_pri_fixup_chans(old_chan, new_chan);
01448 
01449       /* Fix it all up now */
01450       new_chan->owner = old_chan->owner;
01451       old_chan->owner = NULL;
01452 
01453       new_chan->call = old_chan->call;
01454       old_chan->call = NULL;
01455 
01456       /* Transfer flags from the old channel. */
01457 #if defined(HAVE_PRI_AOC_EVENTS)
01458       new_chan->aoc_s_request_invoke_id_valid = old_chan->aoc_s_request_invoke_id_valid;
01459       new_chan->waiting_for_aoce = old_chan->waiting_for_aoce;
01460       new_chan->holding_aoce = old_chan->holding_aoce;
01461 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
01462       new_chan->alreadyhungup = old_chan->alreadyhungup;
01463       new_chan->isidlecall = old_chan->isidlecall;
01464       new_chan->progress = old_chan->progress;
01465       new_chan->allocated = old_chan->allocated;
01466       new_chan->outgoing = old_chan->outgoing;
01467       new_chan->digital = old_chan->digital;
01468 #if defined(HAVE_PRI_CALL_WAITING)
01469       new_chan->is_call_waiting = old_chan->is_call_waiting;
01470 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
01471 
01472 #if defined(HAVE_PRI_AOC_EVENTS)
01473       old_chan->aoc_s_request_invoke_id_valid = 0;
01474       old_chan->waiting_for_aoce = 0;
01475       old_chan->holding_aoce = 0;
01476 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
01477       old_chan->alreadyhungup = 0;
01478       old_chan->isidlecall = 0;
01479       old_chan->progress = 0;
01480       old_chan->allocated = 0;
01481       old_chan->outgoing = 0;
01482       old_chan->digital = 0;
01483 #if defined(HAVE_PRI_CALL_WAITING)
01484       old_chan->is_call_waiting = 0;
01485 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
01486 
01487       /* More stuff to transfer to the new channel. */
01488       new_chan->call_level = old_chan->call_level;
01489       old_chan->call_level = SIG_PRI_CALL_LEVEL_IDLE;
01490 #if defined(HAVE_PRI_REVERSE_CHARGE)
01491       new_chan->reverse_charging_indication = old_chan->reverse_charging_indication;
01492 #endif   /* defined(HAVE_PRI_REVERSE_CHARGE) */
01493 #if defined(HAVE_PRI_SETUP_KEYPAD)
01494       strcpy(new_chan->keypad_digits, old_chan->keypad_digits);
01495 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
01496       strcpy(new_chan->deferred_digits, old_chan->deferred_digits);
01497 #if defined(HAVE_PRI_AOC_EVENTS)
01498       new_chan->aoc_s_request_invoke_id = old_chan->aoc_s_request_invoke_id;
01499       new_chan->aoc_e = old_chan->aoc_e;
01500 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
01501       strcpy(new_chan->user_tag, old_chan->user_tag);
01502 
01503       if (new_chan->no_b_channel) {
01504          /* Copy the real channel configuration to the no B channel interface. */
01505          new_chan->hidecallerid = old_chan->hidecallerid;
01506          new_chan->hidecalleridname = old_chan->hidecalleridname;
01507          new_chan->immediate = old_chan->immediate;
01508          new_chan->priexclusive = old_chan->priexclusive;
01509          new_chan->priindication_oob = old_chan->priindication_oob;
01510          new_chan->use_callerid = old_chan->use_callerid;
01511          new_chan->use_callingpres = old_chan->use_callingpres;
01512          new_chan->stripmsd = old_chan->stripmsd;
01513          strcpy(new_chan->context, old_chan->context);
01514          strcpy(new_chan->mohinterpret, old_chan->mohinterpret);
01515 
01516          /* Become a member of the old channel span/trunk-group. */
01517          new_chan->logicalspan = old_chan->logicalspan;
01518          new_chan->mastertrunkgroup = old_chan->mastertrunkgroup;
01519       } else if (old_chan->no_b_channel) {
01520          /*
01521           * We are transitioning from a held/call-waiting channel to a
01522           * real channel so we need to make sure that the media path is
01523           * open.  (Needed especially if the channel is natively
01524           * bridged.)
01525           */
01526          sig_pri_open_media(new_chan);
01527       }
01528 
01529       if (new_chan->owner) {
01530          sig_pri_ami_channel_event(new_chan);
01531       }
01532 
01533       sig_pri_unlock_private(old_chan);
01534       if (new_chan->owner) {
01535          ast_channel_unlock(new_chan->owner);
01536       }
01537       sig_pri_unlock_private(new_chan);
01538 
01539       return principle;
01540    }
01541    ast_verb(3, "Call specified, but not found.\n");
01542    return -1;
01543 }

static int pri_grab ( struct sig_pri_chan p,
struct sig_pri_span pri 
) [inline, static]

Definition at line 342 of file sig_pri.c.

References ast_mutex_trylock, AST_PTHREADT_NULL, sig_pri_span::lock, sig_pri_span::master, sig_pri_lock_private(), and sig_pri_unlock_private().

Referenced by pri_send_callrerouting_facility_exec(), pri_send_keypad_facility_exec(), pri_ss_thread(), sig_pri_answer(), sig_pri_call(), sig_pri_chan_alarm_notify(), sig_pri_digit_begin(), sig_pri_hangup(), and sig_pri_indicate().

00343 {
00344    /* Grab the lock first */
00345    while (ast_mutex_trylock(&pri->lock)) {
00346       /* Avoid deadlock */
00347       sig_pri_unlock_private(p);
00348       sched_yield();
00349       sig_pri_lock_private(p);
00350    }
00351    /* Then break the poll */
00352    if (pri->master != AST_PTHREADT_NULL) {
00353       pthread_kill(pri->master, SIGURG);
00354    }
00355    return 0;
00356 }

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 }

static const char* pri_order ( int  level  )  [static]

Definition at line 1036 of file sig_pri.c.

Referenced by pri_dchannel(), and sig_pri_cli_show_span().

01037 {
01038    switch (level) {
01039    case 0:
01040       return "Primary";
01041    case 1:
01042       return "Secondary";
01043    case 2:
01044       return "Tertiary";
01045    case 3:
01046       return "Quaternary";
01047    default:
01048       return "<Unknown>";
01049    }
01050 }

static void pri_queue_control ( struct sig_pri_span pri,
int  chanpos,
int  subclass 
) [static]

Definition at line 1238 of file sig_pri.c.

References AST_FRAME_CONTROL, sig_pri_chan::calls, sig_pri_chan::chan_pvt, f, sig_pri_chan::pri, pri_queue_frame(), sig_pri_span::pvts, and sig_pri_callback::queue_control.

Referenced by sig_pri_handle_retrieve(), and sig_pri_kill_call().

01239 {
01240    struct ast_frame f = {AST_FRAME_CONTROL, };
01241    struct sig_pri_chan *p = pri->pvts[chanpos];
01242 
01243    if (p->calls->queue_control) {
01244       p->calls->queue_control(p->chan_pvt, subclass);
01245    }
01246 
01247    f.subclass.integer = subclass;
01248    pri_queue_frame(pri, chanpos, &f);
01249 }

static void pri_queue_frame ( struct sig_pri_span pri,
int  chanpos,
struct ast_frame frame 
) [static]

Definition at line 1215 of file sig_pri.c.

References ast_channel_unlock, ast_queue_frame(), sig_pri_chan::owner, sig_pri_span::pvts, and sig_pri_lock_owner().

Referenced by pri_queue_control().

01216 {
01217    sig_pri_lock_owner(pri, chanpos);
01218    if (pri->pvts[chanpos]->owner) {
01219       ast_queue_frame(pri->pvts[chanpos]->owner, frame);
01220       ast_channel_unlock(pri->pvts[chanpos]->owner);
01221    }
01222 }

static void pri_rel ( struct sig_pri_span pri  )  [inline, static]

Definition at line 144 of file sig_pri.c.

References ast_mutex_unlock, and sig_pri_span::lock.

Referenced by pri_send_callrerouting_facility_exec(), pri_send_keypad_facility_exec(), pri_ss_thread(), sig_pri_answer(), sig_pri_call(), sig_pri_chan_alarm_notify(), sig_pri_digit_begin(), sig_pri_hangup(), and sig_pri_indicate().

00145 {
00146    ast_mutex_unlock(&pri->lock);
00147 }

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_chan::pri, sig_pri_span::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_chan::pri, sig_pri_span::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 }

static void* pri_ss_thread ( void *  data  )  [static]

Definition at line 1876 of file sig_pri.c.

References sig_pri_span::append_msn_to_user_tag, AST_CAUSE_UNALLOCATED, ast_copy_string(), ast_exists_extension(), ast_free, ast_hangup(), ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_pbx_run(), ast_setstate(), AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_verb, ast_waitfordigit(), sig_pri_chan::call, sig_pri_chan::call_level, ast_channel::caller, sig_pri_chan::cid_num, ast_channel::context, DAHDI_OVERLAPDIAL_INCOMING, ast_channel::dialed, ast_channel::exten, sig_pri_chan::exten, exten, ast_channel::hangupcause, ast_party_caller::id, sig_pri_span::initial_user_tag, len(), sig_pri_span::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, sig_pri_span::nodetype, ast_party_dialed::number, sig_pri_span::overlapdial, sig_pri_chan::owner, sig_pri_span::pri, sig_pri_chan::pri, pri_gendigittimeout, pri_grab(), pri_matchdigittimeout, pri_rel(), PVT_TO_CHANNEL(), SIG_PRI_CALL_LEVEL_PROCEEDING, sig_pri_dsp_reset_and_flush_digits(), sig_pri_lock_private(), sig_pri_play_tone(), sig_pri_set_echocanceller(), sig_pri_span_devstate_changed(), SIG_PRI_TONE_DIALTONE, sig_pri_unlock_private(), ast_party_dialed::str, ast_party_id::tag, ast_channel::tech_pvt, and sig_pri_chan::user_tag.

01877 {
01878    struct sig_pri_chan *p = data;
01879    struct ast_channel *chan = p->owner;
01880    char exten[AST_MAX_EXTENSION];
01881    int res;
01882    int len;
01883    int timeout;
01884 
01885    if (!chan) {
01886       /* We lost the owner before we could get started. */
01887       return NULL;
01888    }
01889 
01890    /*
01891     * In the bizarre case where the channel has become a zombie before we
01892     * even get started here, abort safely.
01893     */
01894    if (!chan->tech_pvt) {
01895       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
01896       ast_hangup(chan);
01897       return NULL;
01898    }
01899 
01900    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
01901 
01902    sig_pri_dsp_reset_and_flush_digits(p);
01903 
01904    /* Now loop looking for an extension */
01905    ast_copy_string(exten, p->exten, sizeof(exten));
01906    len = strlen(exten);
01907    res = 0;
01908    while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
01909       if (len && !ast_ignore_pattern(chan->context, exten))
01910          sig_pri_play_tone(p, -1);
01911       else
01912          sig_pri_play_tone(p, SIG_PRI_TONE_DIALTONE);
01913       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
01914          timeout = pri_matchdigittimeout;
01915       else
01916          timeout = pri_gendigittimeout;
01917       res = ast_waitfordigit(chan, timeout);
01918       if (res < 0) {
01919          ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
01920          ast_hangup(chan);
01921          return NULL;
01922       } else if (res) {
01923          exten[len++] = res;
01924          exten[len] = '\0';
01925       } else
01926          break;
01927    }
01928    /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
01929    if (ast_strlen_zero(exten)) {
01930       ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
01931       exten[0] = 's';
01932       exten[1] = '\0';
01933    } else {
01934       ast_free(chan->dialed.number.str);
01935       chan->dialed.number.str = ast_strdup(exten);
01936 
01937       if (p->pri->append_msn_to_user_tag && p->pri->nodetype != PRI_NETWORK) {
01938          /*
01939           * Update the user tag for party id's from this device for this call
01940           * now that we have a complete MSN from the network.
01941           */
01942          snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
01943             exten);
01944          ast_free(chan->caller.id.tag);
01945          chan->caller.id.tag = ast_strdup(p->user_tag);
01946       }
01947    }
01948    sig_pri_play_tone(p, -1);
01949    if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
01950       /* Start the real PBX */
01951       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
01952       sig_pri_dsp_reset_and_flush_digits(p);
01953 #if defined(ISSUE_16789)
01954       /*
01955        * Conditionaled out this code to effectively revert the Mantis
01956        * issue 16789 change.  It breaks overlap dialing through
01957        * Asterisk.  There is not enough information available at this
01958        * point to know if dialing is complete.  The
01959        * ast_exists_extension(), ast_matchmore_extension(), and
01960        * ast_canmatch_extension() calls are not adequate to detect a
01961        * dial through extension pattern of "_9!".
01962        *
01963        * Workaround is to use the dialplan Proceeding() application
01964        * early on non-dial through extensions.
01965        */
01966       if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
01967          && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
01968          sig_pri_lock_private(p);
01969          if (p->pri->pri) {
01970             pri_grab(p, p->pri);
01971             if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
01972                p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
01973             }
01974             pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
01975             pri_rel(p->pri);
01976          }
01977          sig_pri_unlock_private(p);
01978       }
01979 #endif   /* defined(ISSUE_16789) */
01980 
01981       sig_pri_set_echocanceller(p, 1);
01982       ast_setstate(chan, AST_STATE_RING);
01983       res = ast_pbx_run(chan);
01984       if (res) {
01985          ast_log(LOG_WARNING, "PBX exited non-zero!\n");
01986       }
01987    } else {
01988       ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
01989       chan->hangupcause = AST_CAUSE_UNALLOCATED;
01990       ast_hangup(chan);
01991       p->exten[0] = '\0';
01992       /* Since we send release complete here, we won't get one */
01993       p->call = NULL;
01994       ast_mutex_lock(&p->pri->lock);
01995       sig_pri_span_devstate_changed(p->pri);
01996       ast_mutex_unlock(&p->pri->lock);
01997    }
01998    return NULL;
01999 }

static enum AST_PARTY_CHAR_SET pri_to_ast_char_set ( int  pri_char_set  )  [static]

Definition at line 547 of file sig_pri.c.

References AST_PARTY_CHAR_SET_ISO10646_BMPSTRING, AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING, AST_PARTY_CHAR_SET_ISO8859_1, AST_PARTY_CHAR_SET_ISO8859_2, AST_PARTY_CHAR_SET_ISO8859_3, AST_PARTY_CHAR_SET_ISO8859_4, AST_PARTY_CHAR_SET_ISO8859_5, AST_PARTY_CHAR_SET_ISO8859_7, AST_PARTY_CHAR_SET_UNKNOWN, and AST_PARTY_CHAR_SET_WITHDRAWN.

Referenced by sig_pri_party_name_convert().

00548 {
00549    enum AST_PARTY_CHAR_SET ast_char_set;
00550 
00551    switch (pri_char_set) {
00552    default:
00553    case PRI_CHAR_SET_UNKNOWN:
00554       ast_char_set = AST_PARTY_CHAR_SET_UNKNOWN;
00555       break;
00556    case PRI_CHAR_SET_ISO8859_1:
00557       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_1;
00558       break;
00559    case PRI_CHAR_SET_WITHDRAWN:
00560       ast_char_set = AST_PARTY_CHAR_SET_WITHDRAWN;
00561       break;
00562    case PRI_CHAR_SET_ISO8859_2:
00563       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_2;
00564       break;
00565    case PRI_CHAR_SET_ISO8859_3:
00566       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_3;
00567       break;
00568    case PRI_CHAR_SET_ISO8859_4:
00569       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_4;
00570       break;
00571    case PRI_CHAR_SET_ISO8859_5:
00572       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_5;
00573       break;
00574    case PRI_CHAR_SET_ISO8859_7:
00575       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_7;
00576       break;
00577    case PRI_CHAR_SET_ISO10646_BMPSTRING:
00578       ast_char_set = AST_PARTY_CHAR_SET_ISO10646_BMPSTRING;
00579       break;
00580    case PRI_CHAR_SET_ISO10646_UTF_8STRING:
00581       ast_char_set = AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING;
00582       break;
00583    }
00584 
00585    return ast_char_set;
00586 }

static int pri_to_ast_presentation ( int  pri_presentation  )  [static]

Definition at line 437 of file sig_pri.c.

References AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.

Referenced by sig_pri_party_name_convert(), and sig_pri_party_number_convert().

00438 {
00439    int ast_presentation;
00440 
00441    switch (pri_presentation) {
00442    case PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED:
00443       ast_presentation = AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED;
00444       break;
00445    case PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN:
00446       ast_presentation = AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN;
00447       break;
00448    case PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN:
00449       ast_presentation = AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN;
00450       break;
00451    case PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER:
00452       ast_presentation = AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER;
00453       break;
00454 
00455    case PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED:
00456       ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
00457       break;
00458    case PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN:
00459       ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN;
00460       break;
00461    case PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN:
00462       ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN;
00463       break;
00464    case PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER:
00465       ast_presentation = AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER;
00466       break;
00467 
00468    case PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED:
00469    case PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_PASSED_SCREEN:
00470    case PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_FAILED_SCREEN:
00471    case PRI_PRES_UNAVAILABLE | PRI_PRES_NETWORK_NUMBER:
00472       ast_presentation = AST_PRES_NUMBER_NOT_AVAILABLE;
00473       break;
00474 
00475    default:
00476       ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
00477       break;
00478    }
00479 
00480    return ast_presentation;
00481 }

static enum AST_REDIRECTING_REASON pri_to_ast_reason ( int  pri_reason  )  [static]

Definition at line 367 of file sig_pri.c.

References AST_REDIRECTING_REASON_DEFLECTION, AST_REDIRECTING_REASON_NO_ANSWER, AST_REDIRECTING_REASON_UNCONDITIONAL, AST_REDIRECTING_REASON_UNKNOWN, and AST_REDIRECTING_REASON_USER_BUSY.

Referenced by sig_pri_redirecting_convert().

00368 {
00369    enum AST_REDIRECTING_REASON ast_reason;
00370 
00371    switch (pri_reason) {
00372    case PRI_REDIR_FORWARD_ON_BUSY:
00373       ast_reason = AST_REDIRECTING_REASON_USER_BUSY;
00374       break;
00375    case PRI_REDIR_FORWARD_ON_NO_REPLY:
00376       ast_reason = AST_REDIRECTING_REASON_NO_ANSWER;
00377       break;
00378    case PRI_REDIR_DEFLECTION:
00379       ast_reason = AST_REDIRECTING_REASON_DEFLECTION;
00380       break;
00381    case PRI_REDIR_UNCONDITIONAL:
00382       ast_reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
00383       break;
00384    case PRI_REDIR_UNKNOWN:
00385    default:
00386       ast_reason = AST_REDIRECTING_REASON_UNKNOWN;
00387       break;
00388    }
00389 
00390    return ast_reason;
00391 }

static unsigned int PVT_TO_CHANNEL ( struct sig_pri_chan p  )  [static]

Definition at line 149 of file sig_pri.c.

References ast_debug, sig_pri_chan::logicalspan, sig_pri_chan::mastertrunkgroup, PRI_EXPLICIT, and sig_pri_chan::prioffset.

Referenced by pri_check_restart(), pri_maintenance_bservice(), pri_ss_thread(), sig_pri_call(), sig_pri_handle_retrieve(), and sig_pri_indicate().

00150 {
00151    int res = (((p)->prioffset) | ((p)->logicalspan << 8) | (p->mastertrunkgroup ? PRI_EXPLICIT : 0));
00152    ast_debug(5, "prioffset: %d mastertrunkgroup: %d logicalspan: %d result: %d\n",
00153       p->prioffset, p->mastertrunkgroup, p->logicalspan, res);
00154 
00155    return res;
00156 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 1591 of file sig_pri.c.

01592 {
01593    switch (redirectingreason) {
01594    case 0:
01595       return "UNKNOWN";
01596    case 1:
01597       return "BUSY";
01598    case 2:
01599       return "NO_REPLY";
01600    case 0xF:
01601       return "UNCONDITIONAL";
01602    default:
01603       return "NOREDIRECT";
01604    }
01605 }

static void sig_pri_ami_channel_event ( struct sig_pri_chan p  )  [static]

Definition at line 1005 of file sig_pri.c.

References sig_pri_callback::ami_channel_event, sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_chan::owner.

Referenced by pri_fixup_principle().

01006 {
01007    if (p->calls->ami_channel_event) {
01008       p->calls->ami_channel_event(p->chan_pvt, p->owner);
01009    }
01010 }

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_chan::pri, sig_pri_span::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 }

static enum ast_aoc_s_charged_item sig_pri_aoc_charged_item_to_ast ( enum PRI_AOC_CHARGED_ITEM  value  )  [static]

Definition at line 2905 of file sig_pri.c.

References AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION, AST_AOC_CHARGED_ITEM_CALL_ATTEMPT, AST_AOC_CHARGED_ITEM_CALL_SETUP, AST_AOC_CHARGED_ITEM_NA, AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT, AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE, and AST_AOC_CHARGED_ITEM_USER_USER_INFO.

Referenced by sig_pri_aoc_s_from_pri().

02906 {
02907    switch (value) {
02908    case PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE:
02909       return AST_AOC_CHARGED_ITEM_NA;
02910    case PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
02911       return AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
02912    case PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
02913       return AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
02914    case PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT:
02915       return AST_AOC_CHARGED_ITEM_CALL_ATTEMPT;
02916    case PRI_AOC_CHARGED_ITEM_CALL_SETUP:
02917       return AST_AOC_CHARGED_ITEM_CALL_SETUP;
02918    case PRI_AOC_CHARGED_ITEM_USER_USER_INFO:
02919       return AST_AOC_CHARGED_ITEM_USER_USER_INFO;
02920    case PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
02921       return AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
02922    }
02923    return AST_AOC_CHARGED_ITEM_NA;
02924 }

static enum PRI_AOC_CHARGED_ITEM sig_pri_aoc_charged_item_to_pri ( enum PRI_AOC_CHARGED_ITEM  value  )  [static]

Definition at line 2873 of file sig_pri.c.

References AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION, AST_AOC_CHARGED_ITEM_CALL_ATTEMPT, AST_AOC_CHARGED_ITEM_CALL_SETUP, AST_AOC_CHARGED_ITEM_NA, AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT, AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE, and AST_AOC_CHARGED_ITEM_USER_USER_INFO.

Referenced by sig_pri_aoc_s_from_ast().

02874 {
02875    switch (value) {
02876    case AST_AOC_CHARGED_ITEM_NA:
02877       return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
02878    case AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
02879       return PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
02880    case AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
02881       return PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
02882    case AST_AOC_CHARGED_ITEM_CALL_ATTEMPT:
02883       return PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT;
02884    case AST_AOC_CHARGED_ITEM_CALL_SETUP:
02885       return PRI_AOC_CHARGED_ITEM_CALL_SETUP;
02886    case AST_AOC_CHARGED_ITEM_USER_USER_INFO:
02887       return PRI_AOC_CHARGED_ITEM_USER_USER_INFO;
02888    case AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
02889       return PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
02890    }
02891    return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
02892 }

static void sig_pri_aoc_d_from_ast ( struct sig_pri_chan pvt,
struct ast_aoc_decoded decoded 
) [static]

Definition at line 3561 of file sig_pri.c.

References ast_aoc_unit_entry::amount, ARRAY_LEN, AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_NA, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_UNIT, ast_aoc_get_billing_id(), ast_aoc_get_charge_type(), ast_aoc_get_currency_amount(), ast_aoc_get_currency_multiplier(), ast_aoc_get_currency_name(), ast_aoc_get_total_type(), ast_aoc_get_unit_count(), ast_aoc_get_unit_info(), AST_AOC_TOTAL, ast_copy_string(), ast_strlen_zero(), sig_pri_chan::call, sig_pri_span::pri, sig_pri_chan::pri, sig_pri_aoc_multiplier_from_ast(), ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.

Referenced by sig_pri_indicate().

03562 {
03563    struct pri_subcmd_aoc_d aoc_d = { 0, };
03564 
03565    aoc_d.billing_accumulation = (ast_aoc_get_total_type(decoded) == AST_AOC_TOTAL) ? 1 : 0;
03566 
03567    switch (ast_aoc_get_billing_id(decoded)) {
03568    case AST_AOC_BILLING_NORMAL:
03569       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_NORMAL;
03570       break;
03571    case AST_AOC_BILLING_REVERSE_CHARGE:
03572       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_REVERSE;
03573       break;
03574    case AST_AOC_BILLING_CREDIT_CARD:
03575       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_CREDIT_CARD;
03576       break;
03577    case AST_AOC_BILLING_NA:
03578    default:
03579       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_NOT_AVAILABLE;
03580       break;
03581    }
03582 
03583    switch (ast_aoc_get_charge_type(decoded)) {
03584    case AST_AOC_CHARGE_FREE:
03585       aoc_d.charge = PRI_AOC_DE_CHARGE_FREE;
03586       break;
03587    case AST_AOC_CHARGE_CURRENCY:
03588       {
03589          const char *currency_name = ast_aoc_get_currency_name(decoded);
03590          aoc_d.charge = PRI_AOC_DE_CHARGE_CURRENCY;
03591          aoc_d.recorded.money.amount.cost = ast_aoc_get_currency_amount(decoded);
03592          aoc_d.recorded.money.amount.multiplier = sig_pri_aoc_multiplier_from_ast(ast_aoc_get_currency_multiplier(decoded));
03593          if (!ast_strlen_zero(currency_name)) {
03594             ast_copy_string(aoc_d.recorded.money.currency, currency_name, sizeof(aoc_d.recorded.money.currency));
03595          }
03596       }
03597       break;
03598    case AST_AOC_CHARGE_UNIT:
03599       {
03600          const struct ast_aoc_unit_entry *entry;
03601          int i;
03602          aoc_d.charge = PRI_AOC_DE_CHARGE_UNITS;
03603          for (i = 0; i < ast_aoc_get_unit_count(decoded); i++) {
03604             if ((entry = ast_aoc_get_unit_info(decoded, i)) && i < ARRAY_LEN(aoc_d.recorded.unit.item)) {
03605                if (entry->valid_amount) {
03606                   aoc_d.recorded.unit.item[i].number = entry->amount;
03607                } else {
03608                   aoc_d.recorded.unit.item[i].number = -1;
03609                }
03610                if (entry->valid_type) {
03611                   aoc_d.recorded.unit.item[i].type = entry->type;
03612                } else {
03613                   aoc_d.recorded.unit.item[i].type = -1;
03614                }
03615                aoc_d.recorded.unit.num_items++;
03616             } else {
03617                break;
03618             }
03619          }
03620       }
03621       break;
03622    case AST_AOC_CHARGE_NA:
03623    default:
03624       aoc_d.charge = PRI_AOC_DE_CHARGE_NOT_AVAILABLE;
03625       break;
03626    }
03627 
03628    pri_aoc_d_send(pvt->pri->pri, pvt->call, &aoc_d);
03629 }

static void sig_pri_aoc_d_from_pri ( const struct pri_subcmd_aoc_d *  aoc_d,
struct ast_channel owner,
int  passthrough 
) [static]

Definition at line 3234 of file sig_pri.c.

References ast_aoc_add_unit_entry(), AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_NA, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_UNIT, ast_aoc_create(), AST_AOC_D, ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), ast_aoc_encode(), ast_aoc_manager_event(), ast_aoc_set_billing_id(), ast_aoc_set_currency_info(), ast_aoc_set_total_type(), AST_AOC_SUBTOTAL, AST_AOC_TOTAL, AST_CONTROL_AOC, ast_debug, ast_queue_control_data(), sig_pri_aoc_multiplier_from_pri(), and type.

Referenced by sig_pri_handle_subcmds().

03235 {
03236    struct ast_aoc_decoded *decoded = NULL;
03237    struct ast_aoc_encoded *encoded = NULL;
03238    size_t encoded_size = 0;
03239    enum ast_aoc_charge_type type;
03240 
03241    if (!owner || !aoc_d) {
03242       return;
03243    }
03244 
03245    switch (aoc_d->charge) {
03246    case PRI_AOC_DE_CHARGE_CURRENCY:
03247       type = AST_AOC_CHARGE_CURRENCY;
03248       break;
03249    case PRI_AOC_DE_CHARGE_UNITS:
03250       type = AST_AOC_CHARGE_UNIT;
03251       break;
03252    case PRI_AOC_DE_CHARGE_FREE:
03253       type = AST_AOC_CHARGE_FREE;
03254       break;
03255    default:
03256       type = AST_AOC_CHARGE_NA;
03257       break;
03258    }
03259 
03260    if (!(decoded = ast_aoc_create(AST_AOC_D, type, 0))) {
03261       return;
03262    }
03263 
03264    switch (aoc_d->billing_accumulation) {
03265    default:
03266       ast_debug(1, "AOC-D billing accumulation has unknown value: %d\n",
03267          aoc_d->billing_accumulation);
03268       /* Fall through */
03269    case 0:/* subTotal */
03270       ast_aoc_set_total_type(decoded, AST_AOC_SUBTOTAL);
03271       break;
03272    case 1:/* total */
03273       ast_aoc_set_total_type(decoded, AST_AOC_TOTAL);
03274       break;
03275    }
03276 
03277    switch (aoc_d->billing_id) {
03278    case PRI_AOC_D_BILLING_ID_NORMAL:
03279       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NORMAL);
03280       break;
03281    case PRI_AOC_D_BILLING_ID_REVERSE:
03282       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_REVERSE_CHARGE);
03283       break;
03284    case PRI_AOC_D_BILLING_ID_CREDIT_CARD:
03285       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CREDIT_CARD);
03286       break;
03287    case PRI_AOC_D_BILLING_ID_NOT_AVAILABLE:
03288    default:
03289       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NA);
03290       break;
03291    }
03292 
03293    switch (aoc_d->charge) {
03294    case PRI_AOC_DE_CHARGE_CURRENCY:
03295       ast_aoc_set_currency_info(decoded,
03296          aoc_d->recorded.money.amount.cost,
03297          sig_pri_aoc_multiplier_from_pri(aoc_d->recorded.money.amount.multiplier),
03298          aoc_d->recorded.money.currency);
03299       break;
03300    case PRI_AOC_DE_CHARGE_UNITS:
03301       {
03302          int i;
03303          for (i = 0; i < aoc_d->recorded.unit.num_items; ++i) {
03304             /* if type or number are negative, then they are not present */
03305             ast_aoc_add_unit_entry(decoded,
03306                (aoc_d->recorded.unit.item[i].number >= 0 ? 1 : 0),
03307                aoc_d->recorded.unit.item[i].number,
03308                (aoc_d->recorded.unit.item[i].type >= 0 ? 1 : 0),
03309                aoc_d->recorded.unit.item[i].type);
03310          }
03311       }
03312       break;
03313    }
03314 
03315    if (passthrough && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
03316       ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
03317    }
03318 
03319    ast_aoc_manager_event(decoded, owner);
03320 
03321    ast_aoc_destroy_decoded(decoded);
03322    ast_aoc_destroy_encoded(encoded);
03323 }

static void sig_pri_aoc_e_from_ast ( struct sig_pri_chan pvt,
struct ast_aoc_decoded decoded 
) [static]

Definition at line 3644 of file sig_pri.c.

References ast_aoc_unit_entry::amount, sig_pri_chan::aoc_e, ARRAY_LEN, AST_AOC_BILLING_CALL_DEFLECTION, AST_AOC_BILLING_CALL_FWD_BUSY, AST_AOC_BILLING_CALL_FWD_NO_REPLY, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL, AST_AOC_BILLING_CALL_TRANSFER, AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_NA, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_UNIT, AST_AOC_CHARGING_ASSOCIATION_ID, AST_AOC_CHARGING_ASSOCIATION_NA, AST_AOC_CHARGING_ASSOCIATION_NUMBER, ast_aoc_get_association_info(), ast_aoc_get_billing_id(), ast_aoc_get_charge_type(), ast_aoc_get_currency_amount(), ast_aoc_get_currency_multiplier(), ast_aoc_get_currency_name(), ast_aoc_get_unit_count(), ast_aoc_get_unit_info(), ast_copy_string(), ast_strlen_zero(), ast_aoc_charging_association::charge, ast_aoc_charging_association::charging_type, sig_pri_chan::holding_aoce, ast_aoc_charging_association::id, ast_aoc_charging_association_number::number, ast_aoc_charging_association::number, ast_aoc_charging_association_number::plan, sig_pri_aoc_multiplier_from_ast(), ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.

Referenced by sig_pri_indicate().

03645 {
03646    struct pri_subcmd_aoc_e *aoc_e = &pvt->aoc_e;
03647    const struct ast_aoc_charging_association *ca = ast_aoc_get_association_info(decoded);
03648 
03649    memset(aoc_e, 0, sizeof(*aoc_e));
03650    pvt->holding_aoce = 1;
03651 
03652    switch (ca->charging_type) {
03653    case AST_AOC_CHARGING_ASSOCIATION_NUMBER:
03654       aoc_e->associated.charge.number.valid = 1;
03655       ast_copy_string(aoc_e->associated.charge.number.str,
03656          ca->charge.number.number,
03657          sizeof(aoc_e->associated.charge.number.str));
03658       aoc_e->associated.charge.number.plan = ca->charge.number.plan;
03659       aoc_e->associated.charging_type = PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER;
03660       break;
03661    case AST_AOC_CHARGING_ASSOCIATION_ID:
03662       aoc_e->associated.charge.id = ca->charge.id;
03663       aoc_e->associated.charging_type = PRI_AOC_E_CHARGING_ASSOCIATION_ID;
03664       break;
03665    case AST_AOC_CHARGING_ASSOCIATION_NA:
03666    default:
03667       break;
03668    }
03669 
03670    switch (ast_aoc_get_billing_id(decoded)) {
03671    case AST_AOC_BILLING_NORMAL:
03672       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_NORMAL;
03673       break;
03674    case AST_AOC_BILLING_REVERSE_CHARGE:
03675       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_REVERSE;
03676       break;
03677    case AST_AOC_BILLING_CREDIT_CARD:
03678       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CREDIT_CARD;
03679       break;
03680    case AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL:
03681       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL;
03682       break;
03683    case AST_AOC_BILLING_CALL_FWD_BUSY:
03684       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY;
03685       break;
03686    case AST_AOC_BILLING_CALL_FWD_NO_REPLY:
03687       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY;
03688       break;
03689    case AST_AOC_BILLING_CALL_DEFLECTION:
03690       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_DEFLECTION;
03691       break;
03692    case AST_AOC_BILLING_CALL_TRANSFER:
03693       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_TRANSFER;
03694       break;
03695    case AST_AOC_BILLING_NA:
03696    default:
03697       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_NOT_AVAILABLE;
03698       break;
03699    }
03700 
03701    switch (ast_aoc_get_charge_type(decoded)) {
03702    case AST_AOC_CHARGE_FREE:
03703       aoc_e->charge = PRI_AOC_DE_CHARGE_FREE;
03704       break;
03705    case AST_AOC_CHARGE_CURRENCY:
03706       {
03707          const char *currency_name = ast_aoc_get_currency_name(decoded);
03708          aoc_e->charge = PRI_AOC_DE_CHARGE_CURRENCY;
03709          aoc_e->recorded.money.amount.cost = ast_aoc_get_currency_amount(decoded);
03710          aoc_e->recorded.money.amount.multiplier = sig_pri_aoc_multiplier_from_ast(ast_aoc_get_currency_multiplier(decoded));
03711          if (!ast_strlen_zero(currency_name)) {
03712             ast_copy_string(aoc_e->recorded.money.currency, currency_name, sizeof(aoc_e->recorded.money.currency));
03713          }
03714       }
03715       break;
03716    case AST_AOC_CHARGE_UNIT:
03717       {
03718          const struct ast_aoc_unit_entry *entry;
03719          int i;
03720          aoc_e->charge = PRI_AOC_DE_CHARGE_UNITS;
03721          for (i = 0; i < ast_aoc_get_unit_count(decoded); i++) {
03722             if ((entry = ast_aoc_get_unit_info(decoded, i)) && i < ARRAY_LEN(aoc_e->recorded.unit.item)) {
03723                if (entry->valid_amount) {
03724                   aoc_e->recorded.unit.item[i].number = entry->amount;
03725                } else {
03726                   aoc_e->recorded.unit.item[i].number = -1;
03727                }
03728                if (entry->valid_type) {
03729                   aoc_e->recorded.unit.item[i].type = entry->type;
03730                } else {
03731                   aoc_e->recorded.unit.item[i].type = -1;
03732                }
03733                aoc_e->recorded.unit.num_items++;
03734             }
03735          }
03736       }
03737       break;
03738    case AST_AOC_CHARGE_NA:
03739    default:
03740       aoc_e->charge = PRI_AOC_DE_CHARGE_NOT_AVAILABLE;
03741       break;
03742    }
03743 }

static void sig_pri_aoc_e_from_pri ( const struct pri_subcmd_aoc_e *  aoc_e,
struct ast_channel owner,
int  passthrough 
) [static]

Definition at line 3343 of file sig_pri.c.

References ast_aoc_add_unit_entry(), AST_AOC_BILLING_CALL_DEFLECTION, AST_AOC_BILLING_CALL_FWD_BUSY, AST_AOC_BILLING_CALL_FWD_NO_REPLY, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL, AST_AOC_BILLING_CALL_TRANSFER, AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_NA, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_UNIT, ast_aoc_create(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), AST_AOC_E, ast_aoc_encode(), ast_aoc_manager_event(), ast_aoc_set_association_id(), ast_aoc_set_association_number(), ast_aoc_set_billing_id(), ast_aoc_set_currency_info(), AST_CONTROL_AOC, ast_queue_control_data(), sig_pri_aoc_multiplier_from_pri(), and type.

Referenced by sig_pri_handle_cis_subcmds(), and sig_pri_handle_subcmds().

03344 {
03345    struct ast_aoc_decoded *decoded = NULL;
03346    struct ast_aoc_encoded *encoded = NULL;
03347    size_t encoded_size = 0;
03348    enum ast_aoc_charge_type type;
03349 
03350    if (!aoc_e) {
03351       return;
03352    }
03353 
03354    switch (aoc_e->charge) {
03355    case PRI_AOC_DE_CHARGE_CURRENCY:
03356       type = AST_AOC_CHARGE_CURRENCY;
03357       break;
03358    case PRI_AOC_DE_CHARGE_UNITS:
03359       type = AST_AOC_CHARGE_UNIT;
03360       break;
03361    case PRI_AOC_DE_CHARGE_FREE:
03362       type = AST_AOC_CHARGE_FREE;
03363       break;
03364    default:
03365       type = AST_AOC_CHARGE_NA;
03366       break;
03367    }
03368 
03369    if (!(decoded = ast_aoc_create(AST_AOC_E, type, 0))) {
03370       return;
03371    }
03372 
03373    switch (aoc_e->associated.charging_type) {
03374    case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER:
03375       if (!aoc_e->associated.charge.number.valid) {
03376          break;
03377       }
03378       ast_aoc_set_association_number(decoded, aoc_e->associated.charge.number.str, aoc_e->associated.charge.number.plan);
03379       break;
03380    case PRI_AOC_E_CHARGING_ASSOCIATION_ID:
03381       ast_aoc_set_association_id(decoded, aoc_e->associated.charge.id);
03382       break;
03383    default:
03384       break;
03385    }
03386 
03387    switch (aoc_e->billing_id) {
03388    case PRI_AOC_E_BILLING_ID_NORMAL:
03389       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NORMAL);
03390       break;
03391    case PRI_AOC_E_BILLING_ID_REVERSE:
03392       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_REVERSE_CHARGE);
03393       break;
03394    case PRI_AOC_E_BILLING_ID_CREDIT_CARD:
03395       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CREDIT_CARD);
03396       break;
03397    case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL:
03398       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL);
03399       break;
03400    case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY:
03401       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_BUSY);
03402       break;
03403    case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY:
03404       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_NO_REPLY);
03405       break;
03406    case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION:
03407       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_DEFLECTION);
03408       break;
03409    case PRI_AOC_E_BILLING_ID_CALL_TRANSFER:
03410       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_TRANSFER);
03411       break;
03412    case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE:
03413    default:
03414       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NA);
03415       break;
03416    }
03417 
03418    switch (aoc_e->charge) {
03419    case PRI_AOC_DE_CHARGE_CURRENCY:
03420       ast_aoc_set_currency_info(decoded,
03421          aoc_e->recorded.money.amount.cost,
03422          sig_pri_aoc_multiplier_from_pri(aoc_e->recorded.money.amount.multiplier),
03423          aoc_e->recorded.money.currency);
03424       break;
03425    case PRI_AOC_DE_CHARGE_UNITS:
03426       {
03427          int i;
03428          for (i = 0; i < aoc_e->recorded.unit.num_items; ++i) {
03429             /* if type or number are negative, then they are not present */
03430             ast_aoc_add_unit_entry(decoded,
03431                (aoc_e->recorded.unit.item[i].number >= 0 ? 1 : 0),
03432                aoc_e->recorded.unit.item[i].number,
03433                (aoc_e->recorded.unit.item[i].type >= 0 ? 1 : 0),
03434                aoc_e->recorded.unit.item[i].type);
03435          }
03436       }
03437    }
03438 
03439    if (passthrough && owner && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
03440       ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
03441    }
03442 
03443    ast_aoc_manager_event(decoded, owner);
03444 
03445    ast_aoc_destroy_decoded(decoded);
03446    ast_aoc_destroy_encoded(encoded);
03447 }

static int sig_pri_aoc_multiplier_from_ast ( enum ast_aoc_currency_multiplier  mult  )  [static]

Definition at line 2935 of file sig_pri.c.

References AST_AOC_MULT_HUNDRED, AST_AOC_MULT_ONE, AST_AOC_MULT_ONEHUNDREDTH, AST_AOC_MULT_ONETENTH, AST_AOC_MULT_ONETHOUSANDTH, AST_AOC_MULT_TEN, and AST_AOC_MULT_THOUSAND.

Referenced by sig_pri_aoc_d_from_ast(), sig_pri_aoc_e_from_ast(), and sig_pri_aoc_s_from_ast().

02936 {
02937    switch (mult) {
02938    case AST_AOC_MULT_ONETHOUSANDTH:
02939       return PRI_AOC_MULTIPLIER_THOUSANDTH;
02940    case AST_AOC_MULT_ONEHUNDREDTH:
02941       return PRI_AOC_MULTIPLIER_HUNDREDTH;
02942    case AST_AOC_MULT_ONETENTH:
02943       return PRI_AOC_MULTIPLIER_TENTH;
02944    case AST_AOC_MULT_ONE:
02945       return PRI_AOC_MULTIPLIER_ONE;
02946    case AST_AOC_MULT_TEN:
02947       return PRI_AOC_MULTIPLIER_TEN;
02948    case AST_AOC_MULT_HUNDRED:
02949       return PRI_AOC_MULTIPLIER_HUNDRED;
02950    case AST_AOC_MULT_THOUSAND:
02951       return PRI_AOC_MULTIPLIER_THOUSAND;
02952    default:
02953       return PRI_AOC_MULTIPLIER_ONE;
02954    }
02955 }

static int sig_pri_aoc_multiplier_from_pri ( const int  mult  )  [static]

Definition at line 2966 of file sig_pri.c.

References AST_AOC_MULT_HUNDRED, AST_AOC_MULT_ONE, AST_AOC_MULT_ONEHUNDREDTH, AST_AOC_MULT_ONETENTH, AST_AOC_MULT_ONETHOUSANDTH, AST_AOC_MULT_TEN, and AST_AOC_MULT_THOUSAND.

Referenced by sig_pri_aoc_d_from_pri(), sig_pri_aoc_e_from_pri(), and sig_pri_aoc_s_from_pri().

02967 {
02968    switch (mult) {
02969    case PRI_AOC_MULTIPLIER_THOUSANDTH:
02970       return AST_AOC_MULT_ONETHOUSANDTH;
02971    case PRI_AOC_MULTIPLIER_HUNDREDTH:
02972       return AST_AOC_MULT_ONEHUNDREDTH;
02973    case PRI_AOC_MULTIPLIER_TENTH:
02974       return AST_AOC_MULT_ONETENTH;
02975    case PRI_AOC_MULTIPLIER_ONE:
02976       return AST_AOC_MULT_ONE;
02977    case PRI_AOC_MULTIPLIER_TEN:
02978       return AST_AOC_MULT_TEN;
02979    case PRI_AOC_MULTIPLIER_HUNDRED:
02980       return AST_AOC_MULT_HUNDRED;
02981    case PRI_AOC_MULTIPLIER_THOUSAND:
02982       return AST_AOC_MULT_THOUSAND;
02983    default:
02984       return AST_AOC_MULT_ONE;
02985    }
02986 }

static void sig_pri_aoc_request_from_pri ( const struct pri_subcmd_aoc_request *  aoc_request,
struct sig_pri_chan pvt,
q931_call *  call 
) [static]

Definition at line 3163 of file sig_pri.c.

References sig_pri_span::aoc_passthrough_flag, sig_pri_chan::aoc_s_request_invoke_id, sig_pri_chan::aoc_s_request_invoke_id_valid, sig_pri_span::pri, sig_pri_chan::pri, SIG_PRI_AOC_GRANT_D, SIG_PRI_AOC_GRANT_E, and SIG_PRI_AOC_GRANT_S.

Referenced by sig_pri_handle_subcmds().

03164 {
03165    int request;
03166 
03167    if (!aoc_request) {
03168       return;
03169    }
03170 
03171    request = aoc_request->charging_request;
03172 
03173    if (request & PRI_AOC_REQUEST_S) {
03174       if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
03175          /* An AOC-S response must come from the other side, so save off this invoke_id
03176           * and see if an AOC-S message comes in before the call is answered. */
03177          pvt->aoc_s_request_invoke_id = aoc_request->invoke_id;
03178          pvt->aoc_s_request_invoke_id_valid = 1;
03179 
03180       } else {
03181          pri_aoc_s_request_response_send(pvt->pri->pri,
03182             call,
03183             aoc_request->invoke_id,
03184             NULL);
03185       }
03186    }
03187 
03188    if (request & PRI_AOC_REQUEST_D) {
03189       if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
03190          pri_aoc_de_request_response_send(pvt->pri->pri,
03191             call,
03192             PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
03193             aoc_request->invoke_id);
03194       } else {
03195          pri_aoc_de_request_response_send(pvt->pri->pri,
03196             call,
03197             PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
03198             aoc_request->invoke_id);
03199       }
03200    }
03201 
03202    if (request & PRI_AOC_REQUEST_E) {
03203       if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
03204          pri_aoc_de_request_response_send(pvt->pri->pri,
03205             call,
03206             PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
03207             aoc_request->invoke_id);
03208       } else {
03209          pri_aoc_de_request_response_send(pvt->pri->pri,
03210             call,
03211             PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
03212             aoc_request->invoke_id);
03213       }
03214    }
03215 }

static void sig_pri_aoc_s_from_ast ( struct sig_pri_chan pvt,
struct ast_aoc_decoded decoded 
) [static]

Definition at line 3462 of file sig_pri.c.

References ast_aoc_volume_rate::amount, ast_aoc_flat_rate::amount, ast_aoc_duration_rate::amount, sig_pri_chan::aoc_s_request_invoke_id, sig_pri_chan::aoc_s_request_invoke_id_valid, AST_AOC_RATE_TYPE_DURATION, AST_AOC_RATE_TYPE_FLAT, AST_AOC_RATE_TYPE_FREE, AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING, AST_AOC_RATE_TYPE_NA, AST_AOC_RATE_TYPE_SPECIAL_CODE, AST_AOC_RATE_TYPE_VOLUME, ast_aoc_s_get_count(), ast_aoc_s_get_rate_info(), ast_copy_string(), ast_strlen_zero(), sig_pri_chan::call, ast_aoc_s_entry::charged_item, ast_aoc_duration_rate::charging_type, ast_aoc_volume_rate::currency_name, ast_aoc_flat_rate::currency_name, ast_aoc_duration_rate::currency_name, ast_aoc_s_entry::duration, ast_aoc_s_entry::flat, ast_aoc_duration_rate::granularity_time, ast_aoc_duration_rate::granularity_time_scale, ast_aoc_volume_rate::multiplier, ast_aoc_flat_rate::multiplier, ast_aoc_duration_rate::multiplier, sig_pri_span::pri, sig_pri_chan::pri, ast_aoc_s_entry::rate, ast_aoc_s_entry::rate_type, sig_pri_aoc_charged_item_to_pri(), sig_pri_aoc_multiplier_from_ast(), sig_pri_aoc_scale_to_pri(), ast_aoc_s_entry::special_code, ast_aoc_duration_rate::time, ast_aoc_duration_rate::time_scale, ast_aoc_s_entry::volume, and ast_aoc_volume_rate::volume_unit.

Referenced by sig_pri_indicate().

03463 {
03464    struct pri_subcmd_aoc_s aoc_s = { 0, };
03465    const struct ast_aoc_s_entry *entry;
03466    int idx;
03467 
03468    for (idx = 0; idx < ast_aoc_s_get_count(decoded); idx++) {
03469       if (!(entry = ast_aoc_s_get_rate_info(decoded, idx))) {
03470          break;
03471       }
03472 
03473       aoc_s.item[idx].chargeable = sig_pri_aoc_charged_item_to_pri(entry->charged_item);
03474 
03475       switch (entry->rate_type) {
03476       case AST_AOC_RATE_TYPE_DURATION:
03477          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_DURATION;
03478          aoc_s.item[idx].rate.duration.amount.cost = entry->rate.duration.amount;
03479          aoc_s.item[idx].rate.duration.amount.multiplier =
03480             sig_pri_aoc_multiplier_from_ast(entry->rate.duration.multiplier);
03481          aoc_s.item[idx].rate.duration.time.length = entry->rate.duration.time;
03482          aoc_s.item[idx].rate.duration.time.scale =
03483             sig_pri_aoc_scale_to_pri(entry->rate.duration.time_scale);
03484          aoc_s.item[idx].rate.duration.granularity.length = entry->rate.duration.granularity_time;
03485          aoc_s.item[idx].rate.duration.granularity.scale =
03486             sig_pri_aoc_scale_to_pri(entry->rate.duration.granularity_time_scale);
03487          aoc_s.item[idx].rate.duration.charging_type = entry->rate.duration.charging_type;
03488 
03489          if (!ast_strlen_zero(entry->rate.duration.currency_name)) {
03490             ast_copy_string(aoc_s.item[idx].rate.duration.currency,
03491                entry->rate.duration.currency_name,
03492                sizeof(aoc_s.item[idx].rate.duration.currency));
03493          }
03494          break;
03495       case AST_AOC_RATE_TYPE_FLAT:
03496          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FLAT;
03497          aoc_s.item[idx].rate.flat.amount.cost = entry->rate.flat.amount;
03498          aoc_s.item[idx].rate.flat.amount.multiplier =
03499             sig_pri_aoc_multiplier_from_ast(entry->rate.flat.multiplier);
03500 
03501          if (!ast_strlen_zero(entry->rate.flat.currency_name)) {
03502             ast_copy_string(aoc_s.item[idx].rate.flat.currency,
03503                entry->rate.flat.currency_name,
03504                sizeof(aoc_s.item[idx].rate.flat.currency));
03505          }
03506          break;
03507       case AST_AOC_RATE_TYPE_VOLUME:
03508          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_VOLUME;
03509          aoc_s.item[idx].rate.volume.unit = entry->rate.volume.volume_unit;
03510          aoc_s.item[idx].rate.volume.amount.cost = entry->rate.volume.amount;
03511          aoc_s.item[idx].rate.volume.amount.multiplier =
03512             sig_pri_aoc_multiplier_from_ast(entry->rate.volume.multiplier);
03513 
03514          if (!ast_strlen_zero(entry->rate.volume.currency_name)) {
03515             ast_copy_string(aoc_s.item[idx].rate.volume.currency,
03516                entry->rate.volume.currency_name,
03517                sizeof(aoc_s.item[idx].rate.volume.currency));
03518          }
03519          break;
03520       case AST_AOC_RATE_TYPE_SPECIAL_CODE:
03521          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_SPECIAL_CODE;
03522          aoc_s.item[idx].rate.special = entry->rate.special_code;
03523          break;
03524       case AST_AOC_RATE_TYPE_FREE:
03525          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FREE;
03526          break;
03527       case AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
03528          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING;
03529          break;
03530       default:
03531       case AST_AOC_RATE_TYPE_NA:
03532          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_NOT_AVAILABLE;
03533          break;
03534       }
03535    }
03536    aoc_s.num_items = idx;
03537 
03538    /* if this rate should be sent as a response to an AOC-S request we will
03539     * have an aoc_s_request_invoke_id associated with this pvt */
03540    if (pvt->aoc_s_request_invoke_id_valid) {
03541       pri_aoc_s_request_response_send(pvt->pri->pri, pvt->call, pvt->aoc_s_request_invoke_id, &aoc_s);
03542       pvt->aoc_s_request_invoke_id_valid = 0;
03543    } else {
03544       pri_aoc_s_send(pvt->pri->pri, pvt->call, &aoc_s);
03545    }
03546 }

static void sig_pri_aoc_s_from_pri ( const struct pri_subcmd_aoc_s *  aoc_s,
struct ast_channel owner,
int  passthrough 
) [static]

Definition at line 3070 of file sig_pri.c.

References AST_AOC_CHARGED_ITEM_NA, ast_aoc_create(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), ast_aoc_encode(), ast_aoc_manager_event(), AST_AOC_S, ast_aoc_s_add_rate_duration(), ast_aoc_s_add_rate_flat(), ast_aoc_s_add_rate_free(), ast_aoc_s_add_rate_na(), ast_aoc_s_add_rate_special_charge_code(), ast_aoc_s_add_rate_volume(), AST_CONTROL_AOC, ast_queue_control_data(), sig_pri_aoc_charged_item_to_ast(), sig_pri_aoc_multiplier_from_pri(), and sig_pri_aoc_scale_to_ast().

Referenced by sig_pri_handle_subcmds().

03071 {
03072    struct ast_aoc_decoded *decoded = NULL;
03073    struct ast_aoc_encoded *encoded = NULL;
03074    size_t encoded_size = 0;
03075    int idx;
03076 
03077    if (!owner || !aoc_s) {
03078       return;
03079    }
03080 
03081    if (!(decoded = ast_aoc_create(AST_AOC_S, 0, 0))) {
03082       return;
03083    }
03084 
03085    for (idx = 0; idx < aoc_s->num_items; ++idx) {
03086       enum ast_aoc_s_charged_item charged_item;
03087 
03088       charged_item = sig_pri_aoc_charged_item_to_ast(aoc_s->item[idx].chargeable);
03089       if (charged_item == AST_AOC_CHARGED_ITEM_NA) {
03090          /* Delete the unknown charged item from the list. */
03091          continue;
03092       }
03093       switch (aoc_s->item[idx].rate_type) {
03094       case PRI_AOC_RATE_TYPE_DURATION:
03095          ast_aoc_s_add_rate_duration(decoded,
03096             charged_item,
03097             aoc_s->item[idx].rate.duration.amount.cost,
03098             sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.duration.amount.multiplier),
03099             aoc_s->item[idx].rate.duration.currency,
03100             aoc_s->item[idx].rate.duration.time.length,
03101             sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.time.scale),
03102             aoc_s->item[idx].rate.duration.granularity.length,
03103             sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.granularity.scale),
03104             aoc_s->item[idx].rate.duration.charging_type);
03105          break;
03106       case PRI_AOC_RATE_TYPE_FLAT:
03107          ast_aoc_s_add_rate_flat(decoded,
03108             charged_item,
03109             aoc_s->item[idx].rate.flat.amount.cost,
03110             sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.flat.amount.multiplier),
03111             aoc_s->item[idx].rate.flat.currency);
03112          break;
03113       case PRI_AOC_RATE_TYPE_VOLUME:
03114          ast_aoc_s_add_rate_volume(decoded,
03115             charged_item,
03116             aoc_s->item[idx].rate.volume.unit,
03117             aoc_s->item[idx].rate.volume.amount.cost,
03118             sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.volume.amount.multiplier),
03119             aoc_s->item[idx].rate.volume.currency);
03120          break;
03121       case PRI_AOC_RATE_TYPE_SPECIAL_CODE:
03122          ast_aoc_s_add_rate_special_charge_code(decoded,
03123             charged_item,
03124             aoc_s->item[idx].rate.special);
03125          break;
03126       case PRI_AOC_RATE_TYPE_FREE:
03127          ast_aoc_s_add_rate_free(decoded, charged_item, 0);
03128          break;
03129       case PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
03130          ast_aoc_s_add_rate_free(decoded, charged_item, 1);
03131          break;
03132       default:
03133          ast_aoc_s_add_rate_na(decoded, charged_item);
03134          break;
03135       }
03136    }
03137 
03138    if (passthrough && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
03139       ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
03140    }
03141 
03142    ast_aoc_manager_event(decoded, owner);
03143 
03144    ast_aoc_destroy_decoded(decoded);
03145    ast_aoc_destroy_encoded(encoded);
03146 }

static enum ast_aoc_time_scale sig_pri_aoc_scale_to_ast ( enum PRI_AOC_TIME_SCALE  value  )  [static]

Definition at line 3031 of file sig_pri.c.

References AST_AOC_TIME_SCALE_DAY, AST_AOC_TIME_SCALE_HOUR, AST_AOC_TIME_SCALE_HUNDREDTH_SECOND, AST_AOC_TIME_SCALE_MINUTE, AST_AOC_TIME_SCALE_SECOND, AST_AOC_TIME_SCALE_TEN_SECOND, and AST_AOC_TIME_SCALE_TENTH_SECOND.

Referenced by sig_pri_aoc_s_from_pri().

03032 {
03033    switch (value) {
03034    default:
03035    case PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND:
03036       return AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
03037    case PRI_AOC_TIME_SCALE_TENTH_SECOND:
03038       return AST_AOC_TIME_SCALE_TENTH_SECOND;
03039    case PRI_AOC_TIME_SCALE_SECOND:
03040       return AST_AOC_TIME_SCALE_SECOND;
03041    case PRI_AOC_TIME_SCALE_TEN_SECOND:
03042       return AST_AOC_TIME_SCALE_TEN_SECOND;
03043    case PRI_AOC_TIME_SCALE_MINUTE:
03044       return AST_AOC_TIME_SCALE_MINUTE;
03045    case PRI_AOC_TIME_SCALE_HOUR:
03046       return AST_AOC_TIME_SCALE_HOUR;
03047    case PRI_AOC_TIME_SCALE_DAY:
03048       return AST_AOC_TIME_SCALE_DAY;
03049    }
03050    return AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
03051 }

static enum PRI_AOC_TIME_SCALE sig_pri_aoc_scale_to_pri ( enum ast_aoc_time_scale  value  )  [static]

Definition at line 2999 of file sig_pri.c.

References AST_AOC_TIME_SCALE_DAY, AST_AOC_TIME_SCALE_HOUR, AST_AOC_TIME_SCALE_HUNDREDTH_SECOND, AST_AOC_TIME_SCALE_MINUTE, AST_AOC_TIME_SCALE_SECOND, AST_AOC_TIME_SCALE_TEN_SECOND, and AST_AOC_TIME_SCALE_TENTH_SECOND.

Referenced by sig_pri_aoc_s_from_ast().

03000 {
03001    switch (value) {
03002    default:
03003    case AST_AOC_TIME_SCALE_HUNDREDTH_SECOND:
03004       return PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND;
03005    case AST_AOC_TIME_SCALE_TENTH_SECOND:
03006       return PRI_AOC_TIME_SCALE_TENTH_SECOND;
03007    case AST_AOC_TIME_SCALE_SECOND:
03008       return PRI_AOC_TIME_SCALE_SECOND;
03009    case AST_AOC_TIME_SCALE_TEN_SECOND:
03010       return PRI_AOC_TIME_SCALE_TEN_SECOND;
03011    case AST_AOC_TIME_SCALE_MINUTE:
03012       return PRI_AOC_TIME_SCALE_MINUTE;
03013    case AST_AOC_TIME_SCALE_HOUR:
03014       return PRI_AOC_TIME_SCALE_HOUR;
03015    case AST_AOC_TIME_SCALE_DAY:
03016       return PRI_AOC_TIME_SCALE_DAY;
03017    }
03018 }

static int sig_pri_attempt_transfer ( struct sig_pri_span pri,
q931_call *  call_1_pri,
int  call_1_held,
q931_call *  call_2_pri,
int  call_2_held,
xfer_rsp_callback  rsp_callback,
void *  data 
) [static]

Definition at line 2334 of file sig_pri.c.

References ast_bridged_channel(), ast_channel_transfer_masquerade(), ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, ast_verb, sig_pri_span::lock, sig_pri_chan::owner, pri_find_principle_by_call(), sig_pri_span::pvts, sig_pri_lock_owner(), sig_pri_lock_private(), and sig_pri_unlock_private().

Referenced by sig_pri_handle_subcmds().

02335 {
02336    struct attempt_xfer_call {
02337       q931_call *pri;
02338       struct ast_channel *ast;
02339       int held;
02340       int chanpos;
02341    };
02342    int retval;
02343    struct ast_channel *transferee;
02344    struct attempt_xfer_call *call_1;
02345    struct attempt_xfer_call *call_2;
02346    struct attempt_xfer_call *swap_call;
02347    struct attempt_xfer_call c1;
02348    struct attempt_xfer_call c2;
02349 
02350    c1.pri = call_1_pri;
02351    c1.held = call_1_held;
02352    call_1 = &c1;
02353 
02354    c2.pri = call_2_pri;
02355    c2.held = call_2_held;
02356    call_2 = &c2;
02357 
02358    call_1->chanpos = pri_find_principle_by_call(pri, call_1->pri);
02359    call_2->chanpos = pri_find_principle_by_call(pri, call_2->pri);
02360    if (call_1->chanpos < 0 || call_2->chanpos < 0) {
02361       /* Calls not found in span control. */
02362       if (rsp_callback) {
02363          /* Transfer failed. */
02364          rsp_callback(data, 0);
02365       }
02366       return -1;
02367    }
02368 
02369    /* Attempt to make transferee and target consistent. */
02370    if (!call_1->held && call_2->held) {
02371       /*
02372        * Swap call_1 and call_2 to make call_1 the transferee(held call)
02373        * and call_2 the target(active call).
02374        */
02375       swap_call = call_1;
02376       call_1 = call_2;
02377       call_2 = swap_call;
02378    }
02379 
02380    /* Deadlock avoidance is attempted. */
02381    sig_pri_lock_private(pri->pvts[call_1->chanpos]);
02382    sig_pri_lock_owner(pri, call_1->chanpos);
02383    sig_pri_lock_private(pri->pvts[call_2->chanpos]);
02384    sig_pri_lock_owner(pri, call_2->chanpos);
02385 
02386    call_1->ast = pri->pvts[call_1->chanpos]->owner;
02387    call_2->ast = pri->pvts[call_2->chanpos]->owner;
02388    if (!call_1->ast || !call_2->ast) {
02389       /* At least one owner is not present. */
02390       if (call_1->ast) {
02391          ast_channel_unlock(call_1->ast);
02392       }
02393       if (call_2->ast) {
02394          ast_channel_unlock(call_2->ast);
02395       }
02396       sig_pri_unlock_private(pri->pvts[call_1->chanpos]);
02397       sig_pri_unlock_private(pri->pvts[call_2->chanpos]);
02398       if (rsp_callback) {
02399          /* Transfer failed. */
02400          rsp_callback(data, 0);
02401       }
02402       return -1;
02403    }
02404 
02405    for (;;) {
02406       transferee = ast_bridged_channel(call_1->ast);
02407       if (transferee) {
02408          break;
02409       }
02410 
02411       /* Try masquerading the other way. */
02412       swap_call = call_1;
02413       call_1 = call_2;
02414       call_2 = swap_call;
02415 
02416       transferee = ast_bridged_channel(call_1->ast);
02417       if (transferee) {
02418          break;
02419       }
02420 
02421       /* Could not transfer.  Neither call is bridged. */
02422       ast_channel_unlock(call_1->ast);
02423       ast_channel_unlock(call_2->ast);
02424       sig_pri_unlock_private(pri->pvts[call_1->chanpos]);
02425       sig_pri_unlock_private(pri->pvts[call_2->chanpos]);
02426 
02427       if (rsp_callback) {
02428          /* Transfer failed. */
02429          rsp_callback(data, 0);
02430       }
02431       return -1;
02432    }
02433 
02434    ast_verb(3, "TRANSFERRING %s to %s\n", call_1->ast->name, call_2->ast->name);
02435 
02436    /*
02437     * Setup transfer masquerade.
02438     *
02439     * Note:  There is an extremely nasty deadlock avoidance issue
02440     * with ast_channel_transfer_masquerade().  Deadlock may be possible if
02441     * the channels involved are proxies (chan_agent channels) and
02442     * it is called with locks.  Unfortunately, there is no simple
02443     * or even merely difficult way to guarantee deadlock avoidance
02444     * and still be able to send an ECT success response without the
02445     * possibility of the bridged channel hanging up on us.
02446     */
02447    ast_mutex_unlock(&pri->lock);
02448    retval = ast_channel_transfer_masquerade(
02449       call_2->ast,
02450       &call_2->ast->connected,
02451       call_2->held,
02452       transferee,
02453       &call_1->ast->connected,
02454       call_1->held);
02455 
02456    /* Reacquire the pri->lock to hold off completion of the transfer masquerade. */
02457    ast_mutex_lock(&pri->lock);
02458 
02459    ast_channel_unlock(call_1->ast);
02460    ast_channel_unlock(call_2->ast);
02461    sig_pri_unlock_private(pri->pvts[call_1->chanpos]);
02462    sig_pri_unlock_private(pri->pvts[call_2->chanpos]);
02463 
02464    if (rsp_callback) {
02465       /*
02466        * Report transfer status.
02467        *
02468        * Must do the callback before the masquerade completes to ensure
02469        * that the protocol message goes out before the call leg is
02470        * disconnected.
02471        */
02472       rsp_callback(data, retval ? 0 : 1);
02473    }
02474    return retval;
02475 }

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_span::pri, sig_pri_chan::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 }

static int sig_pri_available_check ( struct sig_pri_chan pvt  )  [static]

Definition at line 7276 of file sig_pri.c.

References sig_pri_chan::no_b_channel, and sig_pri_is_chan_available().

Referenced by sig_pri_available(), and sig_pri_cw_available().

07277 {
07278    /*
07279     * If interface has a B channel and is available for use
07280     * then the channel is available.
07281     */
07282    if (!pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
07283       return 1;
07284    }
07285    return 0;
07286 }

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_connected_line::id, ast_party_caller::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_party_id::name, ast_channel::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_chan::pri, sig_pri_span::pri, sig_pri_cc_monitor_instance::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_name::str, ast_party_number::str, ast_party_subaddress::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_name::valid, ast_party_number::valid, and ast_party_subaddress::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 }

static const char* sig_pri_call_level2str ( enum sig_pri_call_level  level  )  [static]

Definition at line 123 of file sig_pri.c.

References SIG_PRI_CALL_LEVEL_ALERTING, SIG_PRI_CALL_LEVEL_CONNECT, SIG_PRI_CALL_LEVEL_DEFER_DIAL, SIG_PRI_CALL_LEVEL_IDLE, SIG_PRI_CALL_LEVEL_OVERLAP, SIG_PRI_CALL_LEVEL_PROCEEDING, and SIG_PRI_CALL_LEVEL_SETUP.

Referenced by sig_pri_cli_show_channels(), and sig_pri_digit_begin().

00124 {
00125    switch (level) {
00126    case SIG_PRI_CALL_LEVEL_IDLE:
00127       return "Idle";
00128    case SIG_PRI_CALL_LEVEL_SETUP:
00129       return "Setup";
00130    case SIG_PRI_CALL_LEVEL_OVERLAP:
00131       return "Overlap";
00132    case SIG_PRI_CALL_LEVEL_PROCEEDING:
00133       return "Proceeding";
00134    case SIG_PRI_CALL_LEVEL_ALERTING:
00135       return "Alerting";
00136    case SIG_PRI_CALL_LEVEL_DEFER_DIAL:
00137       return "DeferDial";
00138    case SIG_PRI_CALL_LEVEL_CONNECT:
00139       return "Connect";
00140    }
00141    return "Unknown";
00142 }

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_cc_agent_prv::pri, sig_pri_span::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 }

static int sig_pri_cc_agent_cmp_cc_id ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 2490 of file sig_pri.c.

References sig_pri_cc_agent_prv::cc_id, CMP_MATCH, CMP_STOP, sig_pri_cc_agent_prv::pri, and ast_cc_agent::private_data.

Referenced by sig_pri_find_cc_agent_by_cc_id().

02491 {
02492    struct ast_cc_agent *agent_1 = obj;
02493    struct sig_pri_cc_agent_prv *agent_prv_1 = agent_1->private_data;
02494    struct sig_pri_cc_agent_prv *agent_prv_2 = arg;
02495 
02496    return (agent_prv_1 && agent_prv_1->pri == agent_prv_2->pri
02497       && agent_prv_1->cc_id == agent_prv_2->cc_id) ? CMP_MATCH | CMP_STOP : 0;
02498 }

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_cc_agent_prv::pri, sig_pri_span::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_chan::pri, sig_pri_span::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_cc_agent_prv::pri, sig_pri_span::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_cc_agent_prv::pri, sig_pri_span::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_cc_agent_prv::pri, sig_pri_span::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_cc_agent_prv::pri, sig_pri_span::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 }

static int sig_pri_cc_available ( struct sig_pri_span pri,
int  chanpos,
long  cc_id,
enum ast_cc_service_type  service 
) [static]

Definition at line 2666 of file sig_pri.c.

References ao2_ref, ao2_unlink, AST_CC_GENERIC_MONITOR_TYPE, ast_cc_get_current_core_id(), AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_get_cc_monitor_policy(), ast_queue_cc_frame(), sig_pri_cc_monitor_instance::core_id, monitor, sig_pri_chan::owner, sig_pri_cc_monitor_instance::pri, sig_pri_span::pvts, sig_pri_cc_monitor_instance_init(), sig_pri_cc_monitors, sig_pri_cc_type_name, sig_pri_get_orig_dialstring(), and sig_pri_make_cc_dialstring().

Referenced by sig_pri_handle_subcmds().

02667 {
02668    struct sig_pri_chan *pvt;
02669    struct ast_cc_config_params *cc_params;
02670    struct sig_pri_cc_monitor_instance *monitor;
02671    enum ast_cc_monitor_policies monitor_policy;
02672    int core_id;
02673    int res;
02674    char device_name[AST_CHANNEL_NAME];
02675    char dialstring[AST_CHANNEL_NAME];
02676 
02677    pvt = pri->pvts[chanpos];
02678 
02679    core_id = ast_cc_get_current_core_id(pvt->owner);
02680    if (core_id == -1) {
02681       return -1;
02682    }
02683 
02684    cc_params = ast_channel_get_cc_config_params(pvt->owner);
02685    if (!cc_params) {
02686       return -1;
02687    }
02688 
02689    res = -1;
02690    monitor_policy = ast_get_cc_monitor_policy(cc_params);
02691    switch (monitor_policy) {
02692    case AST_CC_MONITOR_NEVER:
02693       /* CCSS is not enabled. */
02694       break;
02695    case AST_CC_MONITOR_NATIVE:
02696    case AST_CC_MONITOR_ALWAYS:
02697       /*
02698        * If it is AST_CC_MONITOR_ALWAYS and native fails we will attempt the fallback
02699        * later in the call to sig_pri_cc_generic_check().
02700        */
02701       ast_channel_get_device_name(pvt->owner, device_name, sizeof(device_name));
02702       sig_pri_make_cc_dialstring(pvt, dialstring, sizeof(dialstring));
02703       monitor = sig_pri_cc_monitor_instance_init(core_id, pri, cc_id, device_name);
02704       if (!monitor) {
02705          break;
02706       }
02707       res = ast_queue_cc_frame(pvt->owner, sig_pri_cc_type_name, dialstring, service,
02708          monitor);
02709       if (res) {
02710          monitor->cc_id = -1;
02711          ao2_unlink(sig_pri_cc_monitors, monitor);
02712          ao2_ref(monitor, -1);
02713       }
02714       break;
02715    case AST_CC_MONITOR_GENERIC:
02716       ast_queue_cc_frame(pvt->owner, AST_CC_GENERIC_MONITOR_TYPE,
02717          sig_pri_get_orig_dialstring(pvt), service, NULL);
02718       /* Say it failed to force caller to cancel native CC. */
02719       break;
02720    }
02721    return res;
02722 }

static void sig_pri_cc_generic_check ( struct sig_pri_span pri,
int  chanpos,
enum ast_cc_service_type  service 
) [static]

Definition at line 2739 of file sig_pri.c.

References ao2_ref, AST_CC_GENERIC_MONITOR_TYPE, ast_cc_get_current_core_id(), ast_cc_get_monitor_by_recall_core_id(), AST_CC_MONITOR_ALWAYS, AST_CC_MONITOR_GENERIC, AST_CC_MONITOR_NATIVE, AST_CC_MONITOR_NEVER, ast_channel_get_cc_config_params(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_channel_unlock, ast_get_cc_monitor_policy(), ast_queue_cc_frame(), ast_cc_monitor::core_id, monitor, sig_pri_span::nodetype, sig_pri_chan::outgoing, sig_pri_chan::owner, sig_pri_span::pvts, sig_pri_span::sig, SIG_BRI_PTMP, sig_pri_get_orig_dialstring(), and sig_pri_lock_owner().

02740 {
02741    struct ast_channel *owner;
02742    struct ast_cc_config_params *cc_params;
02743 #if defined(HAVE_PRI_CCSS)
02744    struct ast_cc_monitor *monitor;
02745    char device_name[AST_CHANNEL_NAME];
02746 #endif   /* defined(HAVE_PRI_CCSS) */
02747    enum ast_cc_monitor_policies monitor_policy;
02748    int core_id;
02749 
02750    if (!pri->pvts[chanpos]->outgoing) {
02751       /* This is not an outgoing call so it cannot be CC monitor. */
02752       return;
02753    }
02754 
02755    sig_pri_lock_owner(pri, chanpos);
02756    owner = pri->pvts[chanpos]->owner;
02757    if (!owner) {
02758       return;
02759    }
02760    core_id = ast_cc_get_current_core_id(owner);
02761    if (core_id == -1) {
02762       /* No CC core setup */
02763       goto done;
02764    }
02765 
02766    cc_params = ast_channel_get_cc_config_params(owner);
02767    if (!cc_params) {
02768       /* Could not get CC config parameters. */
02769       goto done;
02770    }
02771 
02772 #if defined(HAVE_PRI_CCSS)
02773    ast_channel_get_device_name(owner, device_name, sizeof(device_name));
02774    monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
02775    if (monitor) {
02776       /* CC monitor is already present so no need for generic CC. */
02777       ao2_ref(monitor, -1);
02778       goto done;
02779    }
02780 #endif   /* defined(HAVE_PRI_CCSS) */
02781 
02782    monitor_policy = ast_get_cc_monitor_policy(cc_params);
02783    switch (monitor_policy) {
02784    case AST_CC_MONITOR_NEVER:
02785       /* CCSS is not enabled. */
02786       break;
02787    case AST_CC_MONITOR_NATIVE:
02788       if (pri->sig == SIG_BRI_PTMP && pri->nodetype == PRI_NETWORK) {
02789          /* Request generic CC monitor. */
02790          ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
02791             sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
02792       }
02793       break;
02794    case AST_CC_MONITOR_ALWAYS:
02795       if (pri->sig == SIG_BRI_PTMP && pri->nodetype != PRI_NETWORK) {
02796          /*
02797           * Cannot monitor PTMP TE side since this is not defined.
02798           * We are playing the roll of a phone in this case and
02799           * a phone cannot monitor a party over the network without
02800           * protocol help.
02801           */
02802          break;
02803       }
02804       /*
02805        * We are either falling back or this is a PTMP NT span.
02806        * Request generic CC monitor.
02807        */
02808       ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
02809          sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
02810       break;
02811    case AST_CC_MONITOR_GENERIC:
02812       if (pri->sig == SIG_BRI_PTMP && pri->nodetype == PRI_NETWORK) {
02813          /* Request generic CC monitor. */
02814          ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
02815             sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
02816       }
02817       break;
02818    }
02819 
02820 done:
02821    ast_channel_unlock(owner);
02822 }

static void sig_pri_cc_link_canceled ( struct sig_pri_span pri,
long  cc_id,
int  is_agent 
) [static]

Definition at line 2836 of file sig_pri.c.

References ao2_ref, ast_cc_failed(), ast_cc_monitor_failed(), ast_cc_agent::core_id, monitor, sig_pri_cc_monitor_instance::pri, sig_pri_cc_type_name, sig_pri_find_cc_agent_by_cc_id(), and sig_pri_find_cc_monitor_by_cc_id().

Referenced by sig_pri_handle_cis_subcmds(), and sig_pri_handle_subcmds().

02837 {
02838    if (is_agent) {
02839       struct ast_cc_agent *agent;
02840 
02841       agent = sig_pri_find_cc_agent_by_cc_id(pri, cc_id);
02842       if (!agent) {
02843          return;
02844       }
02845       ast_cc_failed(agent->core_id, "%s agent got canceled by link",
02846          sig_pri_cc_type_name);
02847       ao2_ref(agent, -1);
02848    } else {
02849       struct sig_pri_cc_monitor_instance *monitor;
02850 
02851       monitor = sig_pri_find_cc_monitor_by_cc_id(pri, cc_id);
02852       if (!monitor) {
02853          return;
02854       }
02855       monitor->cc_id = -1;
02856       ast_cc_monitor_failed(monitor->core_id, monitor->name,
02857          "%s monitor got canceled by link", sig_pri_cc_type_name);
02858       ao2_ref(monitor, -1);
02859    }
02860 }

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 }

static int sig_pri_cc_monitor_cmp_cc_id ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 2542 of file sig_pri.c.

References sig_pri_cc_monitor_instance::cc_id, CMP_MATCH, CMP_STOP, and sig_pri_cc_monitor_instance::pri.

Referenced by sig_pri_find_cc_monitor_by_cc_id().

02543 {
02544    struct sig_pri_cc_monitor_instance *monitor_1 = obj;
02545    struct sig_pri_cc_monitor_instance *monitor_2 = arg;
02546 
02547    return (monitor_1->pri == monitor_2->pri
02548       && monitor_1->cc_id == monitor_2->cc_id) ? CMP_MATCH | CMP_STOP : 0;
02549 }

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 }

static int sig_pri_cc_monitor_instance_cmp_fn ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 8435 of file sig_pri.c.

References CMP_MATCH, CMP_STOP, and sig_pri_cc_monitor_instance::core_id.

Referenced by sig_pri_load().

08436 {
08437    struct sig_pri_cc_monitor_instance *monitor_1 = obj;
08438    struct sig_pri_cc_monitor_instance *monitor_2 = arg;
08439 
08440    return monitor_1->core_id == monitor_2->core_id ? CMP_MATCH | CMP_STOP : 0;
08441 }

static void sig_pri_cc_monitor_instance_destroy ( void *  data  )  [static]

Definition at line 2590 of file sig_pri.c.

References ast_mutex_lock, ast_mutex_unlock, sig_pri_span::calls, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, sig_pri_callback::module_unref, sig_pri_span::pri, and sig_pri_cc_monitor_instance::pri.

Referenced by sig_pri_cc_monitor_instance_init().

02591 {
02592    struct sig_pri_cc_monitor_instance *monitor_instance = data;
02593 
02594    if (monitor_instance->cc_id != -1) {
02595       ast_mutex_lock(&monitor_instance->pri->lock);
02596       pri_cc_cancel(monitor_instance->pri->pri, monitor_instance->cc_id);
02597       ast_mutex_unlock(&monitor_instance->pri->lock);
02598    }
02599    monitor_instance->pri->calls->module_unref();
02600 }

static int sig_pri_cc_monitor_instance_hash_fn ( const void *  obj,
const int  flags 
) [static]

Definition at line 8415 of file sig_pri.c.

References sig_pri_cc_monitor_instance::core_id.

Referenced by sig_pri_load().

08416 {
08417    const struct sig_pri_cc_monitor_instance *monitor_instance = obj;
08418 
08419    return monitor_instance->core_id;
08420 }

static struct sig_pri_cc_monitor_instance* sig_pri_cc_monitor_instance_init ( int  core_id,
struct sig_pri_span pri,
long  cc_id,
const char *  device_name 
) [static]

Definition at line 2622 of file sig_pri.c.

References ao2_alloc, ao2_link, sig_pri_span::calls, sig_pri_callback::module_ref, sig_pri_callback::module_unref, sig_pri_cc_monitor_instance::pri, sig_pri_cc_monitor_instance_destroy(), and sig_pri_cc_monitors.

Referenced by sig_pri_cc_available().

02623 {
02624    struct sig_pri_cc_monitor_instance *monitor_instance;
02625 
02626    if (!pri->calls->module_ref || !pri->calls->module_unref) {
02627       return NULL;
02628    }
02629 
02630    monitor_instance = ao2_alloc(sizeof(*monitor_instance) + strlen(device_name),
02631       sig_pri_cc_monitor_instance_destroy);
02632    if (!monitor_instance) {
02633       return NULL;
02634    }
02635 
02636    monitor_instance->cc_id = cc_id;
02637    monitor_instance->pri = pri;
02638    monitor_instance->core_id = core_id;
02639    strcpy(monitor_instance->name, device_name);
02640 
02641    pri->calls->module_ref();
02642 
02643    ao2_link(sig_pri_cc_monitors, monitor_instance);
02644    return monitor_instance;
02645 }

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_cc_monitor_instance::pri, and sig_pri_span::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_cc_monitor_instance::pri, and sig_pri_span::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_cc_monitor_instance::pri, and sig_pri_span::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_cc_monitor_instance::pri, and sig_pri_span::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_chan::pri, sig_pri_span::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_chan::pri, sig_pri_span::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_chan::pri, sig_pri_span::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 }

static int sig_pri_cmp_pri_chans ( const void *  left,
const void *  right 
) [static]

Definition at line 7587 of file sig_pri.c.

References sig_pri_chan::channel.

Referenced by sig_pri_sort_pri_chans().

07588 {
07589    const struct sig_pri_chan *pvt_left;
07590    const struct sig_pri_chan *pvt_right;
07591 
07592    pvt_left = *(struct sig_pri_chan **) left;
07593    pvt_right = *(struct sig_pri_chan **) right;
07594    if (!pvt_left) {
07595       if (!pvt_right) {
07596          return 0;
07597       }
07598       return 1;
07599    }
07600    if (!pvt_right) {
07601       return -1;
07602    }
07603 
07604    return pvt_left->channel - pvt_right->channel;
07605 }

static struct sig_pri_chan* sig_pri_cw_available ( struct sig_pri_span pri  )  [static]

Definition at line 7301 of file sig_pri.c.

References ast_atomic_fetchadd_int(), sig_pri_chan::is_call_waiting, sig_pri_span::max_call_waiting_calls, sig_pri_span::num_call_waiting_calls, sig_pri_span::numchans, sig_pri_chan::pri, pri_find_empty_nobch(), sig_pri_span::pvts, sig_pri_available_check(), and sig_pri_init_config().

Referenced by sig_pri_available().

07302 {
07303    struct sig_pri_chan *cw;
07304    int idx;
07305 
07306    cw = NULL;
07307    if (pri->num_call_waiting_calls < pri->max_call_waiting_calls) {
07308       if (!pri->num_call_waiting_calls) {
07309          /*
07310           * There are no outstanding call waiting calls.  Check to see
07311           * if the span is in a congested state for the first call
07312           * waiting call.
07313           */
07314          for (idx = 0; idx < pri->numchans; ++idx) {
07315             if (pri->pvts[idx] && sig_pri_available_check(pri->pvts[idx])) {
07316                /* There is another channel that is available on this span. */
07317                return cw;
07318             }
07319          }
07320       }
07321       idx = pri_find_empty_nobch(pri);
07322       if (0 <= idx) {
07323          /* Setup the call waiting interface to use. */
07324          cw = pri->pvts[idx];
07325          cw->is_call_waiting = 1;
07326          sig_pri_init_config(cw, pri);
07327          ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, 1);
07328       }
07329    }
07330    return cw;
07331 }

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 }

static void sig_pri_dial_digits ( struct sig_pri_chan p,
const char *  dial_string 
) [static]

Definition at line 228 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::dial_digits.

00229 {
00230    if (p->calls->dial_digits) {
00231       p->calls->dial_digits(p->chan_pvt, dial_string);
00232    }
00233 }

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 }

static void sig_pri_dsp_reset_and_flush_digits ( struct sig_pri_chan p  )  [static]

Definition at line 913 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::dsp_reset_and_flush_digits.

Referenced by pri_ss_thread().

00914 {
00915    if (p->calls->dsp_reset_and_flush_digits) {
00916       p->calls->dsp_reset_and_flush_digits(p->chan_pvt);
00917    }
00918 }

static void sig_pri_event_party_id ( struct ast_str **  msg,
const char *  prefix,
struct ast_party_id party 
) [static]

Definition at line 2165 of file sig_pri.c.

References ast_describe_caller_presentation(), ast_party_id_presentation(), ast_party_name_charset_describe(), ast_str_append(), ast_party_name::char_set, ast_party_id::name, ast_party_id::number, ast_party_subaddress::odd_even_indicator, ast_party_number::plan, ast_party_name::presentation, ast_party_number::presentation, S_COR, S_OR, ast_party_subaddress::str, ast_party_name::str, ast_party_number::str, ast_party_id::subaddress, ast_party_subaddress::type, ast_party_subaddress::valid, ast_party_name::valid, and ast_party_number::valid.

Referenced by sig_pri_mcid_event().

02166 {
02167    int pres;
02168 
02169    /* Combined party presentation */
02170    pres = ast_party_id_presentation(party);
02171    ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix, pres,
02172       ast_describe_caller_presentation(pres));
02173 
02174    /* Party number */
02175    ast_str_append(msg, 0, "%sNumValid: %d\r\n", prefix,
02176       (unsigned) party->number.valid);
02177    ast_str_append(msg, 0, "%sNum: %s\r\n", prefix,
02178       S_COR(party->number.valid, party->number.str, ""));
02179    ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number.plan);
02180    if (party->number.valid) {
02181       ast_str_append(msg, 0, "%sNumPlan: %d\r\n", prefix, party->number.plan);
02182       ast_str_append(msg, 0, "%sNumPres: %d (%s)\r\n", prefix,
02183          party->number.presentation,
02184          ast_describe_caller_presentation(party->number.presentation));
02185    }
02186 
02187    /* Party name */
02188    ast_str_append(msg, 0, "%sNameValid: %d\r\n", prefix,
02189       (unsigned) party->name.valid);
02190    ast_str_append(msg, 0, "%sName: %s\r\n", prefix,
02191       S_COR(party->name.valid, party->name.str, ""));
02192    if (party->name.valid) {
02193       ast_str_append(msg, 0, "%sNameCharSet: %s\r\n", prefix,
02194          ast_party_name_charset_describe(party->name.char_set));
02195       ast_str_append(msg, 0, "%sNamePres: %d (%s)\r\n", prefix,
02196          party->name.presentation,
02197          ast_describe_caller_presentation(party->name.presentation));
02198    }
02199 
02200 #if defined(HAVE_PRI_SUBADDR)
02201    /* Party subaddress */
02202    if (party->subaddress.valid) {
02203       static const char subaddress[] = "Subaddr";
02204 
02205       ast_str_append(msg, 0, "%s%s: %s\r\n", prefix, subaddress,
02206          S_OR(party->subaddress.str, ""));
02207       ast_str_append(msg, 0, "%s%sType: %d\r\n", prefix, subaddress,
02208          party->subaddress.type);
02209       ast_str_append(msg, 0, "%s%sOdd: %d\r\n", prefix, subaddress,
02210          party->subaddress.odd_even_indicator);
02211    }
02212 #endif   /* defined(HAVE_PRI_SUBADDR) */
02213 }

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 }

static struct ast_cc_agent* sig_pri_find_cc_agent_by_cc_id ( struct sig_pri_span pri,
long  cc_id 
) [static]

Definition at line 2518 of file sig_pri.c.

References ast_cc_agent_callback(), sig_pri_cc_agent_prv::pri, sig_pri_cc_agent_cmp_cc_id(), and sig_pri_cc_type_name.

Referenced by sig_pri_cc_link_canceled(), sig_pri_handle_cis_subcmds(), and sig_pri_handle_subcmds().

02519 {
02520    struct sig_pri_cc_agent_prv finder = {
02521       .pri = pri,
02522       .cc_id = cc_id,
02523    };
02524 
02525    return ast_cc_agent_callback(0, sig_pri_cc_agent_cmp_cc_id, &finder,
02526       sig_pri_cc_type_name);
02527 }

static struct sig_pri_cc_monitor_instance* sig_pri_find_cc_monitor_by_cc_id ( struct sig_pri_span pri,
long  cc_id 
) [static]

Definition at line 2569 of file sig_pri.c.

References ao2_callback, sig_pri_cc_monitor_instance::pri, sig_pri_cc_monitor_cmp_cc_id(), and sig_pri_cc_monitors.

Referenced by sig_pri_cc_link_canceled(), and sig_pri_handle_cis_subcmds().

02570 {
02571    struct sig_pri_cc_monitor_instance finder = {
02572       .pri = pri,
02573       .cc_id = cc_id,
02574    };
02575 
02576    return ao2_callback(sig_pri_cc_monitors, 0, sig_pri_cc_monitor_cmp_cc_id, &finder);
02577 }

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 }

static void sig_pri_fixup_chans ( struct sig_pri_chan old_chan,
struct sig_pri_chan new_chan 
) [static]

Definition at line 928 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::fixup_chans.

Referenced by pri_fixup_principle().

00929 {
00930    if (old_chan->calls->fixup_chans)
00931       old_chan->calls->fixup_chans(old_chan->chan_pvt, new_chan->chan_pvt);
00932 }

static const char* sig_pri_get_orig_dialstring ( struct sig_pri_chan p  )  [static]

Definition at line 207 of file sig_pri.c.

References ast_log(), sig_pri_chan::calls, sig_pri_chan::chan_pvt, sig_pri_callback::get_orig_dialstring, and LOG_ERROR.

Referenced by sig_pri_cc_available(), and sig_pri_cc_generic_check().

00208 {
00209    if (p->calls->get_orig_dialstring) {
00210       return p->calls->get_orig_dialstring(p->chan_pvt);
00211    }
00212    ast_log(LOG_ERROR, "get_orig_dialstring callback not defined\n");
00213    return "";
00214 }

static void sig_pri_handle_cis_subcmds ( struct sig_pri_span pri,
int  event_id,
const struct pri_subcommands *  subcmds,
q931_call *  call_rsp 
) [static]

Definition at line 3838 of file sig_pri.c.

References ao2_ref, ast_cc_agent_accept_request(), ast_cc_agent_caller_available(), ast_cc_agent_caller_busy(), ast_cc_agent_status_response(), ast_cc_failed(), ast_cc_monitor_callee_available(), ast_cc_monitor_failed(), ast_cc_monitor_party_b_free(), ast_cc_monitor_request_acked(), ast_cc_monitor_status_request(), ast_cc_monitor_stop_ringing(), ast_cc_request_is_within_limits(), ast_debug, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_verb, sig_pri_cc_agent_prv::cc_request_response_pending, ast_cc_agent::core_id, monitor, sig_pri_span::pri, sig_pri_cc_monitor_instance::pri, ast_cc_agent::private_data, sig_pri_aoc_e_from_pri(), sig_pri_cc_link_canceled(), sig_pri_cc_type_name, sig_pri_find_cc_agent_by_cc_id(), sig_pri_find_cc_monitor_by_cc_id(), and sig_pri_span::span.

03840 {
03841    int index;
03842 #if defined(HAVE_PRI_CCSS)
03843    struct ast_cc_agent *agent;
03844    struct sig_pri_cc_agent_prv *agent_prv;
03845    struct sig_pri_cc_monitor_instance *monitor;
03846 #endif   /* defined(HAVE_PRI_CCSS) */
03847 
03848    if (!subcmds) {
03849       return;
03850    }
03851    for (index = 0; index < subcmds->counter_subcmd; ++index) {
03852       const struct pri_subcommand *subcmd = &subcmds->subcmd[index];
03853 
03854       switch (subcmd->cmd) {
03855 #if defined(STATUS_REQUEST_PLACE_HOLDER)
03856       case PRI_SUBCMD_STATUS_REQ:
03857       case PRI_SUBCMD_STATUS_REQ_RSP:
03858          /* Ignore for now. */
03859          break;
03860 #endif   /* defined(STATUS_REQUEST_PLACE_HOLDER) */
03861 #if defined(HAVE_PRI_CCSS)
03862       case PRI_SUBCMD_CC_REQ:
03863          agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_request.cc_id);
03864          if (!agent) {
03865             pri_cc_cancel(pri->pri, subcmd->u.cc_request.cc_id);
03866             break;
03867          }
03868          if (!ast_cc_request_is_within_limits()) {
03869             if (pri_cc_req_rsp(pri->pri, subcmd->u.cc_request.cc_id,
03870                5/* queue_full */)) {
03871                pri_cc_cancel(pri->pri, subcmd->u.cc_request.cc_id);
03872             }
03873             ast_cc_failed(agent->core_id, "%s agent system CC queue full",
03874                sig_pri_cc_type_name);
03875             ao2_ref(agent, -1);
03876             break;
03877          }
03878          agent_prv = agent->private_data;
03879          agent_prv->cc_request_response_pending = 1;
03880          if (ast_cc_agent_accept_request(agent->core_id,
03881             "%s caller accepted CC offer.", sig_pri_cc_type_name)) {
03882             agent_prv->cc_request_response_pending = 0;
03883             if (pri_cc_req_rsp(pri->pri, subcmd->u.cc_request.cc_id,
03884                2/* short_term_denial */)) {
03885                pri_cc_cancel(pri->pri, subcmd->u.cc_request.cc_id);
03886             }
03887             ast_cc_failed(agent->core_id, "%s agent CC core request accept failed",
03888                sig_pri_cc_type_name);
03889          }
03890          ao2_ref(agent, -1);
03891          break;
03892 #endif   /* defined(HAVE_PRI_CCSS) */
03893 #if defined(HAVE_PRI_CCSS)
03894       case PRI_SUBCMD_CC_REQ_RSP:
03895          monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
03896             subcmd->u.cc_request_rsp.cc_id);
03897          if (!monitor) {
03898             pri_cc_cancel(pri->pri, subcmd->u.cc_request_rsp.cc_id);
03899             break;
03900          }
03901          switch (subcmd->u.cc_request_rsp.status) {
03902          case 0:/* success */
03903             ast_cc_monitor_request_acked(monitor->core_id,
03904                "%s far end accepted CC request", sig_pri_cc_type_name);
03905             break;
03906          case 1:/* timeout */
03907             ast_verb(2, "core_id:%d %s CC request timeout\n", monitor->core_id,
03908                sig_pri_cc_type_name);
03909             ast_cc_monitor_failed(monitor->core_id, monitor->name,
03910                "%s CC request timeout", sig_pri_cc_type_name);
03911             break;
03912          case 2:/* error */
03913             ast_verb(2, "core_id:%d %s CC request error: %s\n", monitor->core_id,
03914                sig_pri_cc_type_name,
03915                pri_facility_error2str(subcmd->u.cc_request_rsp.fail_code));
03916             ast_cc_monitor_failed(monitor->core_id, monitor->name,
03917                "%s CC request error", sig_pri_cc_type_name);
03918             break;
03919          case 3:/* reject */
03920             ast_verb(2, "core_id:%d %s CC request reject: %s\n", monitor->core_id,
03921                sig_pri_cc_type_name,
03922                pri_facility_reject2str(subcmd->u.cc_request_rsp.fail_code));
03923             ast_cc_monitor_failed(monitor->core_id, monitor->name,
03924                "%s CC request reject", sig_pri_cc_type_name);
03925             break;
03926          default:
03927             ast_verb(2, "core_id:%d %s CC request unknown status %d\n",
03928                monitor->core_id, sig_pri_cc_type_name,
03929                subcmd->u.cc_request_rsp.status);
03930             ast_cc_monitor_failed(monitor->core_id, monitor->name,
03931                "%s CC request unknown status", sig_pri_cc_type_name);
03932             break;
03933          }
03934          ao2_ref(monitor, -1);
03935          break;
03936 #endif   /* defined(HAVE_PRI_CCSS) */
03937 #if defined(HAVE_PRI_CCSS)
03938       case PRI_SUBCMD_CC_REMOTE_USER_FREE:
03939          monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
03940             subcmd->u.cc_remote_user_free.cc_id);
03941          if (!monitor) {
03942             pri_cc_cancel(pri->pri, subcmd->u.cc_remote_user_free.cc_id);
03943             break;
03944          }
03945          ast_cc_monitor_callee_available(monitor->core_id,
03946             "%s callee has become available", sig_pri_cc_type_name);
03947          ao2_ref(monitor, -1);
03948          break;
03949 #endif   /* defined(HAVE_PRI_CCSS) */
03950 #if defined(HAVE_PRI_CCSS)
03951       case PRI_SUBCMD_CC_B_FREE:
03952          monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
03953             subcmd->u.cc_b_free.cc_id);
03954          if (!monitor) {
03955             pri_cc_cancel(pri->pri, subcmd->u.cc_b_free.cc_id);
03956             break;
03957          }
03958          ast_cc_monitor_party_b_free(monitor->core_id);
03959          ao2_ref(monitor, -1);
03960          break;
03961 #endif   /* defined(HAVE_PRI_CCSS) */
03962 #if defined(HAVE_PRI_CCSS)
03963       case PRI_SUBCMD_CC_STATUS_REQ:
03964          monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
03965             subcmd->u.cc_status_req.cc_id);
03966          if (!monitor) {
03967             pri_cc_cancel(pri->pri, subcmd->u.cc_status_req.cc_id);
03968             break;
03969          }
03970          ast_cc_monitor_status_request(monitor->core_id);
03971          ao2_ref(monitor, -1);
03972          break;
03973 #endif   /* defined(HAVE_PRI_CCSS) */
03974 #if defined(HAVE_PRI_CCSS)
03975       case PRI_SUBCMD_CC_STATUS_REQ_RSP:
03976          agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_status_req_rsp.cc_id);
03977          if (!agent) {
03978             pri_cc_cancel(pri->pri, subcmd->u.cc_status_req_rsp.cc_id);
03979             break;
03980          }
03981          ast_cc_agent_status_response(agent->core_id,
03982             subcmd->u.cc_status_req_rsp.status ? AST_DEVICE_INUSE
03983             : AST_DEVICE_NOT_INUSE);
03984          ao2_ref(agent, -1);
03985          break;
03986 #endif   /* defined(HAVE_PRI_CCSS) */
03987 #if defined(HAVE_PRI_CCSS)
03988       case PRI_SUBCMD_CC_STATUS:
03989          agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_status.cc_id);
03990          if (!agent) {
03991             pri_cc_cancel(pri->pri, subcmd->u.cc_status.cc_id);
03992             break;
03993          }
03994          if (subcmd->u.cc_status.status) {
03995             ast_cc_agent_caller_busy(agent->core_id, "%s agent caller is busy",
03996                sig_pri_cc_type_name);
03997          } else {
03998             ast_cc_agent_caller_available(agent->core_id,
03999                "%s agent caller is available", sig_pri_cc_type_name);
04000          }
04001          ao2_ref(agent, -1);
04002          break;
04003 #endif   /* defined(HAVE_PRI_CCSS) */
04004 #if defined(HAVE_PRI_CCSS)
04005       case PRI_SUBCMD_CC_CANCEL:
04006          sig_pri_cc_link_canceled(pri, subcmd->u.cc_cancel.cc_id,
04007             subcmd->u.cc_cancel.is_agent);
04008          break;
04009 #endif   /* defined(HAVE_PRI_CCSS) */
04010 #if defined(HAVE_PRI_CCSS)
04011       case PRI_SUBCMD_CC_STOP_ALERTING:
04012          monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
04013             subcmd->u.cc_stop_alerting.cc_id);
04014          if (!monitor) {
04015             pri_cc_cancel(pri->pri, subcmd->u.cc_stop_alerting.cc_id);
04016             break;
04017          }
04018          ast_cc_monitor_stop_ringing(monitor->core_id);
04019          ao2_ref(monitor, -1);
04020          break;
04021 #endif   /* defined(HAVE_PRI_CCSS) */
04022 #if defined(HAVE_PRI_AOC_EVENTS)
04023       case PRI_SUBCMD_AOC_E:
04024          /* Queue AST_CONTROL_AOC frame */
04025          sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, NULL, 0);
04026          break;
04027 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
04028       default:
04029          ast_debug(2,
04030             "Unknown CIS subcommand(%d) in %s event on span %d.\n",
04031             subcmd->cmd, pri_event2str(event_id), pri->span);
04032          break;
04033       }
04034    }
04035 }

static void sig_pri_handle_dchan_exception ( struct sig_pri_span pri,
int  index 
) [static]

Definition at line 158 of file sig_pri.c.

References sig_pri_span::calls, and sig_pri_callback::handle_dchan_exception.

Referenced by pri_dchannel().

00159 {
00160    if (pri->calls->handle_dchan_exception)
00161       pri->calls->handle_dchan_exception(pri, index);
00162 }

static int sig_pri_handle_hold ( struct sig_pri_span pri,
pri_event *  ev 
) [static]

Definition at line 4449 of file sig_pri.c.

References ast_channel_unlock, AST_CONTROL_HOLD, AST_FRAME_CONTROL, ast_log(), ast_queue_frame(), sig_pri_chan::call_level, f, LOG_WARNING, sig_pri_chan::no_b_channel, sig_pri_chan::owner, pri_find_empty_nobch(), pri_find_principle_by_call(), pri_fixup_principle(), sig_pri_span::pvts, SIG_PRI_CALL_LEVEL_CONNECT, sig_pri_handle_subcmds(), sig_pri_lock_owner(), sig_pri_lock_private(), sig_pri_span_devstate_changed(), sig_pri_unlock_private(), and sig_pri_span::span.

04450 {
04451    int retval;
04452    int chanpos_old;
04453    int chanpos_new;
04454    struct ast_channel *owner;
04455 
04456    chanpos_old = pri_find_principle_by_call(pri, ev->hold.call);
04457    if (chanpos_old < 0) {
04458       ast_log(LOG_WARNING, "Span %d: Received HOLD for unknown call.\n", pri->span);
04459       return -1;
04460    }
04461    if (pri->pvts[chanpos_old]->no_b_channel) {
04462       /* Call is already on hold or is call waiting call. */
04463       return -1;
04464    }
04465 
04466    chanpos_new = -1;
04467 
04468    sig_pri_lock_private(pri->pvts[chanpos_old]);
04469    sig_pri_lock_owner(pri, chanpos_old);
04470    owner = pri->pvts[chanpos_old]->owner;
04471    if (!owner) {
04472       goto done_with_private;
04473    }
04474    if (pri->pvts[chanpos_old]->call_level != SIG_PRI_CALL_LEVEL_CONNECT) {
04475       /*
04476        * Make things simple.  Don't allow placing a call on hold that
04477        * is not connected.
04478        */
04479       goto done_with_owner;
04480    }
04481    chanpos_new = pri_find_empty_nobch(pri);
04482    if (chanpos_new < 0) {
04483       /* No hold channel available. */
04484       goto done_with_owner;
04485    }
04486    sig_pri_handle_subcmds(pri, chanpos_old, ev->e, ev->hold.channel, ev->hold.subcmds,
04487       ev->hold.call);
04488    chanpos_new = pri_fixup_principle(pri, chanpos_new, ev->hold.call);
04489    if (chanpos_new < 0) {
04490       /* Should never happen. */
04491    } else {
04492       struct ast_frame f = { AST_FRAME_CONTROL, };
04493 
04494       /*
04495        * Things are in an odd state here so we cannot use pri_queue_control().
04496        * However, we already have the owner lock so we can simply queue the frame.
04497        */
04498       f.subclass.integer = AST_CONTROL_HOLD;
04499       ast_queue_frame(owner, &f);
04500    }
04501 
04502 done_with_owner:;
04503    ast_channel_unlock(owner);
04504 done_with_private:;
04505    sig_pri_unlock_private(pri->pvts[chanpos_old]);
04506 
04507    if (chanpos_new < 0) {
04508       retval = -1;
04509    } else {
04510       sig_pri_span_devstate_changed(pri);
04511       retval = 0;
04512    }
04513 
04514    return retval;
04515 }

static void sig_pri_handle_retrieve ( struct sig_pri_span pri,
pri_event *  ev 
) [static]

Definition at line 4531 of file sig_pri.c.

References AST_CONTROL_UNHOLD, ast_log(), LOG_WARNING, sig_pri_span::pri, PRI_CHANNEL, pri_find_empty_chan(), pri_find_principle(), pri_find_principle_by_call(), pri_fixup_principle(), PRI_HELD_CALL, pri_queue_control(), PVT_TO_CHANNEL(), sig_pri_span::pvts, sig_pri_handle_subcmds(), sig_pri_is_chan_available(), sig_pri_lock_private(), sig_pri_span_devstate_changed(), sig_pri_unlock_private(), and sig_pri_span::span.

04532 {
04533    int chanpos;
04534 
04535    if (!(ev->retrieve.channel & PRI_HELD_CALL)) {
04536       /* The call is not currently held. */
04537       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04538          PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
04539       return;
04540    }
04541    if (pri_find_principle_by_call(pri, ev->retrieve.call) < 0) {
04542       ast_log(LOG_WARNING, "Span %d: Received RETRIEVE for unknown call.\n", pri->span);
04543       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04544          PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
04545       return;
04546    }
04547    if (PRI_CHANNEL(ev->retrieve.channel) == 0xFF) {
04548       chanpos = pri_find_empty_chan(pri, 1);
04549    } else {
04550       chanpos = pri_find_principle(pri,
04551          ev->retrieve.channel & ~PRI_HELD_CALL, ev->retrieve.call);
04552       if (ev->retrieve.flexible
04553          && (chanpos < 0 || !sig_pri_is_chan_available(pri->pvts[chanpos]))) {
04554          /*
04555           * Channel selection is flexible and the requested channel
04556           * is bad or not available.  Pick another channel.
04557           */
04558          chanpos = pri_find_empty_chan(pri, 1);
04559       }
04560    }
04561    if (chanpos < 0) {
04562       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04563          ev->retrieve.flexible ? PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
04564          : PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
04565       return;
04566    }
04567    chanpos = pri_fixup_principle(pri, chanpos, ev->retrieve.call);
04568    if (chanpos < 0) {
04569       /* Channel is already in use. */
04570       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04571          PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
04572       return;
04573    }
04574    sig_pri_lock_private(pri->pvts[chanpos]);
04575    sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.channel,
04576       ev->retrieve.subcmds, ev->retrieve.call);
04577    pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
04578    sig_pri_unlock_private(pri->pvts[chanpos]);
04579    pri_retrieve_ack(pri->pri, ev->retrieve.call,
04580       PVT_TO_CHANNEL(pri->pvts[chanpos]));
04581    sig_pri_span_devstate_changed(pri);
04582 }

static void sig_pri_handle_subcmds ( struct sig_pri_span pri,
int  chanpos,
int  event_id,
int  channel,
const struct pri_subcommands *  subcmds,
q931_call *  call_rsp 
) [static]

Definition at line 4094 of file sig_pri.c.

References ast_party_caller::ani, ao2_ref, ast_cc_agent_recalling(), ast_cc_agent_set_interfaces_chanvar(), AST_CC_CCBS, AST_CC_CCNR, AST_CC_NONE, ast_channel_queue_connected_line_update(), ast_channel_queue_redirecting_update(), ast_channel_set_caller_event(), ast_channel_set_redirecting(), ast_channel_unlock, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, ast_copy_string(), ast_debug, ast_log(), ast_null_frame, ast_party_caller_set_init(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_id_presentation(), ast_party_redirecting_free(), ast_party_subaddress_set(), ast_queue_frame(), ast_setup_cc_recall_datastore(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verb, xfer_rsp_data::call, ast_channel::caller, ast_cc_agent::core_id, ast_party_redirecting::from, ast_party_caller::id, xfer_rsp_data::invoke_id, LOG_ERROR, LOG_WARNING, ast_channel::name, xfer_rsp_data::pri, PRI_CHANNEL, PRI_SPAN, ast_channel::redirecting, service, sig_pri_aoc_d_from_pri(), sig_pri_aoc_e_from_pri(), SIG_PRI_AOC_GRANT_D, SIG_PRI_AOC_GRANT_E, SIG_PRI_AOC_GRANT_S, sig_pri_aoc_request_from_pri(), sig_pri_aoc_s_from_pri(), sig_pri_attempt_transfer(), sig_pri_cc_available(), sig_pri_cc_link_canceled(), sig_pri_cc_type_name, sig_pri_find_cc_agent_by_cc_id(), sig_pri_lock_owner(), sig_pri_lock_private(), sig_pri_mcid_event(), sig_pri_party_id_convert(), sig_pri_redirecting_convert(), sig_pri_set_caller_id(), sig_pri_transfer_rsp(), sig_pri_unlock_private(), ast_party_id::subaddress, ast_party_id::tag, and ast_party_redirecting::to.

Referenced by sig_pri_handle_hold(), and sig_pri_handle_retrieve().

04096 {
04097    int index;
04098    struct ast_channel *owner;
04099    struct ast_party_redirecting ast_redirecting;
04100 #if defined(HAVE_PRI_TRANSFER)
04101    struct xfer_rsp_data xfer_rsp;
04102 #endif   /* defined(HAVE_PRI_TRANSFER) */
04103 
04104    if (!subcmds) {
04105       return;
04106    }
04107    for (index = 0; index < subcmds->counter_subcmd; ++index) {
04108       const struct pri_subcommand *subcmd = &subcmds->subcmd[index];
04109 
04110       switch (subcmd->cmd) {
04111       case PRI_SUBCMD_CONNECTED_LINE:
04112          sig_pri_lock_owner(pri, chanpos);
04113          owner = pri->pvts[chanpos]->owner;
04114          if (owner) {
04115             struct ast_party_connected_line ast_connected;
04116             int caller_id_update;
04117 
04118             /* Extract the connected line information */
04119             ast_party_connected_line_init(&ast_connected);
04120             sig_pri_party_id_convert(&ast_connected.id, &subcmd->u.connected_line.id,
04121                pri);
04122             ast_connected.id.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
04123 
04124             caller_id_update = 0;
04125             if (ast_connected.id.name.str) {
04126                /* Save name for Caller-ID update */
04127                ast_copy_string(pri->pvts[chanpos]->cid_name,
04128                   ast_connected.id.name.str, sizeof(pri->pvts[chanpos]->cid_name));
04129                caller_id_update = 1;
04130             }
04131             if (ast_connected.id.number.str) {
04132                /* Save number for Caller-ID update */
04133                ast_copy_string(pri->pvts[chanpos]->cid_num,
04134                   ast_connected.id.number.str, sizeof(pri->pvts[chanpos]->cid_num));
04135                pri->pvts[chanpos]->cid_ton = ast_connected.id.number.plan;
04136                caller_id_update = 1;
04137             }
04138             ast_connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
04139 
04140             pri->pvts[chanpos]->cid_subaddr[0] = '\0';
04141 #if defined(HAVE_PRI_SUBADDR)
04142             if (ast_connected.id.subaddress.valid) {
04143                ast_party_subaddress_set(&owner->caller.id.subaddress,
04144                   &ast_connected.id.subaddress);
04145                if (ast_connected.id.subaddress.str) {
04146                   ast_copy_string(pri->pvts[chanpos]->cid_subaddr,
04147                      ast_connected.id.subaddress.str,
04148                      sizeof(pri->pvts[chanpos]->cid_subaddr));
04149                }
04150             }
04151 #endif   /* defined(HAVE_PRI_SUBADDR) */
04152             if (caller_id_update) {
04153                struct ast_party_caller ast_caller;
04154 
04155                pri->pvts[chanpos]->callingpres =
04156                   ast_party_id_presentation(&ast_connected.id);
04157                sig_pri_set_caller_id(pri->pvts[chanpos]);
04158 
04159                ast_party_caller_set_init(&ast_caller, &owner->caller);
04160                ast_caller.id = ast_connected.id;
04161                ast_caller.ani = ast_connected.id;
04162                ast_channel_set_caller_event(owner, &ast_caller, NULL);
04163             }
04164 
04165             /* Update the connected line information on the other channel */
04166             if (event_id != PRI_EVENT_RING) {
04167                /* This connected_line update was not from a SETUP message. */
04168                ast_channel_queue_connected_line_update(owner, &ast_connected, NULL);
04169             }
04170 
04171             ast_party_connected_line_free(&ast_connected);
04172             ast_channel_unlock(owner);
04173          }
04174          break;
04175       case PRI_SUBCMD_REDIRECTING:
04176          sig_pri_lock_owner(pri, chanpos);
04177          owner = pri->pvts[chanpos]->owner;
04178          if (owner) {
04179             sig_pri_redirecting_convert(&ast_redirecting, &subcmd->u.redirecting,
04180                &owner->redirecting, pri);
04181             ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
04182             ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
04183 
04184 /*! \todo XXX Original called data can be put in a channel data store that is inherited. */
04185 
04186             ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
04187             if (event_id != PRI_EVENT_RING) {
04188                /* This redirection was not from a SETUP message. */
04189                ast_channel_queue_redirecting_update(owner, &ast_redirecting, NULL);
04190             }
04191             ast_party_redirecting_free(&ast_redirecting);
04192 
04193             ast_channel_unlock(owner);
04194          }
04195          break;
04196 #if defined(HAVE_PRI_CALL_REROUTING)
04197       case PRI_SUBCMD_REROUTING:
04198          sig_pri_lock_owner(pri, chanpos);
04199          owner = pri->pvts[chanpos]->owner;
04200          if (owner) {
04201             struct pri_party_redirecting pri_deflection;
04202 
04203             if (!call_rsp) {
04204                ast_log(LOG_WARNING,
04205                   "Span %d: %s tried CallRerouting/CallDeflection to '%s' without call!\n",
04206                   pri->span, owner->name, subcmd->u.rerouting.deflection.to.number.str);
04207                ast_channel_unlock(owner);
04208                break;
04209             }
04210             if (ast_strlen_zero(subcmd->u.rerouting.deflection.to.number.str)) {
04211                ast_log(LOG_WARNING,
04212                   "Span %d: %s tried CallRerouting/CallDeflection to empty number!\n",
04213                   pri->span, owner->name);
04214                pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
04215                   PRI_REROUTING_RSP_INVALID_NUMBER);
04216                ast_channel_unlock(owner);
04217                break;
04218             }
04219 
04220             ast_verb(3, "Span %d: %s is CallRerouting/CallDeflection to '%s'.\n",
04221                pri->span, owner->name, subcmd->u.rerouting.deflection.to.number.str);
04222 
04223             /*
04224              * Send back positive ACK to CallRerouting/CallDeflection.
04225              *
04226              * Note:  This call will be hungup by the core when it processes
04227              * the call_forward string.
04228              */
04229             pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
04230                PRI_REROUTING_RSP_OK_CLEAR);
04231 
04232             pri_deflection = subcmd->u.rerouting.deflection;
04233 
04234             /* Adjust the deflecting to number based upon the subscription option. */
04235             switch (subcmd->u.rerouting.subscription_option) {
04236             case 0:  /* noNotification */
04237             case 1:  /* notificationWithoutDivertedToNr */
04238                /* Delete the number because the far end is not supposed to see it. */
04239                pri_deflection.to.number.presentation =
04240                   PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
04241                pri_deflection.to.number.plan =
04242                   (PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
04243                pri_deflection.to.number.str[0] = '\0';
04244                break;
04245             case 2:  /* notificationWithDivertedToNr */
04246                break;
04247             case 3:  /* notApplicable */
04248             default:
04249                break;
04250             }
04251             sig_pri_redirecting_convert(&ast_redirecting, &pri_deflection,
04252                &owner->redirecting, pri);
04253             ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
04254             ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
04255             ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
04256             ast_party_redirecting_free(&ast_redirecting);
04257 
04258             /* Request the core to forward to the new number. */
04259             ast_string_field_set(owner, call_forward,
04260                subcmd->u.rerouting.deflection.to.number.str);
04261 
04262             /* Wake up the channel. */
04263             ast_queue_frame(owner, &ast_null_frame);
04264 
04265             ast_channel_unlock(owner);
04266          }
04267          break;
04268 #endif   /* defined(HAVE_PRI_CALL_REROUTING) */
04269 #if defined(HAVE_PRI_CCSS)
04270       case PRI_SUBCMD_CC_AVAILABLE:
04271          sig_pri_lock_owner(pri, chanpos);
04272          owner = pri->pvts[chanpos]->owner;
04273          if (owner) {
04274             enum ast_cc_service_type service;
04275 
04276             switch (event_id) {
04277             case PRI_EVENT_RINGING:
04278                service = AST_CC_CCNR;
04279                break;
04280             case PRI_EVENT_HANGUP_REQ:
04281                /* We will assume that the cause was busy/congestion. */
04282                service = AST_CC_CCBS;
04283                break;
04284             default:
04285                service = AST_CC_NONE;
04286                break;
04287             }
04288             if (service == AST_CC_NONE
04289                || sig_pri_cc_available(pri, chanpos, subcmd->u.cc_available.cc_id,
04290                service)) {
04291                pri_cc_cancel(pri->pri, subcmd->u.cc_available.cc_id);
04292             }
04293             ast_channel_unlock(owner);
04294          } else {
04295             /* No asterisk channel. */
04296             pri_cc_cancel(pri->pri, subcmd->u.cc_available.cc_id);
04297          }
04298          break;
04299 #endif   /* defined(HAVE_PRI_CCSS) */
04300 #if defined(HAVE_PRI_CCSS)
04301       case PRI_SUBCMD_CC_CALL:
04302          sig_pri_lock_owner(pri, chanpos);
04303          owner = pri->pvts[chanpos]->owner;
04304          if (owner) {
04305             struct ast_cc_agent *agent;
04306 
04307             agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_call.cc_id);
04308             if (agent) {
04309                ast_setup_cc_recall_datastore(owner, agent->core_id);
04310                ast_cc_agent_set_interfaces_chanvar(owner);
04311                ast_cc_agent_recalling(agent->core_id,
04312                   "%s caller is attempting recall", sig_pri_cc_type_name);
04313                ao2_ref(agent, -1);
04314             }
04315 
04316             ast_channel_unlock(owner);
04317          }
04318          break;
04319 #endif   /* defined(HAVE_PRI_CCSS) */
04320 #if defined(HAVE_PRI_CCSS)
04321       case PRI_SUBCMD_CC_CANCEL:
04322          sig_pri_cc_link_canceled(pri, subcmd->u.cc_cancel.cc_id,
04323             subcmd->u.cc_cancel.is_agent);
04324          break;
04325 #endif   /* defined(HAVE_PRI_CCSS) */
04326 #if defined(HAVE_PRI_TRANSFER)
04327       case PRI_SUBCMD_TRANSFER_CALL:
04328          if (!call_rsp) {
04329             /* Should never happen. */
04330             ast_log(LOG_ERROR,
04331                "Call transfer subcommand without call to send response!\n");
04332             break;
04333          }
04334 
04335          sig_pri_unlock_private(pri->pvts[chanpos]);
04336          xfer_rsp.pri = pri;
04337          xfer_rsp.call = call_rsp;
04338          xfer_rsp.invoke_id = subcmd->u.transfer.invoke_id;
04339          sig_pri_attempt_transfer(pri,
04340             subcmd->u.transfer.call_1, subcmd->u.transfer.is_call_1_held,
04341             subcmd->u.transfer.call_2, subcmd->u.transfer.is_call_2_held,
04342             sig_pri_transfer_rsp, &xfer_rsp);
04343          sig_pri_lock_private(pri->pvts[chanpos]);
04344          break;
04345 #endif   /* defined(HAVE_PRI_TRANSFER) */
04346 #if defined(HAVE_PRI_AOC_EVENTS)
04347       case PRI_SUBCMD_AOC_S:
04348          sig_pri_lock_owner(pri, chanpos);
04349          owner = pri->pvts[chanpos]->owner;
04350          if (owner) {
04351             sig_pri_aoc_s_from_pri(&subcmd->u.aoc_s, owner,
04352                (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
04353             ast_channel_unlock(owner);
04354          }
04355          break;
04356 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
04357 #if defined(HAVE_PRI_AOC_EVENTS)
04358       case PRI_SUBCMD_AOC_D:
04359          sig_pri_lock_owner(pri, chanpos);
04360          owner = pri->pvts[chanpos]->owner;
04361          if (owner) {
04362             /* Queue AST_CONTROL_AOC frame on channel */
04363             sig_pri_aoc_d_from_pri(&subcmd->u.aoc_d, owner,
04364                (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D));
04365             ast_channel_unlock(owner);
04366          }
04367          break;
04368 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
04369 #if defined(HAVE_PRI_AOC_EVENTS)
04370       case PRI_SUBCMD_AOC_E:
04371          sig_pri_lock_owner(pri, chanpos);
04372          owner = pri->pvts[chanpos]->owner;
04373          /* Queue AST_CONTROL_AOC frame */
04374          sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, owner,
04375             (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E));
04376          if (owner) {
04377             ast_channel_unlock(owner);
04378          }
04379          break;
04380 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
04381 #if defined(HAVE_PRI_AOC_EVENTS)
04382       case PRI_SUBCMD_AOC_CHARGING_REQ:
04383          sig_pri_lock_owner(pri, chanpos);
04384          owner = pri->pvts[chanpos]->owner;
04385          if (owner) {
04386             sig_pri_aoc_request_from_pri(&subcmd->u.aoc_request, pri->pvts[chanpos],
04387                call_rsp);
04388             ast_channel_unlock(owner);
04389          }
04390          break;
04391 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
04392 #if defined(HAVE_PRI_AOC_EVENTS)
04393       case PRI_SUBCMD_AOC_CHARGING_REQ_RSP:
04394          /*
04395           * An AOC request response may contain an AOC-S rate list.
04396           * If this is the case handle this just like we
04397           * would an incoming AOC-S msg.
04398           */
04399          if (subcmd->u.aoc_request_response.valid_aoc_s) {
04400             sig_pri_lock_owner(pri, chanpos);
04401             owner = pri->pvts[chanpos]->owner;
04402             if (owner) {
04403                sig_pri_aoc_s_from_pri(&subcmd->u.aoc_request_response.aoc_s, owner,
04404                   (pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
04405                ast_channel_unlock(owner);
04406             }
04407          }
04408          break;
04409 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
04410 #if defined(HAVE_PRI_MCID)
04411       case PRI_SUBCMD_MCID_REQ:
04412          sig_pri_lock_owner(pri, chanpos);
04413          owner = pri->pvts[chanpos]->owner;
04414          sig_pri_mcid_event(pri, &subcmd->u.mcid_req, owner);
04415          if (owner) {
04416             ast_channel_unlock(owner);
04417          }
04418          break;
04419 #endif   /* defined(HAVE_PRI_MCID) */
04420 #if defined(HAVE_PRI_MCID)
04421       case PRI_SUBCMD_MCID_RSP:
04422          /* Ignore for now. */
04423          break;
04424 #endif   /* defined(HAVE_PRI_MCID) */
04425       default:
04426          ast_debug(2,
04427             "Unknown call subcommand(%d) in %s event on channel %d/%d on span %d.\n",
04428             subcmd->cmd, pri_event2str(event_id), PRI_SPAN(channel),
04429             PRI_CHANNEL(channel), pri->span);
04430          break;
04431       }
04432    }
04433 }

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_chan::pri, sig_pri_span::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_chan::pri, sig_pri_span::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 }

static void sig_pri_init_config ( struct sig_pri_chan pvt,
struct sig_pri_span pri 
) [static]

Definition at line 1733 of file sig_pri.c.

References ast_copy_string(), sig_pri_span::calls, sig_pri_span::ch_cfg, sig_pri_chan::chan_pvt, sig_pri_span::context, sig_pri_chan::context, sig_pri_span::hidecallerid, sig_pri_chan::hidecallerid, sig_pri_span::hidecalleridname, sig_pri_chan::hidecalleridname, sig_pri_span::immediate, sig_pri_chan::immediate, sig_pri_callback::init_config, sig_pri_span::mohinterpret, sig_pri_chan::mohinterpret, sig_pri_chan::pri, sig_pri_span::priexclusive, sig_pri_chan::priexclusive, sig_pri_span::priindication_oob, sig_pri_chan::priindication_oob, sig_pri_span::stripmsd, sig_pri_chan::stripmsd, sig_pri_span::use_callerid, sig_pri_chan::use_callerid, sig_pri_span::use_callingpres, and sig_pri_chan::use_callingpres.

Referenced by sig_pri_cw_available().

01734 {
01735    pvt->stripmsd = pri->ch_cfg.stripmsd;
01736    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
01737    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
01738    pvt->immediate = pri->ch_cfg.immediate;
01739    pvt->priexclusive = pri->ch_cfg.priexclusive;
01740    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
01741    pvt->use_callerid = pri->ch_cfg.use_callerid;
01742    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
01743    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
01744    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
01745 
01746    if (pri->calls->init_config) {
01747       pri->calls->init_config(pvt->chan_pvt, pri);
01748    }
01749 }

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 }

static int sig_pri_is_chan_in_use ( struct sig_pri_chan pvt  )  [static]

Definition at line 1145 of file sig_pri.c.

References sig_pri_chan::allocated, sig_pri_chan::call, sig_pri_chan::inalarm, sig_pri_chan::owner, sig_pri_chan::resetting, and SIG_PRI_RESET_IDLE.

Referenced by pri_check_restart(), and sig_pri_is_chan_available().

01146 {
01147    return pvt->owner || pvt->call || pvt->allocated || pvt->inalarm
01148       || pvt->resetting != SIG_PRI_RESET_IDLE;
01149 }

static int sig_pri_is_cis_call ( int  channel  )  [static]

Definition at line 3816 of file sig_pri.c.

References PRI_CIS_CALL.

03817 {
03818    return channel != -1 && (channel & PRI_CIS_CALL);
03819 }

static void sig_pri_kill_call ( struct sig_pri_span pri,
q931_call *  call,
int  cause 
) [static]

Definition at line 1294 of file sig_pri.c.

References AST_CONTROL_HANGUP, sig_pri_chan::call, ast_channel::hangupcause, sig_pri_chan::owner, sig_pri_span::pri, sig_pri_chan::pri, pri_find_principle_by_call(), pri_queue_control(), sig_pri_span::pvts, sig_pri_lock_private(), sig_pri_span_devstate_changed(), and sig_pri_unlock_private().

Referenced by pri_find_fixup_principle().

01295 {
01296    int chanpos;
01297 
01298    chanpos = pri_find_principle_by_call(pri, call);
01299    if (chanpos < 0) {
01300       pri_hangup(pri->pri, call, cause);
01301       return;
01302    }
01303    sig_pri_lock_private(pri->pvts[chanpos]);
01304    if (!pri->pvts[chanpos]->owner) {
01305       pri_hangup(pri->pri, call, cause);
01306       pri->pvts[chanpos]->call = NULL;
01307       sig_pri_unlock_private(pri->pvts[chanpos]);
01308       sig_pri_span_devstate_changed(pri);
01309       return;
01310    }
01311    pri->pvts[chanpos]->owner->hangupcause = cause;
01312    pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
01313    sig_pri_unlock_private(pri->pvts[chanpos]);
01314 }

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 }

static void sig_pri_lock_owner ( struct sig_pri_span pri,
int  chanpos 
) [static]

Definition at line 1182 of file sig_pri.c.

References ast_channel_trylock, sig_pri_chan::owner, and sig_pri_span::pvts.

Referenced by pri_fixup_principle(), pri_queue_frame(), sig_pri_attempt_transfer(), sig_pri_cc_generic_check(), sig_pri_cli_show_channels(), sig_pri_handle_hold(), sig_pri_handle_subcmds(), and sig_pri_send_aoce_termination_request().

01183 {
01184    for (;;) {
01185       if (!pri->pvts[chanpos]->owner) {
01186          /* There is no owner lock to get. */
01187          break;
01188       }
01189       if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
01190          /* We got the lock */
01191          break;
01192       }
01193 
01194       /* Avoid deadlock */
01195       sig_pri_unlock_private(pri->pvts[chanpos]);
01196       DEADLOCK_AVOIDANCE(&pri->lock);
01197       sig_pri_lock_private(pri->pvts[chanpos]);
01198    }
01199 }

static void sig_pri_lock_private ( struct sig_pri_chan p  )  [static]

Definition at line 336 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::lock_private.

Referenced by pri_dchannel(), pri_fixup_principle(), pri_grab(), pri_send_callrerouting_facility_exec(), pri_send_keypad_facility_exec(), pri_ss_thread(), sig_pri_attempt_transfer(), sig_pri_cli_show_channels(), sig_pri_handle_hold(), sig_pri_handle_retrieve(), sig_pri_handle_subcmds(), and sig_pri_kill_call().

00337 {
00338    if (p->calls->lock_private)
00339       p->calls->lock_private(p->chan_pvt);
00340 }

static void sig_pri_make_cc_dialstring ( struct sig_pri_chan p,
char *  buf,
size_t  buf_size 
) [static]

Definition at line 217 of file sig_pri.c.

References ast_log(), sig_pri_chan::calls, sig_pri_chan::chan_pvt, LOG_ERROR, and sig_pri_callback::make_cc_dialstring.

Referenced by sig_pri_cc_available().

00218 {
00219    if (p->calls->make_cc_dialstring) {
00220       p->calls->make_cc_dialstring(p->chan_pvt, buf, buf_size);
00221    } else {
00222       ast_log(LOG_ERROR, "make_cc_dialstring callback not defined\n");
00223       buf[0] = '\0';
00224    }
00225 }

static void sig_pri_mcid_event ( struct sig_pri_span pri,
const struct pri_subcmd_mcid_req *  mcid,
struct ast_channel owner 
) [static]

Definition at line 2232 of file sig_pri.c.

References ast_free, ast_manager_event_multichan, ast_party_id_free(), ast_party_id_init(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_channel::connected, EVENT_FLAG_CALL, ast_party_connected_line::id, ast_channel::name, sig_pri_event_party_id(), sig_pri_party_id_convert(), and ast_channel::uniqueid.

Referenced by sig_pri_handle_subcmds().

02233 {
02234    struct ast_channel *chans[1];
02235    struct ast_str *msg;
02236    struct ast_party_id party;
02237 
02238    msg = ast_str_create(4096);
02239    if (!msg) {
02240       return;
02241    }
02242 
02243    if (owner) {
02244       /* The owner channel is present. */
02245       ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name);
02246       ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid);
02247 
02248       sig_pri_event_party_id(&msg, "CallerID", &owner->connected.id);
02249    } else {
02250       /*
02251        * Since we no longer have an owner channel,
02252        * we have to use the caller information supplied by libpri.
02253        */
02254       ast_party_id_init(&party);
02255       sig_pri_party_id_convert(&party, &mcid->originator, pri);
02256       sig_pri_event_party_id(&msg, "CallerID", &party);
02257       ast_party_id_free(&party);
02258    }
02259 
02260    /* Always use libpri's called party information. */
02261    ast_party_id_init(&party);
02262    sig_pri_party_id_convert(&party, &mcid->answerer, pri);
02263    sig_pri_event_party_id(&msg, "ConnectedID", &party);
02264    ast_party_id_free(&party);
02265 
02266    chans[0] = owner;
02267    ast_manager_event_multichan(EVENT_FLAG_CALL, "MCID", owner ? 1 : 0, chans, "%s",
02268       ast_str_buffer(msg));
02269    ast_free(msg);
02270 }

static int sig_pri_msn_match ( const char *  msn_patterns,
const char *  exten 
) [static]

Definition at line 2131 of file sig_pri.c.

References ast_extension_match(), ast_strdupa, ast_strip(), and ast_strlen_zero().

02132 {
02133    char *pattern;
02134    char *msn_list;
02135    char *list_tail;
02136 
02137    msn_list = ast_strdupa(msn_patterns);
02138 
02139    list_tail = NULL;
02140    pattern = strtok_r(msn_list, ",", &list_tail);
02141    while (pattern) {
02142       pattern = ast_strip(pattern);
02143       if (!ast_strlen_zero(pattern) && ast_extension_match(pattern, exten)) {
02144          /* Extension matched the pattern. */
02145          return 1;
02146       }
02147       pattern = strtok_r(NULL, ",", &list_tail);
02148    }
02149    /* Did not match any pattern in the list. */
02150    return 0;
02151 }

static void sig_pri_mwi_cache_update ( struct sig_pri_span pri  )  [static]

Definition at line 7524 of file sig_pri.c.

References ARRAY_LEN, ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, sig_pri_mbox::context, sig_pri_span::mbox, sig_pri_mbox::number, sig_pri_send_mwi_indication(), and sig_pri_mbox::sub.

07525 {
07526    int idx;
07527    int num_messages;
07528    struct ast_event *event;
07529 
07530    for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
07531       if (!pri->mbox[idx].sub) {
07532          /* There are no more mailboxes on this span. */
07533          break;
07534       }
07535 
07536       event = ast_event_get_cached(AST_EVENT_MWI,
07537          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, pri->mbox[idx].number,
07538          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, pri->mbox[idx].context,
07539          AST_EVENT_IE_END);
07540       if (!event) {
07541          /* No cached event for this mailbox. */
07542          continue;
07543       }
07544       num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
07545       sig_pri_send_mwi_indication(pri, pri->mbox[idx].number, pri->mbox[idx].context,
07546          num_messages);
07547       ast_event_destroy(event);
07548    }
07549 }

static void sig_pri_mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 7494 of file sig_pri.c.

References ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, ast_strlen_zero(), sig_pri_span::pri, and sig_pri_send_mwi_indication().

Referenced by sig_pri_start_pri().

07495 {
07496    struct sig_pri_span *pri = userdata;
07497    const char *mbox_context;
07498    const char *mbox_number;
07499    int num_messages;
07500 
07501    mbox_number = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
07502    if (ast_strlen_zero(mbox_number)) {
07503       return;
07504    }
07505    mbox_context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
07506    if (ast_strlen_zero(mbox_context)) {
07507       return;
07508    }
07509    num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
07510    sig_pri_send_mwi_indication(pri, mbox_number, mbox_context, num_messages);
07511 }

static struct ast_channel* sig_pri_new_ast_channel ( struct sig_pri_chan p,
int  state,
int  ulaw,
int  transfercapability,
char *  exten,
const struct ast_channel requestor 
) [static]

Definition at line 942 of file sig_pri.c.

References sig_pri_chan::alreadyhungup, ast_mutex_lock, ast_mutex_unlock, AST_TRANS_CAP_DIGITAL, ast_transfercapability2str(), sig_pri_chan::calls, sig_pri_chan::chan_pvt, sig_pri_chan::isidlecall, sig_pri_span::lock, sig_pri_callback::new_ast_channel, sig_pri_chan::owner, pbx_builtin_setvar_helper(), sig_pri_chan::pri, sig_pri_set_digital(), sig_pri_span_devstate_changed(), and ast_channel::transfercapability.

Referenced by sig_pri_request().

00943 {
00944    struct ast_channel *c;
00945 
00946    if (p->calls->new_ast_channel) {
00947       c = p->calls->new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor);
00948    } else {
00949       return NULL;
00950    }
00951    if (!c) {
00952       return NULL;
00953    }
00954 
00955    if (!p->owner)
00956       p->owner = c;
00957    p->isidlecall = 0;
00958    p->alreadyhungup = 0;
00959    c->transfercapability = transfercapability;
00960    pbx_builtin_setvar_helper(c, "TRANSFERCAPABILITY",
00961       ast_transfercapability2str(transfercapability));
00962    if (transfercapability & AST_TRANS_CAP_DIGITAL) {
00963       sig_pri_set_digital(p, 1);
00964    }
00965    if (p->pri) {
00966       ast_mutex_lock(&p->pri->lock);
00967       sig_pri_span_devstate_changed(p->pri);
00968       ast_mutex_unlock(&p->pri->lock);
00969    }
00970 
00971    return c;
00972 }

static void sig_pri_open_media ( struct sig_pri_chan p  )  [static]

Definition at line 983 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, sig_pri_chan::no_b_channel, and sig_pri_callback::open_media.

Referenced by pri_fixup_principle(), sig_pri_answer(), and sig_pri_dial_complete().

00984 {
00985    if (p->no_b_channel) {
00986       return;
00987    }
00988 
00989    if (p->calls->open_media) {
00990       p->calls->open_media(p->chan_pvt);
00991    }
00992 }

static void sig_pri_party_id_convert ( struct ast_party_id ast_id,
const struct pri_party_id *  pri_id,
struct sig_pri_span pri 
) [static]

Definition at line 2077 of file sig_pri.c.

References ast_party_id::name, ast_party_id::number, sig_pri_party_name_convert(), sig_pri_party_number_convert(), sig_pri_set_subaddress(), and ast_party_id::subaddress.

Referenced by sig_pri_handle_subcmds(), sig_pri_mcid_event(), and sig_pri_redirecting_convert().

02078 {
02079    if (pri_id->name.valid) {
02080       sig_pri_party_name_convert(&ast_id->name, &pri_id->name);
02081    }
02082    if (pri_id->number.valid) {
02083       sig_pri_party_number_convert(&ast_id->number, &pri_id->number, pri);
02084    }
02085 #if defined(HAVE_PRI_SUBADDR)
02086    if (pri_id->subaddress.valid) {
02087       sig_pri_set_subaddress(&ast_id->subaddress, &pri_id->subaddress);
02088    }
02089 #endif   /* defined(HAVE_PRI_SUBADDR) */
02090 }

static void sig_pri_party_id_from_ast ( struct pri_party_id *  pri_id,
const struct ast_party_id ast_id 
) [static]

Definition at line 868 of file sig_pri.c.

References ast_party_id::name, ast_party_id::number, sig_pri_party_name_from_ast(), sig_pri_party_number_from_ast(), sig_pri_party_subaddress_from_ast(), and ast_party_id::subaddress.

Referenced by sig_pri_indicate(), and sig_pri_redirecting_update().

00869 {
00870    sig_pri_party_name_from_ast(&pri_id->name, &ast_id->name);
00871    sig_pri_party_number_from_ast(&pri_id->number, &ast_id->number);
00872 #if defined(HAVE_PRI_SUBADDR)
00873    sig_pri_party_subaddress_from_ast(&pri_id->subaddress, &ast_id->subaddress);
00874 #endif   /* defined(HAVE_PRI_SUBADDR) */
00875 }

static void sig_pri_party_name_convert ( struct ast_party_name ast_name,
const struct pri_party_name *  pri_name 
) [static]

Definition at line 2029 of file sig_pri.c.

References ast_strdup, ast_party_name::char_set, ast_party_name::presentation, pri_to_ast_char_set(), pri_to_ast_presentation(), ast_party_name::str, and ast_party_name::valid.

Referenced by sig_pri_party_id_convert().

02030 {
02031    ast_name->str = ast_strdup(pri_name->str);
02032    ast_name->char_set = pri_to_ast_char_set(pri_name->char_set);
02033    ast_name->presentation = pri_to_ast_presentation(pri_name->presentation);
02034    ast_name->valid = 1;
02035 }

static void sig_pri_party_name_from_ast ( struct pri_party_name *  pri_name,
const struct ast_party_name ast_name 
) [static]

Definition at line 818 of file sig_pri.c.

References ast_copy_string(), ast_strlen_zero(), ast_to_pri_char_set(), ast_to_pri_presentation(), ast_party_name::char_set, ast_party_name::presentation, ast_party_name::str, and ast_party_name::valid.

Referenced by sig_pri_party_id_from_ast().

00819 {
00820    if (!ast_name->valid) {
00821       return;
00822    }
00823    pri_name->valid = 1;
00824    pri_name->presentation = ast_to_pri_presentation(ast_name->presentation);
00825    pri_name->char_set = ast_to_pri_char_set(ast_name->char_set);
00826    if (!ast_strlen_zero(ast_name->str)) {
00827       ast_copy_string(pri_name->str, ast_name->str, sizeof(pri_name->str));
00828    }
00829 }

static void sig_pri_party_number_convert ( struct ast_party_number ast_number,
const struct pri_party_number *  pri_number,
struct sig_pri_span pri 
) [static]

Definition at line 2051 of file sig_pri.c.

References apply_plan_to_existing_number(), AST_MAX_EXTENSION, ast_strdup, ast_party_number::plan, ast_party_number::presentation, pri_to_ast_presentation(), ast_party_number::str, and ast_party_number::valid.

Referenced by sig_pri_party_id_convert().

02052 {
02053    char number[AST_MAX_EXTENSION];
02054 
02055    apply_plan_to_existing_number(number, sizeof(number), pri, pri_number->str,
02056       pri_number->plan);
02057    ast_number->str = ast_strdup(number);
02058    ast_number->plan = pri_number->plan;
02059    ast_number->presentation = pri_to_ast_presentation(pri_number->presentation);
02060    ast_number->valid = 1;
02061 }

static void sig_pri_party_number_from_ast ( struct pri_party_number *  pri_number,
const struct ast_party_number ast_number 
) [static]

Definition at line 843 of file sig_pri.c.

References ast_copy_string(), ast_strlen_zero(), ast_to_pri_presentation(), ast_party_number::plan, ast_party_number::presentation, ast_party_number::str, and ast_party_number::valid.

Referenced by sig_pri_party_id_from_ast().

00844 {
00845    if (!ast_number->valid) {
00846       return;
00847    }
00848    pri_number->valid = 1;
00849    pri_number->presentation = ast_to_pri_presentation(ast_number->presentation);
00850    pri_number->plan = ast_number->plan;
00851    if (!ast_strlen_zero(ast_number->str)) {
00852       ast_copy_string(pri_number->str, ast_number->str, sizeof(pri_number->str));
00853    }
00854 }

static void sig_pri_party_subaddress_from_ast ( struct pri_party_subaddress *  pri_subaddress,
const struct ast_party_subaddress ast_subaddress 
) [static]

Definition at line 772 of file sig_pri.c.

References ast_copy_string(), ast_pri_pack_hex_string(), ast_strlen_zero(), ast_party_subaddress::str, ast_party_subaddress::type, and ast_party_subaddress::valid.

Referenced by sig_pri_call(), and sig_pri_party_id_from_ast().

00773 {
00774    if (ast_subaddress->valid && !ast_strlen_zero(ast_subaddress->str)) {
00775       pri_subaddress->type = ast_subaddress->type;
00776       if (!ast_subaddress->type) {
00777          /* 0 = NSAP */
00778          ast_copy_string((char *) pri_subaddress->data, ast_subaddress->str,
00779             sizeof(pri_subaddress->data));
00780          pri_subaddress->length = strlen((char *) pri_subaddress->data);
00781          pri_subaddress->odd_even_indicator = 0;
00782          pri_subaddress->valid = 1;
00783       } else {
00784          /* 2 = User Specified */
00785          /*
00786           * Copy HexString to packed HexData,
00787           * if odd length then right pad trailing byte with 0
00788           */
00789          int length = ast_pri_pack_hex_string(pri_subaddress->data,
00790             ast_subaddress->str, sizeof(pri_subaddress->data));
00791 
00792          pri_subaddress->length = length; /* packed data length */
00793 
00794          length = strlen(ast_subaddress->str);
00795          if (length > 2 * sizeof(pri_subaddress->data)) {
00796             pri_subaddress->odd_even_indicator = 0;
00797          } else {
00798             pri_subaddress->odd_even_indicator = (length & 1);
00799          }
00800          pri_subaddress->valid = 1;
00801       }
00802    }
00803 }

static int sig_pri_play_tone ( struct sig_pri_chan p,
enum sig_pri_tone  tone 
) [static]

Definition at line 934 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::play_tone.

Referenced by pri_ss_thread(), and sig_pri_indicate().

00935 {
00936    if (p->calls->play_tone)
00937       return p->calls->play_tone(p->chan_pvt, tone);
00938    else
00939       return -1;
00940 }

static void sig_pri_redirecting_convert ( struct ast_party_redirecting ast_redirecting,
const struct pri_party_redirecting *  pri_redirecting,
const struct ast_party_redirecting ast_guide,
struct sig_pri_span pri 
) [static]

Definition at line 2107 of file sig_pri.c.

References ast_party_redirecting_set_init(), ast_party_redirecting::count, ast_party_redirecting::from, pri_to_ast_reason(), ast_party_redirecting::reason, sig_pri_party_id_convert(), and ast_party_redirecting::to.

Referenced by sig_pri_handle_subcmds().

02111 {
02112    ast_party_redirecting_set_init(ast_redirecting, ast_guide);
02113 
02114    sig_pri_party_id_convert(&ast_redirecting->from, &pri_redirecting->from, pri);
02115    sig_pri_party_id_convert(&ast_redirecting->to, &pri_redirecting->to, pri);
02116    ast_redirecting->count = pri_redirecting->count;
02117    ast_redirecting->reason = pri_to_ast_reason(pri_redirecting->reason);
02118 }

static void sig_pri_redirecting_update ( struct sig_pri_chan pvt,
struct ast_channel ast 
) [static]

Definition at line 889 of file sig_pri.c.

References ast_to_pri_reason(), sig_pri_chan::call, ast_party_redirecting::count, ast_party_redirecting::from, sig_pri_span::pri, sig_pri_chan::pri, ast_party_redirecting::reason, ast_channel::redirecting, sig_pri_party_id_from_ast(), and ast_party_redirecting::to.

Referenced by sig_pri_call(), and sig_pri_indicate().

00890 {
00891    struct pri_party_redirecting pri_redirecting;
00892 
00893 /*! \todo XXX Original called data can be put in a channel data store that is inherited. */
00894 
00895    memset(&pri_redirecting, 0, sizeof(pri_redirecting));
00896    sig_pri_party_id_from_ast(&pri_redirecting.from, &ast->redirecting.from);
00897    sig_pri_party_id_from_ast(&pri_redirecting.to, &ast->redirecting.to);
00898    pri_redirecting.count = ast->redirecting.count;
00899    pri_redirecting.reason = ast_to_pri_reason(ast->redirecting.reason);
00900 
00901    pri_redirecting_update(pvt->pri->pri, pvt->call, &pri_redirecting);
00902 }

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 }

static void sig_pri_send_aoce_termination_request ( struct sig_pri_span pri,
int  chanpos,
unsigned int  ms 
) [static]

Definition at line 3761 of file sig_pri.c.

References ast_aoc_create(), ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), ast_aoc_encode(), AST_AOC_REQUEST, AST_AOC_REQUEST_E, ast_aoc_set_termination_request(), ast_channel_setwhentohangup_tv(), ast_channel_unlock, AST_CONTROL_AOC, ast_log(), ast_queue_control_data(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), LOG_DEBUG, ast_channel::name, sig_pri_chan::owner, sig_pri_span::pvts, sig_pri_lock_owner(), and sig_pri_chan::waiting_for_aoce.

03762 {
03763    struct sig_pri_chan *pvt;
03764    struct ast_aoc_decoded *decoded = NULL;
03765    struct ast_aoc_encoded *encoded = NULL;
03766    size_t encoded_size;
03767    struct timeval whentohangup = { 0, };
03768 
03769    sig_pri_lock_owner(pri, chanpos);
03770    pvt = pri->pvts[chanpos];
03771    if (!pvt->owner) {
03772       return;
03773    }
03774 
03775    if (!(decoded = ast_aoc_create(AST_AOC_REQUEST, 0, AST_AOC_REQUEST_E))) {
03776       ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
03777       goto cleanup_termination_request;
03778    }
03779 
03780    ast_aoc_set_termination_request(decoded);
03781 
03782    if (!(encoded = ast_aoc_encode(decoded, &encoded_size, pvt->owner))) {
03783       ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
03784       goto cleanup_termination_request;
03785    }
03786 
03787    /* convert ms to timeval */
03788    whentohangup.tv_usec = (ms % 1000) * 1000;
03789    whentohangup.tv_sec = ms / 1000;
03790 
03791    if (ast_queue_control_data(pvt->owner, AST_CONTROL_AOC, encoded, encoded_size)) {
03792       ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
03793       goto cleanup_termination_request;
03794    }
03795 
03796    pvt->waiting_for_aoce = 1;
03797    ast_channel_setwhentohangup_tv(pvt->owner, whentohangup);
03798    ast_log(LOG_DEBUG, "Delaying hangup on %s for aoc-e msg\n", pvt->owner->name);
03799 
03800 cleanup_termination_request:
03801    ast_channel_unlock(pvt->owner);
03802    ast_aoc_destroy_decoded(decoded);
03803    ast_aoc_destroy_encoded(encoded);
03804 }

static void sig_pri_send_mwi_indication ( struct sig_pri_span pri,
const char *  mbox_number,
const char *  mbox_context,
int  num_messages 
) [static]

Definition at line 7464 of file sig_pri.c.

References ast_copy_string(), ast_debug, ast_mutex_lock, ast_mutex_unlock, sig_pri_span::lock, and sig_pri_span::pri.

Referenced by sig_pri_mwi_cache_update(), and sig_pri_mwi_event_cb().

07465 {
07466    struct pri_party_id mailbox;
07467 
07468    ast_debug(1, "Send MWI indication for %s@%s num_messages:%d\n", mbox_number,
07469       mbox_context, num_messages);
07470 
07471    memset(&mailbox, 0, sizeof(mailbox));
07472    mailbox.number.valid = 1;
07473    mailbox.number.presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
07474    mailbox.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_UNKNOWN;
07475    ast_copy_string(mailbox.number.str, mbox_number, sizeof(mailbox.number.str));
07476 
07477    ast_mutex_lock(&pri->lock);
07478    pri_mwi_indicate(pri->pri, &mailbox, 1 /* speech */, num_messages, NULL, NULL, -1, 0);
07479    ast_mutex_unlock(&pri->lock);
07480 }

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 }

static void sig_pri_set_caller_id ( struct sig_pri_chan p  )  [static]

Definition at line 262 of file sig_pri.c.

References ast_party_caller::ani, ast_party_caller::ani2, ast_party_caller_init(), ast_strlen_zero(), sig_pri_chan::callingpres, sig_pri_chan::calls, sig_pri_chan::chan_pvt, sig_pri_chan::cid_ani, sig_pri_chan::cid_ani2, sig_pri_chan::cid_name, sig_pri_chan::cid_num, sig_pri_chan::cid_subaddr, sig_pri_chan::cid_ton, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, sig_pri_callback::set_callerid, ast_party_subaddress::str, ast_party_number::str, ast_party_name::str, ast_party_id::subaddress, ast_party_id::tag, sig_pri_chan::user_tag, ast_party_subaddress::valid, ast_party_number::valid, and ast_party_name::valid.

Referenced by sig_pri_handle_subcmds().

00263 {
00264    struct ast_party_caller caller;
00265 
00266    if (p->calls->set_callerid) {
00267       ast_party_caller_init(&caller);
00268 
00269       caller.id.name.str = p->cid_name;
00270       caller.id.name.presentation = p->callingpres;
00271       caller.id.name.valid = 1;
00272 
00273       caller.id.number.str = p->cid_num;
00274       caller.id.number.plan = p->cid_ton;
00275       caller.id.number.presentation = p->callingpres;
00276       caller.id.number.valid = 1;
00277 
00278       if (!ast_strlen_zero(p->cid_subaddr)) {
00279          caller.id.subaddress.valid = 1;
00280          //caller.id.subaddress.type = 0;/* nsap */
00281          //caller.id.subaddress.odd_even_indicator = 0;
00282          caller.id.subaddress.str = p->cid_subaddr;
00283       }
00284       caller.id.tag = p->user_tag;
00285 
00286       caller.ani.number.str = p->cid_ani;
00287       //caller.ani.number.plan = p->xxx;
00288       //caller.ani.number.presentation = p->xxx;
00289       caller.ani.number.valid = 1;
00290 
00291       caller.ani2 = p->cid_ani2;
00292       p->calls->set_callerid(p->chan_pvt, &caller);
00293    }
00294 }

static void sig_pri_set_dialing ( struct sig_pri_chan p,
int  is_dialing 
) [static]

Definition at line 164 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::set_dialing.

Referenced by sig_pri_answer(), sig_pri_call(), sig_pri_dial_complete(), sig_pri_hangup(), and sig_pri_indicate().

00165 {
00166    if (p->calls->set_dialing) {
00167       p->calls->set_dialing(p->chan_pvt, is_dialing);
00168    }
00169 }

static void sig_pri_set_digital ( struct sig_pri_chan p,
int  is_digital 
) [static]

Definition at line 171 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, sig_pri_chan::digital, and sig_pri_callback::set_digital.

Referenced by sig_pri_call(), sig_pri_hangup(), sig_pri_indicate(), and sig_pri_new_ast_channel().

00172 {
00173    p->digital = is_digital;
00174    if (p->calls->set_digital) {
00175       p->calls->set_digital(p->chan_pvt, is_digital);
00176    }
00177 }

static void sig_pri_set_dnid ( struct sig_pri_chan p,
const char *  dnid 
) [static]

Definition at line 306 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::set_dnid.

00307 {
00308    if (p->calls->set_dnid) {
00309       p->calls->set_dnid(p->chan_pvt, dnid);
00310    }
00311 }

static int sig_pri_set_echocanceller ( struct sig_pri_chan p,
int  enable 
) [static]

Definition at line 920 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::set_echocanceller.

Referenced by pri_ss_thread(), and sig_pri_dial_complete().

00921 {
00922    if (p->calls->set_echocanceller)
00923       return p->calls->set_echocanceller(p->chan_pvt, enable);
00924    else
00925       return -1;
00926 }

static void sig_pri_set_outgoing ( struct sig_pri_chan p,
int  is_outgoing 
) [static]

Definition at line 179 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, sig_pri_chan::outgoing, and sig_pri_callback::set_outgoing.

Referenced by sig_pri_call(), sig_pri_hangup(), and sig_pri_request().

00180 {
00181    p->outgoing = is_outgoing;
00182    if (p->calls->set_outgoing) {
00183       p->calls->set_outgoing(p->chan_pvt, is_outgoing);
00184    }
00185 }

static void sig_pri_set_rdnis ( struct sig_pri_chan p,
const char *  rdnis 
) [static]

Definition at line 323 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::set_rdnis.

00324 {
00325    if (p->calls->set_rdnis) {
00326       p->calls->set_rdnis(p->chan_pvt, rdnis);
00327    }
00328 }

static void sig_pri_set_subaddress ( struct ast_party_subaddress ast_subaddress,
const struct pri_party_subaddress *  pri_subaddress 
) [static]

Definition at line 650 of file sig_pri.c.

References ast_free, ast_malloc, ast_party_subaddress_init(), ast_strdup, len(), and ast_party_subaddress::str.

Referenced by sig_pri_party_id_convert().

00651 {
00652    char *cnum, *ptr;
00653    int x, len;
00654 
00655    if (ast_subaddress->str) {
00656       ast_free(ast_subaddress->str);
00657    }
00658    if (pri_subaddress->length <= 0) {
00659       ast_party_subaddress_init(ast_subaddress);
00660       return;
00661    }
00662 
00663    if (!pri_subaddress->type) {
00664       /* NSAP */
00665       ast_subaddress->str = ast_strdup((char *) pri_subaddress->data);
00666    } else {
00667       /* User Specified */
00668       if (!(cnum = ast_malloc(2 * pri_subaddress->length + 1))) {
00669          ast_party_subaddress_init(ast_subaddress);
00670          return;
00671       }
00672 
00673       ptr = cnum;
00674       len = pri_subaddress->length - 1; /* -1 account for zero based indexing */
00675       for (x = 0; x < len; ++x) {
00676          ptr += sprintf(ptr, "%02x", pri_subaddress->data[x]);
00677       }
00678 
00679       if (pri_subaddress->odd_even_indicator) {
00680          /* ODD */
00681          sprintf(ptr, "%01x", (pri_subaddress->data[len]) >> 4);
00682       } else {
00683          /* EVEN */
00684          sprintf(ptr, "%02x", pri_subaddress->data[len]);
00685       }
00686       ast_subaddress->str = cnum;
00687    }
00688    ast_subaddress->type = pri_subaddress->type;
00689    ast_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
00690    ast_subaddress->valid = 1;
00691 }

static void sig_pri_sort_pri_chans ( struct sig_pri_span pri  )  [static]

Definition at line 7620 of file sig_pri.c.

References sig_pri_span::numchans, sig_pri_chan::pri, sig_pri_span::pvts, and sig_pri_cmp_pri_chans().

Referenced by sig_pri_start_pri().

07621 {
07622    qsort(&pri->pvts, pri->numchans, sizeof(pri->pvts[0]), sig_pri_cmp_pri_chans);
07623 }

static void sig_pri_span_devstate_changed ( struct sig_pri_span pri  )  [static]

Definition at line 246 of file sig_pri.c.

References sig_pri_span::calls, and sig_pri_callback::update_span_devstate.

Referenced by pri_check_restart(), pri_dchannel(), pri_ss_thread(), sig_pri_chan_alarm_notify(), sig_pri_handle_hold(), sig_pri_handle_retrieve(), sig_pri_hangup(), sig_pri_kill_call(), and sig_pri_new_ast_channel().

00247 {
00248    if (pri->calls->update_span_devstate) {
00249       pri->calls->update_span_devstate(pri);
00250    }
00251 }

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 }

static void sig_pri_transfer_rsp ( void *  data,
int  is_successful 
) [static]

Definition at line 2294 of file sig_pri.c.

References xfer_rsp_data::call, xfer_rsp_data::invoke_id, sig_pri_span::pri, and xfer_rsp_data::pri.

Referenced by sig_pri_handle_subcmds().

02295 {
02296    struct xfer_rsp_data *rsp = data;
02297 
02298    pri_transfer_rsp(rsp->pri->pri, rsp->call, rsp->invoke_id, is_successful);
02299 }

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 }

static void sig_pri_unlock_private ( struct sig_pri_chan p  )  [static]

Definition at line 330 of file sig_pri.c.

References sig_pri_chan::calls, sig_pri_chan::chan_pvt, and sig_pri_callback::unlock_private.

Referenced by pri_dchannel(), pri_fixup_principle(), pri_grab(), pri_send_callrerouting_facility_exec(), pri_send_keypad_facility_exec(), pri_ss_thread(), sig_pri_attempt_transfer(), sig_pri_cli_show_channels(), sig_pri_handle_hold(), sig_pri_handle_retrieve(), sig_pri_handle_subcmds(), and sig_pri_kill_call().

00331 {
00332    if (p->calls->unlock_private)
00333       p->calls->unlock_private(p->chan_pvt);
00334 }


Variable Documentation

int pri_gendigittimeout = 8000 [static]

Definition at line 106 of file sig_pri.c.

Referenced by pri_ss_thread().

int pri_matchdigittimeout = 3000 [static]

Definition at line 104 of file sig_pri.c.

Referenced by pri_ss_thread().

struct ast_app_option sig_pri_call_opts[128] = { [ 'K' ] = { .flag = OPT_KEYPAD , .arg_index = OPT_ARG_KEYPAD + 1 }, [ 'R' ] = { .flag = OPT_REVERSE_CHARGE }, [ 'A' ] = { .flag = OPT_AOC_REQUEST , .arg_index = OPT_ARG_AOC_REQUEST + 1 }, } [static]

Definition at line 6561 of file sig_pri.c.

Referenced by sig_pri_call().

struct ao2_container* sig_pri_cc_monitors [static]

Container of sig_pri monitor instances.

Definition at line 101 of file sig_pri.c.

Referenced by sig_pri_cc_available(), sig_pri_cc_monitor_destructor(), sig_pri_cc_monitor_instance_init(), sig_pri_find_cc_monitor_by_cc_id(), sig_pri_load(), and sig_pri_unload().

const char* sig_pri_cc_type_name [static]

Upper level agent/monitor type name.

Definition at line 99 of file sig_pri.c.

Referenced by sig_pri_call(), sig_pri_cc_agent_req_rsp(), sig_pri_cc_available(), sig_pri_cc_link_canceled(), sig_pri_find_cc_agent_by_cc_id(), sig_pri_handle_cis_subcmds(), sig_pri_handle_subcmds(), sig_pri_load(), and sig_pri_start_pri().


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