#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_instance * | sig_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_chan * | sig_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_chan * | sig_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_agent * | sig_pri_find_cc_agent_by_cc_id (struct sig_pri_span *pri, long cc_id) |
static struct sig_pri_cc_monitor_instance * | sig_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_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 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_channel * | sig_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_container * | sig_pri_cc_monitors |
static const char * | sig_pri_cc_type_name |
Definition in file sig_pri.c.
#define DCHAN_AVAILABLE (DCHAN_NOTINALARM | DCHAN_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) |
#define FORCE_RESTART_UNAVAIL_CHANS 1 |
#define PRI_CHANNEL | ( | p | ) | ((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) |
#define PRI_DEADLOCK_AVOIDANCE | ( | p | ) |
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) |
#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 | ) | (((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" |
#define SIG_PRI_SC_LINE "%4d %4d %-4s %-4s %-10s %-4s %s" |
typedef void(*) xfer_rsp_callback(void *data, int is_successful) |
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 };
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 };
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 | |||
) |
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.
agent | CC core agent control. |
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.
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.
agent | CC core agent control. |
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.
agent | CC core agent control. | |
pvt_chan | Original channel the agent will attempt to recall. |
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.
agent | CC core agent control. |
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.
agent | CC core agent control. | |
reason | CC request response status. |
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.
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.
agent | CC core agent control. |
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.
agent | CC core agent control. |
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.
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.
agent | CC core agent control. |
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.
agent | CC core agent control. |
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.
agent | CC core agent control. |
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.
monitor | CC core monitor control. | |
sched_id | Available timer scheduler id to cancel. Will never be NULL for a device monitor. |
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.
monitor_pvt | CC device monitor private data pointer. |
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.
monitor | CC core monitor control. | |
available_timer_id | Where to put the available timer scheduler id. Will never be NULL for a device monitor. |
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().
monitor | CC core monitor control. | |
devstate | Current status of a Party A device. |
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.
monitor | CC core monitor control. |
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.
monitor | CC core monitor control. |
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.
p | Channel private pointer. | |
noalarm | Non-zero if not in alarm mode. |
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.
doomed | sig_pri private channel structure to delete. |
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.
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. |
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 | |||
) |
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.
pvt | Channel to determine if 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.
cc_type_name | CC type name to use when looking up agent/monitor. |
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.
pri | PRI span control structure. |
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.
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 }
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_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().