Sat Mar 10 01:55:46 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_DEADLOCK_AVOIDANCE(p)
#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)
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_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_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 116 of file sig_pri.c.

Referenced by pri_is_up().

#define DCHAN_NOTINALARM   (1 << 0)

Definition at line 105 of file sig_pri.c.

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

#define DCHAN_UP   (1 << 1)

Definition at line 106 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 72 of file sig_pri.c.

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

Definition at line 109 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 112 of file sig_pri.c.

Referenced by sig_pri_is_cis_call().

#define PRI_DEADLOCK_AVOIDANCE (  ) 

Value:

do { \
      sig_pri_unlock_private(p); \
      usleep(1); \
      sig_pri_lock_private(p); \
   } while (0)

Definition at line 118 of file sig_pri.c.

Referenced by pri_grab().

#define PRI_EXPLICIT   (1 << 16)

Definition at line 111 of file sig_pri.c.

Referenced by PVT_TO_CHANNEL().

#define PRI_HELD_CALL   (1 << 18)

Definition at line 113 of file sig_pri.c.

Referenced by pri_find_principle(), and sig_pri_handle_retrieve().

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

Definition at line 110 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 7726 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 7727 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 2278 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 6456 of file sig_pri.c.

06456                            {
06457    OPT_ARG_KEYPAD = 0,
06458    OPT_ARG_AOC_REQUEST,
06459 
06460    /* note: this entry _MUST_ be the last one in the enum */
06461    OPT_ARG_ARRAY_SIZE,
06462 };

enum SIG_PRI_CALL_OPT_FLAGS

Enumerator:
OPT_KEYPAD 
OPT_REVERSE_CHARGE 
OPT_AOC_REQUEST 

Definition at line 6451 of file sig_pri.c.

06451                             {
06452    OPT_KEYPAD =         (1 << 0),
06453    OPT_REVERSE_CHARGE = (1 << 1),   /* Collect call */
06454    OPT_AOC_REQUEST =    (1 << 2),   /* AOC Request */
06455 };


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 1629 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().

01630 {
01631    /* Make sure a number exists so the prefix isn't placed on an empty string. */
01632    if (ast_strlen_zero(number)) {
01633       if (size) {
01634          *buf = '\0';
01635       }
01636       return;
01637    }
01638    apply_plan_to_number(buf, size, pri, number, plan);
01639 }

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 1593 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().

01594 {
01595    switch (plan) {
01596    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
01597       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
01598       break;
01599    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
01600       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
01601       break;
01602    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
01603       snprintf(buf, size, "%s%s", pri->localprefix, number);
01604       break;
01605    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
01606       snprintf(buf, size, "%s%s", pri->privateprefix, number);
01607       break;
01608    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
01609       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
01610       break;
01611    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
01612       snprintf(buf, size, "%s", number);
01613       break;
01614    }
01615 }

static unsigned char ast_pri_pack_hex_char ( char  c  )  [static]

Definition at line 664 of file sig_pri.c.

Referenced by ast_pri_pack_hex_string().

00665 {
00666    unsigned char res;
00667 
00668    if (c < '0') {
00669       res = 0;
00670    } else if (c < ('9' + 1)) {
00671       res = c - '0';
00672    } else if (c < 'A') {
00673       res = 0;
00674    } else if (c < ('F' + 1)) {
00675       res = c - 'A' + 10;
00676    } else if (c < 'a') {
00677       res = 0;
00678    } else if (c < ('f' + 1)) {
00679       res = c - 'a' + 10;
00680    } else {
00681       res = 0;
00682    }
00683    return res;
00684 }

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

Definition at line 703 of file sig_pri.c.

References ast_pri_pack_hex_char(), and len().

Referenced by sig_pri_party_subaddress_from_ast().

00704 {
00705    int res = 0;
00706    int len = strlen(src);
00707 
00708    if (len > (2 * maxlen)) {
00709       len = 2 * maxlen;
00710    }
00711 
00712    res = len / 2 + len % 2;
00713 
00714    while (len > 1) {
00715       *dst = ast_pri_pack_hex_char(*src) << 4;
00716       src++;
00717       *dst |= ast_pri_pack_hex_char(*src);
00718       dst++, src++;
00719       len -= 2;
00720    }
00721    if (len) { /* 1 left */
00722       *dst = ast_pri_pack_hex_char(*src) << 4;
00723    }
00724    return res;
00725 }

static int ast_to_pri_char_set ( enum AST_PARTY_CHAR_SET  ast_char_set  )  [static]

Definition at line 566 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().

00567 {
00568    int pri_char_set;
00569 
00570    switch (ast_char_set) {
00571    default:
00572    case AST_PARTY_CHAR_SET_UNKNOWN:
00573       pri_char_set = PRI_CHAR_SET_UNKNOWN;
00574       break;
00575    case AST_PARTY_CHAR_SET_ISO8859_1:
00576       pri_char_set = PRI_CHAR_SET_ISO8859_1;
00577       break;
00578    case AST_PARTY_CHAR_SET_WITHDRAWN:
00579       pri_char_set = PRI_CHAR_SET_WITHDRAWN;
00580       break;
00581    case AST_PARTY_CHAR_SET_ISO8859_2:
00582       pri_char_set = PRI_CHAR_SET_ISO8859_2;
00583       break;
00584    case AST_PARTY_CHAR_SET_ISO8859_3:
00585       pri_char_set = PRI_CHAR_SET_ISO8859_3;
00586       break;
00587    case AST_PARTY_CHAR_SET_ISO8859_4:
00588       pri_char_set = PRI_CHAR_SET_ISO8859_4;
00589       break;
00590    case AST_PARTY_CHAR_SET_ISO8859_5:
00591       pri_char_set = PRI_CHAR_SET_ISO8859_5;
00592       break;
00593    case AST_PARTY_CHAR_SET_ISO8859_7:
00594       pri_char_set = PRI_CHAR_SET_ISO8859_7;
00595       break;
00596    case AST_PARTY_CHAR_SET_ISO10646_BMPSTRING:
00597       pri_char_set = PRI_CHAR_SET_ISO10646_BMPSTRING;
00598       break;
00599    case AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING:
00600       pri_char_set = PRI_CHAR_SET_ISO10646_UTF_8STRING;
00601       break;
00602    }
00603 
00604    return pri_char_set;
00605 }

static int ast_to_pri_presentation ( int  ast_presentation  )  [static]

Definition at line 467 of file sig_pri.c.

References AST_PRES_ALLOWED_NETWORK_NUMBER, AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_PROHIB_NETWORK_NUMBER, AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, and AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN.

Referenced by sig_pri_party_name_from_ast(), and sig_pri_party_number_from_ast().

00468 {
00469    int pri_presentation;
00470 
00471    switch (ast_presentation) {
00472    case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
00473       pri_presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
00474       break;
00475    case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
00476       pri_presentation = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
00477       break;
00478    case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
00479       pri_presentation = PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN;
00480       break;
00481    case AST_PRES_ALLOWED_NETWORK_NUMBER:
00482       pri_presentation = PRES_ALLOWED_NETWORK_NUMBER;
00483       break;
00484    case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
00485       pri_presentation = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
00486       break;
00487    case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
00488       pri_presentation = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
00489       break;
00490    case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
00491       pri_presentation = PRES_PROHIB_USER_NUMBER_FAILED_SCREEN;
00492       break;
00493    case AST_PRES_PROHIB_NETWORK_NUMBER:
00494       pri_presentation = PRES_PROHIB_NETWORK_NUMBER;
00495       break;
00496    case AST_PRES_NUMBER_NOT_AVAILABLE:
00497       pri_presentation = PRES_NUMBER_NOT_AVAILABLE;
00498       break;
00499    default:
00500       pri_presentation = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
00501       break;
00502    }
00503 
00504    return pri_presentation;
00505 }

static int ast_to_pri_reason ( enum AST_REDIRECTING_REASON  ast_reason  )  [static]

Definition at line 383 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().

00384 {
00385    int pri_reason;
00386 
00387    switch (ast_reason) {
00388    case AST_REDIRECTING_REASON_USER_BUSY:
00389       pri_reason = PRI_REDIR_FORWARD_ON_BUSY;
00390       break;
00391    case AST_REDIRECTING_REASON_NO_ANSWER:
00392       pri_reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
00393       break;
00394    case AST_REDIRECTING_REASON_UNCONDITIONAL:
00395       pri_reason = PRI_REDIR_UNCONDITIONAL;
00396       break;
00397    case AST_REDIRECTING_REASON_DEFLECTION:
00398       pri_reason = PRI_REDIR_DEFLECTION;
00399       break;
00400    case AST_REDIRECTING_REASON_UNKNOWN:
00401    default:
00402       pri_reason = PRI_REDIR_UNKNOWN;
00403       break;
00404    }
00405 
00406    return pri_reason;
00407 }

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

Definition at line 7775 of file sig_pri.c.

References DCHAN_NOTINALARM.

Referenced by sig_pri_cli_show_span(), and sig_pri_cli_show_spans().

07776 {
07777    if (!s || len < 1) {
07778       return;
07779    }
07780    s[0] = '\0';
07781    if (!(status & DCHAN_NOTINALARM))
07782       strncat(s, "In Alarm, ", len - strlen(s) - 1);
07783    if (status & DCHAN_UP)
07784       strncat(s, "Up", len - strlen(s) - 1);
07785    else
07786       strncat(s, "Down", len - strlen(s) - 1);
07787    if (active)
07788       strncat(s, ", Active", len - strlen(s) - 1);
07789    else
07790       strncat(s, ", Standby", len - strlen(s) - 1);
07791    s[len - 1] = '\0';
07792 }

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

Definition at line 4023 of file sig_pri.c.

04024 {
04025    int i;
04026 
04027    if (!subcmds) {
04028       return 0;
04029    }
04030    for (i = 0; i < subcmds->counter_subcmd; ++i) {
04031       const struct pri_subcommand *subcmd = &subcmds->subcmd[i];
04032       if (subcmd->cmd == PRI_SUBCMD_AOC_E) {
04033          return 1;
04034       }
04035    }
04036    return 0;
04037 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 1573 of file sig_pri.c.

Referenced by sig_pri_call().

01574 {
01575    if (dialplan == -1) {
01576       return("Dynamically set dialplan in ISDN");
01577    }
01578    return (pri_plan2str(dialplan));
01579 }

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

Definition at line 1793 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().

01794 {
01795    struct sig_pri_chan *pvt = v_pvt;
01796    struct ast_channel *chan = pvt->owner;
01797    struct ast_frame *f;
01798    char ex[80];
01799    /* Wait up to 30 seconds for an answer */
01800    int newms, ms = 30000;
01801 
01802    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
01803    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
01804    if (ast_call(chan, ex, 0)) {
01805       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
01806       ast_hangup(chan);
01807       return NULL;
01808    }
01809    while ((newms = ast_waitfor(chan, ms)) > 0) {
01810       f = ast_read(chan);
01811       if (!f) {
01812          /* Got hangup */
01813          break;
01814       }
01815       if (f->frametype == AST_FRAME_CONTROL) {
01816          switch (f->subclass.integer) {
01817          case AST_CONTROL_ANSWER:
01818             /* Launch the PBX */
01819             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
01820             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
01821             chan->priority = 1;
01822             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
01823             ast_pbx_run(chan);
01824             /* It's already hungup, return immediately */
01825             return NULL;
01826          case AST_CONTROL_BUSY:
01827             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
01828             break;
01829          case AST_CONTROL_CONGESTION:
01830             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
01831             break;
01832          };
01833       }
01834       ast_frfree(f);
01835       ms = newms;
01836    }
01837    /* Hangup the channel since nothing happend */
01838    ast_hangup(chan);
01839    return NULL;
01840 }

static int pri_active_dchan_index ( struct sig_pri_span pri  )  [static]

Definition at line 1022 of file sig_pri.c.

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

01023 {
01024    int x;
01025 
01026    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
01027       if ((pri->dchans[x] == pri->pri))
01028          return x;
01029    }
01030 
01031    ast_log(LOG_WARNING, "No active dchan found!\n");
01032    return -1;
01033 }

static void pri_check_restart ( struct sig_pri_span pri  )  [static]

Definition at line 1651 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_span_devstate_changed(), sig_pri_span::span, SRVST_FAREND, and SRVST_NEAREND.

Referenced by pri_dchannel().

01652 {
01653 #if defined(HAVE_PRI_SERVICE_MESSAGES)
01654    unsigned why;
01655 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
01656 
01657    for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
01658       if (!pri->pvts[pri->resetpos]
01659          || pri->pvts[pri->resetpos]->no_b_channel
01660          || sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
01661          continue;
01662       }
01663 #if defined(HAVE_PRI_SERVICE_MESSAGES)
01664       why = pri->pvts[pri->resetpos]->service_status;
01665       if (why) {
01666          ast_log(LOG_NOTICE,
01667             "Span %d: channel %d out-of-service (reason: %s), not sending RESTART\n",
01668             pri->span, pri->pvts[pri->resetpos]->channel,
01669             (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
01670          continue;
01671       }
01672 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
01673       break;
01674    }
01675    if (pri->resetpos < pri->numchans) {
01676       /* Mark the channel as resetting and restart it */
01677       pri->pvts[pri->resetpos]->resetting = 1;
01678       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
01679    } else {
01680       pri->resetting = 0;
01681       time(&pri->lastreset);
01682       sig_pri_span_devstate_changed(pri);
01683    }
01684 }

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

Definition at line 4550 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.

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

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

Definition at line 1967 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().

01968 {
01969    pri->dchanavail[index] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
01970    if (!before_start_pri) {
01971       pri_find_dchan(pri);
01972    }
01973 }

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

Definition at line 1975 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().

01976 {
01977    pri->dchanavail[index] |= DCHAN_NOTINALARM;
01978    if (!before_start_pri)
01979       pri_restart(pri->dchans[index]);
01980 }

static void pri_find_dchan ( struct sig_pri_span pri  )  [static]

Definition at line 1035 of file sig_pri.c.

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

Referenced by pri_event_alarm().

01036 {
01037    struct pri *old;
01038    int oldslot = -1;
01039    int newslot = -1;
01040    int idx;
01041 
01042    old = pri->pri;
01043    for (idx = 0; idx < SIG_PRI_NUM_DCHANS; ++idx) {
01044       if (!pri->dchans[idx]) {
01045          /* No more D channels defined on the span. */
01046          break;
01047       }
01048       if (pri->dchans[idx] == old) {
01049          oldslot = idx;
01050       }
01051       if (newslot < 0 && pri->dchanavail[idx] == DCHAN_AVAILABLE) {
01052          newslot = idx;
01053       }
01054    }
01055    /* At this point, idx is a count of how many D-channels are defined on the span. */
01056 
01057    if (1 < idx) {
01058       /* We have several D-channels defined on the span.  (NFAS PRI setup) */
01059       if (newslot < 0) {
01060          /* No D-channels available.  Default to the primary D-channel. */
01061          newslot = 0;
01062 
01063          if (!pri->no_d_channels) {
01064             pri->no_d_channels = 1;
01065             if (old && oldslot != newslot) {
01066                ast_log(LOG_WARNING,
01067                   "Span %d: No D-channels up!  Switching selected D-channel from %s to %s.\n",
01068                   pri->span, pri_order(oldslot), pri_order(newslot));
01069             } else {
01070                ast_log(LOG_WARNING, "Span %d: No D-channels up!\n", pri->span);
01071             }
01072          }
01073       } else {
01074          pri->no_d_channels = 0;
01075       }
01076       if (old && oldslot != newslot) {
01077          ast_log(LOG_NOTICE,
01078             "Switching selected D-channel from %s (fd %d) to %s (fd %d)!\n",
01079             pri_order(oldslot), pri->fds[oldslot],
01080             pri_order(newslot), pri->fds[newslot]);
01081       }
01082    } else {
01083       if (newslot < 0) {
01084          /* The only D-channel is not up. */
01085          newslot = 0;
01086 
01087          if (!pri->no_d_channels) {
01088             pri->no_d_channels = 1;
01089 
01090             /*
01091              * This is annoying to see on non-persistent layer 2
01092              * connections.  Let's not complain in that case.
01093              */
01094             if (pri->sig != SIG_BRI_PTMP) {
01095                ast_log(LOG_WARNING, "Span %d: D-channel is down!\n", pri->span);
01096             }
01097          }
01098       } else {
01099          pri->no_d_channels = 0;
01100       }
01101    }
01102    pri->pri = pri->dchans[newslot];
01103 }

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

Definition at line 1730 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().

01731 {
01732    int x;
01733    if (backwards)
01734       x = pri->numchans;
01735    else
01736       x = 0;
01737    for (;;) {
01738       if (backwards && (x < 0))
01739          break;
01740       if (!backwards && (x >= pri->numchans))
01741          break;
01742       if (pri->pvts[x]
01743          && !pri->pvts[x]->no_b_channel
01744          && sig_pri_is_chan_available(pri->pvts[x])) {
01745          ast_debug(1, "Found empty available channel %d/%d\n",
01746             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
01747          return x;
01748       }
01749       if (backwards)
01750          x--;
01751       else
01752          x++;
01753    }
01754    return -1;
01755 }

static int pri_find_empty_nobch ( struct sig_pri_span pri  )  [static]

Definition at line 1770 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().

01771 {
01772    int idx;
01773 
01774    for (idx = 0; idx < pri->numchans; ++idx) {
01775       if (pri->pvts[idx]
01776          && pri->pvts[idx]->no_b_channel
01777          && sig_pri_is_chan_available(pri->pvts[idx])) {
01778          ast_debug(1, "Found empty available no B channel interface\n");
01779          return idx;
01780       }
01781    }
01782 
01783    /* Need to create a new interface. */
01784    if (pri->calls->new_nobch_intf) {
01785       idx = pri->calls->new_nobch_intf(pri);
01786    } else {
01787       idx = -1;
01788    }
01789    return idx;
01790 }

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

Definition at line 1529 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.

01530 {
01531    int chanpos;
01532 
01533    chanpos = pri_find_principle(pri, channel, call);
01534    if (chanpos < 0) {
01535       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
01536          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
01537       sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
01538       return -1;
01539    }
01540    chanpos = pri_fixup_principle(pri, chanpos, call);
01541    if (chanpos < 0) {
01542       ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
01543          pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
01544       /*
01545        * Using Q.931 section 5.2.3.1 b) as the reason for picking
01546        * PRI_CAUSE_CHANNEL_UNACCEPTABLE.  Receiving a
01547        * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
01548        * that channel (which is not specified by Q.931) and kill some
01549        * other call which would be bad.
01550        */
01551       sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
01552       return -1;
01553    }
01554    return chanpos;
01555 }

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

Definition at line 1296 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().

01297 {
01298    int x;
01299    int span;
01300    int principle;
01301    int prioffset;
01302 
01303    if (channel < 0) {
01304       /* Channel is not picked yet. */
01305       return -1;
01306    }
01307 
01308    prioffset = PRI_CHANNEL(channel);
01309    if (!prioffset || (channel & PRI_HELD_CALL)) {
01310       if (!call) {
01311          /* Cannot find a call waiting call or held call without a call. */
01312          return -1;
01313       }
01314       principle = -1;
01315       for (x = 0; x < pri->numchans; ++x) {
01316          if (pri->pvts[x]
01317             && pri->pvts[x]->call == call) {
01318             principle = x;
01319             break;
01320          }
01321       }
01322       return principle;
01323    }
01324 
01325    span = PRI_SPAN(channel);
01326    if (!(channel & PRI_EXPLICIT)) {
01327       int index;
01328 
01329       index = pri_active_dchan_index(pri);
01330       if (index == -1) {
01331          return -1;
01332       }
01333       span = pri->dchan_logical_span[index];
01334    }
01335 
01336    principle = -1;
01337    for (x = 0; x < pri->numchans; x++) {
01338       if (pri->pvts[x]
01339          && pri->pvts[x]->prioffset == prioffset
01340          && pri->pvts[x]->logicalspan == span
01341          && !pri->pvts[x]->no_b_channel) {
01342          principle = x;
01343          break;
01344       }
01345    }
01346 
01347    return principle;
01348 }

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

Definition at line 1231 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().

01232 {
01233    int idx;
01234 
01235    if (!call) {
01236       /* Cannot find a call without a call. */
01237       return -1;
01238    }
01239    for (idx = 0; idx < pri->numchans; ++idx) {
01240       if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
01241          /* Found the principle */
01242          return idx;
01243       }
01244    }
01245    return -1;
01246 }

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

Definition at line 1363 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().

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

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

Definition at line 324 of file sig_pri.c.

References ast_mutex_trylock, sig_pri_span::lock, sig_pri_span::master, and PRI_DEADLOCK_AVOIDANCE.

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().

00325 {
00326    int res;
00327    /* Grab the lock first */
00328    do {
00329       res = ast_mutex_trylock(&pri->lock);
00330       if (res) {
00331          PRI_DEADLOCK_AVOIDANCE(p);
00332       }
00333    } while (res);
00334    /* Then break the poll */
00335    pthread_kill(pri->master, SIGURG);
00336    return 0;
00337 }

int pri_is_up ( struct sig_pri_span pri  ) 

Definition at line 995 of file sig_pri.c.

References DCHAN_AVAILABLE, sig_pri_span::dchanavail, and SIG_PRI_NUM_DCHANS.

Referenced by pri_dchannel().

00996 {
00997    int x;
00998    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
00999       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
01000          return 1;
01001    }
01002    return 0;
01003 }

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

Definition at line 7877 of file sig_pri.c.

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

07878 {
07879    int channel = PVT_TO_CHANNEL(p);
07880    int span = PRI_SPAN(channel);
07881 
07882    return pri_maintenance_service(pri, span, channel, changestatus);
07883 }

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

Definition at line 1005 of file sig_pri.c.

Referenced by pri_dchannel(), and sig_pri_cli_show_span().

01006 {
01007    switch (level) {
01008    case 0:
01009       return "Primary";
01010    case 1:
01011       return "Secondary";
01012    case 2:
01013       return "Tertiary";
01014    case 3:
01015       return "Quaternary";
01016    default:
01017       return "<Unknown>";
01018    }
01019 }

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

Definition at line 1205 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().

01206 {
01207    struct ast_frame f = {AST_FRAME_CONTROL, };
01208    struct sig_pri_chan *p = pri->pvts[chanpos];
01209 
01210    if (p->calls->queue_control) {
01211       p->calls->queue_control(p->chan_pvt, subclass);
01212    }
01213 
01214    f.subclass.integer = subclass;
01215    pri_queue_frame(pri, chanpos, &f);
01216 }

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

Definition at line 1182 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().

01183 {
01184    sig_pri_lock_owner(pri, chanpos);
01185    if (pri->pvts[chanpos]->owner) {
01186       ast_queue_frame(pri->pvts[chanpos]->owner, frame);
01187       ast_channel_unlock(pri->pvts[chanpos]->owner);
01188    }
01189 }

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

Definition at line 146 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().

00147 {
00148    ast_mutex_unlock(&pri->lock);
00149 }

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 7855 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().

07856 {
07857    int res = -1;
07858 
07859    sig_pri_lock_private(p);
07860 
07861    if (!p->pri || !p->call) {
07862       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
07863       sig_pri_unlock_private(p);
07864       return -1;
07865    }
07866 
07867    pri_grab(p, p->pri);
07868    res = pri_callrerouting_facility(p->pri->pri, p->call, destination, original, reason);
07869    pri_rel(p->pri);
07870 
07871    sig_pri_unlock_private(p);
07872 
07873    return res;
07874 }

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

Definition at line 7836 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().

07837 {
07838    sig_pri_lock_private(p);
07839 
07840    if (!p->pri || !p->call) {
07841       ast_debug(1, "Unable to find pri or call on channel!\n");
07842       sig_pri_unlock_private(p);
07843       return -1;
07844    }
07845 
07846    pri_grab(p, p->pri);
07847    pri_keypad_facility(p->pri->pri, p->call, digits);
07848    pri_rel(p->pri);
07849 
07850    sig_pri_unlock_private(p);
07851 
07852    return 0;
07853 }

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

Definition at line 1842 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.

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

static enum AST_PARTY_CHAR_SET pri_to_ast_char_set ( int  pri_char_set  )  [static]

Definition at line 516 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().

00517 {
00518    enum AST_PARTY_CHAR_SET ast_char_set;
00519 
00520    switch (pri_char_set) {
00521    default:
00522    case PRI_CHAR_SET_UNKNOWN:
00523       ast_char_set = AST_PARTY_CHAR_SET_UNKNOWN;
00524       break;
00525    case PRI_CHAR_SET_ISO8859_1:
00526       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_1;
00527       break;
00528    case PRI_CHAR_SET_WITHDRAWN:
00529       ast_char_set = AST_PARTY_CHAR_SET_WITHDRAWN;
00530       break;
00531    case PRI_CHAR_SET_ISO8859_2:
00532       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_2;
00533       break;
00534    case PRI_CHAR_SET_ISO8859_3:
00535       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_3;
00536       break;
00537    case PRI_CHAR_SET_ISO8859_4:
00538       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_4;
00539       break;
00540    case PRI_CHAR_SET_ISO8859_5:
00541       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_5;
00542       break;
00543    case PRI_CHAR_SET_ISO8859_7:
00544       ast_char_set = AST_PARTY_CHAR_SET_ISO8859_7;
00545       break;
00546    case PRI_CHAR_SET_ISO10646_BMPSTRING:
00547       ast_char_set = AST_PARTY_CHAR_SET_ISO10646_BMPSTRING;
00548       break;
00549    case PRI_CHAR_SET_ISO10646_UTF_8STRING:
00550       ast_char_set = AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING;
00551       break;
00552    }
00553 
00554    return ast_char_set;
00555 }

static int pri_to_ast_presentation ( int  pri_presentation  )  [static]

Definition at line 418 of file sig_pri.c.

References AST_PRES_ALLOWED_NETWORK_NUMBER, AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_PROHIB_NETWORK_NUMBER, AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED, and AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN.

Referenced by sig_pri_party_name_convert(), and sig_pri_party_number_convert().

00419 {
00420    int ast_presentation;
00421 
00422    switch (pri_presentation) {
00423    case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
00424       ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
00425       break;
00426    case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
00427       ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
00428       break;
00429    case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
00430       ast_presentation = AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN;
00431       break;
00432    case PRES_ALLOWED_NETWORK_NUMBER:
00433       ast_presentation = AST_PRES_ALLOWED_NETWORK_NUMBER;
00434       break;
00435    case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
00436       ast_presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
00437       break;
00438    case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
00439       ast_presentation = AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
00440       break;
00441    case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
00442       ast_presentation = AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN;
00443       break;
00444    case PRES_PROHIB_NETWORK_NUMBER:
00445       ast_presentation = AST_PRES_PROHIB_NETWORK_NUMBER;
00446       break;
00447    case PRES_NUMBER_NOT_AVAILABLE:
00448       ast_presentation = AST_PRES_NUMBER_NOT_AVAILABLE;
00449       break;
00450    default:
00451       ast_presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
00452       break;
00453    }
00454 
00455    return ast_presentation;
00456 }

static enum AST_REDIRECTING_REASON pri_to_ast_reason ( int  pri_reason  )  [static]

Definition at line 348 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().

00349 {
00350    enum AST_REDIRECTING_REASON ast_reason;
00351 
00352    switch (pri_reason) {
00353    case PRI_REDIR_FORWARD_ON_BUSY:
00354       ast_reason = AST_REDIRECTING_REASON_USER_BUSY;
00355       break;
00356    case PRI_REDIR_FORWARD_ON_NO_REPLY:
00357       ast_reason = AST_REDIRECTING_REASON_NO_ANSWER;
00358       break;
00359    case PRI_REDIR_DEFLECTION:
00360       ast_reason = AST_REDIRECTING_REASON_DEFLECTION;
00361       break;
00362    case PRI_REDIR_UNCONDITIONAL:
00363       ast_reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
00364       break;
00365    case PRI_REDIR_UNKNOWN:
00366    default:
00367       ast_reason = AST_REDIRECTING_REASON_UNKNOWN;
00368       break;
00369    }
00370 
00371    return ast_reason;
00372 }

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

Definition at line 151 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().

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

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 1557 of file sig_pri.c.

01558 {
01559    switch (redirectingreason) {
01560    case 0:
01561       return "UNKNOWN";
01562    case 1:
01563       return "BUSY";
01564    case 2:
01565       return "NO_REPLY";
01566    case 0xF:
01567       return "UNCONDITIONAL";
01568    default:
01569       return "NOREDIRECT";
01570    }
01571 }

static void sig_pri_ami_channel_event ( struct sig_pri_chan p  )  [static]

Definition at line 974 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().

00975 {
00976    if (p->calls->ami_channel_event) {
00977       p->calls->ami_channel_event(p->chan_pvt, p->owner);
00978    }
00979 }

int sig_pri_answer ( struct sig_pri_chan p,
struct ast_channel ast 
)

Definition at line 7131 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().

07132 {
07133    int res;
07134 
07135    /* Send a pri acknowledge */
07136    pri_grab(p, p->pri);
07137 #if defined(HAVE_PRI_AOC_EVENTS)
07138    if (p->aoc_s_request_invoke_id_valid) {
07139       /* if AOC-S was requested and the invoke id is still present on answer.  That means
07140        * no AOC-S rate list was provided, so send a NULL response which will indicate that
07141        * AOC-S is not available */
07142       pri_aoc_s_request_response_send(p->pri->pri, p->call,
07143          p->aoc_s_request_invoke_id, NULL);
07144       p->aoc_s_request_invoke_id_valid = 0;
07145    }
07146 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
07147    if (p->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
07148       p->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
07149    }
07150    sig_pri_set_dialing(p, 0);
07151    sig_pri_open_media(p);
07152    res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
07153    pri_rel(p->pri);
07154    ast_setstate(ast, AST_STATE_UP);
07155    return res;
07156 }

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

Definition at line 2871 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().

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

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

Definition at line 2839 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().

02840 {
02841    switch (value) {
02842    case AST_AOC_CHARGED_ITEM_NA:
02843       return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
02844    case AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
02845       return PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
02846    case AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
02847       return PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
02848    case AST_AOC_CHARGED_ITEM_CALL_ATTEMPT:
02849       return PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT;
02850    case AST_AOC_CHARGED_ITEM_CALL_SETUP:
02851       return PRI_AOC_CHARGED_ITEM_CALL_SETUP;
02852    case AST_AOC_CHARGED_ITEM_USER_USER_INFO:
02853       return PRI_AOC_CHARGED_ITEM_USER_USER_INFO;
02854    case AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
02855       return PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
02856    }
02857    return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
02858 }

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

Definition at line 3527 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().

03528 {
03529    struct pri_subcmd_aoc_d aoc_d = { 0, };
03530 
03531    aoc_d.billing_accumulation = (ast_aoc_get_total_type(decoded) == AST_AOC_TOTAL) ? 1 : 0;
03532 
03533    switch (ast_aoc_get_billing_id(decoded)) {
03534    case AST_AOC_BILLING_NORMAL:
03535       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_NORMAL;
03536       break;
03537    case AST_AOC_BILLING_REVERSE_CHARGE:
03538       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_REVERSE;
03539       break;
03540    case AST_AOC_BILLING_CREDIT_CARD:
03541       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_CREDIT_CARD;
03542       break;
03543    case AST_AOC_BILLING_NA:
03544    default:
03545       aoc_d.billing_id = PRI_AOC_D_BILLING_ID_NOT_AVAILABLE;
03546       break;
03547    }
03548 
03549    switch (ast_aoc_get_charge_type(decoded)) {
03550    case AST_AOC_CHARGE_FREE:
03551       aoc_d.charge = PRI_AOC_DE_CHARGE_FREE;
03552       break;
03553    case AST_AOC_CHARGE_CURRENCY:
03554       {
03555          const char *currency_name = ast_aoc_get_currency_name(decoded);
03556          aoc_d.charge = PRI_AOC_DE_CHARGE_CURRENCY;
03557          aoc_d.recorded.money.amount.cost = ast_aoc_get_currency_amount(decoded);
03558          aoc_d.recorded.money.amount.multiplier = sig_pri_aoc_multiplier_from_ast(ast_aoc_get_currency_multiplier(decoded));
03559          if (!ast_strlen_zero(currency_name)) {
03560             ast_copy_string(aoc_d.recorded.money.currency, currency_name, sizeof(aoc_d.recorded.money.currency));
03561          }
03562       }
03563       break;
03564    case AST_AOC_CHARGE_UNIT:
03565       {
03566          const struct ast_aoc_unit_entry *entry;
03567          int i;
03568          aoc_d.charge = PRI_AOC_DE_CHARGE_UNITS;
03569          for (i = 0; i < ast_aoc_get_unit_count(decoded); i++) {
03570             if ((entry = ast_aoc_get_unit_info(decoded, i)) && i < ARRAY_LEN(aoc_d.recorded.unit.item)) {
03571                if (entry->valid_amount) {
03572                   aoc_d.recorded.unit.item[i].number = entry->amount;
03573                } else {
03574                   aoc_d.recorded.unit.item[i].number = -1;
03575                }
03576                if (entry->valid_type) {
03577                   aoc_d.recorded.unit.item[i].type = entry->type;
03578                } else {
03579                   aoc_d.recorded.unit.item[i].type = -1;
03580                }
03581                aoc_d.recorded.unit.num_items++;
03582             } else {
03583                break;
03584             }
03585          }
03586       }
03587       break;
03588    case AST_AOC_CHARGE_NA:
03589    default:
03590       aoc_d.charge = PRI_AOC_DE_CHARGE_NOT_AVAILABLE;
03591       break;
03592    }
03593 
03594    pri_aoc_d_send(pvt->pri->pri, pvt->call, &aoc_d);
03595 }

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 3200 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().

03201 {
03202    struct ast_aoc_decoded *decoded = NULL;
03203    struct ast_aoc_encoded *encoded = NULL;
03204    size_t encoded_size = 0;
03205    enum ast_aoc_charge_type type;
03206 
03207    if (!owner || !aoc_d) {
03208       return;
03209    }
03210 
03211    switch (aoc_d->charge) {
03212    case PRI_AOC_DE_CHARGE_CURRENCY:
03213       type = AST_AOC_CHARGE_CURRENCY;
03214       break;
03215    case PRI_AOC_DE_CHARGE_UNITS:
03216       type = AST_AOC_CHARGE_UNIT;
03217       break;
03218    case PRI_AOC_DE_CHARGE_FREE:
03219       type = AST_AOC_CHARGE_FREE;
03220       break;
03221    default:
03222       type = AST_AOC_CHARGE_NA;
03223       break;
03224    }
03225 
03226    if (!(decoded = ast_aoc_create(AST_AOC_D, type, 0))) {
03227       return;
03228    }
03229 
03230    switch (aoc_d->billing_accumulation) {
03231    default:
03232       ast_debug(1, "AOC-D billing accumulation has unknown value: %d\n",
03233          aoc_d->billing_accumulation);
03234       /* Fall through */
03235    case 0:/* subTotal */
03236       ast_aoc_set_total_type(decoded, AST_AOC_SUBTOTAL);
03237       break;
03238    case 1:/* total */
03239       ast_aoc_set_total_type(decoded, AST_AOC_TOTAL);
03240       break;
03241    }
03242 
03243    switch (aoc_d->billing_id) {
03244    case PRI_AOC_D_BILLING_ID_NORMAL:
03245       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NORMAL);
03246       break;
03247    case PRI_AOC_D_BILLING_ID_REVERSE:
03248       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_REVERSE_CHARGE);
03249       break;
03250    case PRI_AOC_D_BILLING_ID_CREDIT_CARD:
03251       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CREDIT_CARD);
03252       break;
03253    case PRI_AOC_D_BILLING_ID_NOT_AVAILABLE:
03254    default:
03255       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NA);
03256       break;
03257    }
03258 
03259    switch (aoc_d->charge) {
03260    case PRI_AOC_DE_CHARGE_CURRENCY:
03261       ast_aoc_set_currency_info(decoded,
03262          aoc_d->recorded.money.amount.cost,
03263          sig_pri_aoc_multiplier_from_pri(aoc_d->recorded.money.amount.multiplier),
03264          aoc_d->recorded.money.currency);
03265       break;
03266    case PRI_AOC_DE_CHARGE_UNITS:
03267       {
03268          int i;
03269          for (i = 0; i < aoc_d->recorded.unit.num_items; ++i) {
03270             /* if type or number are negative, then they are not present */
03271             ast_aoc_add_unit_entry(decoded,
03272                (aoc_d->recorded.unit.item[i].number >= 0 ? 1 : 0),
03273                aoc_d->recorded.unit.item[i].number,
03274                (aoc_d->recorded.unit.item[i].type >= 0 ? 1 : 0),
03275                aoc_d->recorded.unit.item[i].type);
03276          }
03277       }
03278       break;
03279    }
03280 
03281    if (passthrough && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
03282       ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
03283    }
03284 
03285    ast_aoc_manager_event(decoded, owner);
03286 
03287    ast_aoc_destroy_decoded(decoded);
03288    ast_aoc_destroy_encoded(encoded);
03289 }

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

Definition at line 3610 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().

03611 {
03612    struct pri_subcmd_aoc_e *aoc_e = &pvt->aoc_e;
03613    const struct ast_aoc_charging_association *ca = ast_aoc_get_association_info(decoded);
03614 
03615    memset(aoc_e, 0, sizeof(*aoc_e));
03616    pvt->holding_aoce = 1;
03617 
03618    switch (ca->charging_type) {
03619    case AST_AOC_CHARGING_ASSOCIATION_NUMBER:
03620       aoc_e->associated.charge.number.valid = 1;
03621       ast_copy_string(aoc_e->associated.charge.number.str,
03622          ca->charge.number.number,
03623          sizeof(aoc_e->associated.charge.number.str));
03624       aoc_e->associated.charge.number.plan = ca->charge.number.plan;
03625       aoc_e->associated.charging_type = PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER;
03626       break;
03627    case AST_AOC_CHARGING_ASSOCIATION_ID:
03628       aoc_e->associated.charge.id = ca->charge.id;
03629       aoc_e->associated.charging_type = PRI_AOC_E_CHARGING_ASSOCIATION_ID;
03630       break;
03631    case AST_AOC_CHARGING_ASSOCIATION_NA:
03632    default:
03633       break;
03634    }
03635 
03636    switch (ast_aoc_get_billing_id(decoded)) {
03637    case AST_AOC_BILLING_NORMAL:
03638       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_NORMAL;
03639       break;
03640    case AST_AOC_BILLING_REVERSE_CHARGE:
03641       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_REVERSE;
03642       break;
03643    case AST_AOC_BILLING_CREDIT_CARD:
03644       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CREDIT_CARD;
03645       break;
03646    case AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL:
03647       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL;
03648       break;
03649    case AST_AOC_BILLING_CALL_FWD_BUSY:
03650       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY;
03651       break;
03652    case AST_AOC_BILLING_CALL_FWD_NO_REPLY:
03653       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY;
03654       break;
03655    case AST_AOC_BILLING_CALL_DEFLECTION:
03656       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_DEFLECTION;
03657       break;
03658    case AST_AOC_BILLING_CALL_TRANSFER:
03659       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_TRANSFER;
03660       break;
03661    case AST_AOC_BILLING_NA:
03662    default:
03663       aoc_e->billing_id = PRI_AOC_E_BILLING_ID_NOT_AVAILABLE;
03664       break;
03665    }
03666 
03667    switch (ast_aoc_get_charge_type(decoded)) {
03668    case AST_AOC_CHARGE_FREE:
03669       aoc_e->charge = PRI_AOC_DE_CHARGE_FREE;
03670       break;
03671    case AST_AOC_CHARGE_CURRENCY:
03672       {
03673          const char *currency_name = ast_aoc_get_currency_name(decoded);
03674          aoc_e->charge = PRI_AOC_DE_CHARGE_CURRENCY;
03675          aoc_e->recorded.money.amount.cost = ast_aoc_get_currency_amount(decoded);
03676          aoc_e->recorded.money.amount.multiplier = sig_pri_aoc_multiplier_from_ast(ast_aoc_get_currency_multiplier(decoded));
03677          if (!ast_strlen_zero(currency_name)) {
03678             ast_copy_string(aoc_e->recorded.money.currency, currency_name, sizeof(aoc_e->recorded.money.currency));
03679          }
03680       }
03681       break;
03682    case AST_AOC_CHARGE_UNIT:
03683       {
03684          const struct ast_aoc_unit_entry *entry;
03685          int i;
03686          aoc_e->charge = PRI_AOC_DE_CHARGE_UNITS;
03687          for (i = 0; i < ast_aoc_get_unit_count(decoded); i++) {
03688             if ((entry = ast_aoc_get_unit_info(decoded, i)) && i < ARRAY_LEN(aoc_e->recorded.unit.item)) {
03689                if (entry->valid_amount) {
03690                   aoc_e->recorded.unit.item[i].number = entry->amount;
03691                } else {
03692                   aoc_e->recorded.unit.item[i].number = -1;
03693                }
03694                if (entry->valid_type) {
03695                   aoc_e->recorded.unit.item[i].type = entry->type;
03696                } else {
03697                   aoc_e->recorded.unit.item[i].type = -1;
03698                }
03699                aoc_e->recorded.unit.num_items++;
03700             }
03701          }
03702       }
03703       break;
03704    case AST_AOC_CHARGE_NA:
03705    default:
03706       aoc_e->charge = PRI_AOC_DE_CHARGE_NOT_AVAILABLE;
03707       break;
03708    }
03709 }

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 3309 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().

03310 {
03311    struct ast_aoc_decoded *decoded = NULL;
03312    struct ast_aoc_encoded *encoded = NULL;
03313    size_t encoded_size = 0;
03314    enum ast_aoc_charge_type type;
03315 
03316    if (!aoc_e) {
03317       return;
03318    }
03319 
03320    switch (aoc_e->charge) {
03321    case PRI_AOC_DE_CHARGE_CURRENCY:
03322       type = AST_AOC_CHARGE_CURRENCY;
03323       break;
03324    case PRI_AOC_DE_CHARGE_UNITS:
03325       type = AST_AOC_CHARGE_UNIT;
03326       break;
03327    case PRI_AOC_DE_CHARGE_FREE:
03328       type = AST_AOC_CHARGE_FREE;
03329       break;
03330    default:
03331       type = AST_AOC_CHARGE_NA;
03332       break;
03333    }
03334 
03335    if (!(decoded = ast_aoc_create(AST_AOC_E, type, 0))) {
03336       return;
03337    }
03338 
03339    switch (aoc_e->associated.charging_type) {
03340    case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER:
03341       if (!aoc_e->associated.charge.number.valid) {
03342          break;
03343       }
03344       ast_aoc_set_association_number(decoded, aoc_e->associated.charge.number.str, aoc_e->associated.charge.number.plan);
03345       break;
03346    case PRI_AOC_E_CHARGING_ASSOCIATION_ID:
03347       ast_aoc_set_association_id(decoded, aoc_e->associated.charge.id);
03348       break;
03349    default:
03350       break;
03351    }
03352 
03353    switch (aoc_e->billing_id) {
03354    case PRI_AOC_E_BILLING_ID_NORMAL:
03355       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NORMAL);
03356       break;
03357    case PRI_AOC_E_BILLING_ID_REVERSE:
03358       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_REVERSE_CHARGE);
03359       break;
03360    case PRI_AOC_E_BILLING_ID_CREDIT_CARD:
03361       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CREDIT_CARD);
03362       break;
03363    case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL:
03364       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL);
03365       break;
03366    case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY:
03367       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_BUSY);
03368       break;
03369    case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY:
03370       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_NO_REPLY);
03371       break;
03372    case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION:
03373       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_DEFLECTION);
03374       break;
03375    case PRI_AOC_E_BILLING_ID_CALL_TRANSFER:
03376       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_TRANSFER);
03377       break;
03378    case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE:
03379    default:
03380       ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NA);
03381       break;
03382    }
03383 
03384    switch (aoc_e->charge) {
03385    case PRI_AOC_DE_CHARGE_CURRENCY:
03386       ast_aoc_set_currency_info(decoded,
03387          aoc_e->recorded.money.amount.cost,
03388          sig_pri_aoc_multiplier_from_pri(aoc_e->recorded.money.amount.multiplier),
03389          aoc_e->recorded.money.currency);
03390       break;
03391    case PRI_AOC_DE_CHARGE_UNITS:
03392       {
03393          int i;
03394          for (i = 0; i < aoc_e->recorded.unit.num_items; ++i) {
03395             /* if type or number are negative, then they are not present */
03396             ast_aoc_add_unit_entry(decoded,
03397                (aoc_e->recorded.unit.item[i].number >= 0 ? 1 : 0),
03398                aoc_e->recorded.unit.item[i].number,
03399                (aoc_e->recorded.unit.item[i].type >= 0 ? 1 : 0),
03400                aoc_e->recorded.unit.item[i].type);
03401          }
03402       }
03403    }
03404 
03405    if (passthrough && owner && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
03406       ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
03407    }
03408 
03409    ast_aoc_manager_event(decoded, owner);
03410 
03411    ast_aoc_destroy_decoded(decoded);
03412    ast_aoc_destroy_encoded(encoded);
03413 }

static int sig_pri_aoc_multiplier_from_ast ( enum ast_aoc_currency_multiplier  mult  )  [static]

Definition at line 2901 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().

02902 {
02903    switch (mult) {
02904    case AST_AOC_MULT_ONETHOUSANDTH:
02905       return PRI_AOC_MULTIPLIER_THOUSANDTH;
02906    case AST_AOC_MULT_ONEHUNDREDTH:
02907       return PRI_AOC_MULTIPLIER_HUNDREDTH;
02908    case AST_AOC_MULT_ONETENTH:
02909       return PRI_AOC_MULTIPLIER_TENTH;
02910    case AST_AOC_MULT_ONE:
02911       return PRI_AOC_MULTIPLIER_ONE;
02912    case AST_AOC_MULT_TEN:
02913       return PRI_AOC_MULTIPLIER_TEN;
02914    case AST_AOC_MULT_HUNDRED:
02915       return PRI_AOC_MULTIPLIER_HUNDRED;
02916    case AST_AOC_MULT_THOUSAND:
02917       return PRI_AOC_MULTIPLIER_THOUSAND;
02918    default:
02919       return PRI_AOC_MULTIPLIER_ONE;
02920    }
02921 }

static int sig_pri_aoc_multiplier_from_pri ( const int  mult  )  [static]

Definition at line 2932 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().

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

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 3129 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().

03130 {
03131    int request;
03132 
03133    if (!aoc_request) {
03134       return;
03135    }
03136 
03137    request = aoc_request->charging_request;
03138 
03139    if (request & PRI_AOC_REQUEST_S) {
03140       if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
03141          /* An AOC-S response must come from the other side, so save off this invoke_id
03142           * and see if an AOC-S message comes in before the call is answered. */
03143          pvt->aoc_s_request_invoke_id = aoc_request->invoke_id;
03144          pvt->aoc_s_request_invoke_id_valid = 1;
03145 
03146       } else {
03147          pri_aoc_s_request_response_send(pvt->pri->pri,
03148             call,
03149             aoc_request->invoke_id,
03150             NULL);
03151       }
03152    }
03153 
03154    if (request & PRI_AOC_REQUEST_D) {
03155       if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
03156          pri_aoc_de_request_response_send(pvt->pri->pri,
03157             call,
03158             PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
03159             aoc_request->invoke_id);
03160       } else {
03161          pri_aoc_de_request_response_send(pvt->pri->pri,
03162             call,
03163             PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
03164             aoc_request->invoke_id);
03165       }
03166    }
03167 
03168    if (request & PRI_AOC_REQUEST_E) {
03169       if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
03170          pri_aoc_de_request_response_send(pvt->pri->pri,
03171             call,
03172             PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
03173             aoc_request->invoke_id);
03174       } else {
03175          pri_aoc_de_request_response_send(pvt->pri->pri,
03176             call,
03177             PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
03178             aoc_request->invoke_id);
03179       }
03180    }
03181 }

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

Definition at line 3428 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().

03429 {
03430    struct pri_subcmd_aoc_s aoc_s = { 0, };
03431    const struct ast_aoc_s_entry *entry;
03432    int idx;
03433 
03434    for (idx = 0; idx < ast_aoc_s_get_count(decoded); idx++) {
03435       if (!(entry = ast_aoc_s_get_rate_info(decoded, idx))) {
03436          break;
03437       }
03438 
03439       aoc_s.item[idx].chargeable = sig_pri_aoc_charged_item_to_pri(entry->charged_item);
03440 
03441       switch (entry->rate_type) {
03442       case AST_AOC_RATE_TYPE_DURATION:
03443          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_DURATION;
03444          aoc_s.item[idx].rate.duration.amount.cost = entry->rate.duration.amount;
03445          aoc_s.item[idx].rate.duration.amount.multiplier =
03446             sig_pri_aoc_multiplier_from_ast(entry->rate.duration.multiplier);
03447          aoc_s.item[idx].rate.duration.time.length = entry->rate.duration.time;
03448          aoc_s.item[idx].rate.duration.time.scale =
03449             sig_pri_aoc_scale_to_pri(entry->rate.duration.time_scale);
03450          aoc_s.item[idx].rate.duration.granularity.length = entry->rate.duration.granularity_time;
03451          aoc_s.item[idx].rate.duration.granularity.scale =
03452             sig_pri_aoc_scale_to_pri(entry->rate.duration.granularity_time_scale);
03453          aoc_s.item[idx].rate.duration.charging_type = entry->rate.duration.charging_type;
03454 
03455          if (!ast_strlen_zero(entry->rate.duration.currency_name)) {
03456             ast_copy_string(aoc_s.item[idx].rate.duration.currency,
03457                entry->rate.duration.currency_name,
03458                sizeof(aoc_s.item[idx].rate.duration.currency));
03459          }
03460          break;
03461       case AST_AOC_RATE_TYPE_FLAT:
03462          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FLAT;
03463          aoc_s.item[idx].rate.flat.amount.cost = entry->rate.flat.amount;
03464          aoc_s.item[idx].rate.flat.amount.multiplier =
03465             sig_pri_aoc_multiplier_from_ast(entry->rate.flat.multiplier);
03466 
03467          if (!ast_strlen_zero(entry->rate.flat.currency_name)) {
03468             ast_copy_string(aoc_s.item[idx].rate.flat.currency,
03469                entry->rate.flat.currency_name,
03470                sizeof(aoc_s.item[idx].rate.flat.currency));
03471          }
03472          break;
03473       case AST_AOC_RATE_TYPE_VOLUME:
03474          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_VOLUME;
03475          aoc_s.item[idx].rate.volume.unit = entry->rate.volume.volume_unit;
03476          aoc_s.item[idx].rate.volume.amount.cost = entry->rate.volume.amount;
03477          aoc_s.item[idx].rate.volume.amount.multiplier =
03478             sig_pri_aoc_multiplier_from_ast(entry->rate.volume.multiplier);
03479 
03480          if (!ast_strlen_zero(entry->rate.volume.currency_name)) {
03481             ast_copy_string(aoc_s.item[idx].rate.volume.currency,
03482                entry->rate.volume.currency_name,
03483                sizeof(aoc_s.item[idx].rate.volume.currency));
03484          }
03485          break;
03486       case AST_AOC_RATE_TYPE_SPECIAL_CODE:
03487          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_SPECIAL_CODE;
03488          aoc_s.item[idx].rate.special = entry->rate.special_code;
03489          break;
03490       case AST_AOC_RATE_TYPE_FREE:
03491          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FREE;
03492          break;
03493       case AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
03494          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING;
03495          break;
03496       default:
03497       case AST_AOC_RATE_TYPE_NA:
03498          aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_NOT_AVAILABLE;
03499          break;
03500       }
03501    }
03502    aoc_s.num_items = idx;
03503 
03504    /* if this rate should be sent as a response to an AOC-S request we will
03505     * have an aoc_s_request_invoke_id associated with this pvt */
03506    if (pvt->aoc_s_request_invoke_id_valid) {
03507       pri_aoc_s_request_response_send(pvt->pri->pri, pvt->call, pvt->aoc_s_request_invoke_id, &aoc_s);
03508       pvt->aoc_s_request_invoke_id_valid = 0;
03509    } else {
03510       pri_aoc_s_send(pvt->pri->pri, pvt->call, &aoc_s);
03511    }
03512 }

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 3036 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().

03037 {
03038    struct ast_aoc_decoded *decoded = NULL;
03039    struct ast_aoc_encoded *encoded = NULL;
03040    size_t encoded_size = 0;
03041    int idx;
03042 
03043    if (!owner || !aoc_s) {
03044       return;
03045    }
03046 
03047    if (!(decoded = ast_aoc_create(AST_AOC_S, 0, 0))) {
03048       return;
03049    }
03050 
03051    for (idx = 0; idx < aoc_s->num_items; ++idx) {
03052       enum ast_aoc_s_charged_item charged_item;
03053 
03054       charged_item = sig_pri_aoc_charged_item_to_ast(aoc_s->item[idx].chargeable);
03055       if (charged_item == AST_AOC_CHARGED_ITEM_NA) {
03056          /* Delete the unknown charged item from the list. */
03057          continue;
03058       }
03059       switch (aoc_s->item[idx].rate_type) {
03060       case PRI_AOC_RATE_TYPE_DURATION:
03061          ast_aoc_s_add_rate_duration(decoded,
03062             charged_item,
03063             aoc_s->item[idx].rate.duration.amount.cost,
03064             sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.duration.amount.multiplier),
03065             aoc_s->item[idx].rate.duration.currency,
03066             aoc_s->item[idx].rate.duration.time.length,
03067             sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.time.scale),
03068             aoc_s->item[idx].rate.duration.granularity.length,
03069             sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.granularity.scale),
03070             aoc_s->item[idx].rate.duration.charging_type);
03071          break;
03072       case PRI_AOC_RATE_TYPE_FLAT:
03073          ast_aoc_s_add_rate_flat(decoded,
03074             charged_item,
03075             aoc_s->item[idx].rate.flat.amount.cost,
03076             sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.flat.amount.multiplier),
03077             aoc_s->item[idx].rate.flat.currency);
03078          break;
03079       case PRI_AOC_RATE_TYPE_VOLUME:
03080          ast_aoc_s_add_rate_volume(decoded,
03081             charged_item,
03082             aoc_s->item[idx].rate.volume.unit,
03083             aoc_s->item[idx].rate.volume.amount.cost,
03084             sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.volume.amount.multiplier),
03085             aoc_s->item[idx].rate.volume.currency);
03086          break;
03087       case PRI_AOC_RATE_TYPE_SPECIAL_CODE:
03088          ast_aoc_s_add_rate_special_charge_code(decoded,
03089             charged_item,
03090             aoc_s->item[idx].rate.special);
03091          break;
03092       case PRI_AOC_RATE_TYPE_FREE:
03093          ast_aoc_s_add_rate_free(decoded, charged_item, 0);
03094          break;
03095       case PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
03096          ast_aoc_s_add_rate_free(decoded, charged_item, 1);
03097          break;
03098       default:
03099          ast_aoc_s_add_rate_na(decoded, charged_item);
03100          break;
03101       }
03102    }
03103 
03104    if (passthrough && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
03105       ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
03106    }
03107 
03108    ast_aoc_manager_event(decoded, owner);
03109 
03110    ast_aoc_destroy_decoded(decoded);
03111    ast_aoc_destroy_encoded(encoded);
03112 }

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

Definition at line 2997 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().

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

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

Definition at line 2965 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().

02966 {
02967    switch (value) {
02968    default:
02969    case AST_AOC_TIME_SCALE_HUNDREDTH_SECOND:
02970       return PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND;
02971    case AST_AOC_TIME_SCALE_TENTH_SECOND:
02972       return PRI_AOC_TIME_SCALE_TENTH_SECOND;
02973    case AST_AOC_TIME_SCALE_SECOND:
02974       return PRI_AOC_TIME_SCALE_SECOND;
02975    case AST_AOC_TIME_SCALE_TEN_SECOND:
02976       return PRI_AOC_TIME_SCALE_TEN_SECOND;
02977    case AST_AOC_TIME_SCALE_MINUTE:
02978       return PRI_AOC_TIME_SCALE_MINUTE;
02979    case AST_AOC_TIME_SCALE_HOUR:
02980       return PRI_AOC_TIME_SCALE_HOUR;
02981    case AST_AOC_TIME_SCALE_DAY:
02982       return PRI_AOC_TIME_SCALE_DAY;
02983    }
02984 }

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 2300 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().

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

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

Definition at line 7226 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().

07227 {
07228    struct sig_pri_chan *p = *pvt;
07229    struct sig_pri_span *pri;
07230 
07231    if (!p->pri) {
07232       /* Something is wrong here.  A PRI channel without the pri pointer? */
07233       return 0;
07234    }
07235    pri = p->pri;
07236 
07237    ast_mutex_lock(&pri->lock);
07238    if (
07239 #if defined(HAVE_PRI_CALL_WAITING)
07240       /*
07241        * Only do call waiting calls if we have any
07242        * call waiting call outstanding.  We do not
07243        * want new calls to steal a B channel
07244        * freed for an earlier call waiting call.
07245        */
07246       !pri->num_call_waiting_calls &&
07247 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
07248       sig_pri_available_check(p)) {
07249       p->allocated = 1;
07250       ast_mutex_unlock(&pri->lock);
07251       return 1;
07252    }
07253 
07254 #if defined(HAVE_PRI_CALL_WAITING)
07255    if (!is_specific_channel) {
07256       struct sig_pri_chan *cw;
07257 
07258       cw = sig_pri_cw_available(pri);
07259       if (cw) {
07260          /* We have a call waiting interface to use instead. */
07261          cw->allocated = 1;
07262          *pvt = cw;
07263          ast_mutex_unlock(&pri->lock);
07264          return 1;
07265       }
07266    }
07267 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
07268    ast_mutex_unlock(&pri->lock);
07269    return 0;
07270 }

static int sig_pri_available_check ( struct sig_pri_chan pvt  )  [static]

Definition at line 7168 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().

07169 {
07170    /*
07171     * If interface has a B channel and is available for use
07172     * then the channel is available.
07173     */
07174    if (!pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
07175       return 1;
07176    }
07177    return 0;
07178 }

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 6471 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::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::outgoing, 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(), 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().

06472 {
06473    char dest[256]; /* must be same length as p->dialdest */
06474    struct ast_party_subaddress dialed_subaddress; /* Called subaddress */
06475    struct pri_sr *sr;
06476    char *c, *l, *n, *s;
06477 #ifdef SUPPORT_USERUSER
06478    const char *useruser;
06479 #endif
06480    int core_id;
06481    int pridialplan;
06482    int dp_strip;
06483    int prilocaldialplan;
06484    int ldp_strip;
06485    int exclusive;
06486 #if defined(HAVE_PRI_SETUP_KEYPAD)
06487    const char *keypad;
06488 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06489    AST_DECLARE_APP_ARGS(args,
06490       AST_APP_ARG(group);  /* channel/group token */
06491       AST_APP_ARG(ext); /* extension token */
06492       AST_APP_ARG(opts);   /* options token */
06493       AST_APP_ARG(other);  /* Any remining unused arguments */
06494    );
06495    struct ast_flags opts;
06496    char *opt_args[OPT_ARG_ARRAY_SIZE];
06497 
06498    ast_log(LOG_DEBUG, "CALLER NAME: %s NUM: %s\n",
06499       S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
06500       S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));
06501 
06502    if (!p->pri) {
06503       ast_log(LOG_ERROR, "Could not find pri on channel %d\n", p->channel);
06504       return -1;
06505    }
06506 
06507    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
06508       ast_log(LOG_WARNING, "sig_pri_call called on %s, neither down nor reserved\n", ast->name);
06509       return -1;
06510    }
06511 
06512    p->dialdest[0] = '\0';
06513    p->outgoing = 1;
06514 
06515    ast_copy_string(dest, rdest, sizeof(dest));
06516    AST_NONSTANDARD_APP_ARGS(args, dest, '/');
06517    if (ast_app_parse_options(sig_pri_call_opts, &opts, opt_args, args.opts)) {
06518       /* General invalid option syntax. */
06519       return -1;
06520    }
06521 
06522    c = args.ext;
06523    if (!c) {
06524       c = "";
06525    }
06526 
06527    /* setup dialed_subaddress if found */
06528    ast_party_subaddress_init(&dialed_subaddress);
06529    s = strchr(c, ':');
06530    if (s) {
06531       *s = '\0';
06532       s++;
06533       /* prefix */
06534       /* 'n' = NSAP */
06535       /* 'u' = User Specified */
06536       /* Default = NSAP */
06537       switch (*s) {
06538       case 'U':
06539       case 'u':
06540          s++;
06541          dialed_subaddress.type = 2;
06542          break;
06543       case 'N':
06544       case 'n':
06545          s++;
06546          /* default already covered with ast_party_subaddress_init */
06547          break;
06548       }
06549       dialed_subaddress.str = s;
06550       dialed_subaddress.valid = 1;
06551       s = NULL;
06552    }
06553 
06554    l = NULL;
06555    n = NULL;
06556    if (!p->hidecallerid) {
06557       if (ast->connected.id.number.valid) {
06558          /* If we get to the end of this loop without breaking, there's no
06559           * calleridnum.  This is done instead of testing for "unknown" or
06560           * the thousands of other ways that the calleridnum could be
06561           * invalid. */
06562          for (l = ast->connected.id.number.str; l && *l; l++) {
06563             if (strchr("0123456789", *l)) {
06564                l = ast->connected.id.number.str;
06565                break;
06566             }
06567          }
06568       } else {
06569          l = NULL;
06570       }
06571       if (!p->hidecalleridname) {
06572          n = ast->connected.id.name.valid ? ast->connected.id.name.str : NULL;
06573       }
06574    }
06575 
06576    if (strlen(c) < p->stripmsd) {
06577       ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
06578       return -1;
06579    }
06580    pri_grab(p, p->pri);
06581    if (!(p->call = pri_new_call(p->pri->pri))) {
06582       ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
06583       pri_rel(p->pri);
06584       return -1;
06585    }
06586    if (!(sr = pri_sr_new())) {
06587       ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
06588       pri_destroycall(p->pri->pri, p->call);
06589       p->call = NULL;
06590       pri_rel(p->pri);
06591       return -1;
06592    }
06593 
06594    sig_pri_set_digital(p, IS_DIGITAL(ast->transfercapability));   /* push up to parent for EC */
06595 
06596 #if defined(HAVE_PRI_CALL_WAITING)
06597    if (p->is_call_waiting) {
06598       /*
06599        * Indicate that this is a call waiting call.
06600        * i.e., Normal call but with no B channel.
06601        */
06602       pri_sr_set_channel(sr, 0, 0, 1);
06603    } else
06604 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
06605    {
06606       /* Should the picked channel be used exclusively? */
06607       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
06608          exclusive = 1;
06609       } else {
06610          exclusive = 0;
06611       }
06612       pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
06613    }
06614 
06615    pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
06616       (p->digital ? -1 : layer1));
06617 
06618    if (p->pri->facilityenable)
06619       pri_facility_enable(p->pri->pri);
06620 
06621    ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
06622    dp_strip = 0;
06623    pridialplan = p->pri->dialplan - 1;
06624    if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
06625       if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
06626          if (pridialplan == -2) {
06627             dp_strip = strlen(p->pri->internationalprefix);
06628          }
06629          pridialplan = PRI_INTERNATIONAL_ISDN;
06630       } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
06631          if (pridialplan == -2) {
06632             dp_strip = strlen(p->pri->nationalprefix);
06633          }
06634          pridialplan = PRI_NATIONAL_ISDN;
06635       } else {
06636          pridialplan = PRI_LOCAL_ISDN;
06637       }
06638    }
06639    while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
06640       switch (c[p->stripmsd]) {
06641       case 'U':
06642          pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
06643          break;
06644       case 'I':
06645          pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
06646          break;
06647       case 'N':
06648          pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
06649          break;
06650       case 'L':
06651          pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
06652          break;
06653       case 'S':
06654          pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
06655          break;
06656       case 'V':
06657          pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
06658          break;
06659       case 'R':
06660          pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
06661          break;
06662       case 'u':
06663          pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
06664          break;
06665       case 'e':
06666          pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
06667          break;
06668       case 'x':
06669          pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
06670          break;
06671       case 'f':
06672          pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
06673          break;
06674       case 'n':
06675          pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
06676          break;
06677       case 'p':
06678          pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
06679          break;
06680       case 'r':
06681          pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
06682          break;
06683       default:
06684          if (isalpha(c[p->stripmsd])) {
06685             ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
06686                c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
06687          }
06688          break;
06689       }
06690       c++;
06691    }
06692 #if defined(HAVE_PRI_SETUP_KEYPAD)
06693    if (ast_test_flag(&opts, OPT_KEYPAD)
06694       && !ast_strlen_zero(opt_args[OPT_ARG_KEYPAD])) {
06695       /* We have a keypad facility digits option with digits. */
06696       keypad = opt_args[OPT_ARG_KEYPAD];
06697       pri_sr_set_keypad_digits(sr, keypad);
06698    } else {
06699       keypad = NULL;
06700    }
06701    if (!keypad || !ast_strlen_zero(c + p->stripmsd + dp_strip))
06702 #endif   /* defined(HAVE_PRI_SETUP_KEYPAD) */
06703    {
06704       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
06705    }
06706 
06707 #if defined(HAVE_PRI_SUBADDR)
06708    if (dialed_subaddress.valid) {
06709       struct pri_party_subaddress subaddress;
06710 
06711       memset(&subaddress, 0, sizeof(subaddress));
06712       sig_pri_party_subaddress_from_ast(&subaddress, &dialed_subaddress);
06713       pri_sr_set_called_subaddress(sr, &subaddress);
06714    }
06715 #endif   /* defined(HAVE_PRI_SUBADDR) */
06716 #if defined(HAVE_PRI_REVERSE_CHARGE)
06717    if (ast_test_flag(&opts, OPT_REVERSE_CHARGE)) {
06718       pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
06719    }
06720 #endif   /* defined(HAVE_PRI_REVERSE_CHARGE) */
06721 #if defined(HAVE_PRI_AOC_EVENTS)
06722    if (ast_test_flag(&opts, OPT_AOC_REQUEST)
06723       && !ast_strlen_zero(opt_args[OPT_ARG_AOC_REQUEST])) {
06724       if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 's')) {
06725          pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_S);
06726       }
06727       if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'd')) {
06728          pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_D);
06729       }
06730       if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'e')) {
06731          pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_E);
06732       }
06733    }
06734 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
06735 
06736    /* Setup the user tag for party id's from this device for this call. */
06737    if (p->pri->append_msn_to_user_tag) {
06738       snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
06739          p->pri->nodetype == PRI_NETWORK
06740             ? c + p->stripmsd + dp_strip
06741             : S_COR(ast->connected.id.number.valid,
06742                ast->connected.id.number.str, ""));
06743    } else {
06744       ast_copy_string(p->user_tag, p->pri->initial_user_tag, sizeof(p->user_tag));
06745    }
06746 
06747    /*
06748     * Replace the caller id tag from the channel creation
06749     * with the actual tag value.
06750     */
06751    ast_free(ast->caller.id.tag);
06752    ast->caller.id.tag = ast_strdup(p->user_tag);
06753 
06754    ldp_strip = 0;
06755    prilocaldialplan = p->pri->localdialplan - 1;
06756    if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
06757       if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
06758          if (prilocaldialplan == -2) {
06759             ldp_strip = strlen(p->pri->internationalprefix);
06760          }
06761          prilocaldialplan = PRI_INTERNATIONAL_ISDN;
06762       } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
06763          if (prilocaldialplan == -2) {
06764             ldp_strip = strlen(p->pri->nationalprefix);
06765          }
06766          prilocaldialplan = PRI_NATIONAL_ISDN;
06767       } else {
06768          prilocaldialplan = PRI_LOCAL_ISDN;
06769       }
06770    }
06771    if (l != NULL) {
06772       while (*l > '9' && *l != '*' && *l != '#') {
06773          switch (*l) {
06774          case 'U':
06775             prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
06776             break;
06777          case 'I':
06778             prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
06779             break;
06780          case 'N':
06781             prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
06782             break;
06783          case 'L':
06784             prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
06785             break;
06786          case 'S':
06787             prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
06788             break;
06789          case 'V':
06790             prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
06791             break;
06792          case 'R':
06793             prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
06794             break;
06795          case 'u':
06796             prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
06797             break;
06798          case 'e':
06799             prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
06800             break;
06801          case 'x':
06802             prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
06803             break;
06804          case 'f':
06805             prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
06806             break;
06807          case 'n':
06808             prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
06809             break;
06810          case 'p':
06811             prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
06812             break;
06813          case 'r':
06814             prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
06815             break;
06816          default:
06817             if (isalpha(*l)) {
06818                ast_log(LOG_WARNING,
06819                   "Unrecognized prilocaldialplan %s modifier: %c\n",
06820                   *l > 'Z' ? "NPI" : "TON", *l);
06821             }
06822             break;
06823          }
06824          l++;
06825       }
06826    }
06827    pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
06828       p->use_callingpres ? ast->connected.id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
06829 
06830 #if defined(HAVE_PRI_SUBADDR)
06831    if (ast->connected.id.subaddress.valid) {
06832       struct pri_party_subaddress subaddress;
06833 
06834       memset(&subaddress, 0, sizeof(subaddress));
06835       sig_pri_party_subaddress_from_ast(&subaddress, &ast->connected.id.subaddress);
06836       pri_sr_set_caller_subaddress(sr, &subaddress);
06837    }
06838 #endif   /* defined(HAVE_PRI_SUBADDR) */
06839 
06840    sig_pri_redirecting_update(p, ast);
06841 
06842 #ifdef SUPPORT_USERUSER
06843    /* User-user info */
06844    useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
06845    if (useruser)
06846       pri_sr_set_useruser(sr, useruser);
06847 #endif
06848 
06849 #if defined(HAVE_PRI_CCSS)
06850    if (ast_cc_is_recall(ast, &core_id, sig_pri_cc_type_name)) {
06851       struct ast_cc_monitor *monitor;
06852       char device_name[AST_CHANNEL_NAME];
06853 
06854       /* This is a CC recall call. */
06855       ast_channel_get_device_name(ast, device_name, sizeof(device_name));
06856       monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
06857       if (monitor) {
06858          struct sig_pri_cc_monitor_instance *instance;
06859 
06860          instance = monitor->private_data;
06861 
06862          /* If this fails then we have monitor instance ambiguity. */
06863          ast_assert(p->pri == instance->pri);
06864 
06865          if (pri_cc_call(p->pri->pri, instance->cc_id, p->call, sr)) {
06866             /* The CC recall call failed for some reason. */
06867             ast_log(LOG_WARNING, "Unable to setup CC recall call to device %s\n",
06868                device_name);
06869             ao2_ref(monitor, -1);
06870             pri_destroycall(p->pri->pri, p->call);
06871             p->call = NULL;
06872             pri_rel(p->pri);
06873             pri_sr_free(sr);
06874             return -1;
06875          }
06876          ao2_ref(monitor, -1);
06877       } else {
06878          core_id = -1;
06879       }
06880    } else
06881 #endif   /* defined(HAVE_PRI_CCSS) */
06882    {
06883       core_id = -1;
06884    }
06885    if (core_id == -1 && pri_setup(p->pri->pri, p->call, sr)) {
06886       ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
06887          c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
06888       pri_destroycall(p->pri->pri, p->call);
06889       p->call = NULL;
06890       pri_rel(p->pri);
06891       pri_sr_free(sr);
06892       return -1;
06893    }
06894    p->call_level = SIG_PRI_CALL_LEVEL_SETUP;
06895    pri_sr_free(sr);
06896    ast_setstate(ast, AST_STATE_DIALING);
06897    sig_pri_set_dialing(p, 1);
06898    pri_rel(p->pri);
06899    return 0;
06900 }

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

Definition at line 127 of file sig_pri.c.

References SIG_PRI_CALL_LEVEL_ALERTING, SIG_PRI_CALL_LEVEL_CONNECT, 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().

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

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 8198 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.

08199 {
08200    struct sig_pri_cc_agent_prv *cc_pvt;
08201 
08202    cc_pvt = agent->private_data;
08203    ast_mutex_lock(&cc_pvt->pri->lock);
08204    pri_cc_remote_user_free(cc_pvt->pri->pri, cc_pvt->cc_id);
08205    ast_mutex_unlock(&cc_pvt->pri->lock);
08206    return 0;
08207 }

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

Definition at line 2456 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().

02457 {
02458    struct ast_cc_agent *agent_1 = obj;
02459    struct sig_pri_cc_agent_prv *agent_prv_1 = agent_1->private_data;
02460    struct sig_pri_cc_agent_prv *agent_prv_2 = arg;
02461 
02462    return (agent_prv_1 && agent_prv_1->pri == agent_prv_2->pri
02463       && agent_prv_1->cc_id == agent_prv_2->cc_id) ? CMP_MATCH | CMP_STOP : 0;
02464 }

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 8227 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().

08228 {
08229    struct sig_pri_cc_agent_prv *cc_pvt;
08230    int res;
08231 
08232    cc_pvt = agent->private_data;
08233    if (!cc_pvt) {
08234       /* The agent constructor probably failed. */
08235       return;
08236    }
08237    ast_mutex_lock(&cc_pvt->pri->lock);
08238    res = -1;
08239    if (cc_pvt->cc_request_response_pending) {
08240       res = pri_cc_req_rsp(cc_pvt->pri->pri, cc_pvt->cc_id, 2/* short_term_denial */);
08241    }
08242    if (res) {
08243       pri_cc_cancel(cc_pvt->pri->pri, cc_pvt->cc_id);
08244    }
08245    ast_mutex_unlock(&cc_pvt->pri->lock);
08246    ast_free(cc_pvt);
08247 }

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 7910 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().

07911 {
07912    struct sig_pri_cc_agent_prv *cc_pvt;
07913 
07914    cc_pvt = ast_calloc(1, sizeof(*cc_pvt));
07915    if (!cc_pvt) {
07916       return -1;
07917    }
07918 
07919    ast_mutex_lock(&pvt_chan->pri->lock);
07920    cc_pvt->pri = pvt_chan->pri;
07921    cc_pvt->cc_id = pri_cc_available(pvt_chan->pri->pri, pvt_chan->call);
07922    ast_mutex_unlock(&pvt_chan->pri->lock);
07923    if (cc_pvt->cc_id == -1) {
07924       ast_free(cc_pvt);
07925       return -1;
07926    }
07927    agent->private_data = cc_pvt;
07928    return 0;
07929 }

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 8142 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.

08143 {
08144    struct sig_pri_cc_agent_prv *cc_pvt;
08145 
08146    cc_pvt = agent->private_data;
08147    ast_mutex_lock(&cc_pvt->pri->lock);
08148    pri_cc_b_free(cc_pvt->pri->pri, cc_pvt->cc_id);
08149    ast_mutex_unlock(&cc_pvt->pri->lock);
08150    return 0;
08151 }

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 8003 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.

08004 {
08005    struct sig_pri_cc_agent_prv *cc_pvt;
08006    int res;
08007    int status;
08008    const char *failed_msg;
08009    static const char *failed_to_send = "Failed to send the CC request response.";
08010    static const char *not_accepted = "The core declined the CC request.";
08011 
08012    cc_pvt = agent->private_data;
08013    ast_mutex_lock(&cc_pvt->pri->lock);
08014    if (cc_pvt->cc_request_response_pending) {
08015       cc_pvt->cc_request_response_pending = 0;
08016 
08017       /* Convert core response reason to ISDN response status. */
08018       status = 2;/* short_term_denial */
08019       switch (reason) {
08020       case AST_CC_AGENT_RESPONSE_SUCCESS:
08021          status = 0;/* success */
08022          break;
08023       case AST_CC_AGENT_RESPONSE_FAILURE_INVALID:
08024          status = 2;/* short_term_denial */
08025          break;
08026       case AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY:
08027          status = 5;/* queue_full */
08028          break;
08029       }
08030 
08031       res = pri_cc_req_rsp(cc_pvt->pri->pri, cc_pvt->cc_id, status);
08032       if (!status) {
08033          /* CC core request was accepted. */
08034          if (res) {
08035             failed_msg = failed_to_send;
08036          } else {
08037             failed_msg = NULL;
08038          }
08039       } else {
08040          /* CC core request was declined. */
08041          if (res) {
08042             failed_msg = failed_to_send;
08043          } else {
08044             failed_msg = not_accepted;
08045          }
08046       }
08047    } else {
08048       failed_msg = NULL;
08049    }
08050    ast_mutex_unlock(&cc_pvt->pri->lock);
08051    if (failed_msg) {
08052       ast_cc_failed(agent->core_id, "%s agent: %s", sig_pri_cc_type_name, failed_msg);
08053    }
08054 }

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

08172 {
08173    /* libpri already knows when and how it needs to monitor Party A. */
08174    return 0;
08175 }

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

07955 {
07956    /* libpri maintains it's own offer timer in the form of T_RETENTION. */
07957    return 0;
07958 }

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 8073 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.

08074 {
08075    struct sig_pri_cc_agent_prv *cc_pvt;
08076 
08077    cc_pvt = agent->private_data;
08078    ast_mutex_lock(&cc_pvt->pri->lock);
08079    pri_cc_status_req(cc_pvt->pri->pri, cc_pvt->cc_id);
08080    ast_mutex_unlock(&cc_pvt->pri->lock);
08081    return 0;
08082 }

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

07976 {
07977    /* libpri maintains it's own offer timer in the form of T_RETENTION. */
07978    return 0;
07979 }

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 8108 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.

08109 {
08110    struct sig_pri_cc_agent_prv *cc_pvt;
08111 
08112    cc_pvt = agent->private_data;
08113    ast_mutex_lock(&cc_pvt->pri->lock);
08114    pri_cc_stop_alerting(cc_pvt->pri->pri, cc_pvt->cc_id);
08115    ast_mutex_unlock(&cc_pvt->pri->lock);
08116    return 0;
08117 }

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 2632 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().

02633 {
02634    struct sig_pri_chan *pvt;
02635    struct ast_cc_config_params *cc_params;
02636    struct sig_pri_cc_monitor_instance *monitor;
02637    enum ast_cc_monitor_policies monitor_policy;
02638    int core_id;
02639    int res;
02640    char device_name[AST_CHANNEL_NAME];
02641    char dialstring[AST_CHANNEL_NAME];
02642 
02643    pvt = pri->pvts[chanpos];
02644 
02645    core_id = ast_cc_get_current_core_id(pvt->owner);
02646    if (core_id == -1) {
02647       return -1;
02648    }
02649 
02650    cc_params = ast_channel_get_cc_config_params(pvt->owner);
02651    if (!cc_params) {
02652       return -1;
02653    }
02654 
02655    res = -1;
02656    monitor_policy = ast_get_cc_monitor_policy(cc_params);
02657    switch (monitor_policy) {
02658    case AST_CC_MONITOR_NEVER:
02659       /* CCSS is not enabled. */
02660       break;
02661    case AST_CC_MONITOR_NATIVE:
02662    case AST_CC_MONITOR_ALWAYS:
02663       /*
02664        * If it is AST_CC_MONITOR_ALWAYS and native fails we will attempt the fallback
02665        * later in the call to sig_pri_cc_generic_check().
02666        */
02667       ast_channel_get_device_name(pvt->owner, device_name, sizeof(device_name));
02668       sig_pri_make_cc_dialstring(pvt, dialstring, sizeof(dialstring));
02669       monitor = sig_pri_cc_monitor_instance_init(core_id, pri, cc_id, device_name);
02670       if (!monitor) {
02671          break;
02672       }
02673       res = ast_queue_cc_frame(pvt->owner, sig_pri_cc_type_name, dialstring, service,
02674          monitor);
02675       if (res) {
02676          monitor->cc_id = -1;
02677          ao2_unlink(sig_pri_cc_monitors, monitor);
02678          ao2_ref(monitor, -1);
02679       }
02680       break;
02681    case AST_CC_MONITOR_GENERIC:
02682       ast_queue_cc_frame(pvt->owner, AST_CC_GENERIC_MONITOR_TYPE,
02683          sig_pri_get_orig_dialstring(pvt), service, NULL);
02684       /* Say it failed to force caller to cancel native CC. */
02685       break;
02686    }
02687    return res;
02688 }

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

Definition at line 2705 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().

02706 {
02707    struct ast_channel *owner;
02708    struct ast_cc_config_params *cc_params;
02709 #if defined(HAVE_PRI_CCSS)
02710    struct ast_cc_monitor *monitor;
02711    char device_name[AST_CHANNEL_NAME];
02712 #endif   /* defined(HAVE_PRI_CCSS) */
02713    enum ast_cc_monitor_policies monitor_policy;
02714    int core_id;
02715 
02716    if (!pri->pvts[chanpos]->outgoing) {
02717       /* This is not an outgoing call so it cannot be CC monitor. */
02718       return;
02719    }
02720 
02721    sig_pri_lock_owner(pri, chanpos);
02722    owner = pri->pvts[chanpos]->owner;
02723    if (!owner) {
02724       return;
02725    }
02726    core_id = ast_cc_get_current_core_id(owner);
02727    if (core_id == -1) {
02728       /* No CC core setup */
02729       goto done;
02730    }
02731 
02732    cc_params = ast_channel_get_cc_config_params(owner);
02733    if (!cc_params) {
02734       /* Could not get CC config parameters. */
02735       goto done;
02736    }
02737 
02738 #if defined(HAVE_PRI_CCSS)
02739    ast_channel_get_device_name(owner, device_name, sizeof(device_name));
02740    monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
02741    if (monitor) {
02742       /* CC monitor is already present so no need for generic CC. */
02743       ao2_ref(monitor, -1);
02744       goto done;
02745    }
02746 #endif   /* defined(HAVE_PRI_CCSS) */
02747 
02748    monitor_policy = ast_get_cc_monitor_policy(cc_params);
02749    switch (monitor_policy) {
02750    case AST_CC_MONITOR_NEVER:
02751       /* CCSS is not enabled. */
02752       break;
02753    case AST_CC_MONITOR_NATIVE:
02754       if (pri->sig == SIG_BRI_PTMP && pri->nodetype == PRI_NETWORK) {
02755          /* Request generic CC monitor. */
02756          ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
02757             sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
02758       }
02759       break;
02760    case AST_CC_MONITOR_ALWAYS:
02761       if (pri->sig == SIG_BRI_PTMP && pri->nodetype != PRI_NETWORK) {
02762          /*
02763           * Cannot monitor PTMP TE side since this is not defined.
02764           * We are playing the roll of a phone in this case and
02765           * a phone cannot monitor a party over the network without
02766           * protocol help.
02767           */
02768          break;
02769       }
02770       /*
02771        * We are either falling back or this is a PTMP NT span.
02772        * Request generic CC monitor.
02773        */
02774       ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
02775          sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
02776       break;
02777    case AST_CC_MONITOR_GENERIC:
02778       if (pri->sig == SIG_BRI_PTMP && pri->nodetype == PRI_NETWORK) {
02779          /* Request generic CC monitor. */
02780          ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
02781             sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
02782       }
02783       break;
02784    }
02785 
02786 done:
02787    ast_channel_unlock(owner);
02788 }

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

Definition at line 2802 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().

02803 {
02804    if (is_agent) {
02805       struct ast_cc_agent *agent;
02806 
02807       agent = sig_pri_find_cc_agent_by_cc_id(pri, cc_id);
02808       if (!agent) {
02809          return;
02810       }
02811       ast_cc_failed(agent->core_id, "%s agent got canceled by link",
02812          sig_pri_cc_type_name);
02813       ao2_ref(agent, -1);
02814    } else {
02815       struct sig_pri_cc_monitor_instance *monitor;
02816 
02817       monitor = sig_pri_find_cc_monitor_by_cc_id(pri, cc_id);
02818       if (!monitor) {
02819          return;
02820       }
02821       monitor->cc_id = -1;
02822       ast_cc_monitor_failed(monitor->core_id, monitor->name,
02823          "%s monitor got canceled by link", sig_pri_cc_type_name);
02824       ao2_ref(monitor, -1);
02825    }
02826 }

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

08454 {
08455    /*
08456     * libpri maintains it's own available timer as one of:
08457     * T_CCBS2/T_CCBS5/T_CCBS6/QSIG_CCBS_T2
08458     * T_CCNR2/T_CCNR5/T_CCNR6/QSIG_CCNR_T2
08459     */
08460    return 0;
08461 }

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

Definition at line 2508 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().

02509 {
02510    struct sig_pri_cc_monitor_instance *monitor_1 = obj;
02511    struct sig_pri_cc_monitor_instance *monitor_2 = arg;
02512 
02513    return (monitor_1->pri == monitor_2->pri
02514       && monitor_1->cc_id == monitor_2->cc_id) ? CMP_MATCH | CMP_STOP : 0;
02515 }

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

References ao2_ref, ao2_unlink, and sig_pri_cc_monitors.

08477 {
08478    struct sig_pri_cc_monitor_instance *instance;
08479 
08480    instance = monitor_pvt;
08481    if (!instance) {
08482       return;
08483    }
08484    ao2_unlink(sig_pri_cc_monitors, instance);
08485    ao2_ref(instance, -1);
08486 }

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

Definition at line 8281 of file sig_pri.c.

References CMP_MATCH, CMP_STOP, and sig_pri_cc_monitor_instance::core_id.

Referenced by sig_pri_load().

08282 {
08283    struct sig_pri_cc_monitor_instance *monitor_1 = obj;
08284    struct sig_pri_cc_monitor_instance *monitor_2 = arg;
08285 
08286    return monitor_1->core_id == monitor_2->core_id ? CMP_MATCH | CMP_STOP : 0;
08287 }

static void sig_pri_cc_monitor_instance_destroy ( void *  data  )  [static]

Definition at line 2556 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().

02557 {
02558    struct sig_pri_cc_monitor_instance *monitor_instance = data;
02559 
02560    if (monitor_instance->cc_id != -1) {
02561       ast_mutex_lock(&monitor_instance->pri->lock);
02562       pri_cc_cancel(monitor_instance->pri->pri, monitor_instance->cc_id);
02563       ast_mutex_unlock(&monitor_instance->pri->lock);
02564    }
02565    monitor_instance->pri->calls->module_unref();
02566 }

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

Definition at line 8261 of file sig_pri.c.

References sig_pri_cc_monitor_instance::core_id.

Referenced by sig_pri_load().

08262 {
08263    const struct sig_pri_cc_monitor_instance *monitor_instance = obj;
08264 
08265    return monitor_instance->core_id;
08266 }

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 2588 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().

02589 {
02590    struct sig_pri_cc_monitor_instance *monitor_instance;
02591 
02592    if (!pri->calls->module_ref || !pri->calls->module_unref) {
02593       return NULL;
02594    }
02595 
02596    monitor_instance = ao2_alloc(sizeof(*monitor_instance) + strlen(device_name),
02597       sig_pri_cc_monitor_instance_destroy);
02598    if (!monitor_instance) {
02599       return NULL;
02600    }
02601 
02602    monitor_instance->cc_id = cc_id;
02603    monitor_instance->pri = pri;
02604    monitor_instance->core_id = core_id;
02605    strcpy(monitor_instance->name, device_name);
02606 
02607    pri->calls->module_ref();
02608 
02609    ao2_link(sig_pri_cc_monitors, monitor_instance);
02610    return monitor_instance;
02611 }

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 8309 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.

08310 {
08311    struct sig_pri_cc_monitor_instance *instance;
08312    int cc_mode;
08313    int res;
08314 
08315    switch (monitor->service_offered) {
08316    case AST_CC_CCBS:
08317       cc_mode = 0;/* CCBS */
08318       break;
08319    case AST_CC_CCNR:
08320       cc_mode = 1;/* CCNR */
08321       break;
08322    default:
08323       /* CC service not supported by ISDN. */
08324       return -1;
08325    }
08326 
08327    instance = monitor->private_data;
08328 
08329    /* libpri handles it's own available timer. */
08330    ast_mutex_lock(&instance->pri->lock);
08331    res = pri_cc_req(instance->pri->pri, instance->cc_id, cc_mode);
08332    ast_mutex_unlock(&instance->pri->lock);
08333 
08334    return res;
08335 }

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 8408 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.

08409 {
08410    struct sig_pri_cc_monitor_instance *instance;
08411    int cc_status;
08412 
08413    switch (devstate) {
08414    case AST_DEVICE_UNKNOWN:
08415    case AST_DEVICE_NOT_INUSE:
08416       cc_status = 0;/* free */
08417       break;
08418    case AST_DEVICE_BUSY:
08419    case AST_DEVICE_INUSE:
08420       cc_status = 1;/* busy */
08421       break;
08422    default:
08423       /* Don't know how to interpret this device state into free/busy status. */
08424       return 0;
08425    }
08426    instance = monitor->private_data;
08427    ast_mutex_lock(&instance->pri->lock);
08428    pri_cc_status_req_rsp(instance->pri->pri, instance->cc_id, cc_status);
08429    ast_mutex_unlock(&instance->pri->lock);
08430 
08431    return 0;
08432 }

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 8352 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.

08353 {
08354    struct sig_pri_cc_monitor_instance *instance;
08355 
08356    instance = monitor->private_data;
08357    ast_mutex_lock(&instance->pri->lock);
08358    pri_cc_status(instance->pri->pri, instance->cc_id, 1/* busy */);
08359    ast_mutex_unlock(&instance->pri->lock);
08360 
08361    return 0;
08362 }

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 8378 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.

08379 {
08380    struct sig_pri_cc_monitor_instance *instance;
08381 
08382    instance = monitor->private_data;
08383    ast_mutex_lock(&instance->pri->lock);
08384    pri_cc_status(instance->pri->pri, instance->cc_id, 0/* free */);
08385    ast_mutex_unlock(&instance->pri->lock);
08386 
08387    return 0;
08388 }

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 7674 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().

07675 {
07676    pri_grab(p, p->pri);
07677    sig_pri_set_alarm(p, !noalarm);
07678    if (!noalarm) {
07679       if (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
07680          /* T309 is not enabled : destroy calls when alarm occurs */
07681          if (p->call) {
07682             pri_destroycall(p->pri->pri, p->call);
07683             p->call = NULL;
07684          }
07685          if (p->owner)
07686             p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
07687       }
07688    }
07689    sig_pri_span_devstate_changed(p->pri);
07690    pri_rel(p->pri);
07691 }

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

References ast_free.

Referenced by destroy_dahdi_pvt().

07722 {
07723    ast_free(doomed);
07724 }

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

References ast_calloc, and sig_pri_chan::pri.

07694 {
07695    struct sig_pri_chan *p;
07696 
07697    p = ast_calloc(1, sizeof(*p));
07698    if (!p)
07699       return p;
07700 
07701    p->logicalspan = logicalspan;
07702    p->prioffset = channo;
07703    p->mastertrunkgroup = trunkgroup;
07704 
07705    p->calls = callback;
07706    p->chan_pvt = pvt_data;
07707 
07708    p->pri = pri;
07709 
07710    return p;
07711 }

void sig_pri_cli_show_channels ( int  fd,
struct sig_pri_span pri 
)

Definition at line 7734 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().

07735 {
07736    char line[256];
07737    int idx;
07738    struct sig_pri_chan *pvt;
07739 
07740    ast_mutex_lock(&pri->lock);
07741    for (idx = 0; idx < pri->numchans; ++idx) {
07742       if (!pri->pvts[idx]) {
07743          continue;
07744       }
07745       pvt = pri->pvts[idx];
07746       sig_pri_lock_private(pvt);
07747       sig_pri_lock_owner(pri, idx);
07748       if (pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
07749          /* Don't show held/call-waiting channels if they are not in use. */
07750          sig_pri_unlock_private(pvt);
07751          continue;
07752       }
07753 
07754       snprintf(line, sizeof(line), SIG_PRI_SC_LINE,
07755          pri->span,
07756          pvt->channel,
07757          pvt->no_b_channel ? "No" : "Yes",/* Has media */
07758          sig_pri_is_chan_available(pvt) ? "Yes" : "No",
07759          sig_pri_call_level2str(pvt->call_level),
07760          pvt->call ? "Yes" : "No",
07761          pvt->owner ? pvt->owner->name : "");
07762 
07763       if (pvt->owner) {
07764          ast_channel_unlock(pvt->owner);
07765       }
07766       sig_pri_unlock_private(pvt);
07767 
07768       ast_mutex_unlock(&pri->lock);
07769       ast_cli(fd, "%s\n", line);
07770       ast_mutex_lock(&pri->lock);
07771    }
07772    ast_mutex_unlock(&pri->lock);
07773 }

void sig_pri_cli_show_channels_header ( int  fd  ) 

Definition at line 7728 of file sig_pri.c.

References ast_cli(), and SIG_PRI_SC_HEADER.

Referenced by handle_pri_show_channels().

07729 {
07730    ast_cli(fd, SIG_PRI_SC_HEADER, "PRI",  "",     "B",    "Chan", "Call",  "PRI",  "Channel");
07731    ast_cli(fd, SIG_PRI_SC_HEADER, "Span", "Chan", "Chan", "Idle", "Level", "Call", "Name");
07732 }

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

Definition at line 7806 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().

07807 {
07808    int x;
07809    char status[256];
07810 
07811    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
07812       if (pri->dchans[x]) {
07813 #ifdef PRI_DUMP_INFO_STR
07814          char *info_str = NULL;
07815 #endif
07816          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), dchannels[x]);
07817          build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
07818          ast_cli(fd, "Status: %s\n", status);
07819          ast_mutex_lock(&pri->lock);
07820 #ifdef PRI_DUMP_INFO_STR
07821          info_str = pri_dump_info_str(pri->pri);
07822          if (info_str) {
07823             ast_cli(fd, "%s", info_str);
07824             free(info_str);
07825          }
07826 #else
07827          pri_dump_info(pri->pri);
07828 #endif
07829          ast_mutex_unlock(&pri->lock);
07830          ast_cli(fd, "Overlap Recv: %s\n\n", (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
07831          ast_cli(fd, "\n");
07832       }
07833    }
07834 }

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

Definition at line 7794 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().

07795 {
07796    char status[256];
07797    int x;
07798    for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
07799       if (pri->dchans[x]) {
07800          build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
07801          ast_cli(fd, "PRI span %d/%d: %s\n", span, x, status);
07802       }
07803    }
07804 }

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

Definition at line 7445 of file sig_pri.c.

References sig_pri_chan::channel.

Referenced by sig_pri_sort_pri_chans().

07446 {
07447    const struct sig_pri_chan *pvt_left;
07448    const struct sig_pri_chan *pvt_right;
07449 
07450    pvt_left = *(struct sig_pri_chan **) left;
07451    pvt_right = *(struct sig_pri_chan **) right;
07452    if (!pvt_left) {
07453       if (!pvt_right) {
07454          return 0;
07455       }
07456       return 1;
07457    }
07458    if (!pvt_right) {
07459       return -1;
07460    }
07461 
07462    return pvt_left->channel - pvt_right->channel;
07463 }

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

Definition at line 7193 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().

07194 {
07195    struct sig_pri_chan *cw;
07196    int idx;
07197 
07198    cw = NULL;
07199    if (pri->num_call_waiting_calls < pri->max_call_waiting_calls) {
07200       if (!pri->num_call_waiting_calls) {
07201          /*
07202           * There are no outstanding call waiting calls.  Check to see
07203           * if the span is in a congested state for the first call
07204           * waiting call.
07205           */
07206          for (idx = 0; idx < pri->numchans; ++idx) {
07207             if (pri->pvts[idx] && sig_pri_available_check(pri->pvts[idx])) {
07208                /* There is another channel that is available on this span. */
07209                return cw;
07210             }
07211          }
07212       }
07213       idx = pri_find_empty_nobch(pri);
07214       if (0 <= idx) {
07215          /* Setup the call waiting interface to use. */
07216          cw = pri->pvts[idx];
07217          cw->is_call_waiting = 1;
07218          sig_pri_init_config(cw, pri);
07219          ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, 1);
07220       }
07221    }
07222    return cw;
07223 }

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

Definition at line 7274 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().

07275 {
07276    if (ast->_state == AST_STATE_DIALING) {
07277       if (pvt->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
07278          unsigned int len;
07279 
07280          len = strlen(pvt->dialdest);
07281          if (len < sizeof(pvt->dialdest) - 1) {
07282             ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
07283                digit);
07284             pvt->dialdest[len++] = digit;
07285             pvt->dialdest[len] = '\0';
07286          } else {
07287             ast_log(LOG_WARNING,
07288                "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
07289                pvt->pri->span, digit);
07290          }
07291          return 0;
07292       }
07293       if (pvt->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
07294          pri_grab(pvt, pvt->pri);
07295          pri_information(pvt->pri->pri, pvt->call, digit);
07296          pri_rel(pvt->pri);
07297          return 0;
07298       }
07299       if (pvt->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
07300          ast_log(LOG_WARNING,
07301             "Span %d: Digit '%c' may be ignored by peer. (Call level:%d(%s))\n",
07302             pvt->pri->span, digit, pvt->call_level,
07303             sig_pri_call_level2str(pvt->call_level));
07304       }
07305    }
07306    return 1;
07307 }

static void sig_pri_dsp_reset_and_flush_digits ( struct sig_pri_chan p  )  [static]

Definition at line 882 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().

00883 {
00884    if (p->calls->dsp_reset_and_flush_digits) {
00885       p->calls->dsp_reset_and_flush_digits(p->chan_pvt);
00886    }
00887 }

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

Definition at line 2131 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().

02132 {
02133    int pres;
02134 
02135    /* Combined party presentation */
02136    pres = ast_party_id_presentation(party);
02137    ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix, pres,
02138       ast_describe_caller_presentation(pres));
02139 
02140    /* Party number */
02141    ast_str_append(msg, 0, "%sNumValid: %d\r\n", prefix,
02142       (unsigned) party->number.valid);
02143    ast_str_append(msg, 0, "%sNum: %s\r\n", prefix,
02144       S_COR(party->number.valid, party->number.str, ""));
02145    ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number.plan);
02146    if (party->number.valid) {
02147       ast_str_append(msg, 0, "%sNumPlan: %d\r\n", prefix, party->number.plan);
02148       ast_str_append(msg, 0, "%sNumPres: %d (%s)\r\n", prefix,
02149          party->number.presentation,
02150          ast_describe_caller_presentation(party->number.presentation));
02151    }
02152 
02153    /* Party name */
02154    ast_str_append(msg, 0, "%sNameValid: %d\r\n", prefix,
02155       (unsigned) party->name.valid);
02156    ast_str_append(msg, 0, "%sName: %s\r\n", prefix,
02157       S_COR(party->name.valid, party->name.str, ""));
02158    if (party->name.valid) {
02159       ast_str_append(msg, 0, "%sNameCharSet: %s\r\n", prefix,
02160          ast_party_name_charset_describe(party->name.char_set));
02161       ast_str_append(msg, 0, "%sNamePres: %d (%s)\r\n", prefix,
02162          party->name.presentation,
02163          ast_describe_caller_presentation(party->name.presentation));
02164    }
02165 
02166 #if defined(HAVE_PRI_SUBADDR)
02167    /* Party subaddress */
02168    if (party->subaddress.valid) {
02169       static const char subaddress[] = "Subaddr";
02170 
02171       ast_str_append(msg, 0, "%s%s: %s\r\n", prefix, subaddress,
02172          S_OR(party->subaddress.str, ""));
02173       ast_str_append(msg, 0, "%s%sType: %d\r\n", prefix, subaddress,
02174          party->subaddress.type);
02175       ast_str_append(msg, 0, "%s%sOdd: %d\r\n", prefix, subaddress,
02176          party->subaddress.odd_even_indicator);
02177    }
02178 #endif   /* defined(HAVE_PRI_SUBADDR) */
02179 }

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 6392 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().

06393 {
06394    char *dial;
06395    char *number;
06396    char *subaddr;
06397    AST_DECLARE_APP_ARGS(args,
06398       AST_APP_ARG(group);  /* channel/group token */
06399       AST_APP_ARG(ext); /* extension token */
06400       //AST_APP_ARG(opts); /* options token */
06401       AST_APP_ARG(other);  /* Any remining unused arguments */
06402    );
06403 
06404    /* Get private copy of dial string and break it up. */
06405    dial = ast_strdupa(rdest);
06406    AST_NONSTANDARD_APP_ARGS(args, dial, '/');
06407 
06408    number = args.ext;
06409    if (!number) {
06410       number = "";
06411    }
06412 
06413    /* Find and extract dialed_subaddress */
06414    subaddr = strchr(number, ':');
06415    if (subaddr) {
06416       *subaddr++ = '\0';
06417 
06418       /* Skip subaddress type prefix. */
06419       switch (*subaddr) {
06420       case 'U':
06421       case 'u':
06422       case 'N':
06423       case 'n':
06424          ++subaddr;
06425          break;
06426       default:
06427          break;
06428       }
06429    }
06430 
06431    /* Skip type-of-number/dial-plan prefix characters. */
06432    if (strlen(number) < p->stripmsd) {
06433       number = "";
06434    } else {
06435       number += p->stripmsd;
06436       while (isalpha(*number)) {
06437          ++number;
06438       }
06439    }
06440 
06441    /* Fill buffer with extracted number and subaddress. */
06442    if (ast_strlen_zero(subaddr)) {
06443       /* Put in called number only since there is no subaddress. */
06444       snprintf(called, called_buff_size, "%s", number);
06445    } else {
06446       /* Put in called number and subaddress. */
06447       snprintf(called, called_buff_size, "%s:%s", number, subaddr);
06448    }
06449 }

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 2484 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().

02485 {
02486    struct sig_pri_cc_agent_prv finder = {
02487       .pri = pri,
02488       .cc_id = cc_id,
02489    };
02490 
02491    return ast_cc_agent_callback(0, sig_pri_cc_agent_cmp_cc_id, &finder,
02492       sig_pri_cc_type_name);
02493 }

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 2535 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().

02536 {
02537    struct sig_pri_cc_monitor_instance finder = {
02538       .pri = pri,
02539       .cc_id = cc_id,
02540    };
02541 
02542    return ao2_callback(sig_pri_cc_monitors, 0, sig_pri_cc_monitor_cmp_cc_id, &finder);
02543 }

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

Definition at line 7886 of file sig_pri.c.

References sig_pri_chan::owner.

07887 {
07888    if (pchan->owner == oldchan) {
07889       pchan->owner = newchan;
07890    }
07891 }

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

Definition at line 897 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().

00898 {
00899    if (old_chan->calls->fixup_chans)
00900       old_chan->calls->fixup_chans(old_chan->chan_pvt, new_chan->chan_pvt);
00901 }

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

Definition at line 196 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().

00197 {
00198    if (p->calls->get_orig_dialstring) {
00199       return p->calls->get_orig_dialstring(p->chan_pvt);
00200    }
00201    ast_log(LOG_ERROR, "get_orig_dialstring callback not defined\n");
00202    return "";
00203 }

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 3804 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.

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

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

Definition at line 160 of file sig_pri.c.

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

Referenced by pri_dchannel().

00161 {
00162    if (pri->calls->handle_dchan_exception)
00163       pri->calls->handle_dchan_exception(pri, index);
00164 }

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

Definition at line 4415 of file sig_pri.c.

References ast_bridged_channel(), ast_channel_unlock, AST_CONTROL_HOLD, AST_FRAME_CONTROL, ast_log(), ast_queue_frame(), 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_handle_subcmds(), sig_pri_lock_owner(), sig_pri_lock_private(), sig_pri_span_devstate_changed(), sig_pri_unlock_private(), and sig_pri_span::span.

04416 {
04417    int retval;
04418    int chanpos_old;
04419    int chanpos_new;
04420    struct ast_channel *bridged;
04421    struct ast_channel *owner;
04422 
04423    chanpos_old = pri_find_principle_by_call(pri, ev->hold.call);
04424    if (chanpos_old < 0) {
04425       ast_log(LOG_WARNING, "Span %d: Received HOLD for unknown call.\n", pri->span);
04426       return -1;
04427    }
04428    if (pri->pvts[chanpos_old]->no_b_channel) {
04429       /* Call is already on hold or is call waiting call. */
04430       return -1;
04431    }
04432 
04433    chanpos_new = -1;
04434 
04435    sig_pri_lock_private(pri->pvts[chanpos_old]);
04436    sig_pri_lock_owner(pri, chanpos_old);
04437    owner = pri->pvts[chanpos_old]->owner;
04438    if (!owner) {
04439       goto done_with_private;
04440    }
04441    bridged = ast_bridged_channel(owner);
04442    if (!bridged) {
04443       /* Cannot hold a call that is not bridged. */
04444       goto done_with_owner;
04445    }
04446    chanpos_new = pri_find_empty_nobch(pri);
04447    if (chanpos_new < 0) {
04448       /* No hold channel available. */
04449       goto done_with_owner;
04450    }
04451    sig_pri_handle_subcmds(pri, chanpos_old, ev->e, ev->hold.channel, ev->hold.subcmds,
04452       ev->hold.call);
04453    chanpos_new = pri_fixup_principle(pri, chanpos_new, ev->hold.call);
04454    if (chanpos_new < 0) {
04455       /* Should never happen. */
04456    } else {
04457       struct ast_frame f = { AST_FRAME_CONTROL, };
04458 
04459       /*
04460        * Things are in an odd state here so we cannot use pri_queue_control().
04461        * However, we already have the owner lock so we can simply queue the frame.
04462        */
04463       f.subclass.integer = AST_CONTROL_HOLD;
04464       ast_queue_frame(owner, &f);
04465    }
04466 
04467 done_with_owner:;
04468    ast_channel_unlock(owner);
04469 done_with_private:;
04470    sig_pri_unlock_private(pri->pvts[chanpos_old]);
04471 
04472    if (chanpos_new < 0) {
04473       retval = -1;
04474    } else {
04475       sig_pri_span_devstate_changed(pri);
04476       retval = 0;
04477    }
04478 
04479    return retval;
04480 }

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

Definition at line 4496 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.

04497 {
04498    int chanpos;
04499 
04500    if (!(ev->retrieve.channel & PRI_HELD_CALL)) {
04501       /* The call is not currently held. */
04502       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04503          PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
04504       return;
04505    }
04506    if (pri_find_principle_by_call(pri, ev->retrieve.call) < 0) {
04507       ast_log(LOG_WARNING, "Span %d: Received RETRIEVE for unknown call.\n", pri->span);
04508       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04509          PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
04510       return;
04511    }
04512    if (PRI_CHANNEL(ev->retrieve.channel) == 0xFF) {
04513       chanpos = pri_find_empty_chan(pri, 1);
04514    } else {
04515       chanpos = pri_find_principle(pri,
04516          ev->retrieve.channel & ~PRI_HELD_CALL, ev->retrieve.call);
04517       if (ev->retrieve.flexible
04518          && (chanpos < 0 || !sig_pri_is_chan_available(pri->pvts[chanpos]))) {
04519          /*
04520           * Channel selection is flexible and the requested channel
04521           * is bad or not available.  Pick another channel.
04522           */
04523          chanpos = pri_find_empty_chan(pri, 1);
04524       }
04525    }
04526    if (chanpos < 0) {
04527       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04528          ev->retrieve.flexible ? PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
04529          : PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
04530       return;
04531    }
04532    chanpos = pri_fixup_principle(pri, chanpos, ev->retrieve.call);
04533    if (chanpos < 0) {
04534       /* Channel is already in use. */
04535       pri_retrieve_rej(pri->pri, ev->retrieve.call,
04536          PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
04537       return;
04538    }
04539    sig_pri_lock_private(pri->pvts[chanpos]);
04540    sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.channel,
04541       ev->retrieve.subcmds, ev->retrieve.call);
04542    pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
04543    sig_pri_unlock_private(pri->pvts[chanpos]);
04544    pri_retrieve_ack(pri->pri, ev->retrieve.call,
04545       PVT_TO_CHANNEL(pri->pvts[chanpos]));
04546    sig_pri_span_devstate_changed(pri);
04547 }

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 4060 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().

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

int sig_pri_hangup ( struct sig_pri_chan p,
struct ast_channel ast 
)

Definition at line 6301 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::outgoing, 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_span_devstate_changed(), ast_channel::tech_pvt, sig_pri_chan::user_tag, and sig_pri_chan::waiting_for_aoce.

Referenced by dahdi_hangup().

06302 {
06303    ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
06304    if (!ast->tech_pvt) {
06305       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
06306       return 0;
06307    }
06308 
06309    p->outgoing = 0;
06310    sig_pri_set_digital(p, 0); /* push up to parent for EC*/
06311 #if defined(HAVE_PRI_CALL_WAITING)
06312    if (p->is_call_waiting) {
06313       p->is_call_waiting = 0;
06314       ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
06315    }
06316 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
06317    p->call_level = SIG_PRI_CALL_LEVEL_IDLE;
06318    p->progress = 0;
06319    p->cid_num[0] = '\0';
06320    p->cid_subaddr[0] = '\0';
06321    p->cid_name[0] = '\0';
06322    p->user_tag[0] = '\0';
06323    p->exten[0] = '\0';
06324    sig_pri_set_dialing(p, 0);
06325 
06326    /* Make sure we really have a call */
06327    pri_grab(p, p->pri);
06328    if (p->call) {
06329 #if defined(SUPPORT_USERUSER)
06330       const char *useruser = pbx_builtin_getvar_helper(ast, "USERUSERINFO");
06331 
06332       if (!ast_strlen_zero(useruser)) {
06333          pri_call_set_useruser(p->call, useruser);
06334       }
06335 #endif   /* defined(SUPPORT_USERUSER) */
06336 
06337 #if defined(HAVE_PRI_AOC_EVENTS)
06338       if (p->holding_aoce) {
06339          pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
06340       }
06341 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
06342 
06343       if (p->alreadyhungup) {
06344          ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
06345 
06346          pri_hangup(p->pri->pri, p->call, -1);
06347          p->call = NULL;
06348       } else {
06349          const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
06350          int icause = ast->hangupcause ? ast->hangupcause : -1;
06351 
06352          p->alreadyhungup = 1;
06353          if (!ast_strlen_zero(cause)) {
06354             if (atoi(cause)) {
06355                icause = atoi(cause);
06356             }
06357          }
06358          ast_debug(1,
06359             "Not yet hungup...  Calling hangup with cause %d, and clearing call\n",
06360             icause);
06361 
06362          pri_hangup(p->pri->pri, p->call, icause);
06363       }
06364    }
06365 #if defined(HAVE_PRI_AOC_EVENTS)
06366    p->aoc_s_request_invoke_id_valid = 0;
06367    p->holding_aoce = 0;
06368    p->waiting_for_aoce = 0;
06369 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
06370 
06371    p->allocated = 0;
06372    p->owner = NULL;
06373 
06374    sig_pri_span_devstate_changed(p->pri);
06375    pri_rel(p->pri);
06376    return 0;
06377 }

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

Definition at line 6902 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().

06903 {
06904    int res = -1;
06905 
06906    switch (condition) {
06907    case AST_CONTROL_BUSY:
06908       if (p->priindication_oob || p->no_b_channel) {
06909          chan->hangupcause = AST_CAUSE_USER_BUSY;
06910          chan->_softhangup |= AST_SOFTHANGUP_DEV;
06911          res = 0;
06912          break;
06913       }
06914       res = sig_pri_play_tone(p, SIG_PRI_TONE_BUSY);
06915       if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
06916          chan->hangupcause = AST_CAUSE_USER_BUSY;
06917          p->progress = 1;/* No need to send plain PROGRESS after this. */
06918          if (p->pri && p->pri->pri) {
06919             pri_grab(p, p->pri);
06920 #ifdef HAVE_PRI_PROG_W_CAUSE
06921             pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
06922 #else
06923             pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06924 #endif
06925             pri_rel(p->pri);
06926          }
06927       }
06928       break;
06929    case AST_CONTROL_RINGING:
06930       if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
06931          p->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
06932          if (p->pri && p->pri->pri) {
06933             pri_grab(p, p->pri);
06934             pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
06935                p->no_b_channel || p->digital ? 0 : 1);
06936             pri_rel(p->pri);
06937          }
06938       }
06939       res = sig_pri_play_tone(p, SIG_PRI_TONE_RINGTONE);
06940       if (chan->_state != AST_STATE_UP) {
06941          if (chan->_state != AST_STATE_RING)
06942             ast_setstate(chan, AST_STATE_RINGING);
06943       }
06944       break;
06945    case AST_CONTROL_PROCEEDING:
06946       ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06947       if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
06948          p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
06949          if (p->pri && p->pri->pri) {
06950             pri_grab(p, p->pri);
06951             pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
06952                p->no_b_channel || p->digital ? 0 : 1);
06953             if (!p->no_b_channel && !p->digital) {
06954                sig_pri_set_dialing(p, 0);
06955             }
06956             pri_rel(p->pri);
06957          }
06958       }
06959       /* don't continue in ast_indicate */
06960       res = 0;
06961       break;
06962    case AST_CONTROL_PROGRESS:
06963       ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06964       sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */
06965       if (!p->progress && p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing
06966          && !p->no_b_channel) {
06967          p->progress = 1;/* No need to send plain PROGRESS again. */
06968          if (p->pri && p->pri->pri) {
06969             pri_grab(p, p->pri);
06970 #ifdef HAVE_PRI_PROG_W_CAUSE
06971             pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
06972 #else
06973             pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06974 #endif
06975             pri_rel(p->pri);
06976          }
06977       }
06978       /* don't continue in ast_indicate */
06979       res = 0;
06980       break;
06981    case AST_CONTROL_INCOMPLETE:
06982       /* If we are connected or if we support overlap dialing, wait for additional digits */
06983       if (p->call_level == SIG_PRI_CALL_LEVEL_CONNECT || (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
06984          res = 0;
06985          break;
06986       }
06987       /* Otherwise, treat as congestion */
06988       chan->hangupcause = AST_CAUSE_INVALID_NUMBER_FORMAT;
06989       /* Falls through */
06990    case AST_CONTROL_CONGESTION:
06991       if (p->priindication_oob || p->no_b_channel) {
06992          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
06993          switch (chan->hangupcause) {
06994          case AST_CAUSE_USER_BUSY:
06995          case AST_CAUSE_NORMAL_CLEARING:
06996          case 0:/* Cause has not been set. */
06997             /* Supply a more appropriate cause. */
06998             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06999             break;
07000          default:
07001             break;
07002          }
07003          chan->_softhangup |= AST_SOFTHANGUP_DEV;
07004          res = 0;
07005          break;
07006       }
07007       res = sig_pri_play_tone(p, SIG_PRI_TONE_CONGESTION);
07008       if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
07009          /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
07010          switch (chan->hangupcause) {
07011          case AST_CAUSE_USER_BUSY:
07012          case AST_CAUSE_NORMAL_CLEARING:
07013          case 0:/* Cause has not been set. */
07014             /* Supply a more appropriate cause. */
07015             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07016             break;
07017          default:
07018             break;
07019          }
07020          p->progress = 1;/* No need to send plain PROGRESS after this. */
07021          if (p->pri && p->pri->pri) {
07022             pri_grab(p, p->pri);
07023 #ifdef HAVE_PRI_PROG_W_CAUSE
07024             pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
07025 #else
07026             pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07027 #endif
07028             pri_rel(p->pri);
07029          }
07030       }
07031       break;
07032    case AST_CONTROL_HOLD:
07033       if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07034          pri_grab(p, p->pri);
07035          res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07036          pri_rel(p->pri);
07037       } else
07038          ast_moh_start(chan, data, p->mohinterpret);
07039       break;
07040    case AST_CONTROL_UNHOLD:
07041       if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07042          pri_grab(p, p->pri);
07043          res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07044          pri_rel(p->pri);
07045       } else
07046          ast_moh_stop(chan);
07047       break;
07048    case AST_CONTROL_SRCUPDATE:
07049       res = 0;
07050       break;
07051    case -1:
07052       res = sig_pri_play_tone(p, -1);
07053       break;
07054    case AST_CONTROL_CONNECTED_LINE:
07055       ast_debug(1, "Received AST_CONTROL_CONNECTED_LINE on %s\n", chan->name);
07056       if (p->pri) {
07057          struct pri_party_connected_line connected;
07058 
07059          pri_grab(p, p->pri);
07060          memset(&connected, 0, sizeof(connected));
07061          sig_pri_party_id_from_ast(&connected.id, &chan->connected.id);
07062 
07063          pri_connected_line_update(p->pri->pri, p->call, &connected);
07064          pri_rel(p->pri);
07065       }
07066       break;
07067    case AST_CONTROL_REDIRECTING:
07068       ast_debug(1, "Received AST_CONTROL_REDIRECTING on %s\n", chan->name);
07069       if (p->pri) {
07070          pri_grab(p, p->pri);
07071          sig_pri_redirecting_update(p, chan);
07072          pri_rel(p->pri);
07073       }
07074       break;
07075    case AST_CONTROL_AOC:
07076 #if defined(HAVE_PRI_AOC_EVENTS)
07077       {
07078          struct ast_aoc_decoded *decoded
07079             = ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, chan);
07080          ast_debug(1, "Received AST_CONTROL_AOC on %s\n", chan->name);
07081          if (decoded && p->pri) {
07082             pri_grab(p, p->pri);
07083             switch (ast_aoc_get_msg_type(decoded)) {
07084             case AST_AOC_S:
07085                if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
07086                   sig_pri_aoc_s_from_ast(p, decoded);
07087                }
07088                break;
07089             case AST_AOC_D:
07090                if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
07091                   sig_pri_aoc_d_from_ast(p, decoded);
07092                }
07093                break;
07094             case AST_AOC_E:
07095                if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
07096                   sig_pri_aoc_e_from_ast(p, decoded);
07097                }
07098                /* if hangup was delayed for this AOC-E msg, waiting_for_aoc
07099                 * will be set.  A hangup is already occuring via a timeout during
07100                 * this delay.  Instead of waiting for that timeout to occur, go ahead
07101                 * and initiate the softhangup since the delay is no longer necessary */
07102                if (p->waiting_for_aoce) {
07103                   p->waiting_for_aoce = 0;
07104                   ast_log(LOG_DEBUG,
07105                      "Received final AOC-E msg, continue with hangup on %s\n",
07106                      chan->name);
07107                   ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
07108                }
07109                break;
07110             case AST_AOC_REQUEST:
07111                /* We do not pass through AOC requests, So unless this
07112                 * is an AOC termination request it will be ignored */
07113                if (ast_aoc_get_termination_request(decoded)) {
07114                   pri_hangup(p->pri->pri, p->call, -1);
07115                }
07116                break;
07117             default:
07118                break;
07119             }
07120             pri_rel(p->pri);
07121          }
07122          ast_aoc_destroy_decoded(decoded);
07123       }
07124 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
07125       break;
07126    }
07127 
07128    return res;
07129 }

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

Definition at line 1699 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().

01700 {
01701    pvt->stripmsd = pri->ch_cfg.stripmsd;
01702    pvt->hidecallerid = pri->ch_cfg.hidecallerid;
01703    pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
01704    pvt->immediate = pri->ch_cfg.immediate;
01705    pvt->priexclusive = pri->ch_cfg.priexclusive;
01706    pvt->priindication_oob = pri->ch_cfg.priindication_oob;
01707    pvt->use_callerid = pri->ch_cfg.use_callerid;
01708    pvt->use_callingpres = pri->ch_cfg.use_callingpres;
01709    ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
01710    ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
01711 
01712    if (pri->calls->init_config) {
01713       pri->calls->init_config(pvt->chan_pvt, pri);
01714    }
01715 }

void sig_pri_init_pri ( struct sig_pri_span pri  ) 

Definition at line 6288 of file sig_pri.c.

References ast_mutex_init, AST_PTHREADT_NULL, and SIG_PRI_NUM_DCHANS.

Referenced by load_module().

06289 {
06290    int i;
06291 
06292    memset(pri, 0, sizeof(*pri));
06293 
06294    ast_mutex_init(&pri->lock);
06295 
06296    pri->master = AST_PTHREADT_NULL;
06297    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++)
06298       pri->fds[i] = -1;
06299 }

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 1127 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().

01128 {
01129    return !sig_pri_is_chan_in_use(pvt)
01130 #if defined(HAVE_PRI_SERVICE_MESSAGES)
01131       /* And not out-of-service */
01132       && !pvt->service_status
01133 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
01134       ;
01135 }

static int sig_pri_is_chan_in_use ( struct sig_pri_chan pvt  )  [static]

Definition at line 1114 of file sig_pri.c.

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

Referenced by pri_check_restart(), and sig_pri_is_chan_available().

01115 {
01116    return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
01117 }

static int sig_pri_is_cis_call ( int  channel  )  [static]

Definition at line 3782 of file sig_pri.c.

References PRI_CIS_CALL.

03783 {
03784    return channel != -1 && (channel & PRI_CIS_CALL);
03785 }

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

Definition at line 1261 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().

01262 {
01263    int chanpos;
01264 
01265    chanpos = pri_find_principle_by_call(pri, call);
01266    if (chanpos < 0) {
01267       pri_hangup(pri->pri, call, cause);
01268       return;
01269    }
01270    sig_pri_lock_private(pri->pvts[chanpos]);
01271    if (!pri->pvts[chanpos]->owner) {
01272       pri_hangup(pri->pri, call, cause);
01273       pri->pvts[chanpos]->call = NULL;
01274       sig_pri_unlock_private(pri->pvts[chanpos]);
01275       sig_pri_span_devstate_changed(pri);
01276       return;
01277    }
01278    pri->pvts[chanpos]->owner->hangupcause = cause;
01279    pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
01280    sig_pri_unlock_private(pri->pvts[chanpos]);
01281 }

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 8498 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().

08499 {
08500 #if defined(HAVE_PRI_CCSS)
08501    sig_pri_cc_type_name = cc_type_name;
08502    sig_pri_cc_monitors = ao2_container_alloc(37, sig_pri_cc_monitor_instance_hash_fn,
08503       sig_pri_cc_monitor_instance_cmp_fn);
08504    if (!sig_pri_cc_monitors) {
08505       return -1;
08506    }
08507 #endif   /* defined(HAVE_PRI_CCSS) */
08508    return 0;
08509 }

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

Definition at line 1150 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().

01151 {
01152    for (;;) {
01153       if (!pri->pvts[chanpos]->owner) {
01154          /* There is no owner lock to get. */
01155          break;
01156       }
01157       if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
01158          /* We got the lock */
01159          break;
01160       }
01161       /* We must unlock the PRI to avoid the possibility of a deadlock */
01162       ast_mutex_unlock(&pri->lock);
01163       PRI_DEADLOCK_AVOIDANCE(pri->pvts[chanpos]);
01164       ast_mutex_lock(&pri->lock);
01165    }
01166 }

static void sig_pri_lock_private ( struct sig_pri_chan p  )  [static]

Definition at line 318 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_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().

00319 {
00320    if (p->calls->lock_private)
00321       p->calls->lock_private(p->chan_pvt);
00322 }

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

Definition at line 206 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().

00207 {
00208    if (p->calls->make_cc_dialstring) {
00209       p->calls->make_cc_dialstring(p->chan_pvt, buf, buf_size);
00210    } else {
00211       ast_log(LOG_ERROR, "make_cc_dialstring callback not defined\n");
00212       buf[0] = '\0';
00213    }
00214 }

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 2198 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().

02199 {
02200    struct ast_channel *chans[1];
02201    struct ast_str *msg;
02202    struct ast_party_id party;
02203 
02204    msg = ast_str_create(4096);
02205    if (!msg) {
02206       return;
02207    }
02208 
02209    if (owner) {
02210       /* The owner channel is present. */
02211       ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name);
02212       ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid);
02213 
02214       sig_pri_event_party_id(&msg, "CallerID", &owner->connected.id);
02215    } else {
02216       /*
02217        * Since we no longer have an owner channel,
02218        * we have to use the caller information supplied by libpri.
02219        */
02220       ast_party_id_init(&party);
02221       sig_pri_party_id_convert(&party, &mcid->originator, pri);
02222       sig_pri_event_party_id(&msg, "CallerID", &party);
02223       ast_party_id_free(&party);
02224    }
02225 
02226    /* Always use libpri's called party information. */
02227    ast_party_id_init(&party);
02228    sig_pri_party_id_convert(&party, &mcid->answerer, pri);
02229    sig_pri_event_party_id(&msg, "ConnectedID", &party);
02230    ast_party_id_free(&party);
02231 
02232    chans[0] = owner;
02233    ast_manager_event_multichan(EVENT_FLAG_CALL, "MCID", owner ? 1 : 0, chans, "%s",
02234       ast_str_buffer(msg));
02235    ast_free(msg);
02236 }

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

Definition at line 2097 of file sig_pri.c.

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

02098 {
02099    char *pattern;
02100    char *msn_list;
02101    char *list_tail;
02102 
02103    msn_list = ast_strdupa(msn_patterns);
02104 
02105    list_tail = NULL;
02106    pattern = strtok_r(msn_list, ",", &list_tail);
02107    while (pattern) {
02108       pattern = ast_strip(pattern);
02109       if (!ast_strlen_zero(pattern) && ast_extension_match(pattern, exten)) {
02110          /* Extension matched the pattern. */
02111          return 1;
02112       }
02113       pattern = strtok_r(NULL, ",", &list_tail);
02114    }
02115    /* Did not match any pattern in the list. */
02116    return 0;
02117 }

static void sig_pri_mwi_cache_update ( struct sig_pri_span pri  )  [static]

Definition at line 7382 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.

07383 {
07384    int idx;
07385    int num_messages;
07386    struct ast_event *event;
07387 
07388    for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
07389       if (!pri->mbox[idx].sub) {
07390          /* There are no more mailboxes on this span. */
07391          break;
07392       }
07393 
07394       event = ast_event_get_cached(AST_EVENT_MWI,
07395          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, pri->mbox[idx].number,
07396          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, pri->mbox[idx].context,
07397          AST_EVENT_IE_END);
07398       if (!event) {
07399          /* No cached event for this mailbox. */
07400          continue;
07401       }
07402       num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
07403       sig_pri_send_mwi_indication(pri, pri->mbox[idx].number, pri->mbox[idx].context,
07404          num_messages);
07405       ast_event_destroy(event);
07406    }
07407 }

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

Definition at line 7352 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().

07353 {
07354    struct sig_pri_span *pri = userdata;
07355    const char *mbox_context;
07356    const char *mbox_number;
07357    int num_messages;
07358 
07359    mbox_number = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
07360    if (ast_strlen_zero(mbox_number)) {
07361       return;
07362    }
07363    mbox_context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
07364    if (ast_strlen_zero(mbox_context)) {
07365       return;
07366    }
07367    num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
07368    sig_pri_send_mwi_indication(pri, mbox_number, mbox_context, num_messages);
07369 }

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 911 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().

00912 {
00913    struct ast_channel *c;
00914 
00915    if (p->calls->new_ast_channel) {
00916       c = p->calls->new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor);
00917    } else {
00918       return NULL;
00919    }
00920    if (!c) {
00921       return NULL;
00922    }
00923 
00924    if (!p->owner)
00925       p->owner = c;
00926    p->isidlecall = 0;
00927    p->alreadyhungup = 0;
00928    c->transfercapability = transfercapability;
00929    pbx_builtin_setvar_helper(c, "TRANSFERCAPABILITY",
00930       ast_transfercapability2str(transfercapability));
00931    if (transfercapability & AST_TRANS_CAP_DIGITAL) {
00932       sig_pri_set_digital(p, 1);
00933    }
00934    if (p->pri) {
00935       ast_mutex_lock(&p->pri->lock);
00936       sig_pri_span_devstate_changed(p->pri);
00937       ast_mutex_unlock(&p->pri->lock);
00938    }
00939 
00940    return c;
00941 }

static void sig_pri_open_media ( struct sig_pri_chan p  )  [static]

Definition at line 952 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(), and sig_pri_answer().

00953 {
00954    if (p->no_b_channel) {
00955       return;
00956    }
00957 
00958    if (p->calls->open_media) {
00959       p->calls->open_media(p->chan_pvt);
00960    }
00961 }

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 2043 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().

02044 {
02045    if (pri_id->name.valid) {
02046       sig_pri_party_name_convert(&ast_id->name, &pri_id->name);
02047    }
02048    if (pri_id->number.valid) {
02049       sig_pri_party_number_convert(&ast_id->number, &pri_id->number, pri);
02050    }
02051 #if defined(HAVE_PRI_SUBADDR)
02052    if (pri_id->subaddress.valid) {
02053       sig_pri_set_subaddress(&ast_id->subaddress, &pri_id->subaddress);
02054    }
02055 #endif   /* defined(HAVE_PRI_SUBADDR) */
02056 }

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 837 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().

00838 {
00839    sig_pri_party_name_from_ast(&pri_id->name, &ast_id->name);
00840    sig_pri_party_number_from_ast(&pri_id->number, &ast_id->number);
00841 #if defined(HAVE_PRI_SUBADDR)
00842    sig_pri_party_subaddress_from_ast(&pri_id->subaddress, &ast_id->subaddress);
00843 #endif   /* defined(HAVE_PRI_SUBADDR) */
00844 }

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

Definition at line 1995 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().

01996 {
01997    ast_name->str = ast_strdup(pri_name->str);
01998    ast_name->char_set = pri_to_ast_char_set(pri_name->char_set);
01999    ast_name->presentation = pri_to_ast_presentation(pri_name->presentation);
02000    ast_name->valid = 1;
02001 }

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 787 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().

00788 {
00789    if (!ast_name->valid) {
00790       return;
00791    }
00792    pri_name->valid = 1;
00793    pri_name->presentation = ast_to_pri_presentation(ast_name->presentation);
00794    pri_name->char_set = ast_to_pri_char_set(ast_name->char_set);
00795    if (!ast_strlen_zero(ast_name->str)) {
00796       ast_copy_string(pri_name->str, ast_name->str, sizeof(pri_name->str));
00797    }
00798 }

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 2017 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().

02018 {
02019    char number[AST_MAX_EXTENSION];
02020 
02021    apply_plan_to_existing_number(number, sizeof(number), pri, pri_number->str,
02022       pri_number->plan);
02023    ast_number->str = ast_strdup(number);
02024    ast_number->plan = pri_number->plan;
02025    ast_number->presentation = pri_to_ast_presentation(pri_number->presentation);
02026    ast_number->valid = 1;
02027 }

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 812 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().

00813 {
00814    if (!ast_number->valid) {
00815       return;
00816    }
00817    pri_number->valid = 1;
00818    pri_number->presentation = ast_to_pri_presentation(ast_number->presentation);
00819    pri_number->plan = ast_number->plan;
00820    if (!ast_strlen_zero(ast_number->str)) {
00821       ast_copy_string(pri_number->str, ast_number->str, sizeof(pri_number->str));
00822    }
00823 }

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 741 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().

00742 {
00743    if (ast_subaddress->valid && !ast_strlen_zero(ast_subaddress->str)) {
00744       pri_subaddress->type = ast_subaddress->type;
00745       if (!ast_subaddress->type) {
00746          /* 0 = NSAP */
00747          ast_copy_string((char *) pri_subaddress->data, ast_subaddress->str,
00748             sizeof(pri_subaddress->data));
00749          pri_subaddress->length = strlen((char *) pri_subaddress->data);
00750          pri_subaddress->odd_even_indicator = 0;
00751          pri_subaddress->valid = 1;
00752       } else {
00753          /* 2 = User Specified */
00754          /*
00755           * Copy HexString to packed HexData,
00756           * if odd length then right pad trailing byte with 0
00757           */
00758          int length = ast_pri_pack_hex_string(pri_subaddress->data,
00759             ast_subaddress->str, sizeof(pri_subaddress->data));
00760 
00761          pri_subaddress->length = length; /* packed data length */
00762 
00763          length = strlen(ast_subaddress->str);
00764          if (length > 2 * sizeof(pri_subaddress->data)) {
00765             pri_subaddress->odd_even_indicator = 0;
00766          } else {
00767             pri_subaddress->odd_even_indicator = (length & 1);
00768          }
00769          pri_subaddress->valid = 1;
00770       }
00771    }
00772 }

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

Definition at line 903 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().

00904 {
00905    if (p->calls->play_tone)
00906       return p->calls->play_tone(p->chan_pvt, tone);
00907    else
00908       return -1;
00909 }

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 2073 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().

02077 {
02078    ast_party_redirecting_set_init(ast_redirecting, ast_guide);
02079 
02080    sig_pri_party_id_convert(&ast_redirecting->from, &pri_redirecting->from, pri);
02081    sig_pri_party_id_convert(&ast_redirecting->to, &pri_redirecting->to, pri);
02082    ast_redirecting->count = pri_redirecting->count;
02083    ast_redirecting->reason = pri_to_ast_reason(pri_redirecting->reason);
02084 }

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

Definition at line 858 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().

00859 {
00860    struct pri_party_redirecting pri_redirecting;
00861 
00862 /*! \todo XXX Original called data can be put in a channel data store that is inherited. */
00863 
00864    memset(&pri_redirecting, 0, sizeof(pri_redirecting));
00865    sig_pri_party_id_from_ast(&pri_redirecting.from, &ast->redirecting.from);
00866    sig_pri_party_id_from_ast(&pri_redirecting.to, &ast->redirecting.to);
00867    pri_redirecting.count = ast->redirecting.count;
00868    pri_redirecting.reason = ast_to_pri_reason(ast->redirecting.reason);
00869 
00870    pri_redirecting_update(pvt->pri->pri, pvt->call, &pri_redirecting);
00871 }

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

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

Referenced by dahdi_request(), and pri_dchannel().

00982 {
00983    struct ast_channel *ast;
00984 
00985    ast_log(LOG_DEBUG, "%s %d\n", __FUNCTION__, p->channel);
00986 
00987    p->outgoing = 1;
00988    ast = sig_pri_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
00989    if (!ast) {
00990       p->outgoing = 0;
00991    }
00992    return ast;
00993 }

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

Definition at line 3727 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.

03728 {
03729    struct sig_pri_chan *pvt;
03730    struct ast_aoc_decoded *decoded = NULL;
03731    struct ast_aoc_encoded *encoded = NULL;
03732    size_t encoded_size;
03733    struct timeval whentohangup = { 0, };
03734 
03735    sig_pri_lock_owner(pri, chanpos);
03736    pvt = pri->pvts[chanpos];
03737    if (!pvt->owner) {
03738       return;
03739    }
03740 
03741    if (!(decoded = ast_aoc_create(AST_AOC_REQUEST, 0, AST_AOC_REQUEST_E))) {
03742       ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
03743       goto cleanup_termination_request;
03744    }
03745 
03746    ast_aoc_set_termination_request(decoded);
03747 
03748    if (!(encoded = ast_aoc_encode(decoded, &encoded_size, pvt->owner))) {
03749       ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
03750       goto cleanup_termination_request;
03751    }
03752 
03753    /* convert ms to timeval */
03754    whentohangup.tv_usec = (ms % 1000) * 1000;
03755    whentohangup.tv_sec = ms / 1000;
03756 
03757    if (ast_queue_control_data(pvt->owner, AST_CONTROL_AOC, encoded, encoded_size)) {
03758       ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
03759       goto cleanup_termination_request;
03760    }
03761 
03762    pvt->waiting_for_aoce = 1;
03763    ast_channel_setwhentohangup_tv(pvt->owner, whentohangup);
03764    ast_log(LOG_DEBUG, "Delaying hangup on %s for aoc-e msg\n", pvt->owner->name);
03765 
03766 cleanup_termination_request:
03767    ast_channel_unlock(pvt->owner);
03768    ast_aoc_destroy_decoded(decoded);
03769    ast_aoc_destroy_encoded(encoded);
03770 }

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 7322 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().

07323 {
07324    struct pri_party_id mailbox;
07325 
07326    ast_debug(1, "Send MWI indication for %s@%s num_messages:%d\n", mbox_number,
07327       mbox_context, num_messages);
07328 
07329    memset(&mailbox, 0, sizeof(mailbox));
07330    mailbox.number.valid = 1;
07331    mailbox.number.presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
07332    mailbox.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_UNKNOWN;
07333    ast_copy_string(mailbox.number.str, mbox_number, sizeof(mailbox.number.str));
07334 
07335    ast_mutex_lock(&pri->lock);
07336    pri_mwi_indicate(pri->pri, &mailbox, 1 /* speech */, num_messages, NULL, NULL, -1, 0);
07337    ast_mutex_unlock(&pri->lock);
07338 }

void sig_pri_set_alarm ( struct sig_pri_chan p,
int  in_alarm 
)

Definition at line 181 of file sig_pri.c.

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

Referenced by sig_pri_chan_alarm_notify().

00182 {
00183    /*
00184     * Clear the channel restart flag when the channel alarm changes
00185     * to prevent the flag from getting stuck when the link goes
00186     * down.
00187     */
00188    p->resetting = 0;
00189 
00190    p->inalarm = in_alarm;
00191    if (p->calls->set_alarm) {
00192       p->calls->set_alarm(p->chan_pvt, in_alarm);
00193    }
00194 }

static void sig_pri_set_caller_id ( struct sig_pri_chan p  )  [static]

Definition at line 244 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().

00245 {
00246    struct ast_party_caller caller;
00247 
00248    if (p->calls->set_callerid) {
00249       ast_party_caller_init(&caller);
00250 
00251       caller.id.name.str = p->cid_name;
00252       caller.id.name.presentation = p->callingpres;
00253       caller.id.name.valid = 1;
00254 
00255       caller.id.number.str = p->cid_num;
00256       caller.id.number.plan = p->cid_ton;
00257       caller.id.number.presentation = p->callingpres;
00258       caller.id.number.valid = 1;
00259 
00260       if (!ast_strlen_zero(p->cid_subaddr)) {
00261          caller.id.subaddress.valid = 1;
00262          //caller.id.subaddress.type = 0;/* nsap */
00263          //caller.id.subaddress.odd_even_indicator = 0;
00264          caller.id.subaddress.str = p->cid_subaddr;
00265       }
00266       caller.id.tag = p->user_tag;
00267 
00268       caller.ani.number.str = p->cid_ani;
00269       //caller.ani.number.plan = p->xxx;
00270       //caller.ani.number.presentation = p->xxx;
00271       caller.ani.number.valid = 1;
00272 
00273       caller.ani2 = p->cid_ani2;
00274       p->calls->set_callerid(p->chan_pvt, &caller);
00275    }
00276 }

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

Definition at line 166 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_hangup(), and sig_pri_indicate().

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

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

Definition at line 173 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().

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

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

Definition at line 288 of file sig_pri.c.

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

00289 {
00290    if (p->calls->set_dnid) {
00291       p->calls->set_dnid(p->chan_pvt, dnid);
00292    }
00293 }

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

Definition at line 889 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().

00890 {
00891    if (p->calls->set_echocanceller)
00892       return p->calls->set_echocanceller(p->chan_pvt, enable);
00893    else
00894       return -1;
00895 }

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

Definition at line 305 of file sig_pri.c.

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

00306 {
00307    if (p->calls->set_rdnis) {
00308       p->calls->set_rdnis(p->chan_pvt, rdnis);
00309    }
00310 }

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

Definition at line 619 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().

00620 {
00621    char *cnum, *ptr;
00622    int x, len;
00623 
00624    if (ast_subaddress->str) {
00625       ast_free(ast_subaddress->str);
00626    }
00627    if (pri_subaddress->length <= 0) {
00628       ast_party_subaddress_init(ast_subaddress);
00629       return;
00630    }
00631 
00632    if (!pri_subaddress->type) {
00633       /* NSAP */
00634       ast_subaddress->str = ast_strdup((char *) pri_subaddress->data);
00635    } else {
00636       /* User Specified */
00637       if (!(cnum = ast_malloc(2 * pri_subaddress->length + 1))) {
00638          ast_party_subaddress_init(ast_subaddress);
00639          return;
00640       }
00641 
00642       ptr = cnum;
00643       len = pri_subaddress->length - 1; /* -1 account for zero based indexing */
00644       for (x = 0; x < len; ++x) {
00645          ptr += sprintf(ptr, "%02x", pri_subaddress->data[x]);
00646       }
00647 
00648       if (pri_subaddress->odd_even_indicator) {
00649          /* ODD */
00650          sprintf(ptr, "%01x", (pri_subaddress->data[len]) >> 4);
00651       } else {
00652          /* EVEN */
00653          sprintf(ptr, "%02x", pri_subaddress->data[len]);
00654       }
00655       ast_subaddress->str = cnum;
00656    }
00657    ast_subaddress->type = pri_subaddress->type;
00658    ast_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
00659    ast_subaddress->valid = 1;
00660 }

static void sig_pri_sort_pri_chans ( struct sig_pri_span pri  )  [static]

Definition at line 7478 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().

07479 {
07480    qsort(&pri->pvts, pri->numchans, sizeof(pri->pvts[0]), sig_pri_cmp_pri_chans);
07481 }

static void sig_pri_span_devstate_changed ( struct sig_pri_span pri  )  [static]

Definition at line 228 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().

00229 {
00230    if (pri->calls->update_span_devstate) {
00231       pri->calls->update_span_devstate(pri);
00232    }
00233 }

int sig_pri_start_pri ( struct sig_pri_span pri  ) 

Definition at line 7483 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().

07484 {
07485    int x;
07486    int i;
07487 #if defined(HAVE_PRI_MWI)
07488    char *saveptr;
07489    char *mbox_number;
07490    char *mbox_context;
07491    struct ast_str *mwi_description = ast_str_alloca(64);
07492 #endif   /* defined(HAVE_PRI_MWI) */
07493 
07494 #if defined(HAVE_PRI_MWI)
07495    /* Prepare the mbox[] for use. */
07496    for (i = 0; i < ARRAY_LEN(pri->mbox); ++i) {
07497       if (pri->mbox[i].sub) {
07498          pri->mbox[i].sub = ast_event_unsubscribe(pri->mbox[i].sub);
07499       }
07500    }
07501 #endif   /* defined(HAVE_PRI_MWI) */
07502 
07503    ast_mutex_init(&pri->lock);
07504    sig_pri_sort_pri_chans(pri);
07505 
07506 #if defined(HAVE_PRI_MWI)
07507    /*
07508     * Split the mwi_mailboxes configuration string into the mbox[]:
07509     * mailbox_number[@context]{,mailbox_number[@context]}
07510     */
07511    i = 0;
07512    saveptr = pri->mwi_mailboxes;
07513    while (i < ARRAY_LEN(pri->mbox)) {
07514       mbox_number = strsep(&saveptr, ",");
07515       if (!mbox_number) {
07516          break;
07517       }
07518       /* Split the mailbox_number and context */
07519       mbox_context = strchr(mbox_number, '@');
07520       if (mbox_context) {
07521          *mbox_context++ = '\0';
07522          mbox_context = ast_strip(mbox_context);
07523       }
07524       mbox_number = ast_strip(mbox_number);
07525       if (ast_strlen_zero(mbox_number)) {
07526          /* There is no mailbox number.  Skip it. */
07527          continue;
07528       }
07529       if (ast_strlen_zero(mbox_context)) {
07530          /* There was no context so use the default. */
07531          mbox_context = "default";
07532       }
07533 
07534       /* Fill the mbox[] element. */
07535       ast_str_set(&mwi_description, -1, "%s span %d[%d] MWI mailbox %s@%s",
07536          sig_pri_cc_type_name, pri->span, i, mbox_number, mbox_context);
07537       pri->mbox[i].sub = ast_event_subscribe(AST_EVENT_MWI, sig_pri_mwi_event_cb,
07538          ast_str_buffer(mwi_description), pri,
07539          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox_number,
07540          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mbox_context,
07541          AST_EVENT_IE_END);
07542       if (!pri->mbox[i].sub) {
07543          ast_log(LOG_ERROR, "%s span %d could not subscribe to MWI events for %s@%s.",
07544             sig_pri_cc_type_name, pri->span, mbox_number, mbox_context);
07545          continue;
07546       }
07547       pri->mbox[i].number = mbox_number;
07548       pri->mbox[i].context = mbox_context;
07549       ++i;
07550    }
07551 #endif   /* defined(HAVE_PRI_MWI) */
07552 
07553    for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
07554       if (pri->fds[i] == -1) {
07555          break;
07556       }
07557 
07558       switch (pri->sig) {
07559       case SIG_BRI:
07560          pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
07561          break;
07562       case SIG_BRI_PTMP:
07563          pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
07564          break;
07565       default:
07566          pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
07567 #if defined(HAVE_PRI_SERVICE_MESSAGES)
07568          if (pri->enable_service_message_support) {
07569             pri_set_service_message_support(pri->dchans[i], 1);
07570          }
07571 #endif   /* defined(HAVE_PRI_SERVICE_MESSAGES) */
07572          break;
07573       }
07574 
07575       pri_set_overlapdial(pri->dchans[i], (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING) ? 1 : 0);
07576 #ifdef HAVE_PRI_PROG_W_CAUSE
07577       pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
07578 #endif
07579 #ifdef HAVE_PRI_INBANDDISCONNECT
07580       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
07581 #endif
07582       /* Enslave to master if appropriate */
07583       if (i)
07584          pri_enslave(pri->dchans[0], pri->dchans[i]);
07585       if (!pri->dchans[i]) {
07586          if (pri->fds[i] > 0)
07587             close(pri->fds[i]);
07588          pri->fds[i] = -1;
07589          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
07590          return -1;
07591       }
07592       pri_set_debug(pri->dchans[i], SIG_PRI_DEBUG_DEFAULT);
07593       pri_set_nsf(pri->dchans[i], pri->nsf);
07594 #ifdef PRI_GETSET_TIMERS
07595       for (x = 0; x < PRI_MAX_TIMERS; x++) {
07596          if (pri->pritimers[x] != 0)
07597             pri_set_timer(pri->dchans[i], x, pri->pritimers[x]);
07598       }
07599 #endif
07600    }
07601 
07602    /* Assume primary is the one we use */
07603    pri->pri = pri->dchans[0];
07604 
07605 #if defined(HAVE_PRI_CALL_HOLD)
07606    pri_hold_enable(pri->pri, 1);
07607 #endif   /* defined(HAVE_PRI_CALL_HOLD) */
07608 #if defined(HAVE_PRI_CALL_REROUTING)
07609    pri_reroute_enable(pri->pri, 1);
07610 #endif   /* defined(HAVE_PRI_CALL_REROUTING) */
07611 #if defined(HAVE_PRI_HANGUP_FIX)
07612    pri_hangup_fix_enable(pri->pri, 1);
07613 #endif   /* defined(HAVE_PRI_HANGUP_FIX) */
07614 #if defined(HAVE_PRI_CCSS)
07615    pri_cc_enable(pri->pri, 1);
07616    pri_cc_recall_mode(pri->pri, pri->cc_ptmp_recall_mode);
07617    pri_cc_retain_signaling_req(pri->pri, pri->cc_qsig_signaling_link_req);
07618    pri_cc_retain_signaling_rsp(pri->pri, pri->cc_qsig_signaling_link_rsp);
07619 #endif   /* defined(HAVE_PRI_CCSS) */
07620 #if defined(HAVE_PRI_TRANSFER)
07621    pri_transfer_enable(pri->pri, 1);
07622 #endif   /* defined(HAVE_PRI_TRANSFER) */
07623 #if defined(HAVE_PRI_AOC_EVENTS)
07624    pri_aoc_events_enable(pri->pri, 1);
07625 #endif   /* defined(HAVE_PRI_AOC_EVENTS) */
07626 #if defined(HAVE_PRI_CALL_WAITING)
07627    pri_connect_ack_enable(pri->pri, 1);
07628 #endif   /* defined(HAVE_PRI_CALL_WAITING) */
07629 #if defined(HAVE_PRI_MCID)
07630    pri_mcid_enable(pri->pri, 1);
07631 #endif   /* defined(HAVE_PRI_MCID) */
07632 #if defined(HAVE_PRI_L2_PERSISTENCE)
07633    pri_persistent_layer2_option(pri->pri, pri->l2_persistence);
07634 #endif   /* defined(HAVE_PRI_L2_PERSISTENCE) */
07635 
07636    pri->resetpos = -1;
07637    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
07638       for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
07639          if (!pri->dchans[i])
07640             break;
07641          if (pri->fds[i] > 0)
07642             close(pri->fds[i]);
07643          pri->fds[i] = -1;
07644       }
07645       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
07646       return -1;
07647    }
07648 
07649 #if defined(HAVE_PRI_MWI)
07650    /*
07651     * Send the initial MWI indications from the event cache for this span.
07652     *
07653     * If we were loaded after app_voicemail the event would already be in
07654     * the cache.  If we were loaded before app_voicemail the event would not
07655     * be in the cache yet and app_voicemail will send the event when it
07656     * gets loaded.
07657     */
07658    sig_pri_mwi_cache_update(pri);
07659 #endif   /* defined(HAVE_PRI_MWI) */
07660 
07661    return 0;
07662 }

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

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

Referenced by __unload_module().

07419 {
07420 #if defined(HAVE_PRI_MWI)
07421    int idx;
07422 #endif   /* defined(HAVE_PRI_MWI) */
07423 
07424 #if defined(HAVE_PRI_MWI)
07425    for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
07426       if (pri->mbox[idx].sub) {
07427          pri->mbox[idx].sub = ast_event_unsubscribe(pri->mbox[idx].sub);
07428       }
07429    }
07430 #endif   /* defined(HAVE_PRI_MWI) */
07431 }

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

Definition at line 2260 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().

02261 {
02262    struct xfer_rsp_data *rsp = data;
02263 
02264    pri_transfer_rsp(rsp->pri->pri, rsp->call, rsp->invoke_id, is_successful);
02265 }

void sig_pri_unload ( void   ) 

Unload the sig_pri submodule.

Since:
1.8
Returns:
Nothing

Definition at line 8517 of file sig_pri.c.

References ao2_ref, and sig_pri_cc_monitors.

Referenced by __unload_module().

08518 {
08519 #if defined(HAVE_PRI_CCSS)
08520    if (sig_pri_cc_monitors) {
08521       ao2_ref(sig_pri_cc_monitors, -1);
08522       sig_pri_cc_monitors = NULL;
08523    }
08524 #endif   /* defined(HAVE_PRI_CCSS) */
08525 }

static void sig_pri_unlock_private ( struct sig_pri_chan p  )  [static]

Definition at line 312 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_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().

00313 {
00314    if (p->calls->unlock_private)
00315       p->calls->unlock_private(p->chan_pvt);
00316 }


Variable Documentation

int pri_gendigittimeout = 8000 [static]

Definition at line 103 of file sig_pri.c.

Referenced by pri_ss_thread().

int pri_matchdigittimeout = 3000 [static]

Definition at line 101 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 6468 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 98 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 96 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 Sat Mar 10 01:55:47 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7