PRI signaling module. More...
#include "asterisk.h"#include <errno.h>#include <ctype.h>#include <signal.h>#include "asterisk/utils.h"#include "asterisk/options.h"#include "asterisk/pbx.h"#include "asterisk/app.h"#include "asterisk/file.h"#include "asterisk/callerid.h"#include "asterisk/say.h"#include "asterisk/manager.h"#include "asterisk/astdb.h"#include "asterisk/causes.h"#include "asterisk/musiconhold.h"#include "asterisk/cli.h"#include "asterisk/transcap.h"#include "asterisk/features.h"#include "asterisk/aoc.h"#include "sig_pri.h"
Go to the source code of this file.
Data Structures | |
| struct | sig_pri_cc_agent_prv |
| struct | sig_pri_cc_monitor_instance |
| struct | xfer_rsp_data |
Defines | |
| #define | DCHAN_AVAILABLE (DCHAN_NOTINALARM | DCHAN_UP) |
| #define | DCHAN_NOTINALARM (1 << 0) |
| #define | DCHAN_UP (1 << 1) |
| #define | FORCE_RESTART_UNAVAIL_CHANS 1 |
| #define | PRI_CHANNEL(p) ((p) & 0xff) |
| #define | PRI_CIS_CALL (1 << 17) /* Call is using the D channel only. */ |
| #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 enum sig_pri_moh_state(* | sig_pri_moh_fsm_state )(struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| 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 struct ast_callid * | func_pri_dchannel_chanpos_callid (struct sig_pri_span *pri, int chanpos) |
| static struct ast_callid * | func_pri_dchannel_new_callid (void) |
| 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 void | 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_queue_pvt_cause_data (struct sig_pri_span *pri, int chanpos, const char *cause, int ast_cause) |
| 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) |
| static void | sig_pri_ami_hold_event (struct ast_channel *chan, int is_held) |
| int | sig_pri_ami_show_spans (struct mansession *s, const char *show_cmd, struct sig_pri_span *pri, const int *dchannels, const char *action_id) |
| Output AMI show spans response events for the given PRI span. | |
| 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, const 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. | |
| struct sig_pri_chan * | sig_pri_chan_new (void *pvt_data, 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) |
| static void | sig_pri_deadlock_avoidance_private (struct sig_pri_chan *p) |
| void | sig_pri_dial_complete (struct sig_pri_chan *pvt, struct ast_channel *ast) |
| DTMF dial string complete. | |
| static void | sig_pri_dial_digits (struct sig_pri_chan *p, const char *dial_string) |
| int | sig_pri_digit_begin (struct sig_pri_chan *pvt, struct ast_channel *ast, char digit) |
| static void | sig_pri_dsp_reset_and_flush_digits (struct sig_pri_chan *p) |
| static void | sig_pri_event_party_id (struct ast_str **msg, const char *prefix, struct ast_party_id *party) |
| void | sig_pri_extract_called_num_subaddr (struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size) |
| Extract the called number and subaddress from the dial string. | |
| static struct ast_cc_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_hold_ack (struct sig_pri_span *pri, pri_event *ev) |
| static void | sig_pri_handle_hold_rej (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_retrieve_ack (struct sig_pri_span *pri, pri_event *ev) |
| static void | sig_pri_handle_retrieve_rej (struct sig_pri_span *pri, pri_event *ev) |
| static void | sig_pri_handle_subcmds (struct sig_pri_span *pri, int chanpos, int event_id, const struct pri_subcommands *subcmds, q931_call *call_rsp) |
| int | sig_pri_hangup (struct sig_pri_chan *p, struct ast_channel *ast) |
| int | sig_pri_indicate (struct sig_pri_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen) |
| static void | sig_pri_init_config (struct sig_pri_chan *pvt, struct sig_pri_span *pri) |
| void | sig_pri_init_pri (struct sig_pri_span *pri) |
| int | sig_pri_is_alarm_ignored (struct sig_pri_span *pri) |
| Determine if layer 1 alarms are ignored. | |
| int | sig_pri_is_chan_available (struct sig_pri_chan *pvt) |
| Determine if a private channel structure is available. | |
| static int | sig_pri_is_chan_in_use (struct sig_pri_chan *pvt) |
| static int | sig_pri_is_cis_call (int channel) |
| static void | sig_pri_kill_call (struct sig_pri_span *pri, q931_call *call, int cause) |
| int | sig_pri_load (const char *cc_type_name) |
| Load the sig_pri submodule. | |
| static void | sig_pri_lock_owner (struct sig_pri_span *pri, int chanpos) |
| static void | sig_pri_lock_private (struct sig_pri_chan *p) |
| static void | sig_pri_make_cc_dialstring (struct sig_pri_chan *p, char *buf, size_t buf_size) |
| static void | sig_pri_mcid_event (struct sig_pri_span *pri, const struct pri_subcmd_mcid_req *mcid, struct ast_channel *owner) |
| static const char * | sig_pri_moh_event_str (enum sig_pri_moh_event event) |
| static void | sig_pri_moh_fsm_event (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_hold (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_hold_req (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_idle (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_moh (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_notify (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_pend_hold (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_pend_unhold (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_retrieve_fail (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_fsm_retrieve_req (struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| static enum sig_pri_moh_state | sig_pri_moh_retrieve_call (struct sig_pri_chan *pvt) |
| static const char * | sig_pri_moh_state_str (enum sig_pri_moh_state state) |
| 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) |
| struct 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 *vm_number, const char *mbox_number, const char *mbox_context, int num_messages) |
| void | sig_pri_sendtext (struct sig_pri_chan *p, const char *text) |
| Send display text. | |
| void | sig_pri_set_alarm (struct sig_pri_chan *p, int in_alarm) |
| static void | sig_pri_set_caller_id (struct sig_pri_chan *p) |
| static void | sig_pri_set_dialing (struct sig_pri_chan *p, int is_dialing) |
| static void | sig_pri_set_digital (struct sig_pri_chan *p, int is_digital) |
| static void | sig_pri_set_dnid (struct sig_pri_chan *p, const char *dnid) |
| static int | sig_pri_set_echocanceller (struct sig_pri_chan *p, int enable) |
| static void | sig_pri_set_outgoing (struct sig_pri_chan *p, int is_outgoing) |
| static void | sig_pri_set_rdnis (struct sig_pri_chan *p, const char *rdnis) |
| static void | sig_pri_set_subaddress (struct ast_party_subaddress *ast_subaddress, const struct pri_party_subaddress *pri_subaddress) |
| static void | sig_pri_sort_pri_chans (struct sig_pri_span *pri) |
| static void | sig_pri_span_devstate_changed (struct sig_pri_span *pri) |
| int | sig_pri_start_pri (struct sig_pri_span *pri) |
| void | sig_pri_stop_pri (struct sig_pri_span *pri) |
| Stop PRI span. | |
| static void | sig_pri_transfer_rsp (void *data, int is_successful) |
| void | sig_pri_unload (void) |
| Unload the sig_pri submodule. | |
| static void | sig_pri_unlock_private (struct sig_pri_chan *p) |
Variables | |
| static int | pri_gendigittimeout = 8000 |
| static int | pri_matchdigittimeout = 3000 |
| static struct ast_app_option | sig_pri_call_opts [128] = { [ 'K' ] = { .flag = OPT_KEYPAD , .arg_index = OPT_ARG_KEYPAD + 1 }, [ 'R' ] = { .flag = OPT_REVERSE_CHARGE }, [ 'A' ] = { .flag = OPT_AOC_REQUEST , .arg_index = OPT_ARG_AOC_REQUEST + 1 }, } |
| static struct ao2_container * | sig_pri_cc_monitors |
| static const char * | sig_pri_cc_type_name |
| static const sig_pri_moh_fsm_state | sig_pri_moh_fsm [SIG_PRI_MOH_STATE_NUM] |
PRI signaling module.
Definition in file sig_pri.c.
| #define DCHAN_AVAILABLE (DCHAN_NOTINALARM | DCHAN_UP) |
Definition at line 123 of file sig_pri.c.
Referenced by pri_find_dchan(), and pri_is_up().
| #define DCHAN_NOTINALARM (1 << 0) |
Definition at line 112 of file sig_pri.c.
Referenced by build_status(), pri_event_alarm(), pri_event_noalarm(), and sig_pri_ami_show_spans().
| #define DCHAN_UP (1 << 1) |
Definition at line 113 of file sig_pri.c.
Referenced by build_status(), pri_dchannel(), pri_event_alarm(), and sig_pri_ami_show_spans().
| #define FORCE_RESTART_UNAVAIL_CHANS 1 |
Define to make always pick a channel if allowed. Useful for testing channel shifting.
Define to force a RESTART on a channel that returns a cause code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause is because of a stuck channel on the peer and the channel is always the next channel we pick for an outgoing call then this can help.
| #define PRI_CHANNEL | ( | p | ) | ((p) & 0xff) |
Definition at line 116 of file sig_pri.c.
Referenced by pri_dchannel(), pri_find_fixup_principle(), pri_find_principle(), sig_pri_handle_hold_ack(), and sig_pri_handle_retrieve().
| #define PRI_CIS_CALL (1 << 17) /* Call is using the D channel only. */ |
Definition at line 119 of file sig_pri.c.
Referenced by sig_pri_is_cis_call().
| #define PRI_EXPLICIT (1 << 16) |
Definition at line 118 of file sig_pri.c.
Referenced by pri_find_principle(), and PVT_TO_CHANNEL().
| #define PRI_HELD_CALL (1 << 18) |
Definition at line 120 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 117 of file sig_pri.c.
Referenced by pri_dchannel(), pri_find_fixup_principle(), pri_find_principle(), pri_maintenance_bservice(), and sig_pri_handle_hold_ack().
| #define SIG_PRI_SC_HEADER "%-4s %4s %-4s %-4s %-10s %-4s %s\n" |
Definition at line 9199 of file sig_pri.c.
Referenced by sig_pri_cli_show_channels_header().
| #define SIG_PRI_SC_LINE "%4d %4d %-4s %-4s %-10s %-4s %s" |
Definition at line 9200 of file sig_pri.c.
Referenced by sig_pri_cli_show_channels().
| typedef enum sig_pri_moh_state(* sig_pri_moh_fsm_state)(struct ast_channel *chan, struct sig_pri_chan *pvt, enum sig_pri_moh_event event) |
| typedef void(* xfer_rsp_callback)(void *data, int is_successful) |
Definition at line 7723 of file sig_pri.c.
{
OPT_ARG_KEYPAD = 0,
OPT_ARG_AOC_REQUEST,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE,
};
Definition at line 7718 of file sig_pri.c.
{
OPT_KEYPAD = (1 << 0),
OPT_REVERSE_CHARGE = (1 << 1), /* Collect call */
OPT_AOC_REQUEST = (1 << 2), /* AOC Request */
};
| 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 1715 of file sig_pri.c.
References apply_plan_to_number(), and ast_strlen_zero().
Referenced by pri_dchannel(), and sig_pri_party_number_convert().
{
/* Make sure a number exists so the prefix isn't placed on an empty string. */
if (ast_strlen_zero(number)) {
if (size) {
*buf = '\0';
}
return;
}
apply_plan_to_number(buf, size, pri, number, plan);
}
| 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 1679 of file sig_pri.c.
References sig_pri_span::internationalprefix, sig_pri_span::localprefix, sig_pri_span::nationalprefix, sig_pri_span::privateprefix, and sig_pri_span::unknownprefix.
Referenced by apply_plan_to_existing_number().
{
switch (plan) {
case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
snprintf(buf, size, "%s%s", pri->internationalprefix, number);
break;
case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
snprintf(buf, size, "%s%s", pri->nationalprefix, number);
break;
case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
snprintf(buf, size, "%s%s", pri->localprefix, number);
break;
case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
snprintf(buf, size, "%s%s", pri->privateprefix, number);
break;
case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
snprintf(buf, size, "%s%s", pri->unknownprefix, number);
break;
default: /* other Q.931 dialplan => don't twiddle with callingnum */
snprintf(buf, size, "%s", number);
break;
}
}
| static unsigned char ast_pri_pack_hex_char | ( | char | c | ) | [static] |
Definition at line 712 of file sig_pri.c.
Referenced by ast_pri_pack_hex_string().
{
unsigned char res;
if (c < '0') {
res = 0;
} else if (c < ('9' + 1)) {
res = c - '0';
} else if (c < 'A') {
res = 0;
} else if (c < ('F' + 1)) {
res = c - 'A' + 10;
} else if (c < 'a') {
res = 0;
} else if (c < ('f' + 1)) {
res = c - 'a' + 10;
} else {
res = 0;
}
return res;
}
| static int ast_pri_pack_hex_string | ( | unsigned char * | dst, |
| char * | src, | ||
| int | maxlen | ||
| ) | [static] |
Definition at line 751 of file sig_pri.c.
References ast_pri_pack_hex_char(), and len().
Referenced by sig_pri_party_subaddress_from_ast().
{
int res = 0;
int len = strlen(src);
if (len > (2 * maxlen)) {
len = 2 * maxlen;
}
res = len / 2 + len % 2;
while (len > 1) {
*dst = ast_pri_pack_hex_char(*src) << 4;
src++;
*dst |= ast_pri_pack_hex_char(*src);
dst++, src++;
len -= 2;
}
if (len) { /* 1 left */
*dst = ast_pri_pack_hex_char(*src) << 4;
}
return res;
}
| static int ast_to_pri_char_set | ( | enum AST_PARTY_CHAR_SET | ast_char_set | ) | [static] |
Definition at line 613 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().
{
int pri_char_set;
switch (ast_char_set) {
default:
case AST_PARTY_CHAR_SET_UNKNOWN:
pri_char_set = PRI_CHAR_SET_UNKNOWN;
break;
case AST_PARTY_CHAR_SET_ISO8859_1:
pri_char_set = PRI_CHAR_SET_ISO8859_1;
break;
case AST_PARTY_CHAR_SET_WITHDRAWN:
pri_char_set = PRI_CHAR_SET_WITHDRAWN;
break;
case AST_PARTY_CHAR_SET_ISO8859_2:
pri_char_set = PRI_CHAR_SET_ISO8859_2;
break;
case AST_PARTY_CHAR_SET_ISO8859_3:
pri_char_set = PRI_CHAR_SET_ISO8859_3;
break;
case AST_PARTY_CHAR_SET_ISO8859_4:
pri_char_set = PRI_CHAR_SET_ISO8859_4;
break;
case AST_PARTY_CHAR_SET_ISO8859_5:
pri_char_set = PRI_CHAR_SET_ISO8859_5;
break;
case AST_PARTY_CHAR_SET_ISO8859_7:
pri_char_set = PRI_CHAR_SET_ISO8859_7;
break;
case AST_PARTY_CHAR_SET_ISO10646_BMPSTRING:
pri_char_set = PRI_CHAR_SET_ISO10646_BMPSTRING;
break;
case AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING:
pri_char_set = PRI_CHAR_SET_ISO10646_UTF_8STRING;
break;
}
return pri_char_set;
}
| static int ast_to_pri_presentation | ( | int | ast_presentation | ) | [static] |
Definition at line 508 of file sig_pri.c.
References AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.
Referenced by sig_pri_party_name_from_ast(), and sig_pri_party_number_from_ast().
{
int pri_presentation;
switch (ast_presentation) {
case AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED:
pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
break;
case AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN:
pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN;
break;
case AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN:
pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN;
break;
case AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER:
pri_presentation = PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER;
break;
case AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED:
pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
break;
case AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN:
pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN;
break;
case AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN:
pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN;
break;
case AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER:
pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER;
break;
case AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_UNSCREENED:
case AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_PASSED_SCREEN:
case AST_PRES_UNAVAILABLE | AST_PRES_USER_NUMBER_FAILED_SCREEN:
case AST_PRES_UNAVAILABLE | AST_PRES_NETWORK_NUMBER:
pri_presentation = PRES_NUMBER_NOT_AVAILABLE;
break;
default:
pri_presentation = PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
break;
}
return pri_presentation;
}
| static int ast_to_pri_reason | ( | enum AST_REDIRECTING_REASON | ast_reason | ) | [static] |
Definition at line 418 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().
{
int pri_reason;
switch (ast_reason) {
case AST_REDIRECTING_REASON_USER_BUSY:
pri_reason = PRI_REDIR_FORWARD_ON_BUSY;
break;
case AST_REDIRECTING_REASON_NO_ANSWER:
pri_reason = PRI_REDIR_FORWARD_ON_NO_REPLY;
break;
case AST_REDIRECTING_REASON_UNCONDITIONAL:
pri_reason = PRI_REDIR_UNCONDITIONAL;
break;
case AST_REDIRECTING_REASON_DEFLECTION:
pri_reason = PRI_REDIR_DEFLECTION;
break;
case AST_REDIRECTING_REASON_UNKNOWN:
default:
pri_reason = PRI_REDIR_UNKNOWN;
break;
}
return pri_reason;
}
| static void build_status | ( | char * | s, |
| size_t | len, | ||
| int | status, | ||
| int | active | ||
| ) | [static] |
Definition at line 9248 of file sig_pri.c.
References DCHAN_NOTINALARM, and DCHAN_UP.
Referenced by sig_pri_cli_show_span(), and sig_pri_cli_show_spans().
| static int detect_aoc_e_subcmd | ( | const struct pri_subcommands * | subcmds | ) | [static] |
Definition at line 4133 of file sig_pri.c.
Referenced by pri_dchannel().
{
int i;
if (!subcmds) {
return 0;
}
for (i = 0; i < subcmds->counter_subcmd; ++i) {
const struct pri_subcommand *subcmd = &subcmds->subcmd[i];
if (subcmd->cmd == PRI_SUBCMD_AOC_E) {
return 1;
}
}
return 0;
}
| static char* dialplan2str | ( | int | dialplan | ) | [static] |
Definition at line 1659 of file sig_pri.c.
Referenced by sig_pri_call().
{
if (dialplan == -1) {
return("Dynamically set dialplan in ISDN");
}
return (pri_plan2str(dialplan));
}
| static void* do_idle_thread | ( | void * | v_pvt | ) | [static] |
Definition at line 1879 of file sig_pri.c.
References ast_call(), ast_callid_threadassoc_add(), ast_callid_unref, ast_channel_callid(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_name(), ast_channel_priority_set(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_remaining_ms(), ast_tvnow(), ast_verb, ast_waitfor(), sig_pri_chan::channel, f, ast_frame::frametype, sig_pri_span::idlecontext, sig_pri_span::idledial, sig_pri_span::idleext, ast_frame_subclass::integer, LOG_WARNING, sig_pri_chan::owner, sig_pri_chan::pri, and ast_frame::subclass.
Referenced by pri_dchannel().
{
struct sig_pri_chan *pvt = v_pvt;
struct ast_channel *chan = pvt->owner;
struct ast_frame *f;
char ex[80];
/* Wait up to 30 seconds for an answer */
int timeout_ms = 30000;
int ms;
struct timeval start;
struct ast_callid *callid;
if ((callid = ast_channel_callid(chan))) {
ast_callid_threadassoc_add(callid);
callid = ast_callid_unref(callid);
}
ast_verb(3, "Initiating idle call on channel %s\n", ast_channel_name(chan));
snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
if (ast_call(chan, ex, 0)) {
ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", ast_channel_name(chan), ex);
ast_hangup(chan);
return NULL;
}
start = ast_tvnow();
while ((ms = ast_remaining_ms(start, timeout_ms))) {
if (ast_waitfor(chan, ms) <= 0) {
break;
}
f = ast_read(chan);
if (!f) {
/* Got hangup */
break;
}
if (f->frametype == AST_FRAME_CONTROL) {
switch (f->subclass.integer) {
case AST_CONTROL_ANSWER:
/* Launch the PBX */
ast_channel_exten_set(chan, pvt->pri->idleext);
ast_channel_context_set(chan, pvt->pri->idlecontext);
ast_channel_priority_set(chan, 1);
ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", ast_channel_name(chan), ast_channel_exten(chan), ast_channel_context(chan));
ast_pbx_run(chan);
/* It's already hungup, return immediately */
return NULL;
case AST_CONTROL_BUSY:
ast_verb(4, "Idle channel '%s' busy, waiting...\n", ast_channel_name(chan));
break;
case AST_CONTROL_CONGESTION:
ast_verb(4, "Idle channel '%s' congested, waiting...\n", ast_channel_name(chan));
break;
};
}
ast_frfree(f);
}
/* Hangup the channel since nothing happend */
ast_hangup(chan);
return NULL;
}
| static struct ast_callid* func_pri_dchannel_chanpos_callid | ( | struct sig_pri_span * | pri, |
| int | chanpos | ||
| ) | [static, read] |
Definition at line 5250 of file sig_pri.c.
References ast_callid_threadassoc_add(), ast_channel_callid(), ast_channel_unlock, sig_pri_chan::owner, sig_pri_span::pvts, and sig_pri_lock_owner().
Referenced by pri_dchannel(), sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), sig_pri_handle_retrieve_ack(), and sig_pri_handle_retrieve_rej().
{
if (chanpos < 0) {
return NULL;
}
sig_pri_lock_owner(pri, chanpos);
if (pri->pvts[chanpos]->owner) {
struct ast_callid *callid;
callid = ast_channel_callid(pri->pvts[chanpos]->owner);
ast_channel_unlock(pri->pvts[chanpos]->owner);
if (callid) {
ast_callid_threadassoc_add(callid);
return callid;
}
}
return NULL;
}
| static struct ast_callid* func_pri_dchannel_new_callid | ( | void | ) | [static, read] |
Definition at line 5224 of file sig_pri.c.
References ast_callid_threadassoc_add(), and ast_create_callid().
Referenced by pri_dchannel().
{
struct ast_callid *callid = ast_create_callid();
if (callid) {
ast_callid_threadassoc_add(callid);
}
return callid;
}
| static int pri_active_dchan_index | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 1078 of file sig_pri.c.
References ast_log(), sig_pri_span::dchans, LOG_WARNING, sig_pri_span::pri, and SIG_PRI_NUM_DCHANS.
Referenced by pri_find_principle().
{
int x;
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
if ((pri->dchans[x] == pri->pri))
return x;
}
ast_log(LOG_WARNING, "No active dchan found!\n");
return -1;
}
| static void pri_check_restart | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 1737 of file sig_pri.c.
References ast_log(), sig_pri_chan::channel, sig_pri_span::lastreset, LOG_NOTICE, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_span::pri, PVT_TO_CHANNEL(), sig_pri_span::pvts, sig_pri_span::resetpos, sig_pri_chan::resetting, sig_pri_span::resetting, sig_pri_chan::service_status, sig_pri_is_chan_in_use(), SIG_PRI_RESET_ACTIVE, sig_pri_span_devstate_changed(), sig_pri_span::span, SRVST_FAREND, and SRVST_NEAREND.
Referenced by pri_dchannel().
{
#if defined(HAVE_PRI_SERVICE_MESSAGES)
unsigned why;
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
if (!pri->pvts[pri->resetpos]
|| pri->pvts[pri->resetpos]->no_b_channel
|| sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
continue;
}
#if defined(HAVE_PRI_SERVICE_MESSAGES)
why = pri->pvts[pri->resetpos]->service_status;
if (why) {
ast_log(LOG_NOTICE,
"Span %d: channel %d out-of-service (reason: %s), not sending RESTART\n",
pri->span, pri->pvts[pri->resetpos]->channel,
(why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
continue;
}
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
break;
}
if (pri->resetpos < pri->numchans) {
/* Mark the channel as resetting and restart it */
pri->pvts[pri->resetpos]->resetting = SIG_PRI_RESET_ACTIVE;
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
} else {
pri->resetting = 0;
time(&pri->lastreset);
sig_pri_span_devstate_changed(pri);
}
}
| static void* pri_dchannel | ( | void * | vpri | ) | [static] |
Definition at line 5636 of file sig_pri.c.
References sig_pri_chan::allocated, sig_pri_span::allow_call_waiting_calls, sig_pri_chan::alreadyhungup, sig_pri_span::aoce_delayhangup, sig_pri_span::append_msn_to_user_tag, apply_plan_to_existing_number(), ast_atomic_fetchadd_int(), ast_bridged_channel(), ast_callid_threadassoc_remove(), ast_callid_unref, ast_canmatch_extension(), AST_CAUSE_USER_BUSY, AST_CC_CCBS, AST_CC_CCNR, ast_channel_caller(), ast_channel_dialed(), ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_name(), ast_channel_softhangup_internal_flag_add(), ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_del(), ast_db_put(), ast_debug, ast_exists_extension(), AST_FORMAT_ULAW, AST_FRAME_DTMF, ast_hangup(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_party_subaddress_free(), ast_party_subaddress_init(), ast_pbx_start(), ast_pthread_create_background, ast_pthread_create_detached, ast_setstate(), ast_shrink_phone_number(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_BUSY, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_verb, ast_verbose(), sig_pri_chan::call, sig_pri_chan::call_level, sig_pri_chan::callingpres, sig_pri_chan::channel, 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, sig_pri_chan::context, dahdi_db, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, ast_channel::data, DCHAN_UP, sig_pri_span::dchanavail, sig_pri_span::dchans, sig_pri_span::debug, sig_pri_chan::deferred_digits, detect_aoc_e_subcmd(), sig_pri_chan::dialdest, sig_pri_chan::digital, sig_pri_span::discardremoteholdretrieval, do_idle_thread(), errno, sig_pri_chan::exten, sig_pri_span::fds, func_pri_dchannel_chanpos_callid(), func_pri_dchannel_new_callid(), sig_pri_span::hold_disconnect_transfer, sig_pri_chan::holding_aoce, ast_party_caller::id, sig_pri_span::idlecontext, sig_pri_span::idledial, sig_pri_span::idleext, sig_pri_chan::immediate, sig_pri_span::inband_on_proceeding, sig_pri_span::initial_user_tag, sig_pri_chan::is_call_waiting, sig_pri_chan::isidlecall, sig_pri_chan::keypad_digits, sig_pri_span::lastreset, len(), sig_pri_span::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sig_pri_chan::logicalspan, sig_pri_span::minidle, sig_pri_span::minunused, sig_pri_span::msn_list, sig_pri_chan::no_b_channel, sig_pri_span::no_d_channels, sig_pri_span::nodetype, sig_pri_span::num_call_waiting_calls, ast_party_dialed::number, sig_pri_span::numchans, sig_pri_chan::outgoing, sig_pri_span::overlapdial, sig_pri_chan::owner, pbx_builtin_setvar_helper(), ast_party_dialed::plan, sig_pri_chan::pri, sig_pri_span::pri, PRI_CHANNEL, pri_check_restart(), pri_find_dchan(), pri_find_empty_chan(), pri_find_empty_nobch(), pri_find_fixup_principle(), pri_find_principle(), pri_find_principle_by_call(), pri_fixup_principle(), pri_is_up(), pri_order(), pri_queue_control(), pri_queue_frame(), pri_queue_pvt_cause_data(), PRI_SPAN, pri_ss_thread(), sig_pri_chan::prioffset, sig_pri_chan::progress, PVT_TO_CHANNEL(), sig_pri_span::pvts, redirectingreason2str(), sig_pri_span::resetinterval, sig_pri_span::resetpos, sig_pri_chan::resetting, sig_pri_span::resetting, sig_pri_chan::reverse_charging_indication, S_OR, sig_pri_chan::service_status, sig_pri_span::sig, SIG_BRI_PTMP, SIG_PRI_ALAW, sig_pri_attempt_transfer(), SIG_PRI_CALL_LEVEL_ALERTING, SIG_PRI_CALL_LEVEL_CONNECT, SIG_PRI_CALL_LEVEL_DEFER_DIAL, SIG_PRI_CALL_LEVEL_OVERLAP, SIG_PRI_CALL_LEVEL_PROCEEDING, sig_pri_cc_generic_check(), SIG_PRI_DEFLAW, sig_pri_dial_digits(), sig_pri_handle_cis_subcmds(), sig_pri_handle_dchan_exception(), sig_pri_handle_hold(), sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), sig_pri_handle_retrieve_ack(), sig_pri_handle_retrieve_rej(), sig_pri_handle_subcmds(), sig_pri_init_config(), sig_pri_is_chan_available(), sig_pri_is_cis_call(), sig_pri_lock_owner(), sig_pri_lock_private(), sig_pri_msn_match(), sig_pri_new_ast_channel(), SIG_PRI_NUM_DCHANS, sig_pri_open_media(), sig_pri_request(), SIG_PRI_RESET_ACTIVE, SIG_PRI_RESET_IDLE, SIG_PRI_RESET_NO_ACK, sig_pri_send_aoce_termination_request(), sig_pri_set_alarm(), sig_pri_set_caller_id(), sig_pri_set_dialing(), sig_pri_set_dnid(), sig_pri_set_echocanceller(), sig_pri_set_rdnis(), sig_pri_set_subaddress(), sig_pri_span_devstate_changed(), SIG_PRI_ULAW, sig_pri_unlock_private(), sig_pri_span::span, SRVST_DBKEY, SRVST_FAREND, SRVST_NEAREND, SRVST_TYPE_OOS, ast_party_subaddress::str, ast_party_id::subaddress, ast_party_dialed::subaddress, sig_pri_span::switchtype, sig_pri_chan::use_callerid, and sig_pri_chan::user_tag.
Referenced by sig_pri_start_pri().
{
struct sig_pri_span *pri = vpri;
pri_event *e;
struct pollfd fds[SIG_PRI_NUM_DCHANS];
int res;
int x;
int law;
struct ast_channel *c;
struct timeval tv, lowest, *next;
int doidling=0;
char *cc;
time_t t;
int i, which=-1;
int numdchans;
pthread_t threadid;
char ani2str[6];
char plancallingnum[AST_MAX_EXTENSION];
char plancallingani[AST_MAX_EXTENSION];
char calledtonstr[10];
struct timeval lastidle = { 0, 0 };
pthread_t p;
struct ast_channel *idle;
char idlen[80];
int nextidle = -1;
int haveidles;
int activeidles;
unsigned int len;
gettimeofday(&lastidle, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
/* Need to do idle dialing, check to be sure though */
cc = strchr(pri->idleext, '@');
if (cc) {
*cc = '\0';
cc++;
ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
#if 0
/* Extensions may not be loaded yet */
if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
else
#endif
doidling = 1;
} else
ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
}
for (;;) {
struct ast_callid *callid = NULL;
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
if (!pri->dchans[i])
break;
fds[i].fd = pri->fds[i];
fds[i].events = POLLIN | POLLPRI;
fds[i].revents = 0;
}
numdchans = i;
time(&t);
ast_mutex_lock(&pri->lock);
if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
if (pri->resetting && pri_is_up(pri)) {
if (pri->resetpos < 0) {
pri_check_restart(pri);
if (pri->resetting) {
sig_pri_span_devstate_changed(pri);
}
}
} else {
if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
pri->resetting = 1;
pri->resetpos = -1;
}
}
}
/* Look for any idle channels if appropriate */
if (doidling && pri_is_up(pri)) {
nextidle = -1;
haveidles = 0;
activeidles = 0;
for (x = pri->numchans; x >= 0; x--) {
if (pri->pvts[x] && !pri->pvts[x]->no_b_channel) {
if (sig_pri_is_chan_available(pri->pvts[x])) {
if (haveidles < pri->minunused) {
haveidles++;
} else {
nextidle = x;
break;
}
} else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
activeidles++;
}
}
}
if (nextidle > -1) {
if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
/* Don't create a new idle call more than once per second */
snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
pri->pvts[nextidle]->allocated = 1;
/*
* Release the PRI lock while we create the channel so other
* threads can send D channel messages.
*/
ast_mutex_unlock(&pri->lock);
/*
* We already have the B channel reserved for this call. We
* just need to make sure that sig_pri_hangup() has completed
* cleaning up before continuing.
*/
sig_pri_lock_private(pri->pvts[nextidle]);
sig_pri_unlock_private(pri->pvts[nextidle]);
idle = sig_pri_request(pri->pvts[nextidle], AST_FORMAT_ULAW, NULL, 0);
ast_mutex_lock(&pri->lock);
if (idle) {
pri->pvts[nextidle]->isidlecall = 1;
if (ast_pthread_create_background(&p, NULL, do_idle_thread, pri->pvts[nextidle])) {
ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", ast_channel_name(idle));
ast_mutex_unlock(&pri->lock);
ast_hangup(idle);
ast_mutex_lock(&pri->lock);
}
} else {
pri->pvts[nextidle]->allocated = 0;
ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
}
gettimeofday(&lastidle, NULL);
}
} else if ((haveidles < pri->minunused) &&
(activeidles > pri->minidle)) {
/* Mark something for hangup if there is something
that can be hungup */
for (x = pri->numchans; x >= 0; x--) {
/* find a candidate channel */
if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
ast_channel_softhangup_internal_flag_add(pri->pvts[x]->owner, AST_SOFTHANGUP_DEV);
haveidles++;
/* Stop if we have enough idle channels or
can't spare any more active idle ones */
if ((haveidles >= pri->minunused) ||
(activeidles <= pri->minidle))
break;
}
}
}
}
/* Start with reasonable max */
if (doidling || pri->resetting) {
/*
* Make sure we stop at least once per second if we're
* monitoring idle channels
*/
lowest = ast_tv(1, 0);
} else {
/* Don't poll for more than 60 seconds */
lowest = ast_tv(60, 0);
}
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
if (!pri->dchans[i]) {
/* We scanned all D channels on this span. */
break;
}
next = pri_schedule_next(pri->dchans[i]);
if (next) {
/* We need relative time here */
tv = ast_tvsub(*next, ast_tvnow());
if (tv.tv_sec < 0) {
/*
* A timer has already expired.
* By definition zero time is the lowest so we can quit early.
*/
lowest = ast_tv(0, 0);
break;
}
if (ast_tvcmp(tv, lowest) < 0) {
lowest = tv;
}
}
}
ast_mutex_unlock(&pri->lock);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_testcancel();
e = NULL;
res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
pthread_testcancel();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
ast_mutex_lock(&pri->lock);
if (!res) {
for (which = 0; which < SIG_PRI_NUM_DCHANS; which++) {
if (!pri->dchans[which])
break;
/* Just a timeout, run the scheduler */
e = pri_schedule_run(pri->dchans[which]);
if (e)
break;
}
} else if (res > -1) {
for (which = 0; which < SIG_PRI_NUM_DCHANS; which++) {
if (!pri->dchans[which])
break;
if (fds[which].revents & POLLPRI) {
sig_pri_handle_dchan_exception(pri, which);
} else if (fds[which].revents & POLLIN) {
e = pri_check_event(pri->dchans[which]);
}
if (e)
break;
}
} else if (errno != EINTR)
ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
if (e) {
int chanpos = -1;
char cause_str[35];
if (pri->debug) {
ast_verbose("Span %d: Processing event %s(%d)\n",
pri->span, pri_event2str(e->e), e->e);
}
if (e->e != PRI_EVENT_DCHAN_DOWN) {
if (!(pri->dchanavail[which] & DCHAN_UP)) {
ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
}
pri->dchanavail[which] |= DCHAN_UP;
} else {
if (pri->dchanavail[which] & DCHAN_UP) {
ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
}
pri->dchanavail[which] &= ~DCHAN_UP;
}
if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
/* Must be an NFAS group that has the secondary dchan active */
pri->pri = pri->dchans[which];
switch (e->e) {
case PRI_EVENT_DCHAN_UP:
pri->no_d_channels = 0;
if (!pri->pri) {
pri_find_dchan(pri);
}
/* Note presense of D-channel */
time(&pri->lastreset);
/* Restart in 5 seconds */
if (pri->resetinterval > -1) {
pri->lastreset -= pri->resetinterval;
pri->lastreset += 5;
}
/* Take the channels from inalarm condition */
pri->resetting = 0;
for (i = 0; i < pri->numchans; i++) {
if (pri->pvts[i]) {
sig_pri_set_alarm(pri->pvts[i], 0);
}
}
sig_pri_span_devstate_changed(pri);
break;
case PRI_EVENT_DCHAN_DOWN:
pri_find_dchan(pri);
if (!pri_is_up(pri)) {
if (pri->sig == SIG_BRI_PTMP) {
/*
* For PTMP connections with non-persistent layer 2 we want to
* *not* declare inalarm unless there actually is an alarm.
*/
break;
}
/* Hangup active channels and put them in alarm mode */
pri->resetting = 0;
for (i = 0; i < pri->numchans; i++) {
struct sig_pri_chan *p = pri->pvts[i];
if (p) {
if (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
/* T309 is not enabled : destroy calls when alarm occurs */
if (p->call) {
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
}
if (p->owner)
ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
}
sig_pri_set_alarm(p, 1);
}
}
sig_pri_span_devstate_changed(pri);
}
break;
case PRI_EVENT_RESTART:
if (e->restart.channel > -1 && PRI_CHANNEL(e->restart.channel) != 0xFF) {
chanpos = pri_find_principle(pri, e->restart.channel, NULL);
if (chanpos < 0)
ast_log(LOG_WARNING,
"Span %d: Restart requested on odd/unavailable channel number %d/%d\n",
pri->span, PRI_SPAN(e->restart.channel),
PRI_CHANNEL(e->restart.channel));
else {
int skipit = 0;
#if defined(HAVE_PRI_SERVICE_MESSAGES)
unsigned why;
why = pri->pvts[chanpos]->service_status;
if (why) {
ast_log(LOG_NOTICE,
"Span %d: Channel %d/%d out-of-service (reason: %s), ignoring RESTART\n",
pri->span, PRI_SPAN(e->restart.channel),
PRI_CHANNEL(e->restart.channel),
(why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
skipit = 1;
}
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
sig_pri_lock_private(pri->pvts[chanpos]);
if (!skipit) {
ast_verb(3, "Span %d: Channel %d/%d restarted\n", pri->span,
PRI_SPAN(e->restart.channel),
PRI_CHANNEL(e->restart.channel));
if (pri->pvts[chanpos]->call) {
pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
pri->pvts[chanpos]->call = NULL;
}
}
/* Force soft hangup if appropriate */
if (pri->pvts[chanpos]->owner)
ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
sig_pri_unlock_private(pri->pvts[chanpos]);
}
} else {
ast_verb(3, "Restart requested on entire span %d\n", pri->span);
for (x = 0; x < pri->numchans; x++)
if (pri->pvts[x]) {
sig_pri_lock_private(pri->pvts[x]);
if (pri->pvts[x]->call) {
pri_destroycall(pri->pri, pri->pvts[x]->call);
pri->pvts[x]->call = NULL;
}
if (pri->pvts[x]->owner)
ast_channel_softhangup_internal_flag_add(pri->pvts[x]->owner, AST_SOFTHANGUP_DEV);
sig_pri_unlock_private(pri->pvts[x]);
}
}
sig_pri_span_devstate_changed(pri);
break;
case PRI_EVENT_KEYPAD_DIGIT:
if (sig_pri_is_cis_call(e->digit.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->digit.subcmds,
e->digit.call);
break;
}
chanpos = pri_find_principle_by_call(pri, e->digit.call);
if (chanpos < 0) {
ast_log(LOG_WARNING,
"Span %d: Received keypad digits for unknown call.\n", pri->span);
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.subcmds,
e->digit.call);
/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
&& pri->pvts[chanpos]->owner) {
/* how to do that */
int digitlen = strlen(e->digit.digits);
int i;
for (i = 0; i < digitlen; i++) {
struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
pri_queue_frame(pri, chanpos, &f);
}
}
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_INFO_RECEIVED:
if (sig_pri_is_cis_call(e->ring.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->ring.subcmds,
e->ring.call);
break;
}
chanpos = pri_find_principle_by_call(pri, e->ring.call);
if (chanpos < 0) {
ast_log(LOG_WARNING,
"Span %d: Received INFORMATION for unknown call.\n", pri->span);
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds, e->ring.call);
/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
&& pri->pvts[chanpos]->owner) {
/* how to do that */
int digitlen = strlen(e->ring.callednum);
int i;
for (i = 0; i < digitlen; i++) {
struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
pri_queue_frame(pri, chanpos, &f);
}
}
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
#if defined(HAVE_PRI_SERVICE_MESSAGES)
case PRI_EVENT_SERVICE:
chanpos = pri_find_principle(pri, e->service.channel, NULL);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n",
e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
} else {
char db_chan_name[20];
char db_answer[5];
int ch;
unsigned *why;
ch = pri->pvts[chanpos]->channel;
snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->span, ch);
why = &pri->pvts[chanpos]->service_status;
switch (e->service.changestatus) {
case 0: /* in-service */
/* Far end wants to be in service now. */
ast_db_del(db_chan_name, SRVST_DBKEY);
*why &= ~SRVST_FAREND;
if (*why) {
snprintf(db_answer, sizeof(db_answer), "%s:%u",
SRVST_TYPE_OOS, *why);
ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
} else {
sig_pri_span_devstate_changed(pri);
}
break;
case 2: /* out-of-service */
/* Far end wants to be out-of-service now. */
ast_db_del(db_chan_name, SRVST_DBKEY);
*why |= SRVST_FAREND;
snprintf(db_answer, sizeof(db_answer), "%s:%u", SRVST_TYPE_OOS,
*why);
ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
sig_pri_span_devstate_changed(pri);
break;
default:
ast_log(LOG_ERROR, "Huh? changestatus is: %d\n", e->service.changestatus);
break;
}
ast_log(LOG_NOTICE, "Channel %d/%d span %d (logical: %d) received a change of service message, status '%d'\n",
PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span, ch, e->service.changestatus);
}
break;
case PRI_EVENT_SERVICE_ACK:
chanpos = pri_find_principle(pri, e->service_ack.channel, NULL);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Received service acknowledge change status '%d' on unconfigured channel %d/%d span %d\n",
e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
} else {
ast_debug(2, "Channel %d/%d span %d received a change os service acknowledgement message, status '%d'\n",
PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span, e->service_ack.changestatus);
}
break;
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
case PRI_EVENT_RING:
if (!ast_strlen_zero(pri->msn_list)
&& !sig_pri_msn_match(pri->msn_list, e->ring.callednum)) {
/* The call is not for us so ignore it. */
ast_verb(3,
"Ignoring call to '%s' on span %d. Its not in the MSN list: %s\n",
e->ring.callednum, pri->span, pri->msn_list);
pri_destroycall(pri->pri, e->ring.call);
break;
}
if (sig_pri_is_cis_call(e->ring.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->ring.subcmds,
e->ring.call);
break;
}
chanpos = pri_find_principle_by_call(pri, e->ring.call);
if (-1 < chanpos) {
/* Libpri has already filtered out duplicate SETUPs. */
ast_log(LOG_WARNING,
"Span %d: Got SETUP with duplicate call ptr (%p). Dropping call.\n",
pri->span, e->ring.call);
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
break;
}
if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
/* Any channel requested. */
chanpos = pri_find_empty_chan(pri, 1);
if (-1 < chanpos) {
callid = func_pri_dchannel_new_callid();
}
} else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
/* No channel specified. */
#if defined(HAVE_PRI_CALL_WAITING)
if (!pri->allow_call_waiting_calls)
#endif /* defined(HAVE_PRI_CALL_WAITING) */
{
/* We will not accept incoming call waiting calls. */
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
break;
}
#if defined(HAVE_PRI_CALL_WAITING)
chanpos = pri_find_empty_nobch(pri);
if (chanpos < 0) {
/* We could not find/create a call interface. */
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
break;
}
callid = func_pri_dchannel_new_callid();
/* Setup the call interface to use. */
sig_pri_init_config(pri->pvts[chanpos], pri);
#endif /* defined(HAVE_PRI_CALL_WAITING) */
} else {
/* A channel is specified. */
callid = func_pri_dchannel_new_callid();
chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
if (chanpos < 0) {
ast_log(LOG_WARNING,
"Span %d: SETUP on unconfigured channel %d/%d\n",
pri->span, PRI_SPAN(e->ring.channel),
PRI_CHANNEL(e->ring.channel));
} else {
switch (pri->pvts[chanpos]->resetting) {
case SIG_PRI_RESET_IDLE:
break;
case SIG_PRI_RESET_ACTIVE:
/*
* The peer may have lost the expected ack or not received the
* RESTART yet.
*/
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_NO_ACK;
break;
case SIG_PRI_RESET_NO_ACK:
/* The peer likely is not going to ack the RESTART. */
ast_debug(1,
"Span %d: Second SETUP while waiting for RESTART ACKNOWLEDGE on channel %d/%d\n",
pri->span, PRI_SPAN(e->ring.channel),
PRI_CHANNEL(e->ring.channel));
/* Assume we got the ack. */
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
if (pri->resetting) {
/* Go on to the next idle channel to RESTART. */
pri_check_restart(pri);
}
break;
}
if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
/* This is where we handle initial glare */
ast_debug(1,
"Span %d: SETUP requested unavailable channel %d/%d. Attempting to renegotiate.\n",
pri->span, PRI_SPAN(e->ring.channel),
PRI_CHANNEL(e->ring.channel));
chanpos = -1;
}
}
#if defined(ALWAYS_PICK_CHANNEL)
if (e->ring.flexible) {
chanpos = -1;
}
#endif /* defined(ALWAYS_PICK_CHANNEL) */
if (chanpos < 0 && e->ring.flexible) {
/* We can try to pick another channel. */
chanpos = pri_find_empty_chan(pri, 1);
}
}
if (chanpos < 0) {
if (e->ring.flexible) {
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
} else {
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
}
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
/* Mark channel as in use so noone else will steal it. */
pri->pvts[chanpos]->call = e->ring.call;
/* Use plancallingnum as a scratch buffer since it is initialized next. */
apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri,
e->ring.redirectingnum, e->ring.callingplanrdnis);
sig_pri_set_rdnis(pri->pvts[chanpos], plancallingnum);
/* Setup caller-id info */
apply_plan_to_existing_number(plancallingnum, sizeof(plancallingnum), pri,
e->ring.callingnum, e->ring.callingplan);
pri->pvts[chanpos]->cid_ani2 = 0;
if (pri->pvts[chanpos]->use_callerid) {
ast_shrink_phone_number(plancallingnum);
ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
#ifdef PRI_ANI
apply_plan_to_existing_number(plancallingani, sizeof(plancallingani),
pri, e->ring.callingani, e->ring.callingplanani);
ast_shrink_phone_number(plancallingani);
ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani,
sizeof(pri->pvts[chanpos]->cid_ani));
#endif
pri->pvts[chanpos]->cid_subaddr[0] = '\0';
#if defined(HAVE_PRI_SUBADDR)
if (e->ring.calling.subaddress.valid) {
struct ast_party_subaddress calling_subaddress;
ast_party_subaddress_init(&calling_subaddress);
sig_pri_set_subaddress(&calling_subaddress,
&e->ring.calling.subaddress);
if (calling_subaddress.str) {
ast_copy_string(pri->pvts[chanpos]->cid_subaddr,
calling_subaddress.str,
sizeof(pri->pvts[chanpos]->cid_subaddr));
}
ast_party_subaddress_free(&calling_subaddress);
}
#endif /* defined(HAVE_PRI_SUBADDR) */
ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
pri->pvts[chanpos]->callingpres = e->ring.callingpres;
if (e->ring.ani2 >= 0) {
pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
}
} else {
pri->pvts[chanpos]->cid_num[0] = '\0';
pri->pvts[chanpos]->cid_subaddr[0] = '\0';
pri->pvts[chanpos]->cid_ani[0] = '\0';
pri->pvts[chanpos]->cid_name[0] = '\0';
pri->pvts[chanpos]->cid_ton = 0;
pri->pvts[chanpos]->callingpres = 0;
}
/* Setup the user tag for party id's from this device for this call. */
if (pri->append_msn_to_user_tag) {
snprintf(pri->pvts[chanpos]->user_tag,
sizeof(pri->pvts[chanpos]->user_tag), "%s_%s",
pri->initial_user_tag,
pri->nodetype == PRI_NETWORK
? plancallingnum : e->ring.callednum);
} else {
ast_copy_string(pri->pvts[chanpos]->user_tag,
pri->initial_user_tag, sizeof(pri->pvts[chanpos]->user_tag));
}
sig_pri_set_caller_id(pri->pvts[chanpos]);
/* Set DNID on all incoming calls -- even immediate */
sig_pri_set_dnid(pri->pvts[chanpos], e->ring.callednum);
/* If immediate=yes go to s|1 */
if (pri->pvts[chanpos]->immediate) {
ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
pri->pvts[chanpos]->exten[0] = 's';
pri->pvts[chanpos]->exten[1] = '\0';
}
/* Get called number */
else if (!ast_strlen_zero(e->ring.callednum)) {
ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
} else if (pri->overlapdial)
pri->pvts[chanpos]->exten[0] = '\0';
else {
/* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
pri->pvts[chanpos]->exten[0] = 's';
pri->pvts[chanpos]->exten[1] = '\0';
}
/* No number yet, but received "sending complete"? */
if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
ast_verb(3, "Going to extension s|1 because of Complete received\n");
pri->pvts[chanpos]->exten[0] = 's';
pri->pvts[chanpos]->exten[1] = '\0';
}
/* Make sure extension exists (or in overlap dial mode, can exist) */
if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
/* Select audio companding mode. */
switch (e->ring.layer1) {
case PRI_LAYER_1_ALAW:
law = SIG_PRI_ALAW;
break;
case PRI_LAYER_1_ULAW:
law = SIG_PRI_ULAW;
break;
default:
/* This is a data call to us. */
law = SIG_PRI_DEFLAW;
break;
}
if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
/* Just announce proceeding */
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
} else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
} else {
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP;
pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
}
/* Start PBX */
if (!e->ring.complete
&& (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
&& ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
/*
* Release the PRI lock while we create the channel so other
* threads can send D channel messages. We must also release
* the private lock to prevent deadlock while creating the
* channel.
*/
sig_pri_unlock_private(pri->pvts[chanpos]);
ast_mutex_unlock(&pri->lock);
c = sig_pri_new_ast_channel(pri->pvts[chanpos],
AST_STATE_RESERVED, law, e->ring.ctype,
pri->pvts[chanpos]->exten, NULL);
ast_mutex_lock(&pri->lock);
sig_pri_lock_private(pri->pvts[chanpos]);
if (c) {
#if defined(HAVE_PRI_SUBADDR)
if (e->ring.calling.subaddress.valid) {
/* Set Calling Subaddress */
sig_pri_lock_owner(pri, chanpos);
sig_pri_set_subaddress(
&ast_channel_caller(pri->pvts[chanpos]->owner)->id.subaddress,
&e->ring.calling.subaddress);
if (!e->ring.calling.subaddress.type
&& !ast_strlen_zero(
(char *) e->ring.calling.subaddress.data)) {
/* NSAP */
pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
(char *) e->ring.calling.subaddress.data);
}
ast_channel_unlock(c);
}
if (e->ring.called_subaddress.valid) {
/* Set Called Subaddress */
sig_pri_lock_owner(pri, chanpos);
sig_pri_set_subaddress(
&ast_channel_dialed(pri->pvts[chanpos]->owner)->subaddress,
&e->ring.called_subaddress);
if (!e->ring.called_subaddress.type
&& !ast_strlen_zero(
(char *) e->ring.called_subaddress.data)) {
/* NSAP */
pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
(char *) e->ring.called_subaddress.data);
}
ast_channel_unlock(c);
}
#else
if (!ast_strlen_zero(e->ring.callingsubaddr)) {
pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
}
#endif /* !defined(HAVE_PRI_SUBADDR) */
if (e->ring.ani2 >= 0) {
snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
pbx_builtin_setvar_helper(c, "ANI2", ani2str);
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->ring.useruserinfo)) {
pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
}
#endif
snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
ast_channel_lock(c);
ast_channel_dialed(c)->number.plan = e->ring.calledplan;
ast_channel_unlock(c);
if (e->ring.redirectingreason >= 0) {
/* This is now just a status variable. Use REDIRECTING() dialplan function. */
pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
}
#if defined(HAVE_PRI_REVERSE_CHARGE)
pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge;
#endif
#if defined(HAVE_PRI_SETUP_KEYPAD)
ast_copy_string(pri->pvts[chanpos]->keypad_digits,
e->ring.keypad_digits,
sizeof(pri->pvts[chanpos]->keypad_digits));
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds,
e->ring.call);
if (!pri->pvts[chanpos]->digital
&& !pri->pvts[chanpos]->no_b_channel) {
/*
* Call has a channel.
* Indicate that we are providing dialtone.
*/
pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(pri->pri, e->ring.call,
PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */
#else
pri_progress(pri->pri, e->ring.call,
PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
#endif
}
}
if (c && !ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, pri->pvts[chanpos])) {
ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
} else {
ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
if (c) {
/* Avoid deadlock while destroying channel */
sig_pri_unlock_private(pri->pvts[chanpos]);
ast_mutex_unlock(&pri->lock);
ast_hangup(c);
ast_mutex_lock(&pri->lock);
} else {
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
pri->pvts[chanpos]->call = NULL;
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
}
break;
}
} else {
/*
* Release the PRI lock while we create the channel so other
* threads can send D channel messages. We must also release
* the private lock to prevent deadlock while creating the
* channel.
*/
sig_pri_unlock_private(pri->pvts[chanpos]);
ast_mutex_unlock(&pri->lock);
c = sig_pri_new_ast_channel(pri->pvts[chanpos],
AST_STATE_RING, law, e->ring.ctype,
pri->pvts[chanpos]->exten, NULL);
ast_mutex_lock(&pri->lock);
sig_pri_lock_private(pri->pvts[chanpos]);
if (c) {
/*
* It is reasonably safe to set the following
* channel variables while the PRI and DAHDI private
* structures are locked. The PBX has not been
* started yet and it is unlikely that any other task
* will do anything with the channel we have just
* created.
*/
#if defined(HAVE_PRI_SUBADDR)
if (e->ring.calling.subaddress.valid) {
/* Set Calling Subaddress */
sig_pri_lock_owner(pri, chanpos);
sig_pri_set_subaddress(
&ast_channel_caller(pri->pvts[chanpos]->owner)->id.subaddress,
&e->ring.calling.subaddress);
if (!e->ring.calling.subaddress.type
&& !ast_strlen_zero(
(char *) e->ring.calling.subaddress.data)) {
/* NSAP */
pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
(char *) e->ring.calling.subaddress.data);
}
ast_channel_unlock(c);
}
if (e->ring.called_subaddress.valid) {
/* Set Called Subaddress */
sig_pri_lock_owner(pri, chanpos);
sig_pri_set_subaddress(
&ast_channel_dialed(pri->pvts[chanpos]->owner)->subaddress,
&e->ring.called_subaddress);
if (!e->ring.called_subaddress.type
&& !ast_strlen_zero(
(char *) e->ring.called_subaddress.data)) {
/* NSAP */
pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
(char *) e->ring.called_subaddress.data);
}
ast_channel_unlock(c);
}
#else
if (!ast_strlen_zero(e->ring.callingsubaddr)) {
pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
}
#endif /* !defined(HAVE_PRI_SUBADDR) */
if (e->ring.ani2 >= 0) {
snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
pbx_builtin_setvar_helper(c, "ANI2", ani2str);
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->ring.useruserinfo)) {
pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
}
#endif
if (e->ring.redirectingreason >= 0) {
/* This is now just a status variable. Use REDIRECTING() dialplan function. */
pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
}
#if defined(HAVE_PRI_REVERSE_CHARGE)
pri->pvts[chanpos]->reverse_charging_indication = e->ring.reversecharge;
#endif
#if defined(HAVE_PRI_SETUP_KEYPAD)
ast_copy_string(pri->pvts[chanpos]->keypad_digits,
e->ring.keypad_digits,
sizeof(pri->pvts[chanpos]->keypad_digits));
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
ast_channel_lock(c);
ast_channel_dialed(c)->number.plan = e->ring.calledplan;
ast_channel_unlock(c);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds,
e->ring.call);
}
if (c && !ast_pbx_start(c)) {
ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
plancallingnum, pri->pvts[chanpos]->exten,
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
} else {
ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
if (c) {
/* Avoid deadlock while destroying channel */
sig_pri_unlock_private(pri->pvts[chanpos]);
ast_mutex_unlock(&pri->lock);
ast_hangup(c);
ast_mutex_lock(&pri->lock);
} else {
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
pri->pvts[chanpos]->call = NULL;
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
}
break;
}
}
} else {
ast_verb(3,
"Span %d: Extension %s@%s does not exist. Rejecting call from '%s'.\n",
pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
pri->pvts[chanpos]->cid_num);
pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
pri->pvts[chanpos]->call = NULL;
pri->pvts[chanpos]->exten[0] = '\0';
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
break;
}
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_RINGING:
if (sig_pri_is_cis_call(e->ringing.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->ringing.subcmds,
e->ringing.call);
break;
}
chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
e->ringing.call);
if (chanpos < 0) {
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.subcmds,
e->ringing.call);
sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
sig_pri_lock_owner(pri, chanpos);
if (pri->pvts[chanpos]->owner) {
ast_setstate(pri->pvts[chanpos]->owner, AST_STATE_RINGING);
ast_channel_unlock(pri->pvts[chanpos]->owner);
}
pri_queue_control(pri, chanpos, AST_CONTROL_RINGING);
if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_ALERTING) {
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
}
if (!pri->pvts[chanpos]->progress
&& !pri->pvts[chanpos]->no_b_channel
#ifdef PRI_PROGRESS_MASK
&& (e->ringing.progressmask
& (PRI_PROG_CALL_NOT_E2E_ISDN | PRI_PROG_INBAND_AVAILABLE))
#else
&& e->ringing.progress == 8
#endif
) {
/* Bring voice path up */
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
pri->pvts[chanpos]->progress = 1;
sig_pri_set_dialing(pri->pvts[chanpos], 0);
sig_pri_open_media(pri->pvts[chanpos]);
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->ringing.useruserinfo)) {
struct ast_channel *owner;
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
pbx_builtin_setvar_helper(owner, "USERUSERINFO",
e->ringing.useruserinfo);
ast_channel_unlock(owner);
}
}
#endif
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_PROGRESS:
if (sig_pri_is_cis_call(e->proceeding.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->proceeding.subcmds,
e->proceeding.call);
break;
}
chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
e->proceeding.call);
if (chanpos < 0) {
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.subcmds,
e->proceeding.call);
if (e->proceeding.cause > -1) {
if (pri->pvts[chanpos]->owner) {
snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_PROGRESS (%d)", e->proceeding.cause);
pri_queue_pvt_cause_data(pri, chanpos, cause_str, e->proceeding.cause);
}
ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
/* Work around broken, out of spec USER_BUSY cause in a progress message */
if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
if (pri->pvts[chanpos]->owner) {
ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->proceeding.cause);
pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
}
}
}
if (!pri->pvts[chanpos]->progress
&& !pri->pvts[chanpos]->no_b_channel
#ifdef PRI_PROGRESS_MASK
&& (e->proceeding.progressmask
& (PRI_PROG_CALL_NOT_E2E_ISDN | PRI_PROG_INBAND_AVAILABLE))
#else
&& e->proceeding.progress == 8
#endif
) {
/* Bring voice path up */
ast_debug(1,
"Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,
pri->span);
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
pri->pvts[chanpos]->progress = 1;
sig_pri_set_dialing(pri->pvts[chanpos], 0);
sig_pri_open_media(pri->pvts[chanpos]);
}
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_PROCEEDING:
if (sig_pri_is_cis_call(e->proceeding.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->proceeding.subcmds,
e->proceeding.call);
break;
}
chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
e->proceeding.call);
if (chanpos < 0) {
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.subcmds,
e->proceeding.call);
if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
ast_debug(1,
"Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,
pri->span);
pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
}
if (!pri->pvts[chanpos]->progress
&& !pri->pvts[chanpos]->no_b_channel
#ifdef PRI_PROGRESS_MASK
&& (e->proceeding.progressmask
& (PRI_PROG_CALL_NOT_E2E_ISDN | PRI_PROG_INBAND_AVAILABLE))
#else
&& e->proceeding.progress == 8
#endif
) {
/* Bring voice path up */
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
pri->pvts[chanpos]->progress = 1;
sig_pri_set_dialing(pri->pvts[chanpos], 0);
sig_pri_open_media(pri->pvts[chanpos]);
} else if (pri->inband_on_proceeding) {
sig_pri_set_dialing(pri->pvts[chanpos], 0);
}
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_FACILITY:
if (!e->facility.call || sig_pri_is_cis_call(e->facility.channel)) {
/* Event came in on the dummy channel or a CIS call. */
#if defined(HAVE_PRI_CALL_REROUTING)
sig_pri_handle_cis_subcmds(pri, e->e, e->facility.subcmds,
e->facility.subcall);
#else
sig_pri_handle_cis_subcmds(pri, e->e, e->facility.subcmds,
e->facility.call);
#endif /* !defined(HAVE_PRI_CALL_REROUTING) */
break;
}
chanpos = pri_find_principle_by_call(pri, e->facility.call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
pri->span);
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
#if defined(HAVE_PRI_CALL_REROUTING)
sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.subcmds,
e->facility.subcall);
#else
sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.subcmds,
e->facility.call);
#endif /* !defined(HAVE_PRI_CALL_REROUTING) */
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_ANSWER:
if (sig_pri_is_cis_call(e->answer.channel)) {
#if defined(HAVE_PRI_CALL_WAITING)
/* Call is CIS so do normal CONNECT_ACKNOWLEDGE. */
pri_connect_ack(pri->pri, e->answer.call, 0);
#endif /* defined(HAVE_PRI_CALL_WAITING) */
sig_pri_handle_cis_subcmds(pri, e->e, e->answer.subcmds,
e->answer.call);
break;
}
chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
if (chanpos < 0) {
break;
}
#if defined(HAVE_PRI_CALL_WAITING)
if (pri->pvts[chanpos]->is_call_waiting) {
if (pri->pvts[chanpos]->no_b_channel) {
int new_chanpos;
/*
* Need to find a free channel now or
* kill the call with PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION.
*/
new_chanpos = pri_find_empty_chan(pri, 1);
if (0 <= new_chanpos) {
new_chanpos = pri_fixup_principle(pri, new_chanpos,
e->answer.call);
}
if (new_chanpos < 0) {
/*
* Either no channel was available or someone stole
* the channel!
*/
ast_verb(3,
"Span %d: Channel not available for call waiting call.\n",
pri->span);
sig_pri_lock_private(pri->pvts[chanpos]);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.subcmds,
e->answer.call);
sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
sig_pri_lock_owner(pri, chanpos);
if (pri->pvts[chanpos]->owner) {
ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
switch (ast_channel_state(pri->pvts[chanpos]->owner)) {
case AST_STATE_BUSY:
case AST_STATE_UP:
ast_softhangup_nolock(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
break;
default:
pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
break;
}
ast_channel_unlock(pri->pvts[chanpos]->owner);
} else {
pri->pvts[chanpos]->is_call_waiting = 0;
ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
pri_hangup(pri->pri, e->answer.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
pri->pvts[chanpos]->call = NULL;
}
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
break;
}
chanpos = new_chanpos;
}
pri_connect_ack(pri->pri, e->answer.call, PVT_TO_CHANNEL(pri->pvts[chanpos]));
sig_pri_span_devstate_changed(pri);
} else {
/* Call is normal so do normal CONNECT_ACKNOWLEDGE. */
pri_connect_ack(pri->pri, e->answer.call, 0);
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
#if defined(HAVE_PRI_CALL_WAITING)
if (pri->pvts[chanpos]->is_call_waiting) {
pri->pvts[chanpos]->is_call_waiting = 0;
ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.subcmds,
e->answer.call);
if (!ast_strlen_zero(pri->pvts[chanpos]->deferred_digits)) {
/* We have some 'w' deferred digits to dial now. */
ast_verb(3,
"Span %d: Channel %d/%d dialing deferred digit string: %s\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset,
pri->pvts[chanpos]->deferred_digits);
if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_DEFER_DIAL) {
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_DEFER_DIAL;
}
sig_pri_dial_digits(pri->pvts[chanpos],
pri->pvts[chanpos]->deferred_digits);
} else {
if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
}
sig_pri_open_media(pri->pvts[chanpos]);
pri_queue_control(pri, chanpos, AST_CONTROL_ANSWER);
sig_pri_set_dialing(pri->pvts[chanpos], 0);
/* Enable echo cancellation if it's not on already */
sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->answer.useruserinfo)) {
struct ast_channel *owner;
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
pbx_builtin_setvar_helper(owner, "USERUSERINFO",
e->answer.useruserinfo);
ast_channel_unlock(owner);
}
}
#endif
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
#if defined(HAVE_PRI_CALL_WAITING)
case PRI_EVENT_CONNECT_ACK:
if (sig_pri_is_cis_call(e->connect_ack.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->connect_ack.subcmds,
e->connect_ack.call);
break;
}
chanpos = pri_find_fixup_principle(pri, e->connect_ack.channel,
e->connect_ack.call);
if (chanpos < 0) {
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->connect_ack.subcmds,
e->connect_ack.call);
sig_pri_open_media(pri->pvts[chanpos]);
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
break;
#endif /* defined(HAVE_PRI_CALL_WAITING) */
case PRI_EVENT_HANGUP:
if (sig_pri_is_cis_call(e->hangup.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->hangup.subcmds,
e->hangup.call);
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
break;
}
chanpos = pri_find_principle_by_call(pri, e->hangup.call);
if (chanpos < 0) {
/*
* Continue hanging up the call even though
* we do not remember it (if we ever did).
*/
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.subcmds,
e->hangup.call);
switch (e->hangup.cause) {
case PRI_CAUSE_INVALID_CALL_REFERENCE:
/*
* The peer denies the existence of this call so we must
* continue hanging it up and forget about it.
*/
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
break;
default:
break;
}
if (!pri->pvts[chanpos]->alreadyhungup) {
/* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
pri->pvts[chanpos]->alreadyhungup = 1;
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
break;
default:
break;
}
if (pri->pvts[chanpos]->owner) {
int do_hangup = 0;
snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP (%d)", e->hangup.cause);
pri_queue_pvt_cause_data(pri, chanpos, cause_str, e->hangup.cause);
/* Queue a BUSY instead of a hangup if our cause is appropriate */
ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
switch (ast_channel_state(pri->pvts[chanpos]->owner)) {
case AST_STATE_BUSY:
case AST_STATE_UP:
do_hangup = 1;
break;
default:
if (!pri->pvts[chanpos]->outgoing) {
/*
* The incoming call leg hung up before getting
* connected so just hangup the call.
*/
do_hangup = 1;
break;
}
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
break;
case PRI_CAUSE_CALL_REJECTED:
case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case PRI_CAUSE_SWITCH_CONGESTION:
case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
break;
default:
do_hangup = 1;
break;
}
break;
}
if (do_hangup) {
#if defined(HAVE_PRI_AOC_EVENTS)
if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
/* If a AOC-E msg was sent during the release, we must use a
* AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
} else {
ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
}
#else
ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
}
} else {
/*
* Continue hanging up the call even though
* we do not have an owner.
*/
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
}
ast_verb(3, "Span %d: Channel %d/%d got hangup, cause %d\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset, e->hangup.cause);
} else {
/* Continue hanging up the call. */
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
}
#if defined(FORCE_RESTART_UNAVAIL_CHANS)
if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
&& pri->sig != SIG_BRI_PTMP && !pri->resetting
&& pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
ast_verb(3,
"Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
}
#endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
if (e->hangup.aoc_units > -1)
ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->hangup.useruserinfo)) {
struct ast_channel *owner;
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
pbx_builtin_setvar_helper(owner, "USERUSERINFO",
e->hangup.useruserinfo);
ast_channel_unlock(owner);
}
}
#endif
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
break;
case PRI_EVENT_HANGUP_REQ:
if (sig_pri_is_cis_call(e->hangup.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->hangup.subcmds,
e->hangup.call);
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
break;
}
chanpos = pri_find_principle_by_call(pri, e->hangup.call);
if (chanpos < 0) {
/*
* Continue hanging up the call even though
* we do not remember it (if we ever did).
*/
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.subcmds,
e->hangup.call);
#if defined(HAVE_PRI_CALL_HOLD)
if (e->hangup.call_active && e->hangup.call_held
&& pri->hold_disconnect_transfer) {
/* We are to transfer the call instead of simply hanging up. */
sig_pri_unlock_private(pri->pvts[chanpos]);
if (!sig_pri_attempt_transfer(pri, e->hangup.call_held, 1,
e->hangup.call_active, 0, NULL, NULL)) {
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
}
#endif /* defined(HAVE_PRI_CALL_HOLD) */
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
break;
case PRI_CAUSE_INVALID_CALL_REFERENCE:
/*
* The peer denies the existence of this call so we must
* continue hanging it up and forget about it. We should not
* get this cause here, but for completeness we will handle it
* anyway.
*/
pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
break;
default:
break;
}
if (pri->pvts[chanpos]->owner) {
int do_hangup = 0;
snprintf(cause_str, sizeof(cause_str), "PRI PRI_EVENT_HANGUP_REQ (%d)", e->hangup.cause);
pri_queue_pvt_cause_data(pri, chanpos, cause_str, e->hangup.cause);
ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, e->hangup.cause);
switch (ast_channel_state(pri->pvts[chanpos]->owner)) {
case AST_STATE_BUSY:
case AST_STATE_UP:
do_hangup = 1;
break;
default:
if (!pri->pvts[chanpos]->outgoing) {
/*
* The incoming call leg hung up before getting
* connected so just hangup the call.
*/
do_hangup = 1;
break;
}
switch (e->hangup.cause) {
case PRI_CAUSE_USER_BUSY:
pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
break;
case PRI_CAUSE_CALL_REJECTED:
case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
case PRI_CAUSE_SWITCH_CONGESTION:
case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
break;
default:
do_hangup = 1;
break;
}
break;
}
if (do_hangup) {
#if defined(HAVE_PRI_AOC_EVENTS)
if (!pri->pvts[chanpos]->holding_aoce
&& pri->aoce_delayhangup
&& ast_bridged_channel(pri->pvts[chanpos]->owner)) {
sig_pri_send_aoce_termination_request(pri, chanpos,
pri_get_timer(pri->pri, PRI_TIMER_T305) / 2);
} else if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
/* If a AOC-E msg was sent during the Disconnect, we must use a AST_CONTROL_HANGUP frame
* to guarantee that frame gets read before hangup */
pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
} else {
ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
}
#else
ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
}
ast_verb(3, "Span %d: Channel %d/%d got hangup request, cause %d\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset, e->hangup.cause);
} else {
/*
* Continue hanging up the call even though
* we do not have an owner.
*/
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
}
#if defined(FORCE_RESTART_UNAVAIL_CHANS)
if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL
&& pri->sig != SIG_BRI_PTMP && !pri->resetting
&& pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
ast_verb(3,
"Span %d: Forcing restart of channel %d/%d since channel reported in use\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE;
pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
}
#endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->hangup.useruserinfo)) {
struct ast_channel *owner;
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
pbx_builtin_setvar_helper(owner, "USERUSERINFO",
e->hangup.useruserinfo);
ast_channel_unlock(owner);
}
}
#endif
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
break;
case PRI_EVENT_HANGUP_ACK:
if (sig_pri_is_cis_call(e->hangup.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->hangup.subcmds,
e->hangup.call);
break;
}
chanpos = pri_find_principle_by_call(pri, e->hangup.call);
if (chanpos < 0) {
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
pri->pvts[chanpos]->call = NULL;
if (pri->pvts[chanpos]->owner) {
ast_verb(3, "Span %d: Channel %d/%d got hangup ACK\n", pri->span,
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset);
}
#ifdef SUPPORT_USERUSER
if (!ast_strlen_zero(e->hangup.useruserinfo)) {
struct ast_channel *owner;
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
pbx_builtin_setvar_helper(owner, "USERUSERINFO",
e->hangup.useruserinfo);
ast_channel_unlock(owner);
}
}
#endif
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
break;
case PRI_EVENT_CONFIG_ERR:
ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->span, e->err.err);
break;
case PRI_EVENT_RESTART_ACK:
chanpos = pri_find_principle(pri, e->restartack.channel, NULL);
if (chanpos < 0) {
/* Sometime switches (e.g. I421 / British Telecom) don't give us the
channel number, so we have to figure it out... This must be why
everybody resets exactly a channel at a time. */
for (x = 0; x < pri->numchans; x++) {
if (pri->pvts[x]
&& pri->pvts[x]->resetting != SIG_PRI_RESET_IDLE) {
chanpos = x;
sig_pri_lock_private(pri->pvts[chanpos]);
ast_debug(1,
"Span %d: Assuming restart ack is for channel %d/%d\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
if (pri->pvts[chanpos]->owner) {
ast_log(LOG_WARNING,
"Span %d: Got restart ack on channel %d/%d with owner\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
}
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
ast_verb(3,
"Span %d: Channel %d/%d successfully restarted\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
sig_pri_unlock_private(pri->pvts[chanpos]);
if (pri->resetting)
pri_check_restart(pri);
break;
}
}
if (chanpos < 0) {
ast_log(LOG_WARNING,
"Span %d: Restart ACK on strange channel %d/%d\n",
pri->span, PRI_SPAN(e->restartack.channel),
PRI_CHANNEL(e->restartack.channel));
}
} else {
sig_pri_lock_private(pri->pvts[chanpos]);
if (pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) {
/* The channel is not in the resetting state. */
ast_debug(1,
"Span %d: Unexpected or late restart ack on channel %d/%d (Ignoring)\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
}
if (pri->pvts[chanpos]->owner) {
ast_log(LOG_WARNING,
"Span %d: Got restart ack on channel %d/%d with owner\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
ast_channel_softhangup_internal_flag_add(pri->pvts[chanpos]->owner, AST_SOFTHANGUP_DEV);
}
pri->pvts[chanpos]->resetting = SIG_PRI_RESET_IDLE;
ast_verb(3,
"Span %d: Channel %d/%d successfully restarted\n",
pri->span, pri->pvts[chanpos]->logicalspan,
pri->pvts[chanpos]->prioffset);
sig_pri_unlock_private(pri->pvts[chanpos]);
if (pri->resetting)
pri_check_restart(pri);
}
break;
case PRI_EVENT_SETUP_ACK:
if (sig_pri_is_cis_call(e->setup_ack.channel)) {
sig_pri_handle_cis_subcmds(pri, e->e, e->setup_ack.subcmds,
e->setup_ack.call);
break;
}
chanpos = pri_find_fixup_principle(pri, e->setup_ack.channel,
e->setup_ack.call);
if (chanpos < 0) {
break;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, e->e, e->setup_ack.subcmds,
e->setup_ack.call);
if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_OVERLAP;
}
/* Send any queued digits */
len = strlen(pri->pvts[chanpos]->dialdest);
for (x = 0; x < len; ++x) {
ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
pri_information(pri->pri, pri->pvts[chanpos]->call,
pri->pvts[chanpos]->dialdest[x]);
}
if (!pri->pvts[chanpos]->progress
&& (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
&& !pri->pvts[chanpos]->digital
&& !pri->pvts[chanpos]->no_b_channel) {
/*
* Call has a channel.
* Indicate for overlap dialing that dialtone may be present.
*/
pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */
sig_pri_set_dialing(pri->pvts[chanpos], 0);
sig_pri_open_media(pri->pvts[chanpos]);
}
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
case PRI_EVENT_NOTIFY:
if (sig_pri_is_cis_call(e->notify.channel)) {
#if defined(HAVE_PRI_CALL_HOLD)
sig_pri_handle_cis_subcmds(pri, e->e, e->notify.subcmds,
e->notify.call);
#else
sig_pri_handle_cis_subcmds(pri, e->e, e->notify.subcmds, NULL);
#endif /* !defined(HAVE_PRI_CALL_HOLD) */
break;
}
#if defined(HAVE_PRI_CALL_HOLD)
chanpos = pri_find_principle_by_call(pri, e->notify.call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Span %d: Received NOTIFY for unknown call.\n",
pri->span);
break;
}
#else
/*
* This version of libpri does not supply a call pointer for
* this message. We are just going to have to trust that the
* correct principle is found.
*/
chanpos = pri_find_principle(pri, e->notify.channel, NULL);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
break;
}
#endif /* !defined(HAVE_PRI_CALL_HOLD) */
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
#if defined(HAVE_PRI_CALL_HOLD)
sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.subcmds,
e->notify.call);
#else
sig_pri_handle_subcmds(pri, chanpos, e->e, e->notify.subcmds, NULL);
#endif /* !defined(HAVE_PRI_CALL_HOLD) */
switch (e->notify.info) {
case PRI_NOTIFY_REMOTE_HOLD:
if (!pri->discardremoteholdretrieval) {
pri_queue_control(pri, chanpos, AST_CONTROL_HOLD);
}
break;
case PRI_NOTIFY_REMOTE_RETRIEVAL:
if (!pri->discardremoteholdretrieval) {
pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
}
break;
}
sig_pri_unlock_private(pri->pvts[chanpos]);
break;
#if defined(HAVE_PRI_CALL_HOLD)
case PRI_EVENT_HOLD:
/* We should not be getting any CIS calls with this message type. */
if (sig_pri_handle_hold(pri, e)) {
pri_hold_rej(pri->pri, e->hold.call,
PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
} else {
pri_hold_ack(pri->pri, e->hold.call);
}
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_HOLD)
case PRI_EVENT_HOLD_ACK:
/* We should not be getting any CIS calls with this message type. */
sig_pri_handle_hold_ack(pri, e);
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_HOLD)
case PRI_EVENT_HOLD_REJ:
/* We should not be getting any CIS calls with this message type. */
sig_pri_handle_hold_rej(pri, e);
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_HOLD)
case PRI_EVENT_RETRIEVE:
/* We should not be getting any CIS calls with this message type. */
sig_pri_handle_retrieve(pri, e);
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_HOLD)
case PRI_EVENT_RETRIEVE_ACK:
/* We should not be getting any CIS calls with this message type. */
sig_pri_handle_retrieve_ack(pri, e);
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_HOLD)
case PRI_EVENT_RETRIEVE_REJ:
/* We should not be getting any CIS calls with this message type. */
sig_pri_handle_retrieve_rej(pri, e);
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
default:
ast_debug(1, "Span: %d Unhandled event: %s(%d)\n",
pri->span, pri_event2str(e->e), e->e);
break;
}
/* If a callid was set, we need to deref it and remove it from thread storage. */
if (callid) {
callid = ast_callid_unref(callid);
ast_callid_threadassoc_remove();
}
}
ast_mutex_unlock(&pri->lock);
}
/* Never reached */
return NULL;
}
| void pri_event_alarm | ( | struct sig_pri_span * | pri, |
| int | index, | ||
| int | before_start_pri | ||
| ) |
Definition at line 2071 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().
{
pri->dchanavail[index] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
if (!before_start_pri) {
pri_find_dchan(pri);
}
}
| void pri_event_noalarm | ( | struct sig_pri_span * | pri, |
| int | index, | ||
| int | before_start_pri | ||
| ) |
Definition at line 2079 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().
{
pri->dchanavail[index] |= DCHAN_NOTINALARM;
if (!before_start_pri)
pri_restart(pri->dchans[index]);
}
| static void pri_find_dchan | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 1091 of file sig_pri.c.
References ast_log(), DCHAN_AVAILABLE, sig_pri_span::dchans, sig_pri_span::fds, LOG_NOTICE, LOG_WARNING, sig_pri_span::no_d_channels, sig_pri_span::pri, pri_order(), sig_pri_span::sig, SIG_BRI_PTMP, SIG_PRI_NUM_DCHANS, and sig_pri_span::span.
Referenced by pri_dchannel(), and pri_event_alarm().
{
struct pri *old;
int oldslot = -1;
int newslot = -1;
int idx;
old = pri->pri;
for (idx = 0; idx < SIG_PRI_NUM_DCHANS; ++idx) {
if (!pri->dchans[idx]) {
/* No more D channels defined on the span. */
break;
}
if (pri->dchans[idx] == old) {
oldslot = idx;
}
if (newslot < 0 && pri->dchanavail[idx] == DCHAN_AVAILABLE) {
newslot = idx;
}
}
/* At this point, idx is a count of how many D-channels are defined on the span. */
if (1 < idx) {
/* We have several D-channels defined on the span. (NFAS PRI setup) */
if (newslot < 0) {
/* No D-channels available. Default to the primary D-channel. */
newslot = 0;
if (!pri->no_d_channels) {
pri->no_d_channels = 1;
if (old && oldslot != newslot) {
ast_log(LOG_WARNING,
"Span %d: No D-channels up! Switching selected D-channel from %s to %s.\n",
pri->span, pri_order(oldslot), pri_order(newslot));
} else {
ast_log(LOG_WARNING, "Span %d: No D-channels up!\n", pri->span);
}
}
} else {
pri->no_d_channels = 0;
}
if (old && oldslot != newslot) {
ast_log(LOG_NOTICE,
"Switching selected D-channel from %s (fd %d) to %s (fd %d)!\n",
pri_order(oldslot), pri->fds[oldslot],
pri_order(newslot), pri->fds[newslot]);
}
} else {
if (newslot < 0) {
/* The only D-channel is not up. */
newslot = 0;
if (!pri->no_d_channels) {
pri->no_d_channels = 1;
/*
* This is annoying to see on non-persistent layer 2
* connections. Let's not complain in that case.
*/
if (pri->sig != SIG_BRI_PTMP) {
ast_log(LOG_WARNING, "Span %d: D-channel is down!\n", pri->span);
}
}
} else {
pri->no_d_channels = 0;
}
}
pri->pri = pri->dchans[newslot];
}
| static int pri_find_empty_chan | ( | struct sig_pri_span * | pri, |
| int | backwards | ||
| ) | [static] |
Definition at line 1816 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::prioffset, sig_pri_span::pvts, and sig_pri_is_chan_available().
Referenced by pri_dchannel(), sig_pri_handle_retrieve(), and sig_pri_moh_retrieve_call().
{
int x;
if (backwards)
x = pri->numchans;
else
x = 0;
for (;;) {
if (backwards && (x < 0))
break;
if (!backwards && (x >= pri->numchans))
break;
if (pri->pvts[x]
&& !pri->pvts[x]->no_b_channel
&& sig_pri_is_chan_available(pri->pvts[x])) {
ast_debug(1, "Found empty available channel %d/%d\n",
pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
return x;
}
if (backwards)
x--;
else
x++;
}
return -1;
}
| static int pri_find_empty_nobch | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 1856 of file sig_pri.c.
References ast_debug, sig_pri_callback::new_nobch_intf, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_span::pvts, sig_pri_callbacks, and sig_pri_is_chan_available().
Referenced by pri_dchannel(), sig_pri_cw_available(), sig_pri_handle_hold(), and sig_pri_handle_hold_ack().
{
int idx;
for (idx = 0; idx < pri->numchans; ++idx) {
if (pri->pvts[idx]
&& pri->pvts[idx]->no_b_channel
&& sig_pri_is_chan_available(pri->pvts[idx])) {
ast_debug(1, "Found empty available no B channel interface\n");
return idx;
}
}
/* Need to create a new interface. */
if (sig_pri_callbacks.new_nobch_intf) {
idx = sig_pri_callbacks.new_nobch_intf(pri);
} else {
idx = -1;
}
return idx;
}
| static int pri_find_fixup_principle | ( | struct sig_pri_span * | pri, |
| int | channel, | ||
| q931_call * | call | ||
| ) | [static] |
Definition at line 1615 of file sig_pri.c.
References ast_log(), LOG_WARNING, PRI_CHANNEL, pri_find_principle(), pri_fixup_principle(), PRI_SPAN, sig_pri_kill_call(), and sig_pri_span::span.
Referenced by pri_dchannel(), and sig_pri_handle_retrieve_ack().
{
int chanpos;
chanpos = pri_find_principle(pri, channel, call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
return -1;
}
chanpos = pri_fixup_principle(pri, chanpos, call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
/*
* Using Q.931 section 5.2.3.1 b) as the reason for picking
* PRI_CAUSE_CHANNEL_UNACCEPTABLE. Receiving a
* PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
* that channel (which is not specified by Q.931) and kill some
* other call which would be bad.
*/
sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
return -1;
}
return chanpos;
}
| static int pri_find_principle | ( | struct sig_pri_span * | pri, |
| int | channel, | ||
| q931_call * | call | ||
| ) | [static] |
Definition at line 1388 of file sig_pri.c.
References sig_pri_span::dchan_logical_span, sig_pri_chan::logicalspan, sig_pri_chan::no_b_channel, sig_pri_span::numchans, pri_active_dchan_index(), PRI_CHANNEL, PRI_EXPLICIT, pri_find_principle_by_call(), PRI_HELD_CALL, PRI_SPAN, sig_pri_chan::prioffset, and sig_pri_span::pvts.
Referenced by pri_dchannel(), pri_find_fixup_principle(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), and sig_pri_handle_retrieve_rej().
{
int x;
int span;
int principle;
int prioffset;
if (channel < 0) {
/* Channel is not picked yet. */
return -1;
}
prioffset = PRI_CHANNEL(channel);
if (!prioffset || (channel & PRI_HELD_CALL)) {
/* Find the call waiting call or held call. */
return pri_find_principle_by_call(pri, call);
}
span = PRI_SPAN(channel);
if (!(channel & PRI_EXPLICIT)) {
int index;
index = pri_active_dchan_index(pri);
if (index == -1) {
return -1;
}
span = pri->dchan_logical_span[index];
}
principle = -1;
for (x = 0; x < pri->numchans; x++) {
if (pri->pvts[x]
&& pri->pvts[x]->prioffset == prioffset
&& pri->pvts[x]->logicalspan == span
&& !pri->pvts[x]->no_b_channel) {
principle = x;
break;
}
}
return principle;
}
| static int pri_find_principle_by_call | ( | struct sig_pri_span * | pri, |
| q931_call * | call | ||
| ) | [static] |
Definition at line 1323 of file sig_pri.c.
References sig_pri_chan::call, sig_pri_span::numchans, and sig_pri_span::pvts.
Referenced by pri_dchannel(), pri_find_principle(), sig_pri_attempt_transfer(), sig_pri_handle_hold(), sig_pri_handle_retrieve(), and sig_pri_kill_call().
| static int pri_fixup_principle | ( | struct sig_pri_span * | pri, |
| int | principle, | ||
| q931_call * | call | ||
| ) | [static] |
Definition at line 1444 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, sig_pri_chan::aoc_s_request_invoke_id_valid, ast_channel_name(), ast_channel_unlock, ast_log(), ast_verb, sig_pri_chan::call, sig_pri_chan::call_level, sig_pri_chan::channel, sig_pri_chan::context, sig_pri_chan::deferred_digits, sig_pri_chan::digital, sig_pri_chan::hidecallerid, sig_pri_chan::hidecalleridname, sig_pri_chan::holding_aoce, sig_pri_chan::immediate, sig_pri_chan::is_call_waiting, sig_pri_chan::isidlecall, sig_pri_chan::keypad_digits, LOG_WARNING, sig_pri_chan::logicalspan, sig_pri_chan::mastertrunkgroup, sig_pri_chan::moh_state, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_chan::outgoing, sig_pri_chan::owner, sig_pri_chan::priexclusive, sig_pri_chan::priindication_oob, sig_pri_chan::progress, sig_pri_span::pvts, sig_pri_chan::reverse_charging_indication, 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_MOH_STATE_IDLE, sig_pri_open_media(), sig_pri_unlock_private(), sig_pri_chan::stripmsd, sig_pri_chan::use_callerid, sig_pri_chan::use_callingpres, sig_pri_chan::user_tag, and sig_pri_chan::waiting_for_aoce.
Referenced by pri_dchannel(), pri_find_fixup_principle(), sig_pri_handle_hold(), sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), and sig_pri_handle_retrieve_rej().
{
int x;
if (principle < 0 || pri->numchans <= principle) {
/* Out of rannge */
return -1;
}
if (!call) {
/* No call */
return principle;
}
if (pri->pvts[principle] && pri->pvts[principle]->call == call) {
/* Call is already on the specified principle. */
return principle;
}
/* Find the old principle location. */
for (x = 0; x < pri->numchans; x++) {
struct sig_pri_chan *new_chan;
struct sig_pri_chan *old_chan;
if (!pri->pvts[x] || pri->pvts[x]->call != call) {
continue;
}
/* Found our call */
new_chan = pri->pvts[principle];
old_chan = pri->pvts[x];
/* Get locks to safely move to the new private structure. */
sig_pri_lock_private(old_chan);
sig_pri_lock_owner(pri, x);
sig_pri_lock_private(new_chan);
ast_verb(3, "Moving call (%s) from channel %d to %d.\n",
old_chan->owner ? ast_channel_name(old_chan->owner) : "",
old_chan->channel, new_chan->channel);
if (!sig_pri_is_chan_available(new_chan)) {
ast_log(LOG_WARNING,
"Can't move call (%s) from channel %d to %d. It is already in use.\n",
old_chan->owner ? ast_channel_name(old_chan->owner) : "",
old_chan->channel, new_chan->channel);
sig_pri_unlock_private(new_chan);
if (old_chan->owner) {
ast_channel_unlock(old_chan->owner);
}
sig_pri_unlock_private(old_chan);
return -1;
}
sig_pri_fixup_chans(old_chan, new_chan);
/* Fix it all up now */
new_chan->owner = old_chan->owner;
old_chan->owner = NULL;
new_chan->call = old_chan->call;
old_chan->call = NULL;
/* Transfer flags from the old channel. */
#if defined(HAVE_PRI_AOC_EVENTS)
new_chan->aoc_s_request_invoke_id_valid = old_chan->aoc_s_request_invoke_id_valid;
new_chan->waiting_for_aoce = old_chan->waiting_for_aoce;
new_chan->holding_aoce = old_chan->holding_aoce;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
new_chan->alreadyhungup = old_chan->alreadyhungup;
new_chan->isidlecall = old_chan->isidlecall;
new_chan->progress = old_chan->progress;
new_chan->allocated = old_chan->allocated;
new_chan->outgoing = old_chan->outgoing;
new_chan->digital = old_chan->digital;
#if defined(HAVE_PRI_CALL_WAITING)
new_chan->is_call_waiting = old_chan->is_call_waiting;
#endif /* defined(HAVE_PRI_CALL_WAITING) */
#if defined(HAVE_PRI_AOC_EVENTS)
old_chan->aoc_s_request_invoke_id_valid = 0;
old_chan->waiting_for_aoce = 0;
old_chan->holding_aoce = 0;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
old_chan->alreadyhungup = 0;
old_chan->isidlecall = 0;
old_chan->progress = 0;
old_chan->allocated = 0;
old_chan->outgoing = 0;
old_chan->digital = 0;
#if defined(HAVE_PRI_CALL_WAITING)
old_chan->is_call_waiting = 0;
#endif /* defined(HAVE_PRI_CALL_WAITING) */
/* More stuff to transfer to the new channel. */
new_chan->call_level = old_chan->call_level;
old_chan->call_level = SIG_PRI_CALL_LEVEL_IDLE;
#if defined(HAVE_PRI_REVERSE_CHARGE)
new_chan->reverse_charging_indication = old_chan->reverse_charging_indication;
#endif /* defined(HAVE_PRI_REVERSE_CHARGE) */
#if defined(HAVE_PRI_SETUP_KEYPAD)
strcpy(new_chan->keypad_digits, old_chan->keypad_digits);
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
strcpy(new_chan->deferred_digits, old_chan->deferred_digits);
strcpy(new_chan->moh_suggested, old_chan->moh_suggested);
new_chan->moh_state = old_chan->moh_state;
old_chan->moh_state = SIG_PRI_MOH_STATE_IDLE;
#if defined(HAVE_PRI_AOC_EVENTS)
new_chan->aoc_s_request_invoke_id = old_chan->aoc_s_request_invoke_id;
new_chan->aoc_e = old_chan->aoc_e;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
strcpy(new_chan->user_tag, old_chan->user_tag);
if (new_chan->no_b_channel) {
/* Copy the real channel configuration to the no B channel interface. */
new_chan->hidecallerid = old_chan->hidecallerid;
new_chan->hidecalleridname = old_chan->hidecalleridname;
new_chan->immediate = old_chan->immediate;
new_chan->priexclusive = old_chan->priexclusive;
new_chan->priindication_oob = old_chan->priindication_oob;
new_chan->use_callerid = old_chan->use_callerid;
new_chan->use_callingpres = old_chan->use_callingpres;
new_chan->stripmsd = old_chan->stripmsd;
strcpy(new_chan->context, old_chan->context);
strcpy(new_chan->mohinterpret, old_chan->mohinterpret);
/* Become a member of the old channel span/trunk-group. */
new_chan->logicalspan = old_chan->logicalspan;
new_chan->mastertrunkgroup = old_chan->mastertrunkgroup;
} else if (old_chan->no_b_channel) {
/*
* We are transitioning from a held/call-waiting channel to a
* real channel so we need to make sure that the media path is
* open. (Needed especially if the channel is natively
* bridged.)
*/
sig_pri_open_media(new_chan);
}
if (new_chan->owner) {
sig_pri_ami_channel_event(new_chan);
}
sig_pri_unlock_private(old_chan);
if (new_chan->owner) {
ast_channel_unlock(new_chan->owner);
}
sig_pri_unlock_private(new_chan);
return principle;
}
ast_verb(3, "Call specified, but not found.\n");
return -1;
}
| static void pri_grab | ( | struct sig_pri_chan * | p, |
| struct sig_pri_span * | pri | ||
| ) | [static] |
Definition at line 361 of file sig_pri.c.
References ast_mutex_trylock, AST_PTHREADT_NULL, sig_pri_span::lock, sig_pri_span::master, and sig_pri_deadlock_avoidance_private().
Referenced by pri_send_callrerouting_facility_exec(), pri_send_keypad_facility_exec(), pri_ss_thread(), sig_pri_answer(), sig_pri_call(), sig_pri_chan_alarm_notify(), sig_pri_digit_begin(), sig_pri_hangup(), sig_pri_indicate(), and sig_pri_sendtext().
{
/* Grab the lock first */
while (ast_mutex_trylock(&pri->lock)) {
/* Avoid deadlock */
sig_pri_deadlock_avoidance_private(p);
}
/* Then break the poll */
if (pri->master != AST_PTHREADT_NULL) {
pthread_kill(pri->master, SIGURG);
}
}
| int pri_is_up | ( | struct sig_pri_span * | pri | ) |
Definition at line 1051 of file sig_pri.c.
References DCHAN_AVAILABLE, sig_pri_span::dchanavail, and SIG_PRI_NUM_DCHANS.
Referenced by pri_dchannel().
{
int x;
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
if (pri->dchanavail[x] == DCHAN_AVAILABLE)
return 1;
}
return 0;
}
| int pri_maintenance_bservice | ( | struct pri * | pri, |
| struct sig_pri_chan * | p, | ||
| int | changestatus | ||
| ) |
Definition at line 9342 of file sig_pri.c.
References sig_pri_chan::channel, PRI_SPAN, and PVT_TO_CHANNEL().
Referenced by handle_pri_service_generic().
{
int channel = PVT_TO_CHANNEL(p);
int span = PRI_SPAN(channel);
return pri_maintenance_service(pri, span, channel, changestatus);
}
| static const char* pri_order | ( | int | level | ) | [static] |
Definition at line 1061 of file sig_pri.c.
Referenced by pri_dchannel(), pri_find_dchan(), sig_pri_ami_show_spans(), and sig_pri_cli_show_span().
{
switch (level) {
case 0:
return "Primary";
case 1:
return "Secondary";
case 2:
return "Tertiary";
case 3:
return "Quaternary";
default:
return "<Unknown>";
}
}
| static void pri_queue_control | ( | struct sig_pri_span * | pri, |
| int | chanpos, | ||
| int | subclass | ||
| ) | [static] |
Definition at line 1263 of file sig_pri.c.
References AST_FRAME_CONTROL, sig_pri_chan::chan_pvt, ast_frame_subclass::integer, pri_queue_frame(), sig_pri_span::pvts, sig_pri_callback::queue_control, sig_pri_callbacks, and ast_frame::subclass.
Referenced by pri_dchannel(), sig_pri_handle_hold(), sig_pri_handle_retrieve(), and sig_pri_kill_call().
{
struct ast_frame f = {AST_FRAME_CONTROL, };
struct sig_pri_chan *p = pri->pvts[chanpos];
if (sig_pri_callbacks.queue_control) {
sig_pri_callbacks.queue_control(p->chan_pvt, subclass);
}
f.subclass.integer = subclass;
pri_queue_frame(pri, chanpos, &f);
}
| static void pri_queue_frame | ( | struct sig_pri_span * | pri, |
| int | chanpos, | ||
| struct ast_frame * | frame | ||
| ) | [static] |
Definition at line 1240 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_dchannel(), and pri_queue_control().
{
sig_pri_lock_owner(pri, chanpos);
if (pri->pvts[chanpos]->owner) {
ast_queue_frame(pri->pvts[chanpos]->owner, frame);
ast_channel_unlock(pri->pvts[chanpos]->owner);
}
}
| static void pri_queue_pvt_cause_data | ( | struct sig_pri_span * | pri, |
| int | chanpos, | ||
| const char * | cause, | ||
| int | ast_cause | ||
| ) | [static] |
Definition at line 1290 of file sig_pri.c.
References ast_alloca, ast_control_pvt_cause_code::ast_cause, ast_channel_hangupcause_hash_set(), AST_CHANNEL_NAME, ast_channel_name(), ast_channel_unlock, AST_CONTROL_PVT_CAUSE_CODE, ast_copy_string(), ast_queue_control_data(), ast_control_pvt_cause_code::chan_name, ast_control_pvt_cause_code::code, sig_pri_chan::owner, sig_pri_span::pvts, and sig_pri_lock_owner().
Referenced by pri_dchannel().
{
struct ast_channel *chan;
struct ast_control_pvt_cause_code *cause_code;
sig_pri_lock_owner(pri, chanpos);
chan = pri->pvts[chanpos]->owner;
if (chan) {
int datalen = sizeof(*cause_code) + strlen(cause);
cause_code = ast_alloca(datalen);
memset(cause_code, 0, datalen);
cause_code->ast_cause = ast_cause;
ast_copy_string(cause_code->chan_name, ast_channel_name(chan), AST_CHANNEL_NAME);
ast_copy_string(cause_code->code, cause, datalen + 1 - sizeof(*cause_code));
ast_queue_control_data(chan, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
ast_channel_hangupcause_hash_set(chan, cause_code, datalen);
ast_channel_unlock(chan);
}
}
| static void pri_rel | ( | struct sig_pri_span * | pri | ) | [inline, static] |
Definition at line 148 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(), sig_pri_indicate(), and sig_pri_sendtext().
{
ast_mutex_unlock(&pri->lock);
}
| 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 9320 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_callrerouting_facility_exec().
{
int res;
sig_pri_lock_private(p);
if (!p->pri || !p->call) {
ast_debug(1, "Unable to find pri or call on channel!\n");
sig_pri_unlock_private(p);
return -1;
}
pri_grab(p, p->pri);
res = pri_callrerouting_facility(p->pri->pri, p->call, destination, original, reason);
pri_rel(p->pri);
sig_pri_unlock_private(p);
return res;
}
| int pri_send_keypad_facility_exec | ( | struct sig_pri_chan * | p, |
| const char * | digits | ||
| ) |
Definition at line 9301 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().
{
sig_pri_lock_private(p);
if (!p->pri || !p->call) {
ast_debug(1, "Unable to find pri or call on channel!\n");
sig_pri_unlock_private(p);
return -1;
}
pri_grab(p, p->pri);
pri_keypad_facility(p->pri->pri, p->call, digits);
pri_rel(p->pri);
sig_pri_unlock_private(p);
return 0;
}
| static void* pri_ss_thread | ( | void * | data | ) | [static] |
Definition at line 1940 of file sig_pri.c.
References sig_pri_span::append_msn_to_user_tag, ast_callid_threadassoc_add(), ast_callid_unref, AST_CAUSE_UNALLOCATED, ast_channel_caller(), ast_channel_callid(), ast_channel_context(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_tech_pvt(), ast_copy_string(), ast_debug, 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, sig_pri_chan::cid_num, DAHDI_OVERLAPDIAL_INCOMING, exten, sig_pri_chan::exten, ast_party_caller::id, sig_pri_span::initial_user_tag, len(), sig_pri_span::lock, LOG_WARNING, sig_pri_span::nodetype, ast_party_dialed::number, sig_pri_span::overlapdial, sig_pri_chan::owner, sig_pri_chan::pri, sig_pri_span::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, and sig_pri_chan::user_tag.
Referenced by pri_dchannel().
{
struct sig_pri_chan *p = data;
struct ast_channel *chan = p->owner;
char exten[AST_MAX_EXTENSION];
int res;
int len;
int timeout;
struct ast_callid *callid;
if (!chan) {
/* We lost the owner before we could get started. */
return NULL;
}
if ((callid = ast_channel_callid(chan))) {
ast_callid_threadassoc_add(callid);
ast_callid_unref(callid);
}
/*
* In the bizarre case where the channel has become a zombie before we
* even get started here, abort safely.
*/
if (!ast_channel_tech_pvt(chan)) {
ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", ast_channel_name(chan));
ast_hangup(chan);
return NULL;
}
ast_verb(3, "Starting simple switch on '%s'\n", ast_channel_name(chan));
sig_pri_dsp_reset_and_flush_digits(p);
/* Now loop looking for an extension */
ast_copy_string(exten, p->exten, sizeof(exten));
len = strlen(exten);
res = 0;
while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
if (len && !ast_ignore_pattern(ast_channel_context(chan), exten))
sig_pri_play_tone(p, -1);
else
sig_pri_play_tone(p, SIG_PRI_TONE_DIALTONE);
if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num))
timeout = pri_matchdigittimeout;
else
timeout = pri_gendigittimeout;
res = ast_waitfordigit(chan, timeout);
if (res < 0) {
ast_debug(1, "waitfordigit returned < 0...\n");
ast_hangup(chan);
return NULL;
} else if (res) {
exten[len++] = res;
exten[len] = '\0';
} else
break;
}
/* if no extension was received ('unspecified') on overlap call, use the 's' extension */
if (ast_strlen_zero(exten)) {
ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
exten[0] = 's';
exten[1] = '\0';
} else {
ast_free(ast_channel_dialed(chan)->number.str);
ast_channel_dialed(chan)->number.str = ast_strdup(exten);
if (p->pri->append_msn_to_user_tag && p->pri->nodetype != PRI_NETWORK) {
/*
* Update the user tag for party id's from this device for this call
* now that we have a complete MSN from the network.
*/
snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
exten);
ast_free(ast_channel_caller(chan)->id.tag);
ast_channel_caller(chan)->id.tag = ast_strdup(p->user_tag);
}
}
sig_pri_play_tone(p, -1);
if (ast_exists_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
/* Start the real PBX */
ast_channel_exten_set(chan, exten);
sig_pri_dsp_reset_and_flush_digits(p);
#if defined(ISSUE_16789)
/*
* Conditionaled out this code to effectively revert the Mantis
* issue 16789 change. It breaks overlap dialing through
* Asterisk. There is not enough information available at this
* point to know if dialing is complete. The
* ast_exists_extension(), ast_matchmore_extension(), and
* ast_canmatch_extension() calls are not adequate to detect a
* dial through extension pattern of "_9!".
*
* Workaround is to use the dialplan Proceeding() application
* early on non-dial through extensions.
*/
if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
&& !ast_matchmore_extension(chan, ast_channel_context(chan), exten, 1, p->cid_num)) {
sig_pri_lock_private(p);
if (p->pri->pri) {
pri_grab(p, p->pri);
if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
}
pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
pri_rel(p->pri);
}
sig_pri_unlock_private(p);
}
#endif /* defined(ISSUE_16789) */
sig_pri_set_echocanceller(p, 1);
ast_setstate(chan, AST_STATE_RING);
res = ast_pbx_run(chan);
if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero!\n");
}
} else {
ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, ast_channel_context(chan));
ast_channel_hangupcause_set(chan, AST_CAUSE_UNALLOCATED);
ast_hangup(chan);
p->exten[0] = '\0';
/* Since we send release complete here, we won't get one */
p->call = NULL;
ast_mutex_lock(&p->pri->lock);
sig_pri_span_devstate_changed(p->pri);
ast_mutex_unlock(&p->pri->lock);
}
return NULL;
}
| static enum AST_PARTY_CHAR_SET pri_to_ast_char_set | ( | int | pri_char_set | ) | [static] |
Definition at line 563 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().
{
enum AST_PARTY_CHAR_SET ast_char_set;
switch (pri_char_set) {
default:
case PRI_CHAR_SET_UNKNOWN:
ast_char_set = AST_PARTY_CHAR_SET_UNKNOWN;
break;
case PRI_CHAR_SET_ISO8859_1:
ast_char_set = AST_PARTY_CHAR_SET_ISO8859_1;
break;
case PRI_CHAR_SET_WITHDRAWN:
ast_char_set = AST_PARTY_CHAR_SET_WITHDRAWN;
break;
case PRI_CHAR_SET_ISO8859_2:
ast_char_set = AST_PARTY_CHAR_SET_ISO8859_2;
break;
case PRI_CHAR_SET_ISO8859_3:
ast_char_set = AST_PARTY_CHAR_SET_ISO8859_3;
break;
case PRI_CHAR_SET_ISO8859_4:
ast_char_set = AST_PARTY_CHAR_SET_ISO8859_4;
break;
case PRI_CHAR_SET_ISO8859_5:
ast_char_set = AST_PARTY_CHAR_SET_ISO8859_5;
break;
case PRI_CHAR_SET_ISO8859_7:
ast_char_set = AST_PARTY_CHAR_SET_ISO8859_7;
break;
case PRI_CHAR_SET_ISO10646_BMPSTRING:
ast_char_set = AST_PARTY_CHAR_SET_ISO10646_BMPSTRING;
break;
case PRI_CHAR_SET_ISO10646_UTF_8STRING:
ast_char_set = AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING;
break;
}
return ast_char_set;
}
| static int pri_to_ast_presentation | ( | int | pri_presentation | ) | [static] |
Definition at line 453 of file sig_pri.c.
References AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_NUMBER_NOT_AVAILABLE, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.
Referenced by sig_pri_party_name_convert(), and sig_pri_party_number_convert().
{
int ast_presentation;
switch (pri_presentation) {
case PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED:
ast_presentation = AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED;
break;
case PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN:
ast_presentation = AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_PASSED_SCREEN;
break;
case PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN:
ast_presentation = AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_FAILED_SCREEN;
break;
case PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER:
ast_presentation = AST_PRES_ALLOWED | AST_PRES_NETWORK_NUMBER;
break;
case PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED:
ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
break;
case PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN:
ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_PASSED_SCREEN;
break;
case PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN:
ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_FAILED_SCREEN;
break;
case PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER:
ast_presentation = AST_PRES_RESTRICTED | AST_PRES_NETWORK_NUMBER;
break;
case PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_UNSCREENED:
case PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_PASSED_SCREEN:
case PRI_PRES_UNAVAILABLE | PRI_PRES_USER_NUMBER_FAILED_SCREEN:
case PRI_PRES_UNAVAILABLE | PRI_PRES_NETWORK_NUMBER:
ast_presentation = AST_PRES_NUMBER_NOT_AVAILABLE;
break;
default:
ast_presentation = AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
break;
}
return ast_presentation;
}
| static enum AST_REDIRECTING_REASON pri_to_ast_reason | ( | int | pri_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_convert().
{
enum AST_REDIRECTING_REASON ast_reason;
switch (pri_reason) {
case PRI_REDIR_FORWARD_ON_BUSY:
ast_reason = AST_REDIRECTING_REASON_USER_BUSY;
break;
case PRI_REDIR_FORWARD_ON_NO_REPLY:
ast_reason = AST_REDIRECTING_REASON_NO_ANSWER;
break;
case PRI_REDIR_DEFLECTION:
ast_reason = AST_REDIRECTING_REASON_DEFLECTION;
break;
case PRI_REDIR_UNCONDITIONAL:
ast_reason = AST_REDIRECTING_REASON_UNCONDITIONAL;
break;
case PRI_REDIR_UNKNOWN:
default:
ast_reason = AST_REDIRECTING_REASON_UNKNOWN;
break;
}
return ast_reason;
}
| static unsigned int PVT_TO_CHANNEL | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 153 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_dchannel(), pri_maintenance_bservice(), pri_ss_thread(), sig_pri_call(), sig_pri_handle_retrieve(), sig_pri_indicate(), and sig_pri_moh_retrieve_call().
{
int res = (((p)->prioffset) | ((p)->logicalspan << 8) | (p->mastertrunkgroup ? PRI_EXPLICIT : 0));
ast_debug(5, "prioffset: %d mastertrunkgroup: %d logicalspan: %d result: %d\n",
p->prioffset, p->mastertrunkgroup, p->logicalspan, res);
return res;
}
| static char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 1643 of file sig_pri.c.
Referenced by pri_dchannel().
{
switch (redirectingreason) {
case 0:
return "UNKNOWN";
case 1:
return "BUSY";
case 2:
return "NO_REPLY";
case 0xF:
return "UNCONDITIONAL";
default:
return "NOREDIRECT";
}
}
| static void sig_pri_ami_channel_event | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 1030 of file sig_pri.c.
References sig_pri_callback::ami_channel_event, sig_pri_chan::chan_pvt, sig_pri_chan::owner, and sig_pri_callbacks.
Referenced by pri_fixup_principle().
{
if (sig_pri_callbacks.ami_channel_event) {
sig_pri_callbacks.ami_channel_event(p->chan_pvt, p->owner);
}
}
| static void sig_pri_ami_hold_event | ( | struct ast_channel * | chan, |
| int | is_held | ||
| ) | [static] |
Definition at line 5191 of file sig_pri.c.
References ast_channel_name(), ast_channel_uniqueid(), ast_manager_event, and EVENT_FLAG_CALL.
Referenced by sig_pri_handle_hold(), and sig_pri_handle_retrieve().
{
/*** DOCUMENTATION
<managerEventInstance>
<synopsis>Raised when a PRI channel is put on Hold.</synopsis>
<syntax>
<parameter name="Status">
<enumlist>
<enum name="On"/>
<enum name="Off"/>
</enumlist>
</parameter>
</syntax>
</managerEventInstance>
***/
ast_manager_event(chan, EVENT_FLAG_CALL, "Hold",
"Status: %s\r\n"
"Channel: %s\r\n"
"Uniqueid: %s\r\n",
is_held ? "On" : "Off",
ast_channel_name(chan),
ast_channel_uniqueid(chan));
}
| int sig_pri_ami_show_spans | ( | struct mansession * | s, |
| const char * | show_cmd, | ||
| struct sig_pri_span * | pri, | ||
| const int * | dchannels, | ||
| const char * | action_id | ||
| ) |
Output AMI show spans response events for the given PRI span.
| show_cmd | AMI command name |
| s | AMI session to output span information. |
| pri | PRI span control structure. |
| dchannels | Array of D channel channel numbers. |
| action_id | Action ID line to use. |
Definition at line 7513 of file sig_pri.c.
References ARRAY_LEN, astman_append(), DCHAN_NOTINALARM, DCHAN_UP, sig_pri_span::dchanavail, sig_pri_span::dchans, sig_pri_span::pri, pri_order(), and sig_pri_span::span.
Referenced by action_prishowspans().
{
int count;
int x;
count = 0;
for (x = 0; x < ARRAY_LEN(pri->dchans); ++x) {
if (pri->dchans[x]) {
++count;
astman_append(s,
"Event: %s\r\n"
"Span: %d\r\n"
"DChannel: %d\r\n"
"Order: %s\r\n"
"Active: %s\r\n"
"Alarm: %s\r\n"
"Up: %s\r\n"
"%s"
"\r\n",
show_cmd,
pri->span,
dchannels[x],
pri_order(x),
(pri->dchans[x] == pri->pri) ? "Yes" : "No",
(pri->dchanavail[x] & DCHAN_NOTINALARM) ? "No" : "Yes",
(pri->dchanavail[x] & DCHAN_UP) ? "Yes" : "No",
action_id
);
}
}
return count;
}
| int sig_pri_answer | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | ast | ||
| ) |
Definition at line 8494 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().
{
int res;
/* Send a pri acknowledge */
pri_grab(p, p->pri);
#if defined(HAVE_PRI_AOC_EVENTS)
if (p->aoc_s_request_invoke_id_valid) {
/* if AOC-S was requested and the invoke id is still present on answer. That means
* no AOC-S rate list was provided, so send a NULL response which will indicate that
* AOC-S is not available */
pri_aoc_s_request_response_send(p->pri->pri, p->call,
p->aoc_s_request_invoke_id, NULL);
p->aoc_s_request_invoke_id_valid = 0;
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
if (p->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
p->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
}
sig_pri_set_dialing(p, 0);
sig_pri_open_media(p);
res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
pri_rel(p->pri);
ast_setstate(ast, AST_STATE_UP);
return res;
}
| static enum ast_aoc_s_charged_item sig_pri_aoc_charged_item_to_ast | ( | enum PRI_AOC_CHARGED_ITEM | value | ) | [static] |
Definition at line 2982 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().
{
switch (value) {
case PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE:
return AST_AOC_CHARGED_ITEM_NA;
case PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
return AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
case PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
return AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
case PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT:
return AST_AOC_CHARGED_ITEM_CALL_ATTEMPT;
case PRI_AOC_CHARGED_ITEM_CALL_SETUP:
return AST_AOC_CHARGED_ITEM_CALL_SETUP;
case PRI_AOC_CHARGED_ITEM_USER_USER_INFO:
return AST_AOC_CHARGED_ITEM_USER_USER_INFO;
case PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
return AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
}
return AST_AOC_CHARGED_ITEM_NA;
}
| static enum PRI_AOC_CHARGED_ITEM sig_pri_aoc_charged_item_to_pri | ( | enum PRI_AOC_CHARGED_ITEM | value | ) | [static] |
Definition at line 2950 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().
{
switch (value) {
case AST_AOC_CHARGED_ITEM_NA:
return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
case AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT:
return PRI_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
case AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION:
return PRI_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
case AST_AOC_CHARGED_ITEM_CALL_ATTEMPT:
return PRI_AOC_CHARGED_ITEM_CALL_ATTEMPT;
case AST_AOC_CHARGED_ITEM_CALL_SETUP:
return PRI_AOC_CHARGED_ITEM_CALL_SETUP;
case AST_AOC_CHARGED_ITEM_USER_USER_INFO:
return PRI_AOC_CHARGED_ITEM_USER_USER_INFO;
case AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE:
return PRI_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
}
return PRI_AOC_CHARGED_ITEM_NOT_AVAILABLE;
}
| static void sig_pri_aoc_d_from_ast | ( | struct sig_pri_chan * | pvt, |
| struct ast_aoc_decoded * | decoded | ||
| ) | [static] |
Definition at line 3638 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_chan::pri, sig_pri_span::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().
{
struct pri_subcmd_aoc_d aoc_d = { 0, };
aoc_d.billing_accumulation = (ast_aoc_get_total_type(decoded) == AST_AOC_TOTAL) ? 1 : 0;
switch (ast_aoc_get_billing_id(decoded)) {
case AST_AOC_BILLING_NORMAL:
aoc_d.billing_id = PRI_AOC_D_BILLING_ID_NORMAL;
break;
case AST_AOC_BILLING_REVERSE_CHARGE:
aoc_d.billing_id = PRI_AOC_D_BILLING_ID_REVERSE;
break;
case AST_AOC_BILLING_CREDIT_CARD:
aoc_d.billing_id = PRI_AOC_D_BILLING_ID_CREDIT_CARD;
break;
case AST_AOC_BILLING_NA:
default:
aoc_d.billing_id = PRI_AOC_D_BILLING_ID_NOT_AVAILABLE;
break;
}
switch (ast_aoc_get_charge_type(decoded)) {
case AST_AOC_CHARGE_FREE:
aoc_d.charge = PRI_AOC_DE_CHARGE_FREE;
break;
case AST_AOC_CHARGE_CURRENCY:
{
const char *currency_name = ast_aoc_get_currency_name(decoded);
aoc_d.charge = PRI_AOC_DE_CHARGE_CURRENCY;
aoc_d.recorded.money.amount.cost = ast_aoc_get_currency_amount(decoded);
aoc_d.recorded.money.amount.multiplier = sig_pri_aoc_multiplier_from_ast(ast_aoc_get_currency_multiplier(decoded));
if (!ast_strlen_zero(currency_name)) {
ast_copy_string(aoc_d.recorded.money.currency, currency_name, sizeof(aoc_d.recorded.money.currency));
}
}
break;
case AST_AOC_CHARGE_UNIT:
{
const struct ast_aoc_unit_entry *entry;
int i;
aoc_d.charge = PRI_AOC_DE_CHARGE_UNITS;
for (i = 0; i < ast_aoc_get_unit_count(decoded); i++) {
if ((entry = ast_aoc_get_unit_info(decoded, i)) && i < ARRAY_LEN(aoc_d.recorded.unit.item)) {
if (entry->valid_amount) {
aoc_d.recorded.unit.item[i].number = entry->amount;
} else {
aoc_d.recorded.unit.item[i].number = -1;
}
if (entry->valid_type) {
aoc_d.recorded.unit.item[i].type = entry->type;
} else {
aoc_d.recorded.unit.item[i].type = -1;
}
aoc_d.recorded.unit.num_items++;
} else {
break;
}
}
}
break;
case AST_AOC_CHARGE_NA:
default:
aoc_d.charge = PRI_AOC_DE_CHARGE_NOT_AVAILABLE;
break;
}
pri_aoc_d_send(pvt->pri->pri, pvt->call, &aoc_d);
}
| 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 3311 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().
{
struct ast_aoc_decoded *decoded = NULL;
struct ast_aoc_encoded *encoded = NULL;
size_t encoded_size = 0;
enum ast_aoc_charge_type type;
if (!owner || !aoc_d) {
return;
}
switch (aoc_d->charge) {
case PRI_AOC_DE_CHARGE_CURRENCY:
type = AST_AOC_CHARGE_CURRENCY;
break;
case PRI_AOC_DE_CHARGE_UNITS:
type = AST_AOC_CHARGE_UNIT;
break;
case PRI_AOC_DE_CHARGE_FREE:
type = AST_AOC_CHARGE_FREE;
break;
default:
type = AST_AOC_CHARGE_NA;
break;
}
if (!(decoded = ast_aoc_create(AST_AOC_D, type, 0))) {
return;
}
switch (aoc_d->billing_accumulation) {
default:
ast_debug(1, "AOC-D billing accumulation has unknown value: %d\n",
aoc_d->billing_accumulation);
/* Fall through */
case 0:/* subTotal */
ast_aoc_set_total_type(decoded, AST_AOC_SUBTOTAL);
break;
case 1:/* total */
ast_aoc_set_total_type(decoded, AST_AOC_TOTAL);
break;
}
switch (aoc_d->billing_id) {
case PRI_AOC_D_BILLING_ID_NORMAL:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NORMAL);
break;
case PRI_AOC_D_BILLING_ID_REVERSE:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_REVERSE_CHARGE);
break;
case PRI_AOC_D_BILLING_ID_CREDIT_CARD:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CREDIT_CARD);
break;
case PRI_AOC_D_BILLING_ID_NOT_AVAILABLE:
default:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NA);
break;
}
switch (aoc_d->charge) {
case PRI_AOC_DE_CHARGE_CURRENCY:
ast_aoc_set_currency_info(decoded,
aoc_d->recorded.money.amount.cost,
sig_pri_aoc_multiplier_from_pri(aoc_d->recorded.money.amount.multiplier),
aoc_d->recorded.money.currency);
break;
case PRI_AOC_DE_CHARGE_UNITS:
{
int i;
for (i = 0; i < aoc_d->recorded.unit.num_items; ++i) {
/* if type or number are negative, then they are not present */
ast_aoc_add_unit_entry(decoded,
(aoc_d->recorded.unit.item[i].number >= 0 ? 1 : 0),
aoc_d->recorded.unit.item[i].number,
(aoc_d->recorded.unit.item[i].type >= 0 ? 1 : 0),
aoc_d->recorded.unit.item[i].type);
}
}
break;
}
if (passthrough && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
}
ast_aoc_manager_event(decoded, owner);
ast_aoc_destroy_decoded(decoded);
ast_aoc_destroy_encoded(encoded);
}
| static void sig_pri_aoc_e_from_ast | ( | struct sig_pri_chan * | pvt, |
| struct ast_aoc_decoded * | decoded | ||
| ) | [static] |
Definition at line 3721 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().
{
struct pri_subcmd_aoc_e *aoc_e = &pvt->aoc_e;
const struct ast_aoc_charging_association *ca = ast_aoc_get_association_info(decoded);
memset(aoc_e, 0, sizeof(*aoc_e));
pvt->holding_aoce = 1;
switch (ca->charging_type) {
case AST_AOC_CHARGING_ASSOCIATION_NUMBER:
aoc_e->associated.charge.number.valid = 1;
ast_copy_string(aoc_e->associated.charge.number.str,
ca->charge.number.number,
sizeof(aoc_e->associated.charge.number.str));
aoc_e->associated.charge.number.plan = ca->charge.number.plan;
aoc_e->associated.charging_type = PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER;
break;
case AST_AOC_CHARGING_ASSOCIATION_ID:
aoc_e->associated.charge.id = ca->charge.id;
aoc_e->associated.charging_type = PRI_AOC_E_CHARGING_ASSOCIATION_ID;
break;
case AST_AOC_CHARGING_ASSOCIATION_NA:
default:
break;
}
switch (ast_aoc_get_billing_id(decoded)) {
case AST_AOC_BILLING_NORMAL:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_NORMAL;
break;
case AST_AOC_BILLING_REVERSE_CHARGE:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_REVERSE;
break;
case AST_AOC_BILLING_CREDIT_CARD:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CREDIT_CARD;
break;
case AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL;
break;
case AST_AOC_BILLING_CALL_FWD_BUSY:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY;
break;
case AST_AOC_BILLING_CALL_FWD_NO_REPLY:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY;
break;
case AST_AOC_BILLING_CALL_DEFLECTION:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_DEFLECTION;
break;
case AST_AOC_BILLING_CALL_TRANSFER:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_CALL_TRANSFER;
break;
case AST_AOC_BILLING_NA:
default:
aoc_e->billing_id = PRI_AOC_E_BILLING_ID_NOT_AVAILABLE;
break;
}
switch (ast_aoc_get_charge_type(decoded)) {
case AST_AOC_CHARGE_FREE:
aoc_e->charge = PRI_AOC_DE_CHARGE_FREE;
break;
case AST_AOC_CHARGE_CURRENCY:
{
const char *currency_name = ast_aoc_get_currency_name(decoded);
aoc_e->charge = PRI_AOC_DE_CHARGE_CURRENCY;
aoc_e->recorded.money.amount.cost = ast_aoc_get_currency_amount(decoded);
aoc_e->recorded.money.amount.multiplier = sig_pri_aoc_multiplier_from_ast(ast_aoc_get_currency_multiplier(decoded));
if (!ast_strlen_zero(currency_name)) {
ast_copy_string(aoc_e->recorded.money.currency, currency_name, sizeof(aoc_e->recorded.money.currency));
}
}
break;
case AST_AOC_CHARGE_UNIT:
{
const struct ast_aoc_unit_entry *entry;
int i;
aoc_e->charge = PRI_AOC_DE_CHARGE_UNITS;
for (i = 0; i < ast_aoc_get_unit_count(decoded); i++) {
if ((entry = ast_aoc_get_unit_info(decoded, i)) && i < ARRAY_LEN(aoc_e->recorded.unit.item)) {
if (entry->valid_amount) {
aoc_e->recorded.unit.item[i].number = entry->amount;
} else {
aoc_e->recorded.unit.item[i].number = -1;
}
if (entry->valid_type) {
aoc_e->recorded.unit.item[i].type = entry->type;
} else {
aoc_e->recorded.unit.item[i].type = -1;
}
aoc_e->recorded.unit.num_items++;
}
}
}
break;
case AST_AOC_CHARGE_NA:
default:
aoc_e->charge = PRI_AOC_DE_CHARGE_NOT_AVAILABLE;
break;
}
}
| 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 3420 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().
{
struct ast_aoc_decoded *decoded = NULL;
struct ast_aoc_encoded *encoded = NULL;
size_t encoded_size = 0;
enum ast_aoc_charge_type type;
if (!aoc_e) {
return;
}
switch (aoc_e->charge) {
case PRI_AOC_DE_CHARGE_CURRENCY:
type = AST_AOC_CHARGE_CURRENCY;
break;
case PRI_AOC_DE_CHARGE_UNITS:
type = AST_AOC_CHARGE_UNIT;
break;
case PRI_AOC_DE_CHARGE_FREE:
type = AST_AOC_CHARGE_FREE;
break;
default:
type = AST_AOC_CHARGE_NA;
break;
}
if (!(decoded = ast_aoc_create(AST_AOC_E, type, 0))) {
return;
}
switch (aoc_e->associated.charging_type) {
case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER:
if (!aoc_e->associated.charge.number.valid) {
break;
}
ast_aoc_set_association_number(decoded, aoc_e->associated.charge.number.str, aoc_e->associated.charge.number.plan);
break;
case PRI_AOC_E_CHARGING_ASSOCIATION_ID:
ast_aoc_set_association_id(decoded, aoc_e->associated.charge.id);
break;
default:
break;
}
switch (aoc_e->billing_id) {
case PRI_AOC_E_BILLING_ID_NORMAL:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NORMAL);
break;
case PRI_AOC_E_BILLING_ID_REVERSE:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_REVERSE_CHARGE);
break;
case PRI_AOC_E_BILLING_ID_CREDIT_CARD:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CREDIT_CARD);
break;
case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL);
break;
case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_BUSY);
break;
case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_FWD_NO_REPLY);
break;
case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_DEFLECTION);
break;
case PRI_AOC_E_BILLING_ID_CALL_TRANSFER:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_CALL_TRANSFER);
break;
case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE:
default:
ast_aoc_set_billing_id(decoded, AST_AOC_BILLING_NA);
break;
}
switch (aoc_e->charge) {
case PRI_AOC_DE_CHARGE_CURRENCY:
ast_aoc_set_currency_info(decoded,
aoc_e->recorded.money.amount.cost,
sig_pri_aoc_multiplier_from_pri(aoc_e->recorded.money.amount.multiplier),
aoc_e->recorded.money.currency);
break;
case PRI_AOC_DE_CHARGE_UNITS:
{
int i;
for (i = 0; i < aoc_e->recorded.unit.num_items; ++i) {
/* if type or number are negative, then they are not present */
ast_aoc_add_unit_entry(decoded,
(aoc_e->recorded.unit.item[i].number >= 0 ? 1 : 0),
aoc_e->recorded.unit.item[i].number,
(aoc_e->recorded.unit.item[i].type >= 0 ? 1 : 0),
aoc_e->recorded.unit.item[i].type);
}
}
}
if (passthrough && owner && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
}
ast_aoc_manager_event(decoded, owner);
ast_aoc_destroy_decoded(decoded);
ast_aoc_destroy_encoded(encoded);
}
| static int sig_pri_aoc_multiplier_from_ast | ( | enum ast_aoc_currency_multiplier | mult | ) | [static] |
Definition at line 3012 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().
{
switch (mult) {
case AST_AOC_MULT_ONETHOUSANDTH:
return PRI_AOC_MULTIPLIER_THOUSANDTH;
case AST_AOC_MULT_ONEHUNDREDTH:
return PRI_AOC_MULTIPLIER_HUNDREDTH;
case AST_AOC_MULT_ONETENTH:
return PRI_AOC_MULTIPLIER_TENTH;
case AST_AOC_MULT_ONE:
return PRI_AOC_MULTIPLIER_ONE;
case AST_AOC_MULT_TEN:
return PRI_AOC_MULTIPLIER_TEN;
case AST_AOC_MULT_HUNDRED:
return PRI_AOC_MULTIPLIER_HUNDRED;
case AST_AOC_MULT_THOUSAND:
return PRI_AOC_MULTIPLIER_THOUSAND;
default:
return PRI_AOC_MULTIPLIER_ONE;
}
}
| static int sig_pri_aoc_multiplier_from_pri | ( | const int | mult | ) | [static] |
Definition at line 3043 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().
{
switch (mult) {
case PRI_AOC_MULTIPLIER_THOUSANDTH:
return AST_AOC_MULT_ONETHOUSANDTH;
case PRI_AOC_MULTIPLIER_HUNDREDTH:
return AST_AOC_MULT_ONEHUNDREDTH;
case PRI_AOC_MULTIPLIER_TENTH:
return AST_AOC_MULT_ONETENTH;
case PRI_AOC_MULTIPLIER_ONE:
return AST_AOC_MULT_ONE;
case PRI_AOC_MULTIPLIER_TEN:
return AST_AOC_MULT_TEN;
case PRI_AOC_MULTIPLIER_HUNDRED:
return AST_AOC_MULT_HUNDRED;
case PRI_AOC_MULTIPLIER_THOUSAND:
return AST_AOC_MULT_THOUSAND;
default:
return AST_AOC_MULT_ONE;
}
}
| 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 3240 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_chan::pri, sig_pri_span::pri, SIG_PRI_AOC_GRANT_D, SIG_PRI_AOC_GRANT_E, and SIG_PRI_AOC_GRANT_S.
Referenced by sig_pri_handle_subcmds().
{
int request;
if (!aoc_request) {
return;
}
request = aoc_request->charging_request;
if (request & PRI_AOC_REQUEST_S) {
if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
/* An AOC-S response must come from the other side, so save off this invoke_id
* and see if an AOC-S message comes in before the call is answered. */
pvt->aoc_s_request_invoke_id = aoc_request->invoke_id;
pvt->aoc_s_request_invoke_id_valid = 1;
} else {
pri_aoc_s_request_response_send(pvt->pri->pri,
call,
aoc_request->invoke_id,
NULL);
}
}
if (request & PRI_AOC_REQUEST_D) {
if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
pri_aoc_de_request_response_send(pvt->pri->pri,
call,
PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
aoc_request->invoke_id);
} else {
pri_aoc_de_request_response_send(pvt->pri->pri,
call,
PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
aoc_request->invoke_id);
}
}
if (request & PRI_AOC_REQUEST_E) {
if (pvt->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
pri_aoc_de_request_response_send(pvt->pri->pri,
call,
PRI_AOC_REQ_RSP_CHARGING_INFO_FOLLOWS,
aoc_request->invoke_id);
} else {
pri_aoc_de_request_response_send(pvt->pri->pri,
call,
PRI_AOC_REQ_RSP_ERROR_NOT_AVAILABLE,
aoc_request->invoke_id);
}
}
}
| static void sig_pri_aoc_s_from_ast | ( | struct sig_pri_chan * | pvt, |
| struct ast_aoc_decoded * | decoded | ||
| ) | [static] |
Definition at line 3539 of file sig_pri.c.
References ast_aoc_duration_rate::amount, ast_aoc_volume_rate::amount, ast_aoc_flat_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_duration_rate::currency_name, ast_aoc_volume_rate::currency_name, ast_aoc_flat_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_duration_rate::multiplier, ast_aoc_volume_rate::multiplier, ast_aoc_flat_rate::multiplier, sig_pri_chan::pri, sig_pri_span::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().
{
struct pri_subcmd_aoc_s aoc_s = { 0, };
const struct ast_aoc_s_entry *entry;
int idx;
for (idx = 0; idx < ast_aoc_s_get_count(decoded); idx++) {
if (!(entry = ast_aoc_s_get_rate_info(decoded, idx))) {
break;
}
aoc_s.item[idx].chargeable = sig_pri_aoc_charged_item_to_pri(entry->charged_item);
switch (entry->rate_type) {
case AST_AOC_RATE_TYPE_DURATION:
aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_DURATION;
aoc_s.item[idx].rate.duration.amount.cost = entry->rate.duration.amount;
aoc_s.item[idx].rate.duration.amount.multiplier =
sig_pri_aoc_multiplier_from_ast(entry->rate.duration.multiplier);
aoc_s.item[idx].rate.duration.time.length = entry->rate.duration.time;
aoc_s.item[idx].rate.duration.time.scale =
sig_pri_aoc_scale_to_pri(entry->rate.duration.time_scale);
aoc_s.item[idx].rate.duration.granularity.length = entry->rate.duration.granularity_time;
aoc_s.item[idx].rate.duration.granularity.scale =
sig_pri_aoc_scale_to_pri(entry->rate.duration.granularity_time_scale);
aoc_s.item[idx].rate.duration.charging_type = entry->rate.duration.charging_type;
if (!ast_strlen_zero(entry->rate.duration.currency_name)) {
ast_copy_string(aoc_s.item[idx].rate.duration.currency,
entry->rate.duration.currency_name,
sizeof(aoc_s.item[idx].rate.duration.currency));
}
break;
case AST_AOC_RATE_TYPE_FLAT:
aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FLAT;
aoc_s.item[idx].rate.flat.amount.cost = entry->rate.flat.amount;
aoc_s.item[idx].rate.flat.amount.multiplier =
sig_pri_aoc_multiplier_from_ast(entry->rate.flat.multiplier);
if (!ast_strlen_zero(entry->rate.flat.currency_name)) {
ast_copy_string(aoc_s.item[idx].rate.flat.currency,
entry->rate.flat.currency_name,
sizeof(aoc_s.item[idx].rate.flat.currency));
}
break;
case AST_AOC_RATE_TYPE_VOLUME:
aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_VOLUME;
aoc_s.item[idx].rate.volume.unit = entry->rate.volume.volume_unit;
aoc_s.item[idx].rate.volume.amount.cost = entry->rate.volume.amount;
aoc_s.item[idx].rate.volume.amount.multiplier =
sig_pri_aoc_multiplier_from_ast(entry->rate.volume.multiplier);
if (!ast_strlen_zero(entry->rate.volume.currency_name)) {
ast_copy_string(aoc_s.item[idx].rate.volume.currency,
entry->rate.volume.currency_name,
sizeof(aoc_s.item[idx].rate.volume.currency));
}
break;
case AST_AOC_RATE_TYPE_SPECIAL_CODE:
aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_SPECIAL_CODE;
aoc_s.item[idx].rate.special = entry->rate.special_code;
break;
case AST_AOC_RATE_TYPE_FREE:
aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FREE;
break;
case AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING;
break;
default:
case AST_AOC_RATE_TYPE_NA:
aoc_s.item[idx].rate_type = PRI_AOC_RATE_TYPE_NOT_AVAILABLE;
break;
}
}
aoc_s.num_items = idx;
/* if this rate should be sent as a response to an AOC-S request we will
* have an aoc_s_request_invoke_id associated with this pvt */
if (pvt->aoc_s_request_invoke_id_valid) {
pri_aoc_s_request_response_send(pvt->pri->pri, pvt->call, pvt->aoc_s_request_invoke_id, &aoc_s);
pvt->aoc_s_request_invoke_id_valid = 0;
} else {
pri_aoc_s_send(pvt->pri->pri, pvt->call, &aoc_s);
}
}
| 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 3147 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().
{
struct ast_aoc_decoded *decoded = NULL;
struct ast_aoc_encoded *encoded = NULL;
size_t encoded_size = 0;
int idx;
if (!owner || !aoc_s) {
return;
}
if (!(decoded = ast_aoc_create(AST_AOC_S, 0, 0))) {
return;
}
for (idx = 0; idx < aoc_s->num_items; ++idx) {
enum ast_aoc_s_charged_item charged_item;
charged_item = sig_pri_aoc_charged_item_to_ast(aoc_s->item[idx].chargeable);
if (charged_item == AST_AOC_CHARGED_ITEM_NA) {
/* Delete the unknown charged item from the list. */
continue;
}
switch (aoc_s->item[idx].rate_type) {
case PRI_AOC_RATE_TYPE_DURATION:
ast_aoc_s_add_rate_duration(decoded,
charged_item,
aoc_s->item[idx].rate.duration.amount.cost,
sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.duration.amount.multiplier),
aoc_s->item[idx].rate.duration.currency,
aoc_s->item[idx].rate.duration.time.length,
sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.time.scale),
aoc_s->item[idx].rate.duration.granularity.length,
sig_pri_aoc_scale_to_ast(aoc_s->item[idx].rate.duration.granularity.scale),
aoc_s->item[idx].rate.duration.charging_type);
break;
case PRI_AOC_RATE_TYPE_FLAT:
ast_aoc_s_add_rate_flat(decoded,
charged_item,
aoc_s->item[idx].rate.flat.amount.cost,
sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.flat.amount.multiplier),
aoc_s->item[idx].rate.flat.currency);
break;
case PRI_AOC_RATE_TYPE_VOLUME:
ast_aoc_s_add_rate_volume(decoded,
charged_item,
aoc_s->item[idx].rate.volume.unit,
aoc_s->item[idx].rate.volume.amount.cost,
sig_pri_aoc_multiplier_from_pri(aoc_s->item[idx].rate.volume.amount.multiplier),
aoc_s->item[idx].rate.volume.currency);
break;
case PRI_AOC_RATE_TYPE_SPECIAL_CODE:
ast_aoc_s_add_rate_special_charge_code(decoded,
charged_item,
aoc_s->item[idx].rate.special);
break;
case PRI_AOC_RATE_TYPE_FREE:
ast_aoc_s_add_rate_free(decoded, charged_item, 0);
break;
case PRI_AOC_RATE_TYPE_FREE_FROM_BEGINNING:
ast_aoc_s_add_rate_free(decoded, charged_item, 1);
break;
default:
ast_aoc_s_add_rate_na(decoded, charged_item);
break;
}
}
if (passthrough && (encoded = ast_aoc_encode(decoded, &encoded_size, owner))) {
ast_queue_control_data(owner, AST_CONTROL_AOC, encoded, encoded_size);
}
ast_aoc_manager_event(decoded, owner);
ast_aoc_destroy_decoded(decoded);
ast_aoc_destroy_encoded(encoded);
}
| static enum ast_aoc_time_scale sig_pri_aoc_scale_to_ast | ( | enum PRI_AOC_TIME_SCALE | value | ) | [static] |
Definition at line 3108 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().
{
switch (value) {
default:
case PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND:
return AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
case PRI_AOC_TIME_SCALE_TENTH_SECOND:
return AST_AOC_TIME_SCALE_TENTH_SECOND;
case PRI_AOC_TIME_SCALE_SECOND:
return AST_AOC_TIME_SCALE_SECOND;
case PRI_AOC_TIME_SCALE_TEN_SECOND:
return AST_AOC_TIME_SCALE_TEN_SECOND;
case PRI_AOC_TIME_SCALE_MINUTE:
return AST_AOC_TIME_SCALE_MINUTE;
case PRI_AOC_TIME_SCALE_HOUR:
return AST_AOC_TIME_SCALE_HOUR;
case PRI_AOC_TIME_SCALE_DAY:
return AST_AOC_TIME_SCALE_DAY;
}
return AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
}
| static enum PRI_AOC_TIME_SCALE sig_pri_aoc_scale_to_pri | ( | enum ast_aoc_time_scale | value | ) | [static] |
Definition at line 3076 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().
{
switch (value) {
default:
case AST_AOC_TIME_SCALE_HUNDREDTH_SECOND:
return PRI_AOC_TIME_SCALE_HUNDREDTH_SECOND;
case AST_AOC_TIME_SCALE_TENTH_SECOND:
return PRI_AOC_TIME_SCALE_TENTH_SECOND;
case AST_AOC_TIME_SCALE_SECOND:
return PRI_AOC_TIME_SCALE_SECOND;
case AST_AOC_TIME_SCALE_TEN_SECOND:
return PRI_AOC_TIME_SCALE_TEN_SECOND;
case AST_AOC_TIME_SCALE_MINUTE:
return PRI_AOC_TIME_SCALE_MINUTE;
case AST_AOC_TIME_SCALE_HOUR:
return PRI_AOC_TIME_SCALE_HOUR;
case AST_AOC_TIME_SCALE_DAY:
return PRI_AOC_TIME_SCALE_DAY;
}
}
| 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 2411 of file sig_pri.c.
References ast_bridged_channel(), ast_channel_connected(), ast_channel_name(), 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 pri_dchannel(), and sig_pri_handle_subcmds().
{
struct attempt_xfer_call {
q931_call *pri;
struct ast_channel *ast;
int held;
int chanpos;
};
int retval;
struct ast_channel *transferee;
struct attempt_xfer_call *call_1;
struct attempt_xfer_call *call_2;
struct attempt_xfer_call *swap_call;
struct attempt_xfer_call c1;
struct attempt_xfer_call c2;
c1.pri = call_1_pri;
c1.held = call_1_held;
call_1 = &c1;
c2.pri = call_2_pri;
c2.held = call_2_held;
call_2 = &c2;
call_1->chanpos = pri_find_principle_by_call(pri, call_1->pri);
call_2->chanpos = pri_find_principle_by_call(pri, call_2->pri);
if (call_1->chanpos < 0 || call_2->chanpos < 0) {
/* Calls not found in span control. */
if (rsp_callback) {
/* Transfer failed. */
rsp_callback(data, 0);
}
return -1;
}
/* Attempt to make transferee and target consistent. */
if (!call_1->held && call_2->held) {
/*
* Swap call_1 and call_2 to make call_1 the transferee(held call)
* and call_2 the target(active call).
*/
swap_call = call_1;
call_1 = call_2;
call_2 = swap_call;
}
/* Deadlock avoidance is attempted. */
sig_pri_lock_private(pri->pvts[call_1->chanpos]);
sig_pri_lock_owner(pri, call_1->chanpos);
sig_pri_lock_private(pri->pvts[call_2->chanpos]);
sig_pri_lock_owner(pri, call_2->chanpos);
call_1->ast = pri->pvts[call_1->chanpos]->owner;
call_2->ast = pri->pvts[call_2->chanpos]->owner;
if (!call_1->ast || !call_2->ast) {
/* At least one owner is not present. */
if (call_1->ast) {
ast_channel_unlock(call_1->ast);
}
if (call_2->ast) {
ast_channel_unlock(call_2->ast);
}
sig_pri_unlock_private(pri->pvts[call_1->chanpos]);
sig_pri_unlock_private(pri->pvts[call_2->chanpos]);
if (rsp_callback) {
/* Transfer failed. */
rsp_callback(data, 0);
}
return -1;
}
for (;;) {
transferee = ast_bridged_channel(call_1->ast);
if (transferee) {
break;
}
/* Try masquerading the other way. */
swap_call = call_1;
call_1 = call_2;
call_2 = swap_call;
transferee = ast_bridged_channel(call_1->ast);
if (transferee) {
break;
}
/* Could not transfer. Neither call is bridged. */
ast_channel_unlock(call_1->ast);
ast_channel_unlock(call_2->ast);
sig_pri_unlock_private(pri->pvts[call_1->chanpos]);
sig_pri_unlock_private(pri->pvts[call_2->chanpos]);
if (rsp_callback) {
/* Transfer failed. */
rsp_callback(data, 0);
}
return -1;
}
ast_verb(3, "TRANSFERRING %s to %s\n", ast_channel_name(call_1->ast), ast_channel_name(call_2->ast));
/*
* Setup transfer masquerade.
*
* Note: There is an extremely nasty deadlock avoidance issue
* with ast_channel_transfer_masquerade(). Deadlock may be possible if
* the channels involved are proxies (chan_agent channels) and
* it is called with locks. Unfortunately, there is no simple
* or even merely difficult way to guarantee deadlock avoidance
* and still be able to send an ECT success response without the
* possibility of the bridged channel hanging up on us.
*/
ast_mutex_unlock(&pri->lock);
retval = ast_channel_transfer_masquerade(
call_2->ast,
ast_channel_connected(call_2->ast),
call_2->held,
transferee,
ast_channel_connected(call_1->ast),
call_1->held);
/* Reacquire the pri->lock to hold off completion of the transfer masquerade. */
ast_mutex_lock(&pri->lock);
ast_channel_unlock(call_1->ast);
ast_channel_unlock(call_2->ast);
sig_pri_unlock_private(pri->pvts[call_1->chanpos]);
sig_pri_unlock_private(pri->pvts[call_2->chanpos]);
if (rsp_callback) {
/*
* Report transfer status.
*
* Must do the callback before the masquerade completes to ensure
* that the protocol message goes out before the call leg is
* disconnected.
*/
rsp_callback(data, retval ? 0 : 1);
}
return retval;
}
| int sig_pri_available | ( | struct sig_pri_chan ** | pvt, |
| int | is_specific_channel | ||
| ) |
Definition at line 8589 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::num_call_waiting_calls, sig_pri_chan::pri, sig_pri_span::pri, sig_pri_available_check(), and sig_pri_cw_available().
Referenced by available().
{
struct sig_pri_chan *p = *pvt;
struct sig_pri_span *pri;
if (!p->pri) {
/* Something is wrong here. A PRI channel without the pri pointer? */
return 0;
}
pri = p->pri;
ast_mutex_lock(&pri->lock);
if (
#if defined(HAVE_PRI_CALL_WAITING)
/*
* Only do call waiting calls if we have any
* call waiting call outstanding. We do not
* want new calls to steal a B channel
* freed for an earlier call waiting call.
*/
!pri->num_call_waiting_calls &&
#endif /* defined(HAVE_PRI_CALL_WAITING) */
sig_pri_available_check(p)) {
p->allocated = 1;
ast_mutex_unlock(&pri->lock);
return 1;
}
#if defined(HAVE_PRI_CALL_WAITING)
if (!is_specific_channel) {
struct sig_pri_chan *cw;
cw = sig_pri_cw_available(pri);
if (cw) {
/* We have a call waiting interface to use instead. */
cw->allocated = 1;
*pvt = cw;
ast_mutex_unlock(&pri->lock);
return 1;
}
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
ast_mutex_unlock(&pri->lock);
return 0;
}
| static int sig_pri_available_check | ( | struct sig_pri_chan * | pvt | ) | [static] |
Definition at line 8531 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().
{
/*
* If interface has a B channel and is available for use
* then the channel is available.
*/
if (!pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
return 1;
}
return 0;
}
| int sig_pri_call | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | ast, | ||
| const char * | rdest, | ||
| int | timeout, | ||
| int | layer1 | ||
| ) |
Definition at line 7738 of file sig_pri.c.
References 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_caller(), ast_channel_connected(), ast_channel_connected_effective_id(), ast_channel_get_device_name(), AST_CHANNEL_NAME, ast_channel_name(), ast_channel_transfercapability(), ast_copy_string(), ast_debug, 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, sig_pri_cc_monitor_instance::cc_id, sig_pri_chan::channel, sig_pri_chan::deferred_digits, sig_pri_chan::dialdest, sig_pri_span::dialplan, dialplan2str(), sig_pri_chan::digital, ext, sig_pri_span::facilityenable, sig_pri_chan::hidecallerid, sig_pri_chan::hidecalleridname, ast_party_caller::id, sig_pri_span::initial_user_tag, sig_pri_span::internationalprefix, sig_pri_chan::is_call_waiting, IS_DIGITAL, sig_pri_span::localdialplan, LOG_ERROR, LOG_WARNING, monitor, ast_party_id::name, sig_pri_span::nationalprefix, sig_pri_span::nodetype, ast_party_id::number, OPT_AOC_REQUEST, OPT_ARG_AOC_REQUEST, OPT_ARG_ARRAY_SIZE, OPT_ARG_KEYPAD, OPT_KEYPAD, OPT_REVERSE_CHARGE, sig_pri_chan::owner, pbx_builtin_getvar_helper(), ast_party_number::plan, ast_party_number::presentation, sig_pri_cc_monitor_instance::pri, sig_pri_chan::pri, sig_pri_span::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, sig_pri_chan::priexclusive, ast_cc_monitor::private_data, PVT_TO_CHANNEL(), S_COR, SIG_PRI_CALL_LEVEL_SETUP, sig_pri_call_opts, sig_pri_cc_type_name, sig_pri_party_subaddress_from_ast(), sig_pri_redirecting_update(), sig_pri_set_dialing(), sig_pri_set_digital(), sig_pri_set_outgoing(), ast_party_name::str, ast_party_number::str, ast_party_subaddress::str, sig_pri_chan::stripmsd, ast_party_id::subaddress, ast_party_id::tag, ast_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().
{
char dest[256]; /* must be same length as p->dialdest */
struct ast_party_subaddress dialed_subaddress; /* Called subaddress */
struct pri_sr *sr;
char *c, *l, *n, *s;
#ifdef SUPPORT_USERUSER
const char *useruser;
#endif
int core_id;
int pridialplan;
int dp_strip;
int prilocaldialplan;
int ldp_strip;
int exclusive;
#if defined(HAVE_PRI_SETUP_KEYPAD)
const char *keypad;
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(group); /* channel/group token */
AST_APP_ARG(ext); /* extension token */
AST_APP_ARG(opts); /* options token */
AST_APP_ARG(other); /* Any remining unused arguments */
);
struct ast_flags opts;
char *opt_args[OPT_ARG_ARRAY_SIZE];
struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
ast_debug(1, "CALLER NAME: %s NUM: %s\n",
S_COR(connected_id.name.valid, connected_id.name.str, ""),
S_COR(connected_id.number.valid, connected_id.number.str, ""));
if (!p->pri) {
ast_log(LOG_ERROR, "Could not find pri on channel %d\n", p->channel);
return -1;
}
if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "sig_pri_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
return -1;
}
p->dialdest[0] = '\0';
sig_pri_set_outgoing(p, 1);
ast_copy_string(dest, rdest, sizeof(dest));
AST_NONSTANDARD_APP_ARGS(args, dest, '/');
if (ast_app_parse_options(sig_pri_call_opts, &opts, opt_args, args.opts)) {
/* General invalid option syntax. */
return -1;
}
c = args.ext;
if (!c) {
c = "";
}
/* setup dialed_subaddress if found */
ast_party_subaddress_init(&dialed_subaddress);
s = strchr(c, ':');
if (s) {
*s = '\0';
s++;
/* prefix */
/* 'n' = NSAP */
/* 'u' = User Specified */
/* Default = NSAP */
switch (*s) {
case 'U':
case 'u':
s++;
dialed_subaddress.type = 2;
break;
case 'N':
case 'n':
s++;
/* default already covered with ast_party_subaddress_init */
break;
}
dialed_subaddress.str = s;
dialed_subaddress.valid = 1;
}
l = NULL;
n = NULL;
if (!p->hidecallerid) {
if (connected_id.number.valid) {
/* If we get to the end of this loop without breaking, there's no
* calleridnum. This is done instead of testing for "unknown" or
* the thousands of other ways that the calleridnum could be
* invalid. */
for (l = connected_id.number.str; l && *l; l++) {
if (strchr("0123456789", *l)) {
l = connected_id.number.str;
break;
}
}
} else {
l = NULL;
}
if (!p->hidecalleridname) {
n = connected_id.name.valid ? connected_id.name.str : NULL;
}
}
if (strlen(c) < p->stripmsd) {
ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
return -1;
}
/* Extract any 'w' deferred digits. */
s = strchr(c + p->stripmsd, 'w');
if (s) {
*s++ = '\0';
ast_copy_string(p->deferred_digits, s, sizeof(p->deferred_digits));
/*
* Since we have a 'w', this means that there will not be any
* more normal dialed digits. Therefore, the sending complete
* ie needs to be sent with any normal digits.
*/
} else {
p->deferred_digits[0] = '\0';
}
pri_grab(p, p->pri);
if (!(p->call = pri_new_call(p->pri->pri))) {
ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
pri_rel(p->pri);
return -1;
}
if (!(sr = pri_sr_new())) {
ast_log(LOG_WARNING, "Failed to allocate setup request on channel %d\n",
p->channel);
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
pri_rel(p->pri);
return -1;
}
sig_pri_set_digital(p, IS_DIGITAL(ast_channel_transfercapability(ast))); /* push up to parent for EC */
#if defined(HAVE_PRI_CALL_WAITING)
if (p->is_call_waiting) {
/*
* Indicate that this is a call waiting call.
* i.e., Normal call but with no B channel.
*/
pri_sr_set_channel(sr, 0, 0, 1);
} else
#endif /* defined(HAVE_PRI_CALL_WAITING) */
{
/* Should the picked channel be used exclusively? */
if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
exclusive = 1;
} else {
exclusive = 0;
}
pri_sr_set_channel(sr, PVT_TO_CHANNEL(p), exclusive, 1);
}
pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast_channel_transfercapability(ast),
(p->digital ? -1 : layer1));
if (p->pri->facilityenable)
pri_facility_enable(p->pri->pri);
ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast_channel_transfercapability(ast), ast_transfercapability2str(ast_channel_transfercapability(ast)));
dp_strip = 0;
pridialplan = p->pri->dialplan - 1;
if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
if (pridialplan == -2) {
dp_strip = strlen(p->pri->internationalprefix);
}
pridialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
if (pridialplan == -2) {
dp_strip = strlen(p->pri->nationalprefix);
}
pridialplan = PRI_NATIONAL_ISDN;
} else {
pridialplan = PRI_LOCAL_ISDN;
}
}
while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
switch (c[p->stripmsd]) {
case 'U':
pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
break;
case 'I':
pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
break;
case 'N':
pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
break;
case 'L':
pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
break;
case 'S':
pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
break;
case 'V':
pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
break;
case 'R':
pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
break;
case 'u':
pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
break;
case 'e':
pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
break;
case 'x':
pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
break;
case 'f':
pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
break;
case 'n':
pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
break;
case 'p':
pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
break;
case 'r':
pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
break;
default:
if (isalpha(c[p->stripmsd])) {
ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
}
break;
}
c++;
}
#if defined(HAVE_PRI_SETUP_KEYPAD)
if (ast_test_flag(&opts, OPT_KEYPAD)
&& !ast_strlen_zero(opt_args[OPT_ARG_KEYPAD])) {
/* We have a keypad facility digits option with digits. */
keypad = opt_args[OPT_ARG_KEYPAD];
pri_sr_set_keypad_digits(sr, keypad);
} else {
keypad = NULL;
}
if (!keypad || !ast_strlen_zero(c + p->stripmsd + dp_strip))
#endif /* defined(HAVE_PRI_SETUP_KEYPAD) */
{
pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
}
#if defined(HAVE_PRI_SUBADDR)
if (dialed_subaddress.valid) {
struct pri_party_subaddress subaddress;
memset(&subaddress, 0, sizeof(subaddress));
sig_pri_party_subaddress_from_ast(&subaddress, &dialed_subaddress);
pri_sr_set_called_subaddress(sr, &subaddress);
}
#endif /* defined(HAVE_PRI_SUBADDR) */
#if defined(HAVE_PRI_REVERSE_CHARGE)
if (ast_test_flag(&opts, OPT_REVERSE_CHARGE)) {
pri_sr_set_reversecharge(sr, PRI_REVERSECHARGE_REQUESTED);
}
#endif /* defined(HAVE_PRI_REVERSE_CHARGE) */
#if defined(HAVE_PRI_AOC_EVENTS)
if (ast_test_flag(&opts, OPT_AOC_REQUEST)
&& !ast_strlen_zero(opt_args[OPT_ARG_AOC_REQUEST])) {
if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 's')) {
pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_S);
}
if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'd')) {
pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_D);
}
if (strchr(opt_args[OPT_ARG_AOC_REQUEST], 'e')) {
pri_sr_set_aoc_charging_request(sr, PRI_AOC_REQUEST_E);
}
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
/* Setup the user tag for party id's from this device for this call. */
if (p->pri->append_msn_to_user_tag) {
snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
p->pri->nodetype == PRI_NETWORK
? c + p->stripmsd + dp_strip
: S_COR(ast_channel_connected(ast)->id.number.valid,
ast_channel_connected(ast)->id.number.str, ""));
} else {
ast_copy_string(p->user_tag, p->pri->initial_user_tag, sizeof(p->user_tag));
}
/*
* Replace the caller id tag from the channel creation
* with the actual tag value.
*/
ast_free(ast_channel_caller(ast)->id.tag);
ast_channel_caller(ast)->id.tag = ast_strdup(p->user_tag);
ldp_strip = 0;
prilocaldialplan = p->pri->localdialplan - 1;
if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
if (prilocaldialplan == -2) {
ldp_strip = strlen(p->pri->internationalprefix);
}
prilocaldialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
if (prilocaldialplan == -2) {
ldp_strip = strlen(p->pri->nationalprefix);
}
prilocaldialplan = PRI_NATIONAL_ISDN;
} else {
prilocaldialplan = PRI_LOCAL_ISDN;
}
} else if (prilocaldialplan == -1) {
/* Use the numbering plan passed in. */
prilocaldialplan = connected_id.number.plan;
}
if (l != NULL) {
while (*l > '9' && *l != '*' && *l != '#') {
switch (*l) {
case 'U':
prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
break;
case 'I':
prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
break;
case 'N':
prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
break;
case 'L':
prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
break;
case 'S':
prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
break;
case 'V':
prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
break;
case 'R':
prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
break;
case 'u':
prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
break;
case 'e':
prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
break;
case 'x':
prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
break;
case 'f':
prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
break;
case 'n':
prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
break;
case 'p':
prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
break;
case 'r':
prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
break;
default:
if (isalpha(*l)) {
ast_log(LOG_WARNING,
"Unrecognized prilocaldialplan %s modifier: %c\n",
*l > 'Z' ? "NPI" : "TON", *l);
}
break;
}
l++;
}
}
pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
p->use_callingpres ? connected_id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
#if defined(HAVE_PRI_SUBADDR)
if (connected_id.subaddress.valid) {
struct pri_party_subaddress subaddress;
memset(&subaddress, 0, sizeof(subaddress));
sig_pri_party_subaddress_from_ast(&subaddress, &connected_id.subaddress);
pri_sr_set_caller_subaddress(sr, &subaddress);
}
#endif /* defined(HAVE_PRI_SUBADDR) */
sig_pri_redirecting_update(p, ast);
#ifdef SUPPORT_USERUSER
/* User-user info */
useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
if (useruser)
pri_sr_set_useruser(sr, useruser);
#endif
#if defined(HAVE_PRI_CCSS)
if (ast_cc_is_recall(ast, &core_id, sig_pri_cc_type_name)) {
struct ast_cc_monitor *monitor;
char device_name[AST_CHANNEL_NAME];
/* This is a CC recall call. */
ast_channel_get_device_name(ast, device_name, sizeof(device_name));
monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
if (monitor) {
struct sig_pri_cc_monitor_instance *instance;
instance = monitor->private_data;
/* If this fails then we have monitor instance ambiguity. */
ast_assert(p->pri == instance->pri);
if (pri_cc_call(p->pri->pri, instance->cc_id, p->call, sr)) {
/* The CC recall call failed for some reason. */
ast_log(LOG_WARNING, "Unable to setup CC recall call to device %s\n",
device_name);
ao2_ref(monitor, -1);
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
pri_rel(p->pri);
pri_sr_free(sr);
return -1;
}
ao2_ref(monitor, -1);
} else {
core_id = -1;
}
} else
#endif /* defined(HAVE_PRI_CCSS) */
{
core_id = -1;
}
if (core_id == -1 && pri_setup(p->pri->pri, p->call, sr)) {
ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
pri_rel(p->pri);
pri_sr_free(sr);
return -1;
}
p->call_level = SIG_PRI_CALL_LEVEL_SETUP;
pri_sr_free(sr);
ast_setstate(ast, AST_STATE_DIALING);
sig_pri_set_dialing(p, 1);
pri_rel(p->pri);
return 0;
}
| 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_DEFER_DIAL, SIG_PRI_CALL_LEVEL_IDLE, SIG_PRI_CALL_LEVEL_OVERLAP, SIG_PRI_CALL_LEVEL_PROCEEDING, and SIG_PRI_CALL_LEVEL_SETUP.
Referenced by sig_pri_cli_show_channels(), and sig_pri_digit_begin().
{
switch (level) {
case SIG_PRI_CALL_LEVEL_IDLE:
return "Idle";
case SIG_PRI_CALL_LEVEL_SETUP:
return "Setup";
case SIG_PRI_CALL_LEVEL_OVERLAP:
return "Overlap";
case SIG_PRI_CALL_LEVEL_PROCEEDING:
return "Proceeding";
case SIG_PRI_CALL_LEVEL_ALERTING:
return "Alerting";
case SIG_PRI_CALL_LEVEL_DEFER_DIAL:
return "DeferDial";
case SIG_PRI_CALL_LEVEL_CONNECT:
return "Connect";
}
return "Unknown";
}
| 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 core will call this function when it receives notice that a monitored party has become available.
The agent's job is to send a message to the caller to notify it of such a change. If the agent is able to discern that the caller is currently unavailable, then the agent should react by calling the ast_cc_caller_unavailable function.
| 0 | on success. |
| -1 | on error. |
Definition at line 9688 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.
{
struct sig_pri_cc_agent_prv *cc_pvt;
cc_pvt = agent->private_data;
ast_mutex_lock(&cc_pvt->pri->lock);
pri_cc_remote_user_free(cc_pvt->pri->pri, cc_pvt->cc_id);
ast_mutex_unlock(&cc_pvt->pri->lock);
return 0;
}
| static int sig_pri_cc_agent_cmp_cc_id | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 2567 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().
{
struct ast_cc_agent *agent_1 = obj;
struct sig_pri_cc_agent_prv *agent_prv_1 = agent_1->private_data;
struct sig_pri_cc_agent_prv *agent_prv_2 = arg;
return (agent_prv_1 && agent_prv_1->pri == agent_prv_2->pri
&& agent_prv_1->cc_id == agent_prv_2->cc_id) ? CMP_MATCH | CMP_STOP : 0;
}
| void sig_pri_cc_agent_destructor | ( | struct ast_cc_agent * | agent | ) |
Destroy private data on the agent.
| agent | CC core agent control. |
The core will call this function upon completion or failure of CC.
Definition at line 9717 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().
{
struct sig_pri_cc_agent_prv *cc_pvt;
int res;
cc_pvt = agent->private_data;
if (!cc_pvt) {
/* The agent constructor probably failed. */
return;
}
ast_mutex_lock(&cc_pvt->pri->lock);
res = -1;
if (cc_pvt->cc_request_response_pending) {
res = pri_cc_req_rsp(cc_pvt->pri->pri, cc_pvt->cc_id, 2/* short_term_denial */);
}
if (res) {
pri_cc_cancel(cc_pvt->pri->pri, cc_pvt->cc_id);
}
ast_mutex_unlock(&cc_pvt->pri->lock);
ast_free(cc_pvt);
}
| 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. |
This callback is called when the CC core is initialized. Agents should allocate any private data necessary for the call and assign it to the private_data on the agent. Additionally, if any ast_cc_agent_flags are pertinent to the specific agent type, they should be set in this function as well.
| 0 | on success. |
| -1 | on error. |
Definition at line 9400 of file sig_pri.c.
References ast_calloc, ast_free, ast_mutex_lock, ast_mutex_unlock, sig_pri_chan::call, sig_pri_cc_agent_prv::cc_id, sig_pri_span::lock, sig_pri_cc_agent_prv::pri, sig_pri_chan::pri, sig_pri_span::pri, and ast_cc_agent::private_data.
Referenced by dahdi_pri_cc_agent_init().
{
struct sig_pri_cc_agent_prv *cc_pvt;
cc_pvt = ast_calloc(1, sizeof(*cc_pvt));
if (!cc_pvt) {
return -1;
}
ast_mutex_lock(&pvt_chan->pri->lock);
cc_pvt->pri = pvt_chan->pri;
cc_pvt->cc_id = pri_cc_available(pvt_chan->pri->pri, pvt_chan->call);
ast_mutex_unlock(&pvt_chan->pri->lock);
if (cc_pvt->cc_id == -1) {
ast_free(cc_pvt);
return -1;
}
agent->private_data = cc_pvt;
return 0;
}
| 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. |
This is something that really only affects a scenario where a phone places a call over ISDN PTMP to Asterisk, who then connects over PTMP again to the ISDN network. For most agent types, there is no need to implement this callback at all because they don't really need to actually do anything in this situation. If you're having trouble understanding what the purpose of this callback is, then you can be safe simply not implementing it.
| 0 | on success. |
| -1 | on error. |
Definition at line 9632 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.
{
struct sig_pri_cc_agent_prv *cc_pvt;
cc_pvt = agent->private_data;
ast_mutex_lock(&cc_pvt->pri->lock);
pri_cc_b_free(cc_pvt->pri->pri, cc_pvt->cc_id);
ast_mutex_unlock(&cc_pvt->pri->lock);
return 0;
}
| 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. |
When the core receives knowledge that a called party has accepted a CC request, it will call this callback. The core may also call this if there is some error when attempting to process the incoming CC request.
The duty of this is to issue a propper response to a CC request from the caller by acknowledging receipt of that request or rejecting it.
Definition at line 9493 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.
{
struct sig_pri_cc_agent_prv *cc_pvt;
int res;
int status;
const char *failed_msg;
static const char *failed_to_send = "Failed to send the CC request response.";
static const char *not_accepted = "The core declined the CC request.";
cc_pvt = agent->private_data;
ast_mutex_lock(&cc_pvt->pri->lock);
if (cc_pvt->cc_request_response_pending) {
cc_pvt->cc_request_response_pending = 0;
/* Convert core response reason to ISDN response status. */
status = 2;/* short_term_denial */
switch (reason) {
case AST_CC_AGENT_RESPONSE_SUCCESS:
status = 0;/* success */
break;
case AST_CC_AGENT_RESPONSE_FAILURE_INVALID:
status = 2;/* short_term_denial */
break;
case AST_CC_AGENT_RESPONSE_FAILURE_TOO_MANY:
status = 5;/* queue_full */
break;
}
res = pri_cc_req_rsp(cc_pvt->pri->pri, cc_pvt->cc_id, status);
if (!status) {
/* CC core request was accepted. */
if (res) {
failed_msg = failed_to_send;
} else {
failed_msg = NULL;
}
} else {
/* CC core request was declined. */
if (res) {
failed_msg = failed_to_send;
} else {
failed_msg = not_accepted;
}
}
} else {
failed_msg = NULL;
}
ast_mutex_unlock(&cc_pvt->pri->lock);
if (failed_msg) {
ast_cc_failed(agent->core_id, "%s agent: %s", sig_pri_cc_type_name, failed_msg);
}
}
| int sig_pri_cc_agent_start_monitoring | ( | struct ast_cc_agent * | agent | ) |
Begin monitoring a busy device.
| agent | CC core agent control. |
The core will call this callback if the callee becomes available but the caller has reported that he is busy. The agent should begin monitoring the caller's device. When the caller becomes available again, the agent should call ast_cc_agent_caller_available.
| 0 | on success. |
| -1 | on error. |
Definition at line 9661 of file sig_pri.c.
{
/* libpri already knows when and how it needs to monitor Party A. */
return 0;
}
| int sig_pri_cc_agent_start_offer_timer | ( | struct ast_cc_agent * | agent | ) |
Start the offer timer.
| agent | CC core agent control. |
This is called by the core when the caller hangs up after a call for which CC may be requested. The agent should begin the timer as configured.
The primary reason why this functionality is left to the specific agent implementations is due to the differing use of schedulers throughout the code. Some channel drivers may already have a scheduler context they wish to use, and amongst those, some may use the ast_sched API while others may use the ast_sched_thread API, which are incompatible.
| 0 | on success. |
| -1 | on error. |
Definition at line 9444 of file sig_pri.c.
{
/* libpri maintains it's own offer timer in the form of T_RETENTION. */
return 0;
}
| 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. |
Asynchronous request for the status of any caller which may be a valid caller for the CC transaction. Status responses should be made using the ast_cc_status_response function.
| 0 | on success. |
| -1 | on error. |
Definition at line 9563 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.
{
struct sig_pri_cc_agent_prv *cc_pvt;
cc_pvt = agent->private_data;
ast_mutex_lock(&cc_pvt->pri->lock);
pri_cc_status_req(cc_pvt->pri->pri, cc_pvt->cc_id);
ast_mutex_unlock(&cc_pvt->pri->lock);
return 0;
}
| int sig_pri_cc_agent_stop_offer_timer | ( | struct ast_cc_agent * | agent | ) |
Stop the offer timer.
| agent | CC core agent control. |
This callback is called by the CC core when the caller has requested CC.
| 0 | on success. |
| -1 | on error. |
Definition at line 9465 of file sig_pri.c.
{
/* libpri maintains it's own offer timer in the form of T_RETENTION. */
return 0;
}
| 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. |
The usefulness of this is quite limited. The only specific known case for this is if Asterisk requests CC over an ISDN PTMP link as the TE side. If other phones are in the same recall group as the Asterisk server, and one of those phones picks up the recall notice, then Asterisk will receive a "stop ringing" notification from the NT side of the PTMP link. This indication needs to be passed to the phone on the other side of the Asterisk server which originally placed the call so that it will stop ringing. Since the phone may be of any type, it is necessary to have a callback that the core can know about.
| 0 | on success. |
| -1 | on error. |
Definition at line 9598 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.
{
struct sig_pri_cc_agent_prv *cc_pvt;
cc_pvt = agent->private_data;
ast_mutex_lock(&cc_pvt->pri->lock);
pri_cc_stop_alerting(cc_pvt->pri->pri, cc_pvt->cc_id);
ast_mutex_unlock(&cc_pvt->pri->lock);
return 0;
}
| 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 2743 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::cc_id, sig_pri_cc_monitor_instance::core_id, monitor, sig_pri_chan::owner, sig_pri_span::pvts, sig_pri_cc_monitor_instance_init(), sig_pri_cc_type_name, sig_pri_get_orig_dialstring(), and sig_pri_make_cc_dialstring().
Referenced by sig_pri_handle_subcmds().
{
struct sig_pri_chan *pvt;
struct ast_cc_config_params *cc_params;
struct sig_pri_cc_monitor_instance *monitor;
enum ast_cc_monitor_policies monitor_policy;
int core_id;
int res;
char device_name[AST_CHANNEL_NAME];
char dialstring[AST_CHANNEL_NAME];
pvt = pri->pvts[chanpos];
core_id = ast_cc_get_current_core_id(pvt->owner);
if (core_id == -1) {
return -1;
}
cc_params = ast_channel_get_cc_config_params(pvt->owner);
if (!cc_params) {
return -1;
}
res = -1;
monitor_policy = ast_get_cc_monitor_policy(cc_params);
switch (monitor_policy) {
case AST_CC_MONITOR_NEVER:
/* CCSS is not enabled. */
break;
case AST_CC_MONITOR_NATIVE:
case AST_CC_MONITOR_ALWAYS:
/*
* If it is AST_CC_MONITOR_ALWAYS and native fails we will attempt the fallback
* later in the call to sig_pri_cc_generic_check().
*/
ast_channel_get_device_name(pvt->owner, device_name, sizeof(device_name));
sig_pri_make_cc_dialstring(pvt, dialstring, sizeof(dialstring));
monitor = sig_pri_cc_monitor_instance_init(core_id, pri, cc_id, device_name);
if (!monitor) {
break;
}
res = ast_queue_cc_frame(pvt->owner, sig_pri_cc_type_name, dialstring, service,
monitor);
if (res) {
monitor->cc_id = -1;
ao2_unlink(sig_pri_cc_monitors, monitor);
ao2_ref(monitor, -1);
}
break;
case AST_CC_MONITOR_GENERIC:
ast_queue_cc_frame(pvt->owner, AST_CC_GENERIC_MONITOR_TYPE,
sig_pri_get_orig_dialstring(pvt), service, NULL);
/* Say it failed to force caller to cancel native CC. */
break;
}
return res;
}
| static void sig_pri_cc_generic_check | ( | struct sig_pri_span * | pri, |
| int | chanpos, | ||
| enum ast_cc_service_type | service | ||
| ) | [static] |
Definition at line 2816 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().
Referenced by pri_dchannel().
{
struct ast_channel *owner;
struct ast_cc_config_params *cc_params;
#if defined(HAVE_PRI_CCSS)
struct ast_cc_monitor *monitor;
char device_name[AST_CHANNEL_NAME];
#endif /* defined(HAVE_PRI_CCSS) */
enum ast_cc_monitor_policies monitor_policy;
int core_id;
if (!pri->pvts[chanpos]->outgoing) {
/* This is not an outgoing call so it cannot be CC monitor. */
return;
}
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (!owner) {
return;
}
core_id = ast_cc_get_current_core_id(owner);
if (core_id == -1) {
/* No CC core setup */
goto done;
}
cc_params = ast_channel_get_cc_config_params(owner);
if (!cc_params) {
/* Could not get CC config parameters. */
goto done;
}
#if defined(HAVE_PRI_CCSS)
ast_channel_get_device_name(owner, device_name, sizeof(device_name));
monitor = ast_cc_get_monitor_by_recall_core_id(core_id, device_name);
if (monitor) {
/* CC monitor is already present so no need for generic CC. */
ao2_ref(monitor, -1);
goto done;
}
#endif /* defined(HAVE_PRI_CCSS) */
monitor_policy = ast_get_cc_monitor_policy(cc_params);
switch (monitor_policy) {
case AST_CC_MONITOR_NEVER:
/* CCSS is not enabled. */
break;
case AST_CC_MONITOR_NATIVE:
if (pri->sig == SIG_BRI_PTMP && pri->nodetype == PRI_NETWORK) {
/* Request generic CC monitor. */
ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
}
break;
case AST_CC_MONITOR_ALWAYS:
if (pri->sig == SIG_BRI_PTMP && pri->nodetype != PRI_NETWORK) {
/*
* Cannot monitor PTMP TE side since this is not defined.
* We are playing the roll of a phone in this case and
* a phone cannot monitor a party over the network without
* protocol help.
*/
break;
}
/*
* We are either falling back or this is a PTMP NT span.
* Request generic CC monitor.
*/
ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
break;
case AST_CC_MONITOR_GENERIC:
if (pri->sig == SIG_BRI_PTMP && pri->nodetype == PRI_NETWORK) {
/* Request generic CC monitor. */
ast_queue_cc_frame(owner, AST_CC_GENERIC_MONITOR_TYPE,
sig_pri_get_orig_dialstring(pri->pvts[chanpos]), service, NULL);
}
break;
}
done:
ast_channel_unlock(owner);
}
| static void sig_pri_cc_link_canceled | ( | struct sig_pri_span * | pri, |
| long | cc_id, | ||
| int | is_agent | ||
| ) | [static] |
Definition at line 2913 of file sig_pri.c.
References ao2_ref, ast_cc_failed(), ast_cc_monitor_failed(), sig_pri_cc_monitor_instance::cc_id, sig_pri_cc_monitor_instance::core_id, ast_cc_agent::core_id, monitor, sig_pri_cc_monitor_instance::name, 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().
{
if (is_agent) {
struct ast_cc_agent *agent;
agent = sig_pri_find_cc_agent_by_cc_id(pri, cc_id);
if (!agent) {
return;
}
ast_cc_failed(agent->core_id, "%s agent got canceled by link",
sig_pri_cc_type_name);
ao2_ref(agent, -1);
} else {
struct sig_pri_cc_monitor_instance *monitor;
monitor = sig_pri_find_cc_monitor_by_cc_id(pri, cc_id);
if (!monitor) {
return;
}
monitor->cc_id = -1;
ast_cc_monitor_failed(monitor->core_id, monitor->name,
"%s monitor got canceled by link", sig_pri_cc_type_name);
ao2_ref(monitor, -1);
}
}
| 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. |
In most cases, this function will likely consist of just a call to AST_SCHED_DEL. It might have been possible to do this within the core, but unfortunately the mixture of sched_thread and sched usage in Asterisk prevents such usage.
| 0 | on success |
| -1 | on failure. |
Definition at line 9943 of file sig_pri.c.
{
/*
* libpri maintains it's own available timer as one of:
* T_CCBS2/T_CCBS5/T_CCBS6/QSIG_CCBS_T2
* T_CCNR2/T_CCNR5/T_CCNR6/QSIG_CCNR_T2
*/
return 0;
}
| static int sig_pri_cc_monitor_cmp_cc_id | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 2619 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().
{
struct sig_pri_cc_monitor_instance *monitor_1 = obj;
struct sig_pri_cc_monitor_instance *monitor_2 = arg;
return (monitor_1->pri == monitor_2->pri
&& monitor_1->cc_id == monitor_2->cc_id) ? CMP_MATCH | CMP_STOP : 0;
}
| void sig_pri_cc_monitor_destructor | ( | void * | monitor_pvt | ) |
Destroy PRI private data on the monitor.
| monitor_pvt | CC device monitor private data pointer. |
Implementers of this callback are responsible for destroying all heap-allocated data in the monitor's private_data pointer, including the private_data itself.
Definition at line 9966 of file sig_pri.c.
References ao2_ref, and ao2_unlink.
{
struct sig_pri_cc_monitor_instance *instance;
instance = monitor_pvt;
if (!instance) {
return;
}
ao2_unlink(sig_pri_cc_monitors, instance);
ao2_ref(instance, -1);
}
| static int sig_pri_cc_monitor_instance_cmp_fn | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 9771 of file sig_pri.c.
References CMP_MATCH, CMP_STOP, and sig_pri_cc_monitor_instance::core_id.
Referenced by sig_pri_load().
{
struct sig_pri_cc_monitor_instance *monitor_1 = obj;
struct sig_pri_cc_monitor_instance *monitor_2 = arg;
return monitor_1->core_id == monitor_2->core_id ? CMP_MATCH | CMP_STOP : 0;
}
| static void sig_pri_cc_monitor_instance_destroy | ( | void * | data | ) | [static] |
Definition at line 2667 of file sig_pri.c.
References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, sig_pri_callback::module_unref, sig_pri_cc_monitor_instance::pri, sig_pri_span::pri, and sig_pri_callbacks.
Referenced by sig_pri_cc_monitor_instance_init().
{
struct sig_pri_cc_monitor_instance *monitor_instance = data;
if (monitor_instance->cc_id != -1) {
ast_mutex_lock(&monitor_instance->pri->lock);
pri_cc_cancel(monitor_instance->pri->pri, monitor_instance->cc_id);
ast_mutex_unlock(&monitor_instance->pri->lock);
}
sig_pri_callbacks.module_unref();
}
| static int sig_pri_cc_monitor_instance_hash_fn | ( | const void * | obj, |
| const int | flags | ||
| ) | [static] |
Definition at line 9751 of file sig_pri.c.
References sig_pri_cc_monitor_instance::core_id.
Referenced by sig_pri_load().
{
const struct sig_pri_cc_monitor_instance *monitor_instance = obj;
return monitor_instance->core_id;
}
| 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, read] |
Definition at line 2699 of file sig_pri.c.
References ao2_alloc, ao2_link, sig_pri_cc_monitor_instance::cc_id, sig_pri_cc_monitor_instance::core_id, sig_pri_callback::module_ref, sig_pri_callback::module_unref, sig_pri_cc_monitor_instance::name, sig_pri_cc_monitor_instance::pri, sig_pri_callbacks, and sig_pri_cc_monitor_instance_destroy().
Referenced by sig_pri_cc_available().
{
struct sig_pri_cc_monitor_instance *monitor_instance;
if (!sig_pri_callbacks.module_ref || !sig_pri_callbacks.module_unref) {
return NULL;
}
monitor_instance = ao2_alloc(sizeof(*monitor_instance) + strlen(device_name),
sig_pri_cc_monitor_instance_destroy);
if (!monitor_instance) {
return NULL;
}
monitor_instance->cc_id = cc_id;
monitor_instance->pri = pri;
monitor_instance->core_id = core_id;
strcpy(monitor_instance->name, device_name);
sig_pri_callbacks.module_ref();
ao2_link(sig_pri_cc_monitors, monitor_instance);
return monitor_instance;
}
| 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. |
Perform whatever steps are necessary in order to request CC. In addition, the monitor implementation is responsible for starting the available timer in this callback. The scheduler ID for the callback must be stored in the parent_link's child_avail_id field.
| 0 | on success |
| -1 | on failure. |
Definition at line 9799 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, sig_pri_cc_monitor_instance::pri, sig_pri_span::pri, ast_cc_monitor::private_data, and ast_cc_monitor::service_offered.
{
struct sig_pri_cc_monitor_instance *instance;
int cc_mode;
int res;
switch (monitor->service_offered) {
case AST_CC_CCBS:
cc_mode = 0;/* CCBS */
break;
case AST_CC_CCNR:
cc_mode = 1;/* CCNR */
break;
default:
/* CC service not supported by ISDN. */
return -1;
}
instance = monitor->private_data;
/* libpri handles it's own available timer. */
ast_mutex_lock(&instance->pri->lock);
res = pri_cc_req(instance->pri->pri, instance->cc_id, cc_mode);
ast_mutex_unlock(&instance->pri->lock);
return res;
}
| 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. |
Alert a monitor as to the status of the agent for which the monitor had previously requested a status request.
| 0 | on success |
| -1 | on failure. |
Definition at line 9898 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, sig_pri_cc_monitor_instance::pri, sig_pri_span::pri, and ast_cc_monitor::private_data.
{
struct sig_pri_cc_monitor_instance *instance;
int cc_status;
switch (devstate) {
case AST_DEVICE_UNKNOWN:
case AST_DEVICE_NOT_INUSE:
cc_status = 0;/* free */
break;
case AST_DEVICE_BUSY:
case AST_DEVICE_INUSE:
cc_status = 1;/* busy */
break;
default:
/* Don't know how to interpret this device state into free/busy status. */
return 0;
}
instance = monitor->private_data;
ast_mutex_lock(&instance->pri->lock);
pri_cc_status_req_rsp(instance->pri->pri, instance->cc_id, cc_status);
ast_mutex_unlock(&instance->pri->lock);
return 0;
}
| int sig_pri_cc_monitor_suspend | ( | struct ast_cc_monitor * | monitor | ) |
Suspend monitoring.
| monitor | CC core monitor control. |
Implementers must perform the necessary steps to suspend monitoring.
| 0 | on success |
| -1 | on failure. |
Definition at line 9842 of file sig_pri.c.
References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, sig_pri_cc_monitor_instance::pri, sig_pri_span::pri, and ast_cc_monitor::private_data.
{
struct sig_pri_cc_monitor_instance *instance;
instance = monitor->private_data;
ast_mutex_lock(&instance->pri->lock);
pri_cc_status(instance->pri->pri, instance->cc_id, 1/* busy */);
ast_mutex_unlock(&instance->pri->lock);
return 0;
}
| int sig_pri_cc_monitor_unsuspend | ( | struct ast_cc_monitor * | monitor | ) |
Unsuspend monitoring.
| monitor | CC core monitor control. |
Perform the necessary steps to unsuspend monitoring.
| 0 | on success |
| -1 | on failure. |
Definition at line 9868 of file sig_pri.c.
References ast_mutex_lock, ast_mutex_unlock, sig_pri_cc_monitor_instance::cc_id, sig_pri_span::lock, sig_pri_cc_monitor_instance::pri, sig_pri_span::pri, and ast_cc_monitor::private_data.
{
struct sig_pri_cc_monitor_instance *instance;
instance = monitor->private_data;
ast_mutex_lock(&instance->pri->lock);
pri_cc_status(instance->pri->pri, instance->cc_id, 0/* free */);
ast_mutex_unlock(&instance->pri->lock);
return 0;
}
| 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 9136 of file sig_pri.c.
References ast_channel_softhangup_internal_flag_add(), 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().
{
pri_grab(p, p->pri);
sig_pri_set_alarm(p, !noalarm);
if (!noalarm) {
if (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
/* T309 is not enabled : destroy calls when alarm occurs */
if (p->call) {
pri_destroycall(p->pri->pri, p->call);
p->call = NULL;
}
if (p->owner)
ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
}
}
sig_pri_span_devstate_changed(p->pri);
pri_rel(p->pri);
}
| void sig_pri_chan_delete | ( | struct sig_pri_chan * | doomed | ) |
Delete the sig_pri private channel structure.
| doomed | sig_pri private channel structure to delete. |
Definition at line 9194 of file sig_pri.c.
References ast_free.
Referenced by destroy_dahdi_pvt().
{
ast_free(doomed);
}
| struct sig_pri_chan* sig_pri_chan_new | ( | void * | pvt_data, |
| struct sig_pri_span * | pri, | ||
| int | logicalspan, | ||
| int | channo, | ||
| int | trunkgroup | ||
| ) | [read] |
Definition at line 9167 of file sig_pri.c.
References ast_calloc, sig_pri_chan::chan_pvt, sig_pri_chan::logicalspan, sig_pri_chan::mastertrunkgroup, sig_pri_chan::pri, and sig_pri_chan::prioffset.
Referenced by dahdi_new_pri_nobch_channel(), and mkintf().
{
struct sig_pri_chan *p;
p = ast_calloc(1, sizeof(*p));
if (!p)
return p;
p->logicalspan = logicalspan;
p->prioffset = channo;
p->mastertrunkgroup = trunkgroup;
p->chan_pvt = pvt_data;
p->pri = pri;
return p;
}
| void sig_pri_cli_show_channels | ( | int | fd, |
| struct sig_pri_span * | pri | ||
| ) |
Definition at line 9207 of file sig_pri.c.
References ast_channel_name(), 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, sig_pri_chan::no_b_channel, sig_pri_span::numchans, sig_pri_chan::owner, 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().
{
char line[256];
int idx;
struct sig_pri_chan *pvt;
ast_mutex_lock(&pri->lock);
for (idx = 0; idx < pri->numchans; ++idx) {
if (!pri->pvts[idx]) {
continue;
}
pvt = pri->pvts[idx];
sig_pri_lock_private(pvt);
sig_pri_lock_owner(pri, idx);
if (pvt->no_b_channel && sig_pri_is_chan_available(pvt)) {
/* Don't show held/call-waiting channels if they are not in use. */
sig_pri_unlock_private(pvt);
continue;
}
snprintf(line, sizeof(line), SIG_PRI_SC_LINE,
pri->span,
pvt->channel,
pvt->no_b_channel ? "No" : "Yes",/* Has media */
sig_pri_is_chan_available(pvt) ? "Yes" : "No",
sig_pri_call_level2str(pvt->call_level),
pvt->call ? "Yes" : "No",
pvt->owner ? ast_channel_name(pvt->owner) : "");
if (pvt->owner) {
ast_channel_unlock(pvt->owner);
}
sig_pri_unlock_private(pvt);
ast_mutex_unlock(&pri->lock);
ast_cli(fd, "%s\n", line);
ast_mutex_lock(&pri->lock);
}
ast_mutex_unlock(&pri->lock);
}
| void sig_pri_cli_show_channels_header | ( | int | fd | ) |
Definition at line 9201 of file sig_pri.c.
References ast_cli(), and SIG_PRI_SC_HEADER.
Referenced by handle_pri_show_channels().
{
ast_cli(fd, SIG_PRI_SC_HEADER, "PRI", "", "B", "Chan", "Call", "PRI", "Channel");
ast_cli(fd, SIG_PRI_SC_HEADER, "Span", "Chan", "Chan", "Idle", "Level", "Call", "Name");
}
| void sig_pri_cli_show_span | ( | int | fd, |
| int * | dchannels, | ||
| struct sig_pri_span * | pri | ||
| ) |
Definition at line 9271 of file sig_pri.c.
References ast_cli(), ast_mutex_lock, ast_mutex_unlock, ast_std_free(), build_status(), DAHDI_OVERLAPDIAL_INCOMING, sig_pri_span::dchanavail, sig_pri_span::dchans, sig_pri_span::lock, sig_pri_span::overlapdial, sig_pri_span::pri, pri_order(), SIG_PRI_NUM_DCHANS, and status.
Referenced by handle_pri_show_span().
{
int x;
char status[256];
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
if (pri->dchans[x]) {
#ifdef PRI_DUMP_INFO_STR
char *info_str = NULL;
#endif
ast_cli(fd, "%s D-channel: %d\n", pri_order(x), dchannels[x]);
build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
ast_cli(fd, "Status: %s\n", status);
ast_mutex_lock(&pri->lock);
#ifdef PRI_DUMP_INFO_STR
info_str = pri_dump_info_str(pri->pri);
if (info_str) {
ast_cli(fd, "%s", info_str);
ast_std_free(info_str);
}
#else
pri_dump_info(pri->pri);
#endif
ast_mutex_unlock(&pri->lock);
ast_cli(fd, "Overlap Recv: %s\n\n", (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
ast_cli(fd, "\n");
}
}
}
| void sig_pri_cli_show_spans | ( | int | fd, |
| int | span, | ||
| struct sig_pri_span * | pri | ||
| ) |
Definition at line 9259 of file sig_pri.c.
References ast_cli(), build_status(), sig_pri_span::dchanavail, sig_pri_span::dchans, sig_pri_span::pri, SIG_PRI_NUM_DCHANS, and status.
Referenced by handle_pri_show_spans().
{
char status[256];
int x;
for (x = 0; x < SIG_PRI_NUM_DCHANS; x++) {
if (pri->dchans[x]) {
build_status(status, sizeof(status), pri->dchanavail[x], pri->dchans[x] == pri->pri);
ast_cli(fd, "PRI span %d/%d: %s\n", span, x, status);
}
}
}
| static int sig_pri_cmp_pri_chans | ( | const void * | left, |
| const void * | right | ||
| ) | [static] |
Definition at line 8871 of file sig_pri.c.
References sig_pri_chan::channel.
Referenced by sig_pri_sort_pri_chans().
{
const struct sig_pri_chan *pvt_left;
const struct sig_pri_chan *pvt_right;
pvt_left = *(struct sig_pri_chan **) left;
pvt_right = *(struct sig_pri_chan **) right;
if (!pvt_left) {
if (!pvt_right) {
return 0;
}
return 1;
}
if (!pvt_right) {
return -1;
}
return pvt_left->channel - pvt_right->channel;
}
| static struct sig_pri_chan* sig_pri_cw_available | ( | struct sig_pri_span * | pri | ) | [static, read] |
Definition at line 8556 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, pri_find_empty_nobch(), sig_pri_span::pvts, sig_pri_available_check(), and sig_pri_init_config().
Referenced by sig_pri_available().
{
struct sig_pri_chan *cw;
int idx;
cw = NULL;
if (pri->num_call_waiting_calls < pri->max_call_waiting_calls) {
if (!pri->num_call_waiting_calls) {
/*
* There are no outstanding call waiting calls. Check to see
* if the span is in a congested state for the first call
* waiting call.
*/
for (idx = 0; idx < pri->numchans; ++idx) {
if (pri->pvts[idx] && sig_pri_available_check(pri->pvts[idx])) {
/* There is another channel that is available on this span. */
return cw;
}
}
}
idx = pri_find_empty_nobch(pri);
if (0 <= idx) {
/* Setup the call waiting interface to use. */
cw = pri->pvts[idx];
cw->is_call_waiting = 1;
sig_pri_init_config(cw, pri);
ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, 1);
}
}
return cw;
}
| static void sig_pri_deadlock_avoidance_private | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 349 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::deadlock_avoidance_private, sig_pri_callbacks, sig_pri_lock_private(), and sig_pri_unlock_private().
Referenced by pri_grab().
{
if (sig_pri_callbacks.deadlock_avoidance_private) {
sig_pri_callbacks.deadlock_avoidance_private(p->chan_pvt);
} else {
/* Fallback to the old way if callback not present. */
sig_pri_unlock_private(p);
sched_yield();
sig_pri_lock_private(p);
}
}
| void sig_pri_dial_complete | ( | struct sig_pri_chan * | pvt, |
| struct ast_channel * | ast | ||
| ) |
DTMF dial string complete.
| pvt | sig_pri private channel structure. |
| ast | Asterisk channel |
Definition at line 8683 of file sig_pri.c.
References AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_queue_frame(), sig_pri_chan::call_level, sig_pri_chan::chan_pvt, ast_frame_subclass::integer, sig_pri_callback::queue_control, SIG_PRI_CALL_LEVEL_CONNECT, SIG_PRI_CALL_LEVEL_DEFER_DIAL, sig_pri_callbacks, sig_pri_open_media(), sig_pri_set_dialing(), sig_pri_set_echocanceller(), and ast_frame::subclass.
Referenced by dahdi_handle_event().
{
/* If we just completed 'w' deferred dialing digits, we need to answer now. */
if (pvt->call_level == SIG_PRI_CALL_LEVEL_DEFER_DIAL) {
pvt->call_level = SIG_PRI_CALL_LEVEL_CONNECT;
sig_pri_open_media(pvt);
{
struct ast_frame f = {AST_FRAME_CONTROL, };
if (sig_pri_callbacks.queue_control) {
sig_pri_callbacks.queue_control(pvt->chan_pvt, AST_CONTROL_ANSWER);
}
f.subclass.integer = AST_CONTROL_ANSWER;
ast_queue_frame(ast, &f);
}
sig_pri_set_dialing(pvt, 0);
/* Enable echo cancellation if it's not on already */
sig_pri_set_echocanceller(pvt, 1);
}
}
| static void sig_pri_dial_digits | ( | struct sig_pri_chan * | p, |
| const char * | dial_string | ||
| ) | [static] |
Definition at line 233 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::dial_digits, and sig_pri_callbacks.
Referenced by pri_dchannel().
{
if (sig_pri_callbacks.dial_digits) {
sig_pri_callbacks.dial_digits(p->chan_pvt, dial_string);
}
}
| int sig_pri_digit_begin | ( | struct sig_pri_chan * | pvt, |
| struct ast_channel * | ast, | ||
| char | digit | ||
| ) |
Definition at line 8637 of file sig_pri.c.
References ast_debug, ast_log(), AST_STATE_DIALING, sig_pri_chan::call, sig_pri_chan::call_level, sig_pri_chan::dialdest, len(), LOG_WARNING, sig_pri_chan::pri, sig_pri_span::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().
{
if (ast_channel_state(ast) == AST_STATE_DIALING) {
if (pvt->call_level < SIG_PRI_CALL_LEVEL_OVERLAP) {
unsigned int len;
len = strlen(pvt->dialdest);
if (len < sizeof(pvt->dialdest) - 1) {
ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
digit);
pvt->dialdest[len++] = digit;
pvt->dialdest[len] = '\0';
} else {
ast_log(LOG_WARNING,
"Span %d: Deferred digit buffer overflow for digit '%c'.\n",
pvt->pri->span, digit);
}
return 0;
}
if (pvt->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
pri_grab(pvt, pvt->pri);
pri_information(pvt->pri->pri, pvt->call, digit);
pri_rel(pvt->pri);
return 0;
}
if (pvt->call_level < SIG_PRI_CALL_LEVEL_CONNECT) {
ast_log(LOG_WARNING,
"Span %d: Digit '%c' may be ignored by peer. (Call level:%d(%s))\n",
pvt->pri->span, digit, pvt->call_level,
sig_pri_call_level2str(pvt->call_level));
}
}
return 1;
}
| static void sig_pri_dsp_reset_and_flush_digits | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 935 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::dsp_reset_and_flush_digits, and sig_pri_callbacks.
Referenced by pri_ss_thread().
| static void sig_pri_event_party_id | ( | struct ast_str ** | msg, |
| const char * | prefix, | ||
| struct ast_party_id * | party | ||
| ) | [static] |
Definition at line 2237 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_name::str, ast_party_number::str, ast_party_subaddress::str, ast_party_id::subaddress, ast_party_subaddress::type, ast_party_name::valid, ast_party_number::valid, and ast_party_subaddress::valid.
Referenced by sig_pri_mcid_event().
{
int pres;
/* Combined party presentation */
pres = ast_party_id_presentation(party);
ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix, pres,
ast_describe_caller_presentation(pres));
/* Party number */
ast_str_append(msg, 0, "%sNumValid: %d\r\n", prefix,
(unsigned) party->number.valid);
ast_str_append(msg, 0, "%sNum: %s\r\n", prefix,
S_COR(party->number.valid, party->number.str, ""));
ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number.plan);
if (party->number.valid) {
ast_str_append(msg, 0, "%sNumPlan: %d\r\n", prefix, party->number.plan);
ast_str_append(msg, 0, "%sNumPres: %d (%s)\r\n", prefix,
party->number.presentation,
ast_describe_caller_presentation(party->number.presentation));
}
/* Party name */
ast_str_append(msg, 0, "%sNameValid: %d\r\n", prefix,
(unsigned) party->name.valid);
ast_str_append(msg, 0, "%sName: %s\r\n", prefix,
S_COR(party->name.valid, party->name.str, ""));
if (party->name.valid) {
ast_str_append(msg, 0, "%sNameCharSet: %s\r\n", prefix,
ast_party_name_charset_describe(party->name.char_set));
ast_str_append(msg, 0, "%sNamePres: %d (%s)\r\n", prefix,
party->name.presentation,
ast_describe_caller_presentation(party->name.presentation));
}
#if defined(HAVE_PRI_SUBADDR)
/* Party subaddress */
if (party->subaddress.valid) {
static const char subaddress[] = "Subaddr";
ast_str_append(msg, 0, "%s%s: %s\r\n", prefix, subaddress,
S_OR(party->subaddress.str, ""));
ast_str_append(msg, 0, "%s%sType: %d\r\n", prefix, subaddress,
party->subaddress.type);
ast_str_append(msg, 0, "%s%sOdd: %d\r\n", prefix, subaddress,
party->subaddress.odd_even_indicator);
}
#endif /* defined(HAVE_PRI_SUBADDR) */
}
| 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 7652 of file sig_pri.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_NONSTANDARD_APP_ARGS, ast_strlen_zero(), ext, and sig_pri_chan::stripmsd.
Referenced by dahdi_call(), and dahdi_request().
{
char *dial;
char *number;
char *subaddr;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(group); /* channel/group token */
AST_APP_ARG(ext); /* extension token */
//AST_APP_ARG(opts); /* options token */
AST_APP_ARG(other); /* Any remining unused arguments */
);
/* Get private copy of dial string and break it up. */
dial = ast_strdupa(rdest);
AST_NONSTANDARD_APP_ARGS(args, dial, '/');
number = args.ext;
if (!number) {
number = "";
}
/* Find and extract dialed_subaddress */
subaddr = strchr(number, ':');
if (subaddr) {
*subaddr++ = '\0';
/* Skip subaddress type prefix. */
switch (*subaddr) {
case 'U':
case 'u':
case 'N':
case 'n':
++subaddr;
break;
default:
break;
}
}
/* Skip type-of-number/dial-plan prefix characters. */
if (strlen(number) < p->stripmsd) {
number = "";
} else {
char *deferred;
number += p->stripmsd;
deferred = strchr(number, 'w');
if (deferred) {
/* Remove any 'w' deferred digits. */
*deferred = '\0';
}
while (isalpha(*number)) {
++number;
}
}
/* Fill buffer with extracted number and subaddress. */
if (ast_strlen_zero(subaddr)) {
/* Put in called number only since there is no subaddress. */
snprintf(called, called_buff_size, "%s", number);
} else {
/* Put in called number and subaddress. */
snprintf(called, called_buff_size, "%s:%s", number, subaddr);
}
}
| static struct ast_cc_agent* sig_pri_find_cc_agent_by_cc_id | ( | struct sig_pri_span * | pri, |
| long | cc_id | ||
| ) | [static, read] |
Definition at line 2595 of file sig_pri.c.
References ast_cc_agent_callback(), sig_pri_cc_agent_prv::cc_id, 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().
{
struct sig_pri_cc_agent_prv finder = {
.pri = pri,
.cc_id = cc_id,
};
return ast_cc_agent_callback(0, sig_pri_cc_agent_cmp_cc_id, &finder,
sig_pri_cc_type_name);
}
| static struct sig_pri_cc_monitor_instance* sig_pri_find_cc_monitor_by_cc_id | ( | struct sig_pri_span * | pri, |
| long | cc_id | ||
| ) | [static, read] |
Definition at line 2646 of file sig_pri.c.
References ao2_callback, sig_pri_cc_monitor_instance::cc_id, sig_pri_cc_monitor_instance::pri, and sig_pri_cc_monitor_cmp_cc_id().
Referenced by sig_pri_cc_link_canceled(), and sig_pri_handle_cis_subcmds().
{
struct sig_pri_cc_monitor_instance finder = {
.pri = pri,
.cc_id = cc_id,
};
return ao2_callback(sig_pri_cc_monitors, 0, sig_pri_cc_monitor_cmp_cc_id, &finder);
}
| void sig_pri_fixup | ( | struct ast_channel * | oldchan, |
| struct ast_channel * | newchan, | ||
| struct sig_pri_chan * | pchan | ||
| ) |
Definition at line 9351 of file sig_pri.c.
References sig_pri_chan::owner.
Referenced by dahdi_fixup().
| static void sig_pri_fixup_chans | ( | struct sig_pri_chan * | old_chan, |
| struct sig_pri_chan * | new_chan | ||
| ) | [static] |
Definition at line 951 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::fixup_chans, and sig_pri_callbacks.
Referenced by pri_fixup_principle().
{
if (sig_pri_callbacks.fixup_chans) {
sig_pri_callbacks.fixup_chans(old_chan->chan_pvt, new_chan->chan_pvt);
}
}
| static const char* sig_pri_get_orig_dialstring | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 212 of file sig_pri.c.
References ast_log(), sig_pri_chan::chan_pvt, sig_pri_callback::get_orig_dialstring, LOG_ERROR, and sig_pri_callbacks.
Referenced by sig_pri_cc_available(), and sig_pri_cc_generic_check().
{
if (sig_pri_callbacks.get_orig_dialstring) {
return sig_pri_callbacks.get_orig_dialstring(p->chan_pvt);
}
ast_log(LOG_ERROR, "get_orig_dialstring callback not defined\n");
return "";
}
| 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 3915 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, sig_pri_cc_monitor_instance::core_id, ast_cc_agent::core_id, monitor, sig_pri_cc_monitor_instance::name, sig_pri_span::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.
Referenced by pri_dchannel().
{
int index;
#if defined(HAVE_PRI_CCSS)
struct ast_cc_agent *agent;
struct sig_pri_cc_agent_prv *agent_prv;
struct sig_pri_cc_monitor_instance *monitor;
#endif /* defined(HAVE_PRI_CCSS) */
if (!subcmds) {
return;
}
for (index = 0; index < subcmds->counter_subcmd; ++index) {
const struct pri_subcommand *subcmd = &subcmds->subcmd[index];
switch (subcmd->cmd) {
#if defined(STATUS_REQUEST_PLACE_HOLDER)
case PRI_SUBCMD_STATUS_REQ:
case PRI_SUBCMD_STATUS_REQ_RSP:
/* Ignore for now. */
break;
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_REQ:
agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_request.cc_id);
if (!agent) {
pri_cc_cancel(pri->pri, subcmd->u.cc_request.cc_id);
break;
}
if (!ast_cc_request_is_within_limits()) {
if (pri_cc_req_rsp(pri->pri, subcmd->u.cc_request.cc_id,
5/* queue_full */)) {
pri_cc_cancel(pri->pri, subcmd->u.cc_request.cc_id);
}
ast_cc_failed(agent->core_id, "%s agent system CC queue full",
sig_pri_cc_type_name);
ao2_ref(agent, -1);
break;
}
agent_prv = agent->private_data;
agent_prv->cc_request_response_pending = 1;
if (ast_cc_agent_accept_request(agent->core_id,
"%s caller accepted CC offer.", sig_pri_cc_type_name)) {
agent_prv->cc_request_response_pending = 0;
if (pri_cc_req_rsp(pri->pri, subcmd->u.cc_request.cc_id,
2/* short_term_denial */)) {
pri_cc_cancel(pri->pri, subcmd->u.cc_request.cc_id);
}
ast_cc_failed(agent->core_id, "%s agent CC core request accept failed",
sig_pri_cc_type_name);
}
ao2_ref(agent, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_REQ_RSP:
monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
subcmd->u.cc_request_rsp.cc_id);
if (!monitor) {
pri_cc_cancel(pri->pri, subcmd->u.cc_request_rsp.cc_id);
break;
}
switch (subcmd->u.cc_request_rsp.status) {
case 0:/* success */
ast_cc_monitor_request_acked(monitor->core_id,
"%s far end accepted CC request", sig_pri_cc_type_name);
break;
case 1:/* timeout */
ast_verb(2, "core_id:%d %s CC request timeout\n", monitor->core_id,
sig_pri_cc_type_name);
ast_cc_monitor_failed(monitor->core_id, monitor->name,
"%s CC request timeout", sig_pri_cc_type_name);
break;
case 2:/* error */
ast_verb(2, "core_id:%d %s CC request error: %s\n", monitor->core_id,
sig_pri_cc_type_name,
pri_facility_error2str(subcmd->u.cc_request_rsp.fail_code));
ast_cc_monitor_failed(monitor->core_id, monitor->name,
"%s CC request error", sig_pri_cc_type_name);
break;
case 3:/* reject */
ast_verb(2, "core_id:%d %s CC request reject: %s\n", monitor->core_id,
sig_pri_cc_type_name,
pri_facility_reject2str(subcmd->u.cc_request_rsp.fail_code));
ast_cc_monitor_failed(monitor->core_id, monitor->name,
"%s CC request reject", sig_pri_cc_type_name);
break;
default:
ast_verb(2, "core_id:%d %s CC request unknown status %d\n",
monitor->core_id, sig_pri_cc_type_name,
subcmd->u.cc_request_rsp.status);
ast_cc_monitor_failed(monitor->core_id, monitor->name,
"%s CC request unknown status", sig_pri_cc_type_name);
break;
}
ao2_ref(monitor, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_REMOTE_USER_FREE:
monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
subcmd->u.cc_remote_user_free.cc_id);
if (!monitor) {
pri_cc_cancel(pri->pri, subcmd->u.cc_remote_user_free.cc_id);
break;
}
ast_cc_monitor_callee_available(monitor->core_id,
"%s callee has become available", sig_pri_cc_type_name);
ao2_ref(monitor, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_B_FREE:
monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
subcmd->u.cc_b_free.cc_id);
if (!monitor) {
pri_cc_cancel(pri->pri, subcmd->u.cc_b_free.cc_id);
break;
}
ast_cc_monitor_party_b_free(monitor->core_id);
ao2_ref(monitor, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_STATUS_REQ:
monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
subcmd->u.cc_status_req.cc_id);
if (!monitor) {
pri_cc_cancel(pri->pri, subcmd->u.cc_status_req.cc_id);
break;
}
ast_cc_monitor_status_request(monitor->core_id);
ao2_ref(monitor, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_STATUS_REQ_RSP:
agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_status_req_rsp.cc_id);
if (!agent) {
pri_cc_cancel(pri->pri, subcmd->u.cc_status_req_rsp.cc_id);
break;
}
ast_cc_agent_status_response(agent->core_id,
subcmd->u.cc_status_req_rsp.status ? AST_DEVICE_INUSE
: AST_DEVICE_NOT_INUSE);
ao2_ref(agent, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_STATUS:
agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_status.cc_id);
if (!agent) {
pri_cc_cancel(pri->pri, subcmd->u.cc_status.cc_id);
break;
}
if (subcmd->u.cc_status.status) {
ast_cc_agent_caller_busy(agent->core_id, "%s agent caller is busy",
sig_pri_cc_type_name);
} else {
ast_cc_agent_caller_available(agent->core_id,
"%s agent caller is available", sig_pri_cc_type_name);
}
ao2_ref(agent, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_CANCEL:
sig_pri_cc_link_canceled(pri, subcmd->u.cc_cancel.cc_id,
subcmd->u.cc_cancel.is_agent);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_STOP_ALERTING:
monitor = sig_pri_find_cc_monitor_by_cc_id(pri,
subcmd->u.cc_stop_alerting.cc_id);
if (!monitor) {
pri_cc_cancel(pri->pri, subcmd->u.cc_stop_alerting.cc_id);
break;
}
ast_cc_monitor_stop_ringing(monitor->core_id);
ao2_ref(monitor, -1);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_AOC_EVENTS)
case PRI_SUBCMD_AOC_E:
/* Queue AST_CONTROL_AOC frame */
sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, NULL, 0);
break;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
default:
ast_debug(2, "Span %d: Unknown CIS subcommand(%d) in %s event.\n", pri->span,
subcmd->cmd, pri_event2str(event_id));
break;
}
}
}
| static void sig_pri_handle_dchan_exception | ( | struct sig_pri_span * | pri, |
| int | index | ||
| ) | [static] |
Definition at line 162 of file sig_pri.c.
References sig_pri_callback::handle_dchan_exception, and sig_pri_callbacks.
Referenced by pri_dchannel().
{
if (sig_pri_callbacks.handle_dchan_exception) {
sig_pri_callbacks.handle_dchan_exception(pri, index);
}
}
| static int sig_pri_handle_hold | ( | struct sig_pri_span * | pri, |
| pri_event * | ev | ||
| ) | [static] |
Definition at line 5284 of file sig_pri.c.
References ast_callid_threadassoc_add(), ast_callid_threadassoc_remove(), ast_callid_unref, ast_channel_callid(), ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_log(), sig_pri_chan::call_level, LOG_WARNING, sig_pri_chan::no_b_channel, sig_pri_chan::owner, pri_find_empty_nobch(), pri_find_principle_by_call(), pri_fixup_principle(), pri_queue_control(), sig_pri_span::pvts, sig_pri_ami_hold_event(), SIG_PRI_CALL_LEVEL_CONNECT, sig_pri_handle_subcmds(), sig_pri_lock_owner(), sig_pri_lock_private(), sig_pri_span_devstate_changed(), sig_pri_unlock_private(), and sig_pri_span::span.
Referenced by pri_dchannel().
{
int retval;
int chanpos_old;
int chanpos_new;
struct ast_channel *owner;
struct ast_callid *callid = NULL;
chanpos_old = pri_find_principle_by_call(pri, ev->hold.call);
if (chanpos_old < 0) {
ast_log(LOG_WARNING, "Span %d: Received HOLD for unknown call.\n", pri->span);
return -1;
}
if (pri->pvts[chanpos_old]->no_b_channel) {
/* Call is already on hold or is call waiting call. */
return -1;
}
chanpos_new = -1;
sig_pri_lock_private(pri->pvts[chanpos_old]);
sig_pri_lock_owner(pri, chanpos_old);
owner = pri->pvts[chanpos_old]->owner;
if (!owner) {
goto done_with_private;
}
callid = ast_channel_callid(owner);
if (callid) {
ast_callid_threadassoc_add(callid);
}
if (pri->pvts[chanpos_old]->call_level != SIG_PRI_CALL_LEVEL_CONNECT) {
/*
* Make things simple. Don't allow placing a call on hold that
* is not connected.
*/
goto done_with_owner;
}
chanpos_new = pri_find_empty_nobch(pri);
if (chanpos_new < 0) {
/* No hold channel available. */
goto done_with_owner;
}
sig_pri_handle_subcmds(pri, chanpos_old, ev->e, ev->hold.subcmds, ev->hold.call);
pri_queue_control(pri, chanpos_old, AST_CONTROL_HOLD);
chanpos_new = pri_fixup_principle(pri, chanpos_new, ev->hold.call);
if (chanpos_new < 0) {
/* Should never happen. */
pri_queue_control(pri, chanpos_old, AST_CONTROL_UNHOLD);
} else {
sig_pri_ami_hold_event(owner, 1);
}
done_with_owner:;
ast_channel_unlock(owner);
done_with_private:;
sig_pri_unlock_private(pri->pvts[chanpos_old]);
if (chanpos_new < 0) {
retval = -1;
} else {
sig_pri_span_devstate_changed(pri);
retval = 0;
}
if (callid) {
ast_callid_unref(callid);
ast_callid_threadassoc_remove();
}
return retval;
}
| static void sig_pri_handle_hold_ack | ( | struct sig_pri_span * | pri, |
| pri_event * | ev | ||
| ) | [static] |
Definition at line 5373 of file sig_pri.c.
References ast_callid_threadassoc_remove(), ast_callid_unref, ast_log(), func_pri_dchannel_chanpos_callid(), LOG_ERROR, sig_pri_chan::owner, PRI_CHANNEL, pri_find_empty_nobch(), pri_fixup_principle(), PRI_SPAN, sig_pri_span::pvts, sig_pri_handle_subcmds(), sig_pri_kill_call(), sig_pri_lock_private(), SIG_PRI_MOH_EVENT_HOLD_ACK, sig_pri_moh_fsm_event(), sig_pri_span_devstate_changed(), sig_pri_unlock_private(), and sig_pri_span::span.
Referenced by pri_dchannel().
{
int chanpos;
struct ast_callid *callid;
/*
* We were successfully put on hold by the remote party
* so we just need to switch to a no_b_channel channel.
*/
chanpos = pri_find_empty_nobch(pri);
if (chanpos < 0) {
/* Very bad news. No hold channel available. */
ast_log(LOG_ERROR,
"Span %d: No hold channel available for held call that is on %d/%d\n",
pri->span, PRI_SPAN(ev->hold_ack.channel), PRI_CHANNEL(ev->hold_ack.channel));
sig_pri_kill_call(pri, ev->hold_ack.call, PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
return;
}
chanpos = pri_fixup_principle(pri, chanpos, ev->hold_ack.call);
if (chanpos < 0) {
/* Should never happen. */
sig_pri_kill_call(pri, ev->hold_ack.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
return;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->hold_ack.subcmds, ev->hold_ack.call);
sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
SIG_PRI_MOH_EVENT_HOLD_ACK);
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
if (callid) {
ast_callid_unref(callid);
ast_callid_threadassoc_remove();
}
}
| static void sig_pri_handle_hold_rej | ( | struct sig_pri_span * | pri, |
| pri_event * | ev | ||
| ) | [static] |
Definition at line 5427 of file sig_pri.c.
References ast_callid_threadassoc_remove(), ast_callid_unref, ast_debug, ast_log(), func_pri_dchannel_chanpos_callid(), LOG_WARNING, sig_pri_chan::owner, pri_find_principle(), pri_fixup_principle(), sig_pri_span::pvts, sig_pri_handle_subcmds(), sig_pri_kill_call(), sig_pri_lock_private(), SIG_PRI_MOH_EVENT_HOLD_REJ, sig_pri_moh_fsm_event(), sig_pri_unlock_private(), and sig_pri_span::span.
Referenced by pri_dchannel().
{
int chanpos;
struct ast_callid *callid;
chanpos = pri_find_principle(pri, ev->hold_rej.channel, ev->hold_rej.call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Span %d: Could not find principle for HOLD_REJECT\n",
pri->span);
sig_pri_kill_call(pri, ev->hold_rej.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
return;
}
chanpos = pri_fixup_principle(pri, chanpos, ev->hold_rej.call);
if (chanpos < 0) {
/* Should never happen. */
sig_pri_kill_call(pri, ev->hold_rej.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
return;
}
ast_debug(1, "Span %d: HOLD_REJECT cause: %d(%s)\n", pri->span,
ev->hold_rej.cause, pri_cause2str(ev->hold_rej.cause));
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->hold_rej.subcmds, ev->hold_rej.call);
sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
SIG_PRI_MOH_EVENT_HOLD_REJ);
sig_pri_unlock_private(pri->pvts[chanpos]);
if (callid) {
ast_callid_unref(callid);
ast_callid_threadassoc_remove();
}
}
| static void sig_pri_handle_retrieve | ( | struct sig_pri_span * | pri, |
| pri_event * | ev | ||
| ) | [static] |
Definition at line 5477 of file sig_pri.c.
References ast_callid_threadassoc_remove(), ast_callid_unref, ast_channel_unlock, AST_CONTROL_UNHOLD, ast_log(), func_pri_dchannel_chanpos_callid(), LOG_WARNING, sig_pri_chan::owner, 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_ami_hold_event(), sig_pri_handle_subcmds(), sig_pri_is_chan_available(), sig_pri_lock_owner(), sig_pri_lock_private(), SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK, sig_pri_moh_fsm_event(), sig_pri_span_devstate_changed(), sig_pri_unlock_private(), and sig_pri_span::span.
Referenced by pri_dchannel().
{
int chanpos;
struct ast_callid *callid;
if (!(ev->retrieve.channel & PRI_HELD_CALL)) {
/* The call is not currently held. */
pri_retrieve_rej(pri->pri, ev->retrieve.call,
PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
return;
}
if (pri_find_principle_by_call(pri, ev->retrieve.call) < 0) {
ast_log(LOG_WARNING, "Span %d: Received RETRIEVE for unknown call.\n", pri->span);
pri_retrieve_rej(pri->pri, ev->retrieve.call,
PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
return;
}
if (PRI_CHANNEL(ev->retrieve.channel) == 0xFF) {
chanpos = pri_find_empty_chan(pri, 1);
} else {
chanpos = pri_find_principle(pri,
ev->retrieve.channel & ~PRI_HELD_CALL, ev->retrieve.call);
if (ev->retrieve.flexible
&& (chanpos < 0 || !sig_pri_is_chan_available(pri->pvts[chanpos]))) {
/*
* Channel selection is flexible and the requested channel
* is bad or not available. Pick another channel.
*/
chanpos = pri_find_empty_chan(pri, 1);
}
}
if (chanpos < 0) {
pri_retrieve_rej(pri->pri, ev->retrieve.call,
ev->retrieve.flexible ? PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION
: PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
return;
}
chanpos = pri_fixup_principle(pri, chanpos, ev->retrieve.call);
if (chanpos < 0) {
/* Channel is already in use. */
pri_retrieve_rej(pri->pri, ev->retrieve.call,
PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
return;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve.subcmds, ev->retrieve.call);
sig_pri_lock_owner(pri, chanpos);
pri_queue_control(pri, chanpos, AST_CONTROL_UNHOLD);
if (pri->pvts[chanpos]->owner) {
sig_pri_ami_hold_event(pri->pvts[chanpos]->owner, 0);
ast_channel_unlock(pri->pvts[chanpos]->owner);
}
pri_retrieve_ack(pri->pri, ev->retrieve.call,
PVT_TO_CHANNEL(pri->pvts[chanpos]));
sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK);
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
if (callid) {
ast_callid_unref(callid);
ast_callid_threadassoc_remove();
}
}
| static void sig_pri_handle_retrieve_ack | ( | struct sig_pri_span * | pri, |
| pri_event * | ev | ||
| ) | [static] |
Definition at line 5557 of file sig_pri.c.
References ast_callid_threadassoc_remove(), ast_callid_unref, func_pri_dchannel_chanpos_callid(), sig_pri_chan::owner, pri_find_fixup_principle(), sig_pri_span::pvts, sig_pri_handle_subcmds(), sig_pri_lock_private(), SIG_PRI_MOH_EVENT_RETRIEVE_ACK, sig_pri_moh_fsm_event(), sig_pri_span_devstate_changed(), and sig_pri_unlock_private().
Referenced by pri_dchannel().
{
int chanpos;
struct ast_callid *callid;
chanpos = pri_find_fixup_principle(pri, ev->retrieve_ack.channel,
ev->retrieve_ack.call);
if (chanpos < 0) {
return;
}
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve_ack.subcmds,
ev->retrieve_ack.call);
sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
SIG_PRI_MOH_EVENT_RETRIEVE_ACK);
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
if (callid) {
ast_callid_unref(callid);
ast_callid_threadassoc_remove();
}
}
| static void sig_pri_handle_retrieve_rej | ( | struct sig_pri_span * | pri, |
| pri_event * | ev | ||
| ) | [static] |
Definition at line 5598 of file sig_pri.c.
References ast_callid_threadassoc_remove(), ast_callid_unref, ast_debug, ast_log(), func_pri_dchannel_chanpos_callid(), LOG_WARNING, sig_pri_chan::owner, pri_find_principle(), pri_fixup_principle(), sig_pri_span::pvts, sig_pri_handle_subcmds(), sig_pri_kill_call(), sig_pri_lock_private(), SIG_PRI_MOH_EVENT_RETRIEVE_REJ, sig_pri_moh_fsm_event(), sig_pri_unlock_private(), and sig_pri_span::span.
Referenced by pri_dchannel().
{
int chanpos;
struct ast_callid *callid;
chanpos = pri_find_principle(pri, ev->retrieve_rej.channel, ev->retrieve_rej.call);
if (chanpos < 0) {
ast_log(LOG_WARNING, "Span %d: Could not find principle for RETRIEVE_REJECT\n",
pri->span);
sig_pri_kill_call(pri, ev->retrieve_rej.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
return;
}
chanpos = pri_fixup_principle(pri, chanpos, ev->retrieve_rej.call);
if (chanpos < 0) {
/* Should never happen. */
sig_pri_kill_call(pri, ev->retrieve_rej.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
return;
}
ast_debug(1, "Span %d: RETRIEVE_REJECT cause: %d(%s)\n", pri->span,
ev->retrieve_rej.cause, pri_cause2str(ev->retrieve_rej.cause));
sig_pri_lock_private(pri->pvts[chanpos]);
callid = func_pri_dchannel_chanpos_callid(pri, chanpos);
sig_pri_handle_subcmds(pri, chanpos, ev->e, ev->retrieve_rej.subcmds,
ev->retrieve_rej.call);
sig_pri_moh_fsm_event(pri->pvts[chanpos]->owner, pri->pvts[chanpos],
SIG_PRI_MOH_EVENT_RETRIEVE_REJ);
sig_pri_unlock_private(pri->pvts[chanpos]);
if (callid) {
ast_callid_unref(callid);
ast_callid_threadassoc_remove();
}
}
| static void sig_pri_handle_subcmds | ( | struct sig_pri_span * | pri, |
| int | chanpos, | ||
| int | event_id, | ||
| const struct pri_subcommands * | subcmds, | ||
| q931_call * | call_rsp | ||
| ) | [static] |
Definition at line 4169 of file sig_pri.c.
References ast_party_caller::ani, ao2_ref, sig_pri_span::aoc_passthrough_flag, ast_cc_agent_recalling(), ast_cc_agent_set_interfaces_chanvar(), AST_CC_CCBS, AST_CC_CCNR, AST_CC_NONE, ast_channel_caller(), ast_channel_name(), ast_channel_queue_connected_line_update(), ast_channel_queue_redirecting_update(), ast_channel_redirecting(), ast_channel_set_caller_event(), ast_channel_set_redirecting(), ast_channel_unlock, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, ast_copy_string(), ast_debug, AST_FRAME_TEXT, ast_log(), ast_null_frame, ast_party_caller_set_init(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_id_invalidate(), ast_party_id_presentation(), ast_party_redirecting_free(), ast_queue_frame(), ast_setup_cc_recall_datastore(), ast_strdup, ast_strlen_zero(), ast_verb, xfer_rsp_data::call, sig_pri_chan::callingpres, sig_pri_chan::cid_name, sig_pri_chan::cid_num, sig_pri_chan::cid_subaddr, sig_pri_chan::cid_ton, ast_cc_agent::core_id, ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_party_redirecting::from, ast_party_caller::id, ast_party_connected_line::id, ast_frame_subclass::integer, xfer_rsp_data::invoke_id, LOG_ERROR, LOG_WARNING, ast_party_id::name, ast_party_id::number, ast_frame::offset, ast_party_redirecting::orig, sig_pri_chan::owner, ast_party_number::plan, sig_pri_span::pri, xfer_rsp_data::pri, ast_party_redirecting::priv_from, ast_party_redirecting::priv_orig, ast_party_redirecting::priv_to, ast_frame::ptr, sig_pri_span::pvts, 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_connected_line::source, sig_pri_span::span, ast_party_name::str, ast_party_number::str, ast_party_subaddress::str, ast_party_id::subaddress, ast_frame::subclass, ast_party_id::tag, ast_party_redirecting::to, sig_pri_span::transfer, and sig_pri_chan::user_tag.
Referenced by pri_dchannel(), sig_pri_handle_hold(), sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), sig_pri_handle_retrieve_ack(), and sig_pri_handle_retrieve_rej().
{
int index;
struct ast_channel *owner;
struct ast_party_redirecting ast_redirecting;
#if defined(HAVE_PRI_TRANSFER)
struct xfer_rsp_data xfer_rsp;
#endif /* defined(HAVE_PRI_TRANSFER) */
if (!subcmds) {
return;
}
for (index = 0; index < subcmds->counter_subcmd; ++index) {
const struct pri_subcommand *subcmd = &subcmds->subcmd[index];
switch (subcmd->cmd) {
case PRI_SUBCMD_CONNECTED_LINE:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
struct ast_party_connected_line ast_connected;
int caller_id_update;
/* Extract the connected line information */
ast_party_connected_line_init(&ast_connected);
sig_pri_party_id_convert(&ast_connected.id, &subcmd->u.connected_line.id,
pri);
ast_connected.id.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
caller_id_update = 0;
if (ast_connected.id.name.str) {
/* Save name for Caller-ID update */
ast_copy_string(pri->pvts[chanpos]->cid_name,
ast_connected.id.name.str, sizeof(pri->pvts[chanpos]->cid_name));
caller_id_update = 1;
}
if (ast_connected.id.number.str) {
/* Save number for Caller-ID update */
ast_copy_string(pri->pvts[chanpos]->cid_num,
ast_connected.id.number.str, sizeof(pri->pvts[chanpos]->cid_num));
pri->pvts[chanpos]->cid_ton = ast_connected.id.number.plan;
caller_id_update = 1;
}
ast_connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
pri->pvts[chanpos]->cid_subaddr[0] = '\0';
#if defined(HAVE_PRI_SUBADDR)
if (ast_connected.id.subaddress.str) {
ast_copy_string(pri->pvts[chanpos]->cid_subaddr,
ast_connected.id.subaddress.str,
sizeof(pri->pvts[chanpos]->cid_subaddr));
caller_id_update = 1;
}
#endif /* defined(HAVE_PRI_SUBADDR) */
if (caller_id_update) {
struct ast_party_caller ast_caller;
pri->pvts[chanpos]->callingpres =
ast_party_id_presentation(&ast_connected.id);
sig_pri_set_caller_id(pri->pvts[chanpos]);
ast_party_caller_set_init(&ast_caller, ast_channel_caller(owner));
ast_caller.id = ast_connected.id;
ast_caller.ani = ast_connected.id;
ast_channel_set_caller_event(owner, &ast_caller, NULL);
/* Update the connected line information on the other channel */
if (event_id != PRI_EVENT_RING) {
/* This connected_line update was not from a SETUP message. */
ast_channel_queue_connected_line_update(owner, &ast_connected,
NULL);
}
}
ast_party_connected_line_free(&ast_connected);
ast_channel_unlock(owner);
}
break;
case PRI_SUBCMD_REDIRECTING:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
sig_pri_redirecting_convert(&ast_redirecting, &subcmd->u.redirecting,
ast_channel_redirecting(owner), pri);
ast_redirecting.orig.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
if (event_id != PRI_EVENT_RING) {
/* This redirection was not from a SETUP message. */
/* Invalidate any earlier private redirecting id representations */
ast_party_id_invalidate(&ast_redirecting.priv_orig);
ast_party_id_invalidate(&ast_redirecting.priv_from);
ast_party_id_invalidate(&ast_redirecting.priv_to);
ast_channel_queue_redirecting_update(owner, &ast_redirecting, NULL);
}
ast_party_redirecting_free(&ast_redirecting);
ast_channel_unlock(owner);
}
break;
#if defined(HAVE_PRI_CALL_REROUTING)
case PRI_SUBCMD_REROUTING:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
struct pri_party_redirecting pri_deflection;
if (!call_rsp) {
ast_log(LOG_WARNING,
"Span %d: %s tried CallRerouting/CallDeflection to '%s' without call!\n",
pri->span, ast_channel_name(owner), subcmd->u.rerouting.deflection.to.number.str);
ast_channel_unlock(owner);
break;
}
if (ast_strlen_zero(subcmd->u.rerouting.deflection.to.number.str)) {
ast_log(LOG_WARNING,
"Span %d: %s tried CallRerouting/CallDeflection to empty number!\n",
pri->span, ast_channel_name(owner));
pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
PRI_REROUTING_RSP_INVALID_NUMBER);
ast_channel_unlock(owner);
break;
}
ast_verb(3, "Span %d: %s is CallRerouting/CallDeflection to '%s'.\n",
pri->span, ast_channel_name(owner), subcmd->u.rerouting.deflection.to.number.str);
/*
* Send back positive ACK to CallRerouting/CallDeflection.
*
* Note: This call will be hungup by the core when it processes
* the call_forward string.
*/
pri_rerouting_rsp(pri->pri, call_rsp, subcmd->u.rerouting.invoke_id,
PRI_REROUTING_RSP_OK_CLEAR);
pri_deflection = subcmd->u.rerouting.deflection;
/* Adjust the deflecting to number based upon the subscription option. */
switch (subcmd->u.rerouting.subscription_option) {
case 0: /* noNotification */
case 1: /* notificationWithoutDivertedToNr */
/* Delete the number because the far end is not supposed to see it. */
pri_deflection.to.number.presentation =
PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED;
pri_deflection.to.number.plan =
(PRI_TON_UNKNOWN << 4) | PRI_NPI_E163_E164;
pri_deflection.to.number.str[0] = '\0';
break;
case 2: /* notificationWithDivertedToNr */
break;
case 3: /* notApplicable */
default:
break;
}
sig_pri_redirecting_convert(&ast_redirecting, &pri_deflection,
ast_channel_redirecting(owner), pri);
ast_redirecting.orig.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
ast_party_redirecting_free(&ast_redirecting);
/* Request the core to forward to the new number. */
ast_channel_call_forward_set(owner, subcmd->u.rerouting.deflection.to.number.str);
/* Wake up the channel. */
ast_queue_frame(owner, &ast_null_frame);
ast_channel_unlock(owner);
}
break;
#endif /* defined(HAVE_PRI_CALL_REROUTING) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_AVAILABLE:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
enum ast_cc_service_type service;
switch (event_id) {
case PRI_EVENT_RINGING:
service = AST_CC_CCNR;
break;
case PRI_EVENT_HANGUP_REQ:
/* We will assume that the cause was busy/congestion. */
service = AST_CC_CCBS;
break;
default:
service = AST_CC_NONE;
break;
}
if (service == AST_CC_NONE
|| sig_pri_cc_available(pri, chanpos, subcmd->u.cc_available.cc_id,
service)) {
pri_cc_cancel(pri->pri, subcmd->u.cc_available.cc_id);
}
ast_channel_unlock(owner);
} else {
/* No asterisk channel. */
pri_cc_cancel(pri->pri, subcmd->u.cc_available.cc_id);
}
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_CALL:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
struct ast_cc_agent *agent;
agent = sig_pri_find_cc_agent_by_cc_id(pri, subcmd->u.cc_call.cc_id);
if (agent) {
ast_setup_cc_recall_datastore(owner, agent->core_id);
ast_cc_agent_set_interfaces_chanvar(owner);
ast_cc_agent_recalling(agent->core_id,
"%s caller is attempting recall", sig_pri_cc_type_name);
ao2_ref(agent, -1);
}
ast_channel_unlock(owner);
}
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_CCSS)
case PRI_SUBCMD_CC_CANCEL:
sig_pri_cc_link_canceled(pri, subcmd->u.cc_cancel.cc_id,
subcmd->u.cc_cancel.is_agent);
break;
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_TRANSFER)
case PRI_SUBCMD_TRANSFER_CALL:
if (!call_rsp) {
/* Should never happen. */
ast_log(LOG_ERROR,
"Call transfer subcommand without call to send response!\n");
break;
}
sig_pri_unlock_private(pri->pvts[chanpos]);
xfer_rsp.pri = pri;
xfer_rsp.call = call_rsp;
xfer_rsp.invoke_id = subcmd->u.transfer.invoke_id;
sig_pri_attempt_transfer(pri,
subcmd->u.transfer.call_1, subcmd->u.transfer.is_call_1_held,
subcmd->u.transfer.call_2, subcmd->u.transfer.is_call_2_held,
sig_pri_transfer_rsp, &xfer_rsp);
sig_pri_lock_private(pri->pvts[chanpos]);
break;
#endif /* defined(HAVE_PRI_TRANSFER) */
#if defined(HAVE_PRI_AOC_EVENTS)
case PRI_SUBCMD_AOC_S:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
sig_pri_aoc_s_from_pri(&subcmd->u.aoc_s, owner,
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
ast_channel_unlock(owner);
}
break;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_AOC_EVENTS)
case PRI_SUBCMD_AOC_D:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
/* Queue AST_CONTROL_AOC frame on channel */
sig_pri_aoc_d_from_pri(&subcmd->u.aoc_d, owner,
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D));
ast_channel_unlock(owner);
}
break;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_AOC_EVENTS)
case PRI_SUBCMD_AOC_E:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
/* Queue AST_CONTROL_AOC frame */
sig_pri_aoc_e_from_pri(&subcmd->u.aoc_e, owner,
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E));
if (owner) {
ast_channel_unlock(owner);
}
break;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_AOC_EVENTS)
case PRI_SUBCMD_AOC_CHARGING_REQ:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
sig_pri_aoc_request_from_pri(&subcmd->u.aoc_request, pri->pvts[chanpos],
call_rsp);
ast_channel_unlock(owner);
}
break;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_AOC_EVENTS)
case PRI_SUBCMD_AOC_CHARGING_REQ_RSP:
/*
* An AOC request response may contain an AOC-S rate list.
* If this is the case handle this just like we
* would an incoming AOC-S msg.
*/
if (subcmd->u.aoc_request_response.valid_aoc_s) {
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
sig_pri_aoc_s_from_pri(&subcmd->u.aoc_request_response.aoc_s, owner,
(pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S));
ast_channel_unlock(owner);
}
}
break;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_MCID)
case PRI_SUBCMD_MCID_REQ:
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
sig_pri_mcid_event(pri, &subcmd->u.mcid_req, owner);
if (owner) {
ast_channel_unlock(owner);
}
break;
#endif /* defined(HAVE_PRI_MCID) */
#if defined(HAVE_PRI_MCID)
case PRI_SUBCMD_MCID_RSP:
/* Ignore for now. */
break;
#endif /* defined(HAVE_PRI_MCID) */
#if defined(HAVE_PRI_DISPLAY_TEXT)
case PRI_SUBCMD_DISPLAY_TEXT:
if (event_id != PRI_EVENT_RING) {
/*
* This display text was not from a SETUP message. We can do
* something with this display text string.
*/
sig_pri_lock_owner(pri, chanpos);
owner = pri->pvts[chanpos]->owner;
if (owner) {
struct ast_frame f;
/* Pass the display text to the peer channel. */
memset(&f, 0, sizeof(f));
f.frametype = AST_FRAME_TEXT;
f.subclass.integer = 0;
f.offset = 0;
f.data.ptr = &subcmd->u.display.text;
f.datalen = subcmd->u.display.length + 1;
ast_queue_frame(owner, &f);
ast_channel_unlock(owner);
}
}
break;
#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
default:
ast_debug(2, "Span %d: Unknown call subcommand(%d) in %s event.\n",
pri->span, subcmd->cmd, pri_event2str(event_id));
break;
}
}
}
| int sig_pri_hangup | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | ast | ||
| ) |
Definition at line 7560 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_channel_hangupcause(), ast_channel_tech_pvt(), ast_debug, ast_log(), ast_strlen_zero(), sig_pri_chan::call, sig_pri_chan::call_level, sig_pri_chan::channel, sig_pri_chan::cid_name, sig_pri_chan::cid_num, sig_pri_chan::cid_subaddr, sig_pri_chan::exten, sig_pri_chan::holding_aoce, sig_pri_chan::is_call_waiting, LOG_WARNING, sig_pri_span::num_call_waiting_calls, sig_pri_chan::owner, pbx_builtin_getvar_helper(), sig_pri_chan::pri, sig_pri_span::pri, pri_grab(), pri_rel(), sig_pri_chan::progress, SIG_PRI_CALL_LEVEL_IDLE, SIG_PRI_MOH_EVENT_RESET, sig_pri_moh_fsm_event(), sig_pri_set_dialing(), sig_pri_set_digital(), sig_pri_set_outgoing(), sig_pri_span_devstate_changed(), sig_pri_chan::user_tag, and sig_pri_chan::waiting_for_aoce.
Referenced by dahdi_hangup().
{
ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
if (!ast_channel_tech_pvt(ast)) {
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
}
sig_pri_set_outgoing(p, 0);
sig_pri_set_digital(p, 0); /* push up to parent for EC*/
#if defined(HAVE_PRI_CALL_WAITING)
if (p->is_call_waiting) {
p->is_call_waiting = 0;
ast_atomic_fetchadd_int(&p->pri->num_call_waiting_calls, -1);
}
#endif /* defined(HAVE_PRI_CALL_WAITING) */
p->call_level = SIG_PRI_CALL_LEVEL_IDLE;
p->progress = 0;
p->cid_num[0] = '\0';
p->cid_subaddr[0] = '\0';
p->cid_name[0] = '\0';
p->user_tag[0] = '\0';
p->exten[0] = '\0';
sig_pri_set_dialing(p, 0);
/* Make sure we really have a call */
pri_grab(p, p->pri);
sig_pri_moh_fsm_event(ast, p, SIG_PRI_MOH_EVENT_RESET);
if (p->call) {
#if defined(SUPPORT_USERUSER)
const char *useruser = pbx_builtin_getvar_helper(ast, "USERUSERINFO");
if (!ast_strlen_zero(useruser)) {
pri_call_set_useruser(p->call, useruser);
}
#endif /* defined(SUPPORT_USERUSER) */
#if defined(HAVE_PRI_AOC_EVENTS)
if (p->holding_aoce) {
pri_aoc_e_send(p->pri->pri, p->call, &p->aoc_e);
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
if (p->alreadyhungup) {
ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
pri_hangup(p->pri->pri, p->call, -1);
p->call = NULL;
} else {
const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
int icause = ast_channel_hangupcause(ast) ? ast_channel_hangupcause(ast) : -1;
p->alreadyhungup = 1;
if (!ast_strlen_zero(cause)) {
if (atoi(cause)) {
icause = atoi(cause);
}
}
ast_debug(1,
"Not yet hungup... Calling hangup with cause %d, and clearing call\n",
icause);
pri_hangup(p->pri->pri, p->call, icause);
}
}
#if defined(HAVE_PRI_AOC_EVENTS)
p->aoc_s_request_invoke_id_valid = 0;
p->holding_aoce = 0;
p->waiting_for_aoce = 0;
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
p->allocated = 0;
p->owner = NULL;
sig_pri_span_devstate_changed(p->pri);
pri_rel(p->pri);
return 0;
}
| int sig_pri_indicate | ( | struct sig_pri_chan * | p, |
| struct ast_channel * | chan, | ||
| int | condition, | ||
| const void * | data, | ||
| size_t | datalen | ||
| ) |
Definition at line 8188 of file sig_pri.c.
References 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_channel_connected_effective_id(), ast_channel_hangupcause(), ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_softhangup_internal_flag_add(), AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_MCID, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, 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, sig_pri_span::colp_send, sig_pri_span::cpndialplan, DAHDI_OVERLAPDIAL_INCOMING, sig_pri_chan::digital, sig_pri_span::internationalprefix, sig_pri_span::mcid_send, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, sig_pri_span::nationalprefix, 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::progress, PVT_TO_CHANNEL(), S_OR, 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_COLP_BLOCK, SIG_PRI_COLP_CONNECT, SIG_PRI_COLP_UPDATE, SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_EVENT_UNHOLD, sig_pri_moh_fsm_event(), 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().
{
int res = -1;
switch (condition) {
case AST_CONTROL_BUSY:
if (p->priindication_oob || p->no_b_channel) {
ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY);
ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
res = 0;
break;
}
res = sig_pri_play_tone(p, SIG_PRI_TONE_BUSY);
if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY);
p->progress = 1;/* No need to send plain PROGRESS after this. */
if (p->pri && p->pri->pri) {
pri_grab(p, p->pri);
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, ast_channel_hangupcause(chan));
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
}
}
break;
case AST_CONTROL_RINGING:
if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
p->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
if (p->pri && p->pri->pri) {
pri_grab(p, p->pri);
pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
p->no_b_channel || p->digital ? 0 : 1);
pri_rel(p->pri);
}
}
res = sig_pri_play_tone(p, SIG_PRI_TONE_RINGTONE);
if (ast_channel_state(chan) != AST_STATE_UP) {
if (ast_channel_state(chan) != AST_STATE_RING)
ast_setstate(chan, AST_STATE_RINGING);
}
break;
case AST_CONTROL_PROCEEDING:
ast_debug(1, "Received AST_CONTROL_PROCEEDING on %s\n",ast_channel_name(chan));
if (p->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
p->call_level = SIG_PRI_CALL_LEVEL_PROCEEDING;
if (p->pri && p->pri->pri) {
pri_grab(p, p->pri);
pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p),
p->no_b_channel || p->digital ? 0 : 1);
if (!p->no_b_channel && !p->digital) {
sig_pri_set_dialing(p, 0);
}
pri_rel(p->pri);
}
}
/* don't continue in ast_indicate */
res = 0;
break;
case AST_CONTROL_PROGRESS:
ast_debug(1, "Received AST_CONTROL_PROGRESS on %s\n",ast_channel_name(chan));
sig_pri_set_digital(p, 0); /* Digital-only calls isn't allowing any inband progress messages */
if (!p->progress && p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing
&& !p->no_b_channel) {
p->progress = 1;/* No need to send plain PROGRESS again. */
if (p->pri && p->pri->pri) {
pri_grab(p, p->pri);
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1); /* no cause at all */
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
}
}
/* don't continue in ast_indicate */
res = 0;
break;
case AST_CONTROL_INCOMPLETE:
/* If we are connected or if we support overlap dialing, wait for additional digits */
if (p->call_level == SIG_PRI_CALL_LEVEL_CONNECT || (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
res = 0;
break;
}
/* Otherwise, treat as congestion */
ast_channel_hangupcause_set(chan, AST_CAUSE_INVALID_NUMBER_FORMAT);
/* Falls through */
case AST_CONTROL_CONGESTION:
if (p->priindication_oob || p->no_b_channel) {
/* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
switch (ast_channel_hangupcause(chan)) {
case AST_CAUSE_USER_BUSY:
case AST_CAUSE_NORMAL_CLEARING:
case 0:/* Cause has not been set. */
/* Supply a more appropriate cause. */
ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION);
break;
default:
break;
}
ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
res = 0;
break;
}
res = sig_pri_play_tone(p, SIG_PRI_TONE_CONGESTION);
if (p->call_level < SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
/* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
switch (ast_channel_hangupcause(chan)) {
case AST_CAUSE_USER_BUSY:
case AST_CAUSE_NORMAL_CLEARING:
case 0:/* Cause has not been set. */
/* Supply a more appropriate cause. */
ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION);
break;
default:
break;
}
p->progress = 1;/* No need to send plain PROGRESS after this. */
if (p->pri && p->pri->pri) {
pri_grab(p, p->pri);
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, ast_channel_hangupcause(chan));
#else
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
}
}
break;
case AST_CONTROL_HOLD:
ast_copy_string(p->moh_suggested, S_OR(data, ""), sizeof(p->moh_suggested));
if (p->pri) {
pri_grab(p, p->pri);
sig_pri_moh_fsm_event(chan, p, SIG_PRI_MOH_EVENT_HOLD);
pri_rel(p->pri);
} else {
/* Something is wrong here. A PRI channel without the pri pointer? */
ast_moh_start(chan, data, p->mohinterpret);
}
break;
case AST_CONTROL_UNHOLD:
if (p->pri) {
pri_grab(p, p->pri);
sig_pri_moh_fsm_event(chan, p, SIG_PRI_MOH_EVENT_UNHOLD);
pri_rel(p->pri);
} else {
/* Something is wrong here. A PRI channel without the pri pointer? */
ast_moh_stop(chan);
}
break;
case AST_CONTROL_SRCUPDATE:
res = 0;
break;
case -1:
res = sig_pri_play_tone(p, -1);
break;
case AST_CONTROL_CONNECTED_LINE:
ast_debug(1, "Received AST_CONTROL_CONNECTED_LINE on %s\n", ast_channel_name(chan));
if (p->pri) {
struct pri_party_connected_line connected;
int dialplan;
int prefix_strip;
int colp_allowed = 0;
struct ast_party_id connected_id = ast_channel_connected_effective_id(chan);
pri_grab(p, p->pri);
/* Check if a connected line update is allowed at this time. */
switch (p->pri->colp_send) {
case SIG_PRI_COLP_BLOCK:
break;
case SIG_PRI_COLP_CONNECT:
/*
* Outgoing calls receive CONNECT and act like an update before
* the call is connected.
*/
if (p->call_level <= SIG_PRI_CALL_LEVEL_ALERTING && !p->outgoing) {
colp_allowed = 1;
}
break;
case SIG_PRI_COLP_UPDATE:
colp_allowed = 1;
break;
}
if (!colp_allowed) {
pri_rel(p->pri);
ast_debug(1, "Blocked AST_CONTROL_CONNECTED_LINE on %s\n",
ast_channel_name(chan));
break;
}
memset(&connected, 0, sizeof(connected));
sig_pri_party_id_from_ast(&connected.id, &connected_id);
/* Determine the connected line numbering plan to actually use. */
switch (p->pri->cpndialplan) {
case -2:/* redundant */
case -1:/* dynamic */
/* compute dynamically */
prefix_strip = 0;
if (!strncmp(connected.id.number.str, p->pri->internationalprefix,
strlen(p->pri->internationalprefix))) {
prefix_strip = strlen(p->pri->internationalprefix);
dialplan = PRI_INTERNATIONAL_ISDN;
} else if (!strncmp(connected.id.number.str, p->pri->nationalprefix,
strlen(p->pri->nationalprefix))) {
prefix_strip = strlen(p->pri->nationalprefix);
dialplan = PRI_NATIONAL_ISDN;
} else {
dialplan = PRI_LOCAL_ISDN;
}
connected.id.number.plan = dialplan;
if (prefix_strip && p->pri->cpndialplan != -2) {
/* Strip the prefix from the connected line number. */
memmove(connected.id.number.str,
connected.id.number.str + prefix_strip,
strlen(connected.id.number.str + prefix_strip) + 1);
}
break;
case 0:/* from_channel */
/* Use the numbering plan passed in. */
break;
default:
connected.id.number.plan = p->pri->cpndialplan - 1;
break;
}
pri_connected_line_update(p->pri->pri, p->call, &connected);
pri_rel(p->pri);
}
break;
case AST_CONTROL_REDIRECTING:
ast_debug(1, "Received AST_CONTROL_REDIRECTING on %s\n", ast_channel_name(chan));
if (p->pri) {
pri_grab(p, p->pri);
sig_pri_redirecting_update(p, chan);
pri_rel(p->pri);
}
break;
case AST_CONTROL_AOC:
#if defined(HAVE_PRI_AOC_EVENTS)
{
struct ast_aoc_decoded *decoded
= ast_aoc_decode((struct ast_aoc_encoded *) data, datalen, chan);
ast_debug(1, "Received AST_CONTROL_AOC on %s\n", ast_channel_name(chan));
if (decoded && p->pri) {
pri_grab(p, p->pri);
switch (ast_aoc_get_msg_type(decoded)) {
case AST_AOC_S:
if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_S) {
sig_pri_aoc_s_from_ast(p, decoded);
}
break;
case AST_AOC_D:
if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_D) {
sig_pri_aoc_d_from_ast(p, decoded);
}
break;
case AST_AOC_E:
if (p->pri->aoc_passthrough_flag & SIG_PRI_AOC_GRANT_E) {
sig_pri_aoc_e_from_ast(p, decoded);
}
/* if hangup was delayed for this AOC-E msg, waiting_for_aoc
* will be set. A hangup is already occuring via a timeout during
* this delay. Instead of waiting for that timeout to occur, go ahead
* and initiate the softhangup since the delay is no longer necessary */
if (p->waiting_for_aoce) {
p->waiting_for_aoce = 0;
ast_debug(1,
"Received final AOC-E msg, continue with hangup on %s\n",
ast_channel_name(chan));
ast_softhangup_nolock(chan, AST_SOFTHANGUP_DEV);
}
break;
case AST_AOC_REQUEST:
/* We do not pass through AOC requests, So unless this
* is an AOC termination request it will be ignored */
if (ast_aoc_get_termination_request(decoded)) {
pri_hangup(p->pri->pri, p->call, -1);
}
break;
default:
break;
}
pri_rel(p->pri);
}
ast_aoc_destroy_decoded(decoded);
}
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
break;
#if defined(HAVE_PRI_MCID)
case AST_CONTROL_MCID:
if (p->pri && p->pri->pri && p->pri->mcid_send) {
pri_grab(p, p->pri);
pri_mcid_req_send(p->pri->pri, p->call);
pri_rel(p->pri);
}
break;
#endif /* defined(HAVE_PRI_MCID) */
}
return res;
}
| static void sig_pri_init_config | ( | struct sig_pri_chan * | pvt, |
| struct sig_pri_span * | pri | ||
| ) | [static] |
Definition at line 1785 of file sig_pri.c.
References ast_copy_string(), sig_pri_span::ch_cfg, sig_pri_chan::chan_pvt, sig_pri_chan::context, sig_pri_span::context, sig_pri_chan::hidecallerid, sig_pri_span::hidecallerid, sig_pri_chan::hidecalleridname, sig_pri_span::hidecalleridname, sig_pri_chan::immediate, sig_pri_span::immediate, sig_pri_callback::init_config, sig_pri_chan::mohinterpret, sig_pri_span::mohinterpret, sig_pri_chan::priexclusive, sig_pri_span::priexclusive, sig_pri_chan::priindication_oob, sig_pri_span::priindication_oob, sig_pri_callbacks, sig_pri_chan::stripmsd, sig_pri_span::stripmsd, sig_pri_chan::use_callerid, sig_pri_span::use_callerid, sig_pri_chan::use_callingpres, and sig_pri_span::use_callingpres.
Referenced by pri_dchannel(), and sig_pri_cw_available().
{
pvt->stripmsd = pri->ch_cfg.stripmsd;
pvt->hidecallerid = pri->ch_cfg.hidecallerid;
pvt->hidecalleridname = pri->ch_cfg.hidecalleridname;
pvt->immediate = pri->ch_cfg.immediate;
pvt->priexclusive = pri->ch_cfg.priexclusive;
pvt->priindication_oob = pri->ch_cfg.priindication_oob;
pvt->use_callerid = pri->ch_cfg.use_callerid;
pvt->use_callingpres = pri->ch_cfg.use_callingpres;
ast_copy_string(pvt->context, pri->ch_cfg.context, sizeof(pvt->context));
ast_copy_string(pvt->mohinterpret, pri->ch_cfg.mohinterpret, sizeof(pvt->mohinterpret));
if (sig_pri_callbacks.init_config) {
sig_pri_callbacks.init_config(pvt->chan_pvt, pri);
}
}
| void sig_pri_init_pri | ( | struct sig_pri_span * | pri | ) |
Definition at line 7547 of file sig_pri.c.
References ast_mutex_init, AST_PTHREADT_NULL, sig_pri_span::fds, sig_pri_span::lock, sig_pri_span::master, and SIG_PRI_NUM_DCHANS.
Referenced by dahdi_restart(), and load_module().
{
int i;
memset(pri, 0, sizeof(*pri));
ast_mutex_init(&pri->lock);
pri->master = AST_PTHREADT_NULL;
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++)
pri->fds[i] = -1;
}
| int sig_pri_is_alarm_ignored | ( | struct sig_pri_span * | pri | ) |
Determine if layer 1 alarms are ignored.
| p | Channel private pointer. |
Definition at line 9162 of file sig_pri.c.
References sig_pri_span::layer1_ignored.
Referenced by handle_alarms(), handle_clear_alarms(), my_handle_dchan_exception(), and sig_pri_set_alarm().
{
return pri->layer1_ignored;
}
| 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 1184 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().
{
return !sig_pri_is_chan_in_use(pvt)
#if defined(HAVE_PRI_SERVICE_MESSAGES)
/* And not out-of-service */
&& !pvt->service_status
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
;
}
| static int sig_pri_is_chan_in_use | ( | struct sig_pri_chan * | pvt | ) | [static] |
Definition at line 1170 of file sig_pri.c.
References sig_pri_chan::allocated, sig_pri_chan::call, sig_pri_chan::inalarm, sig_pri_chan::owner, sig_pri_chan::resetting, and SIG_PRI_RESET_IDLE.
Referenced by pri_check_restart(), and sig_pri_is_chan_available().
| static int sig_pri_is_cis_call | ( | int | channel | ) | [static] |
Definition at line 3893 of file sig_pri.c.
References PRI_CIS_CALL.
Referenced by pri_dchannel().
{
return channel != -1 && (channel & PRI_CIS_CALL);
}
| static void sig_pri_kill_call | ( | struct sig_pri_span * | pri, |
| q931_call * | call, | ||
| int | cause | ||
| ) | [static] |
Definition at line 1353 of file sig_pri.c.
References ast_channel_hangupcause_set(), AST_CONTROL_HANGUP, sig_pri_chan::call, sig_pri_chan::owner, sig_pri_span::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(), sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), and sig_pri_handle_retrieve_rej().
{
int chanpos;
chanpos = pri_find_principle_by_call(pri, call);
if (chanpos < 0) {
pri_hangup(pri->pri, call, cause);
return;
}
sig_pri_lock_private(pri->pvts[chanpos]);
if (!pri->pvts[chanpos]->owner) {
pri_hangup(pri->pri, call, cause);
pri->pvts[chanpos]->call = NULL;
sig_pri_unlock_private(pri->pvts[chanpos]);
sig_pri_span_devstate_changed(pri);
return;
}
ast_channel_hangupcause_set(pri->pvts[chanpos]->owner, cause);
pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
sig_pri_unlock_private(pri->pvts[chanpos]);
}
| 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 9988 of file sig_pri.c.
References ao2_container_alloc, sig_pri_cc_monitor_instance_cmp_fn(), sig_pri_cc_monitor_instance_hash_fn(), and sig_pri_cc_type_name.
Referenced by load_module().
{
#if defined(HAVE_PRI_CCSS)
sig_pri_cc_type_name = cc_type_name;
sig_pri_cc_monitors = ao2_container_alloc(37, sig_pri_cc_monitor_instance_hash_fn,
sig_pri_cc_monitor_instance_cmp_fn);
if (!sig_pri_cc_monitors) {
return -1;
}
#endif /* defined(HAVE_PRI_CCSS) */
return 0;
}
| static void sig_pri_lock_owner | ( | struct sig_pri_span * | pri, |
| int | chanpos | ||
| ) | [static] |
Definition at line 1207 of file sig_pri.c.
References ast_channel_trylock, DEADLOCK_AVOIDANCE, sig_pri_span::lock, sig_pri_chan::owner, sig_pri_span::pvts, sig_pri_lock_private(), and sig_pri_unlock_private().
Referenced by func_pri_dchannel_chanpos_callid(), pri_dchannel(), pri_fixup_principle(), pri_queue_frame(), pri_queue_pvt_cause_data(), sig_pri_attempt_transfer(), sig_pri_cc_generic_check(), sig_pri_cli_show_channels(), sig_pri_handle_hold(), sig_pri_handle_retrieve(), sig_pri_handle_subcmds(), and sig_pri_send_aoce_termination_request().
{
for (;;) {
if (!pri->pvts[chanpos]->owner) {
/* There is no owner lock to get. */
break;
}
if (!ast_channel_trylock(pri->pvts[chanpos]->owner)) {
/* We got the lock */
break;
}
/* Avoid deadlock */
sig_pri_unlock_private(pri->pvts[chanpos]);
DEADLOCK_AVOIDANCE(&pri->lock);
sig_pri_lock_private(pri->pvts[chanpos]);
}
}
| static void sig_pri_lock_private | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 342 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::lock_private, and sig_pri_callbacks.
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_deadlock_avoidance_private(), sig_pri_handle_hold(), sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), sig_pri_handle_retrieve_ack(), sig_pri_handle_retrieve_rej(), sig_pri_handle_subcmds(), sig_pri_kill_call(), and sig_pri_lock_owner().
{
if (sig_pri_callbacks.lock_private) {
sig_pri_callbacks.lock_private(p->chan_pvt);
}
}
| static void sig_pri_make_cc_dialstring | ( | struct sig_pri_chan * | p, |
| char * | buf, | ||
| size_t | buf_size | ||
| ) | [static] |
Definition at line 222 of file sig_pri.c.
References ast_log(), sig_pri_chan::chan_pvt, LOG_ERROR, sig_pri_callback::make_cc_dialstring, and sig_pri_callbacks.
Referenced by sig_pri_cc_available().
{
if (sig_pri_callbacks.make_cc_dialstring) {
sig_pri_callbacks.make_cc_dialstring(p->chan_pvt, buf, buf_size);
} else {
ast_log(LOG_ERROR, "make_cc_dialstring callback not defined\n");
buf[0] = '\0';
}
}
| 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 2304 of file sig_pri.c.
References ast_channel_connected(), ast_channel_name(), ast_channel_uniqueid(), AST_CONTROL_MCID, ast_free, ast_manager_event_multichan, ast_party_id_free(), ast_party_id_init(), ast_queue_control(), ast_str_append(), ast_str_buffer(), ast_str_create(), EVENT_FLAG_CALL, sig_pri_event_party_id(), and sig_pri_party_id_convert().
Referenced by sig_pri_handle_subcmds().
{
struct ast_channel *chans[1];
struct ast_str *msg;
struct ast_party_id party;
msg = ast_str_create(4096);
if (!msg) {
return;
}
if (owner) {
/*
* The owner channel is present.
* Pass the event to the peer as well.
*/
ast_queue_control(owner, AST_CONTROL_MCID);
ast_str_append(&msg, 0, "Channel: %s\r\n", ast_channel_name(owner));
ast_str_append(&msg, 0, "UniqueID: %s\r\n", ast_channel_uniqueid(owner));
sig_pri_event_party_id(&msg, "CallerID", &ast_channel_connected(owner)->id);
} else {
/*
* Since we no longer have an owner channel,
* we have to use the caller information supplied by libpri.
*/
ast_party_id_init(&party);
sig_pri_party_id_convert(&party, &mcid->originator, pri);
sig_pri_event_party_id(&msg, "CallerID", &party);
ast_party_id_free(&party);
}
/* Always use libpri's called party information. */
ast_party_id_init(&party);
sig_pri_party_id_convert(&party, &mcid->answerer, pri);
sig_pri_event_party_id(&msg, "ConnectedID", &party);
ast_party_id_free(&party);
chans[0] = owner;
ast_manager_event_multichan(EVENT_FLAG_CALL, "MCID", owner ? 1 : 0, chans, "%s",
ast_str_buffer(msg));
ast_free(msg);
}
| static const char* sig_pri_moh_event_str | ( | enum sig_pri_moh_event | event | ) | [static] |
Definition at line 4595 of file sig_pri.c.
References SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_EVENT_HOLD_ACK, SIG_PRI_MOH_EVENT_HOLD_REJ, SIG_PRI_MOH_EVENT_NUM, SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RETRIEVE_REJ, SIG_PRI_MOH_EVENT_UNHOLD, and str.
Referenced by sig_pri_moh_fsm_event().
{
const char *str;
str = "Unknown";
switch (event) {
case SIG_PRI_MOH_EVENT_RESET:
str = "SIG_PRI_MOH_EVENT_RESET";
break;
case SIG_PRI_MOH_EVENT_HOLD:
str = "SIG_PRI_MOH_EVENT_HOLD";
break;
case SIG_PRI_MOH_EVENT_UNHOLD:
str = "SIG_PRI_MOH_EVENT_UNHOLD";
break;
#if defined(HAVE_PRI_CALL_HOLD)
case SIG_PRI_MOH_EVENT_HOLD_ACK:
str = "SIG_PRI_MOH_EVENT_HOLD_ACK";
break;
case SIG_PRI_MOH_EVENT_HOLD_REJ:
str = "SIG_PRI_MOH_EVENT_HOLD_REJ";
break;
case SIG_PRI_MOH_EVENT_RETRIEVE_ACK:
str = "SIG_PRI_MOH_EVENT_RETRIEVE_ACK";
break;
case SIG_PRI_MOH_EVENT_RETRIEVE_REJ:
str = "SIG_PRI_MOH_EVENT_RETRIEVE_REJ";
break;
case SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK:
str = "SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK";
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
case SIG_PRI_MOH_EVENT_NUM:
/* Not a real event. */
break;
}
return str;
}
| static void sig_pri_moh_fsm_event | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 5153 of file sig_pri.c.
References ast_channel_name(), ast_debug, ast_log(), LOG_ERROR, sig_pri_chan::moh_state, sig_pri_moh_event_str(), sig_pri_moh_fsm, SIG_PRI_MOH_STATE_IDLE, SIG_PRI_MOH_STATE_NUM, and sig_pri_moh_state_str().
Referenced by sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), sig_pri_handle_retrieve_ack(), sig_pri_handle_retrieve_rej(), sig_pri_hangup(), and sig_pri_indicate().
{
enum sig_pri_moh_state orig_state;
enum sig_pri_moh_state next_state;
const char *chan_name;
if (chan) {
chan_name = ast_strdupa(ast_channel_name(chan));
} else {
chan_name = "Unknown";
}
orig_state = pvt->moh_state;
ast_debug(2, "Channel '%s' MOH-Event: %s in state %s\n", chan_name,
sig_pri_moh_event_str(event), sig_pri_moh_state_str(orig_state));
if (orig_state < SIG_PRI_MOH_STATE_IDLE || SIG_PRI_MOH_STATE_NUM <= orig_state
|| !sig_pri_moh_fsm[orig_state]) {
/* Programming error: State not implemented. */
ast_log(LOG_ERROR, "MOH state not implemented: %s(%d)\n",
sig_pri_moh_state_str(orig_state), orig_state);
return;
}
/* Execute the state. */
next_state = sig_pri_moh_fsm[orig_state](chan, pvt, event);
ast_debug(2, "Channel '%s' MOH-Next-State: %s\n", chan_name,
(orig_state == next_state) ? "$" : sig_pri_moh_state_str(next_state));
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_hold | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 4918 of file sig_pri.c.
References ast_moh_start(), sig_pri_chan::moh_state, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_UNHOLD, sig_pri_moh_retrieve_call(), SIG_PRI_MOH_STATE_IDLE, and SIG_PRI_MOH_STATE_MOH.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_RESET:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_UNHOLD:
next_state = sig_pri_moh_retrieve_call(pvt);
break;
case SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK:
/* Fall back to MOH */
if (chan) {
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
}
next_state = SIG_PRI_MOH_STATE_MOH;
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_hold_req | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 4832 of file sig_pri.c.
References ast_moh_start(), sig_pri_chan::moh_state, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, SIG_PRI_MOH_EVENT_HOLD_ACK, SIG_PRI_MOH_EVENT_HOLD_REJ, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_UNHOLD, SIG_PRI_MOH_STATE_HOLD, SIG_PRI_MOH_STATE_IDLE, SIG_PRI_MOH_STATE_MOH, and SIG_PRI_MOH_STATE_PEND_UNHOLD.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_RESET:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_UNHOLD:
next_state = SIG_PRI_MOH_STATE_PEND_UNHOLD;
break;
case SIG_PRI_MOH_EVENT_HOLD_REJ:
/* Fall back to MOH */
if (chan) {
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
}
next_state = SIG_PRI_MOH_STATE_MOH;
break;
case SIG_PRI_MOH_EVENT_HOLD_ACK:
next_state = SIG_PRI_MOH_STATE_HOLD;
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_idle | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 4691 of file sig_pri.c.
References ast_moh_start(), sig_pri_chan::call, sig_pri_span::moh_signaling, sig_pri_chan::moh_state, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, sig_pri_chan::pri, sig_pri_span::pri, sig_pri_chan::prioffset, SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_SIGNALING_HOLD, SIG_PRI_MOH_SIGNALING_MOH, SIG_PRI_MOH_SIGNALING_NOTIFY, SIG_PRI_MOH_STATE_HOLD_REQ, SIG_PRI_MOH_STATE_MOH, and SIG_PRI_MOH_STATE_NOTIFY.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_HOLD:
if (!strcasecmp(pvt->mohinterpret, "passthrough")) {
/*
* This config setting is deprecated.
* The old way did not send MOH just in case the notification was ignored.
*/
pri_notify(pvt->pri->pri, pvt->call, pvt->prioffset, PRI_NOTIFY_REMOTE_HOLD);
next_state = SIG_PRI_MOH_STATE_NOTIFY;
break;
}
switch (pvt->pri->moh_signaling) {
default:
case SIG_PRI_MOH_SIGNALING_MOH:
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
next_state = SIG_PRI_MOH_STATE_MOH;
break;
case SIG_PRI_MOH_SIGNALING_NOTIFY:
/* Send MOH anyway in case the far end does not interpret the notification. */
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
pri_notify(pvt->pri->pri, pvt->call, pvt->prioffset, PRI_NOTIFY_REMOTE_HOLD);
next_state = SIG_PRI_MOH_STATE_NOTIFY;
break;
#if defined(HAVE_PRI_CALL_HOLD)
case SIG_PRI_MOH_SIGNALING_HOLD:
if (pri_hold(pvt->pri->pri, pvt->call)) {
/* Fall back to MOH instead */
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
next_state = SIG_PRI_MOH_STATE_MOH;
} else {
next_state = SIG_PRI_MOH_STATE_HOLD_REQ;
}
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
}
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_moh | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 4795 of file sig_pri.c.
References ast_moh_start(), ast_moh_stop(), sig_pri_chan::moh_state, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_UNHOLD, and SIG_PRI_MOH_STATE_IDLE.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_HOLD:
/* Restart MOH in case it was stopped by other means. */
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
break;
case SIG_PRI_MOH_EVENT_RESET:
case SIG_PRI_MOH_EVENT_UNHOLD:
ast_moh_stop(chan);
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_notify | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 4755 of file sig_pri.c.
References ast_moh_start(), ast_moh_stop(), sig_pri_chan::call, sig_pri_chan::moh_state, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, sig_pri_chan::pri, sig_pri_span::pri, sig_pri_chan::prioffset, SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_UNHOLD, and SIG_PRI_MOH_STATE_IDLE.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_HOLD:
if (strcasecmp(pvt->mohinterpret, "passthrough")) {
/* Restart MOH in case it was stopped by other means. */
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
}
break;
case SIG_PRI_MOH_EVENT_UNHOLD:
pri_notify(pvt->pri->pri, pvt->call, pvt->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
/* Fall through */
case SIG_PRI_MOH_EVENT_RESET:
ast_moh_stop(chan);
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_pend_hold | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 5002 of file sig_pri.c.
References ast_moh_start(), sig_pri_chan::call, sig_pri_span::moh_signaling, sig_pri_chan::moh_state, sig_pri_chan::moh_suggested, sig_pri_chan::mohinterpret, sig_pri_chan::pri, sig_pri_span::pri, sig_pri_chan::prioffset, SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RETRIEVE_REJ, SIG_PRI_MOH_EVENT_UNHOLD, SIG_PRI_MOH_SIGNALING_HOLD, SIG_PRI_MOH_SIGNALING_MOH, SIG_PRI_MOH_SIGNALING_NOTIFY, SIG_PRI_MOH_STATE_HOLD, SIG_PRI_MOH_STATE_HOLD_REQ, SIG_PRI_MOH_STATE_IDLE, SIG_PRI_MOH_STATE_MOH, SIG_PRI_MOH_STATE_NOTIFY, and SIG_PRI_MOH_STATE_RETRIEVE_REQ.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_RESET:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_UNHOLD:
next_state = SIG_PRI_MOH_STATE_RETRIEVE_REQ;
break;
case SIG_PRI_MOH_EVENT_RETRIEVE_ACK:
case SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK:
/*
* Successfully came off of hold. Now we can reinterpret the
* MOH signaling option to handle the pending HOLD request.
*/
switch (pvt->pri->moh_signaling) {
default:
case SIG_PRI_MOH_SIGNALING_MOH:
if (chan) {
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
}
next_state = SIG_PRI_MOH_STATE_MOH;
break;
case SIG_PRI_MOH_SIGNALING_NOTIFY:
/* Send MOH anyway in case the far end does not interpret the notification. */
if (chan) {
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
}
pri_notify(pvt->pri->pri, pvt->call, pvt->prioffset, PRI_NOTIFY_REMOTE_HOLD);
next_state = SIG_PRI_MOH_STATE_NOTIFY;
break;
case SIG_PRI_MOH_SIGNALING_HOLD:
if (pri_hold(pvt->pri->pri, pvt->call)) {
/* Fall back to MOH instead */
if (chan) {
ast_moh_start(chan, pvt->moh_suggested, pvt->mohinterpret);
}
next_state = SIG_PRI_MOH_STATE_MOH;
} else {
next_state = SIG_PRI_MOH_STATE_HOLD_REQ;
}
break;
}
break;
case SIG_PRI_MOH_EVENT_RETRIEVE_REJ:
/*
* We cannot reinterpret the MOH signaling option because we
* failed to come off of hold.
*/
next_state = SIG_PRI_MOH_STATE_HOLD;
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_pend_unhold | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 4877 of file sig_pri.c.
References sig_pri_chan::moh_state, SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_EVENT_HOLD_ACK, SIG_PRI_MOH_EVENT_HOLD_REJ, SIG_PRI_MOH_EVENT_RESET, sig_pri_moh_retrieve_call(), SIG_PRI_MOH_STATE_HOLD_REQ, and SIG_PRI_MOH_STATE_IDLE.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_RESET:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_HOLD:
next_state = SIG_PRI_MOH_STATE_HOLD_REQ;
break;
case SIG_PRI_MOH_EVENT_HOLD_REJ:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_HOLD_ACK:
next_state = sig_pri_moh_retrieve_call(pvt);
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_retrieve_fail | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 5080 of file sig_pri.c.
References sig_pri_chan::moh_state, SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_UNHOLD, sig_pri_moh_retrieve_call(), SIG_PRI_MOH_STATE_HOLD, and SIG_PRI_MOH_STATE_IDLE.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_RESET:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_HOLD:
next_state = SIG_PRI_MOH_STATE_HOLD;
break;
case SIG_PRI_MOH_EVENT_UNHOLD:
next_state = sig_pri_moh_retrieve_call(pvt);
break;
case SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_fsm_retrieve_req | ( | struct ast_channel * | chan, |
| struct sig_pri_chan * | pvt, | ||
| enum sig_pri_moh_event | event | ||
| ) | [static] |
Definition at line 4960 of file sig_pri.c.
References sig_pri_chan::moh_state, SIG_PRI_MOH_EVENT_HOLD, SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RESET, SIG_PRI_MOH_EVENT_RETRIEVE_ACK, SIG_PRI_MOH_EVENT_RETRIEVE_REJ, SIG_PRI_MOH_STATE_IDLE, SIG_PRI_MOH_STATE_PEND_HOLD, and SIG_PRI_MOH_STATE_RETRIEVE_FAIL.
{
enum sig_pri_moh_state next_state;
next_state = pvt->moh_state;
switch (event) {
case SIG_PRI_MOH_EVENT_RESET:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_HOLD:
next_state = SIG_PRI_MOH_STATE_PEND_HOLD;
break;
case SIG_PRI_MOH_EVENT_RETRIEVE_ACK:
case SIG_PRI_MOH_EVENT_REMOTE_RETRIEVE_ACK:
next_state = SIG_PRI_MOH_STATE_IDLE;
break;
case SIG_PRI_MOH_EVENT_RETRIEVE_REJ:
next_state = SIG_PRI_MOH_STATE_RETRIEVE_FAIL;
break;
default:
break;
}
pvt->moh_state = next_state;
return next_state;
}
| static enum sig_pri_moh_state sig_pri_moh_retrieve_call | ( | struct sig_pri_chan * | pvt | ) | [static] |
Definition at line 4647 of file sig_pri.c.
References sig_pri_chan::call, sig_pri_span::nodetype, sig_pri_chan::pri, sig_pri_span::pri, pri_find_empty_chan(), PVT_TO_CHANNEL(), sig_pri_span::pvts, SIG_PRI_MOH_STATE_RETRIEVE_FAIL, and SIG_PRI_MOH_STATE_RETRIEVE_REQ.
Referenced by sig_pri_moh_fsm_hold(), sig_pri_moh_fsm_pend_unhold(), and sig_pri_moh_fsm_retrieve_fail().
{
int chanpos;
int channel;
if (pvt->pri->nodetype == PRI_NETWORK) {
/* Find an available channel to propose */
chanpos = pri_find_empty_chan(pvt->pri, 1);
if (chanpos < 0) {
/* No channels available. */
return SIG_PRI_MOH_STATE_RETRIEVE_FAIL;
}
channel = PVT_TO_CHANNEL(pvt->pri->pvts[chanpos]);
/*
* We cannot occupy or reserve this channel at this time because
* the retrieve may fail or we could have a RETRIEVE collision.
*/
} else {
/* Let the network pick the channel. */
channel = 0;
}
if (pri_retrieve(pvt->pri->pri, pvt->call, channel)) {
return SIG_PRI_MOH_STATE_RETRIEVE_FAIL;
}
return SIG_PRI_MOH_STATE_RETRIEVE_REQ;
}
| static const char* sig_pri_moh_state_str | ( | enum sig_pri_moh_state | state | ) | [static] |
Definition at line 4544 of file sig_pri.c.
References SIG_PRI_MOH_STATE_HOLD, SIG_PRI_MOH_STATE_HOLD_REQ, SIG_PRI_MOH_STATE_IDLE, SIG_PRI_MOH_STATE_MOH, SIG_PRI_MOH_STATE_NOTIFY, SIG_PRI_MOH_STATE_NUM, SIG_PRI_MOH_STATE_PEND_HOLD, SIG_PRI_MOH_STATE_PEND_UNHOLD, SIG_PRI_MOH_STATE_RETRIEVE_FAIL, SIG_PRI_MOH_STATE_RETRIEVE_REQ, and str.
Referenced by sig_pri_moh_fsm_event().
{
const char *str;
str = "Unknown";
switch (state) {
case SIG_PRI_MOH_STATE_IDLE:
str = "SIG_PRI_MOH_STATE_IDLE";
break;
case SIG_PRI_MOH_STATE_NOTIFY:
str = "SIG_PRI_MOH_STATE_NOTIFY";
break;
case SIG_PRI_MOH_STATE_MOH:
str = "SIG_PRI_MOH_STATE_MOH";
break;
#if defined(HAVE_PRI_CALL_HOLD)
case SIG_PRI_MOH_STATE_HOLD_REQ:
str = "SIG_PRI_MOH_STATE_HOLD_REQ";
break;
case SIG_PRI_MOH_STATE_PEND_UNHOLD:
str = "SIG_PRI_MOH_STATE_PEND_UNHOLD";
break;
case SIG_PRI_MOH_STATE_HOLD:
str = "SIG_PRI_MOH_STATE_HOLD";
break;
case SIG_PRI_MOH_STATE_RETRIEVE_REQ:
str = "SIG_PRI_MOH_STATE_RETRIEVE_REQ";
break;
case SIG_PRI_MOH_STATE_PEND_HOLD:
str = "SIG_PRI_MOH_STATE_PEND_HOLD";
break;
case SIG_PRI_MOH_STATE_RETRIEVE_FAIL:
str = "SIG_PRI_MOH_STATE_RETRIEVE_FAIL";
break;
#endif /* defined(HAVE_PRI_CALL_HOLD) */
case SIG_PRI_MOH_STATE_NUM:
/* Not a real state. */
break;
}
return str;
}
| static int sig_pri_msn_match | ( | const char * | msn_patterns, |
| const char * | exten | ||
| ) | [static] |
Definition at line 2203 of file sig_pri.c.
References ast_extension_match(), ast_strip(), and ast_strlen_zero().
Referenced by pri_dchannel().
{
char *pattern;
char *msn_list;
char *list_tail;
msn_list = ast_strdupa(msn_patterns);
list_tail = NULL;
pattern = strtok_r(msn_list, ",", &list_tail);
while (pattern) {
pattern = ast_strip(pattern);
if (!ast_strlen_zero(pattern) && ast_extension_match(pattern, exten)) {
/* Extension matched the pattern. */
return 1;
}
pattern = strtok_r(NULL, ",", &list_tail);
}
/* Did not match any pattern in the list. */
return 0;
}
| static void sig_pri_mwi_cache_update | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 8808 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(), sig_pri_mbox::sub, and sig_pri_mbox::vm_number.
Referenced by sig_pri_start_pri().
{
int idx;
int num_messages;
struct ast_event *event;
for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
if (!pri->mbox[idx].sub) {
/* Mailbox slot is empty */
continue;
}
event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, pri->mbox[idx].number,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, pri->mbox[idx].context,
AST_EVENT_IE_END);
if (!event) {
/* No cached event for this mailbox. */
continue;
}
num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
sig_pri_send_mwi_indication(pri, pri->mbox[idx].vm_number, pri->mbox[idx].number,
pri->mbox[idx].context, num_messages);
ast_event_destroy(event);
}
}
| static void sig_pri_mwi_event_cb | ( | const struct ast_event * | event, |
| void * | userdata | ||
| ) | [static] |
Definition at line 8764 of file sig_pri.c.
References ARRAY_LEN, 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_mbox::context, sig_pri_span::mbox, sig_pri_mbox::number, sig_pri_span::pri, sig_pri_send_mwi_indication(), sig_pri_mbox::sub, and sig_pri_mbox::vm_number.
Referenced by sig_pri_start_pri().
{
struct sig_pri_span *pri = userdata;
const char *mbox_context;
const char *mbox_number;
int num_messages;
int idx;
mbox_number = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
if (ast_strlen_zero(mbox_number)) {
return;
}
mbox_context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
if (ast_strlen_zero(mbox_context)) {
return;
}
num_messages = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
for (idx = 0; idx < ARRAY_LEN(pri->mbox); ++idx) {
if (!pri->mbox[idx].sub) {
/* Mailbox slot is empty */
continue;
}
if (!strcmp(pri->mbox[idx].number, mbox_number)
&& !strcmp(pri->mbox[idx].context, mbox_context)) {
/* Found the mailbox. */
sig_pri_send_mwi_indication(pri, pri->mbox[idx].vm_number, mbox_number,
mbox_context, num_messages);
break;
}
}
}
| 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, read] |
Definition at line 967 of file sig_pri.c.
References sig_pri_chan::alreadyhungup, ast_channel_transfercapability_set(), ast_mutex_lock, ast_mutex_unlock, AST_TRANS_CAP_DIGITAL, ast_transfercapability2str(), 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_callbacks, sig_pri_set_digital(), and sig_pri_span_devstate_changed().
Referenced by pri_dchannel(), and sig_pri_request().
{
struct ast_channel *c;
if (sig_pri_callbacks.new_ast_channel) {
c = sig_pri_callbacks.new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor);
} else {
return NULL;
}
if (!c) {
return NULL;
}
if (!p->owner)
p->owner = c;
p->isidlecall = 0;
p->alreadyhungup = 0;
ast_channel_transfercapability_set(c, transfercapability);
pbx_builtin_setvar_helper(c, "TRANSFERCAPABILITY",
ast_transfercapability2str(transfercapability));
if (transfercapability & AST_TRANS_CAP_DIGITAL) {
sig_pri_set_digital(p, 1);
}
if (p->pri) {
ast_mutex_lock(&p->pri->lock);
sig_pri_span_devstate_changed(p->pri);
ast_mutex_unlock(&p->pri->lock);
}
return c;
}
| static void sig_pri_open_media | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 1008 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_chan::no_b_channel, sig_pri_callback::open_media, and sig_pri_callbacks.
Referenced by pri_dchannel(), pri_fixup_principle(), sig_pri_answer(), and sig_pri_dial_complete().
{
if (p->no_b_channel) {
return;
}
if (sig_pri_callbacks.open_media) {
sig_pri_callbacks.open_media(p->chan_pvt);
}
}
| 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 2147 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().
{
if (pri_id->name.valid) {
sig_pri_party_name_convert(&ast_id->name, &pri_id->name);
}
if (pri_id->number.valid) {
sig_pri_party_number_convert(&ast_id->number, &pri_id->number, pri);
}
#if defined(HAVE_PRI_SUBADDR)
if (pri_id->subaddress.valid) {
sig_pri_set_subaddress(&ast_id->subaddress, &pri_id->subaddress);
}
#endif /* defined(HAVE_PRI_SUBADDR) */
}
| 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 885 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().
{
sig_pri_party_name_from_ast(&pri_id->name, &ast_id->name);
sig_pri_party_number_from_ast(&pri_id->number, &ast_id->number);
#if defined(HAVE_PRI_SUBADDR)
sig_pri_party_subaddress_from_ast(&pri_id->subaddress, &ast_id->subaddress);
#endif /* defined(HAVE_PRI_SUBADDR) */
}
| static void sig_pri_party_name_convert | ( | struct ast_party_name * | ast_name, |
| const struct pri_party_name * | pri_name | ||
| ) | [static] |
Definition at line 2099 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().
{
ast_name->str = ast_strdup(pri_name->str);
ast_name->char_set = pri_to_ast_char_set(pri_name->char_set);
ast_name->presentation = pri_to_ast_presentation(pri_name->presentation);
ast_name->valid = 1;
}
| 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 835 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().
{
if (!ast_name->valid) {
return;
}
pri_name->valid = 1;
pri_name->presentation = ast_to_pri_presentation(ast_name->presentation);
pri_name->char_set = ast_to_pri_char_set(ast_name->char_set);
if (!ast_strlen_zero(ast_name->str)) {
ast_copy_string(pri_name->str, ast_name->str, sizeof(pri_name->str));
}
}
| 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 2121 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().
{
char number[AST_MAX_EXTENSION];
apply_plan_to_existing_number(number, sizeof(number), pri, pri_number->str,
pri_number->plan);
ast_number->str = ast_strdup(number);
ast_number->plan = pri_number->plan;
ast_number->presentation = pri_to_ast_presentation(pri_number->presentation);
ast_number->valid = 1;
}
| 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 860 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().
{
if (!ast_number->valid) {
return;
}
pri_number->valid = 1;
pri_number->presentation = ast_to_pri_presentation(ast_number->presentation);
pri_number->plan = ast_number->plan;
if (!ast_strlen_zero(ast_number->str)) {
ast_copy_string(pri_number->str, ast_number->str, sizeof(pri_number->str));
}
}
| 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 789 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().
{
if (ast_subaddress->valid && !ast_strlen_zero(ast_subaddress->str)) {
pri_subaddress->type = ast_subaddress->type;
if (!ast_subaddress->type) {
/* 0 = NSAP */
ast_copy_string((char *) pri_subaddress->data, ast_subaddress->str,
sizeof(pri_subaddress->data));
pri_subaddress->length = strlen((char *) pri_subaddress->data);
pri_subaddress->odd_even_indicator = 0;
pri_subaddress->valid = 1;
} else {
/* 2 = User Specified */
/*
* Copy HexString to packed HexData,
* if odd length then right pad trailing byte with 0
*/
int length = ast_pri_pack_hex_string(pri_subaddress->data,
ast_subaddress->str, sizeof(pri_subaddress->data));
pri_subaddress->length = length; /* packed data length */
length = strlen(ast_subaddress->str);
if (length > 2 * sizeof(pri_subaddress->data)) {
pri_subaddress->odd_even_indicator = 0;
} else {
pri_subaddress->odd_even_indicator = (length & 1);
}
pri_subaddress->valid = 1;
}
}
}
| static int sig_pri_play_tone | ( | struct sig_pri_chan * | p, |
| enum sig_pri_tone | tone | ||
| ) | [static] |
Definition at line 958 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::play_tone, and sig_pri_callbacks.
Referenced by pri_ss_thread(), and sig_pri_indicate().
{
if (sig_pri_callbacks.play_tone) {
return sig_pri_callbacks.play_tone(p->chan_pvt, tone);
} else {
return -1;
}
}
| 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 2177 of file sig_pri.c.
References ast_party_redirecting_set_init(), ast_party_redirecting::count, ast_party_redirecting::from, ast_party_redirecting::orig, ast_party_redirecting::orig_reason, pri_to_ast_reason(), ast_party_redirecting::reason, sig_pri_party_id_convert(), and ast_party_redirecting::to.
Referenced by sig_pri_handle_subcmds().
{
ast_party_redirecting_set_init(ast_redirecting, ast_guide);
sig_pri_party_id_convert(&ast_redirecting->orig, &pri_redirecting->orig_called, pri);
sig_pri_party_id_convert(&ast_redirecting->from, &pri_redirecting->from, pri);
sig_pri_party_id_convert(&ast_redirecting->to, &pri_redirecting->to, pri);
ast_redirecting->count = pri_redirecting->count;
ast_redirecting->reason = pri_to_ast_reason(pri_redirecting->reason);
ast_redirecting->orig_reason = pri_to_ast_reason(pri_redirecting->orig_reason);
}
| static void sig_pri_redirecting_update | ( | struct sig_pri_chan * | pvt, |
| struct ast_channel * | ast | ||
| ) | [static] |
Definition at line 906 of file sig_pri.c.
References ast_channel_redirecting(), ast_channel_redirecting_effective_from(), ast_channel_redirecting_effective_orig(), ast_channel_redirecting_effective_to(), ast_to_pri_reason(), sig_pri_chan::call, ast_party_redirecting::count, ast_party_redirecting::orig_reason, sig_pri_chan::pri, sig_pri_span::pri, ast_party_redirecting::reason, and sig_pri_party_id_from_ast().
Referenced by sig_pri_call(), and sig_pri_indicate().
{
struct pri_party_redirecting pri_redirecting;
const struct ast_party_redirecting *ast_redirecting;
struct ast_party_id redirecting_from = ast_channel_redirecting_effective_from(ast);
struct ast_party_id redirecting_to = ast_channel_redirecting_effective_to(ast);
struct ast_party_id redirecting_orig = ast_channel_redirecting_effective_orig(ast);
memset(&pri_redirecting, 0, sizeof(pri_redirecting));
ast_redirecting = ast_channel_redirecting(ast);
sig_pri_party_id_from_ast(&pri_redirecting.from, &redirecting_from);
sig_pri_party_id_from_ast(&pri_redirecting.to, &redirecting_to);
sig_pri_party_id_from_ast(&pri_redirecting.orig_called, &redirecting_orig);
pri_redirecting.count = ast_redirecting->count;
pri_redirecting.orig_reason = ast_to_pri_reason(ast_redirecting->orig_reason);
pri_redirecting.reason = ast_to_pri_reason(ast_redirecting->reason);
pri_redirecting_update(pvt->pri->pri, pvt->call, &pri_redirecting);
}
| struct ast_channel* sig_pri_request | ( | struct sig_pri_chan * | p, |
| enum sig_pri_law | law, | ||
| const struct ast_channel * | requestor, | ||
| int | transfercapability | ||
| ) | [read] |
Definition at line 1037 of file sig_pri.c.
References ast_debug, AST_STATE_RESERVED, sig_pri_chan::channel, sig_pri_chan::exten, sig_pri_new_ast_channel(), and sig_pri_set_outgoing().
Referenced by dahdi_request(), and pri_dchannel().
{
struct ast_channel *ast;
ast_debug(1, "%s %d\n", __FUNCTION__, p->channel);
sig_pri_set_outgoing(p, 1);
ast = sig_pri_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
if (!ast) {
sig_pri_set_outgoing(p, 0);
}
return ast;
}
| static void sig_pri_send_aoce_termination_request | ( | struct sig_pri_span * | pri, |
| int | chanpos, | ||
| unsigned int | ms | ||
| ) | [static] |
Definition at line 3838 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_name(), ast_channel_setwhentohangup_tv(), ast_channel_unlock, AST_CONTROL_AOC, ast_debug, ast_queue_control_data(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), sig_pri_chan::owner, sig_pri_span::pvts, sig_pri_lock_owner(), and sig_pri_chan::waiting_for_aoce.
Referenced by pri_dchannel().
{
struct sig_pri_chan *pvt;
struct ast_aoc_decoded *decoded = NULL;
struct ast_aoc_encoded *encoded = NULL;
size_t encoded_size;
struct timeval whentohangup = { 0, };
sig_pri_lock_owner(pri, chanpos);
pvt = pri->pvts[chanpos];
if (!pvt->owner) {
return;
}
if (!(decoded = ast_aoc_create(AST_AOC_REQUEST, 0, AST_AOC_REQUEST_E))) {
ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
goto cleanup_termination_request;
}
ast_aoc_set_termination_request(decoded);
if (!(encoded = ast_aoc_encode(decoded, &encoded_size, pvt->owner))) {
ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
goto cleanup_termination_request;
}
/* convert ms to timeval */
whentohangup.tv_usec = (ms % 1000) * 1000;
whentohangup.tv_sec = ms / 1000;
if (ast_queue_control_data(pvt->owner, AST_CONTROL_AOC, encoded, encoded_size)) {
ast_softhangup_nolock(pvt->owner, AST_SOFTHANGUP_DEV);
goto cleanup_termination_request;
}
pvt->waiting_for_aoce = 1;
ast_channel_setwhentohangup_tv(pvt->owner, whentohangup);
ast_debug(1, "Delaying hangup on %s for aoc-e msg\n", ast_channel_name(pvt->owner));
cleanup_termination_request:
ast_channel_unlock(pvt->owner);
ast_aoc_destroy_decoded(decoded);
ast_aoc_destroy_encoded(encoded);
}
| static void sig_pri_send_mwi_indication | ( | struct sig_pri_span * | pri, |
| const char * | vm_number, | ||
| const char * | mbox_number, | ||
| const char * | mbox_context, | ||
| int | num_messages | ||
| ) | [static] |
Definition at line 8720 of file sig_pri.c.
References ast_copy_string(), ast_debug, ast_mutex_lock, ast_mutex_unlock, sig_pri_span::lock, sig_pri_span::pri, and S_OR.
Referenced by sig_pri_mwi_cache_update(), and sig_pri_mwi_event_cb().
{
struct pri_party_id voicemail;
struct pri_party_id mailbox;
ast_debug(1, "Send MWI indication for %s@%s vm_number:%s num_messages:%d\n",
mbox_number, mbox_context, S_OR(vm_number, "<not-present>"), num_messages);
memset(&mailbox, 0, sizeof(mailbox));
mailbox.number.valid = 1;
mailbox.number.presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
mailbox.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_UNKNOWN;
ast_copy_string(mailbox.number.str, mbox_number, sizeof(mailbox.number.str));
memset(&voicemail, 0, sizeof(voicemail));
voicemail.number.valid = 1;
voicemail.number.presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
voicemail.number.plan = (PRI_TON_UNKNOWN << 4) | PRI_NPI_UNKNOWN;
if (vm_number) {
ast_copy_string(voicemail.number.str, vm_number, sizeof(voicemail.number.str));
}
ast_mutex_lock(&pri->lock);
#if defined(HAVE_PRI_MWI_V2)
pri_mwi_indicate_v2(pri->pri, &mailbox, &voicemail, 1 /* speech */, num_messages,
NULL, NULL, -1, 0);
#else /* !defined(HAVE_PRI_MWI_V2) */
pri_mwi_indicate(pri->pri, &mailbox, 1 /* speech */, num_messages, NULL, NULL, -1, 0);
#endif /* !defined(HAVE_PRI_MWI_V2) */
ast_mutex_unlock(&pri->lock);
}
| void sig_pri_sendtext | ( | struct sig_pri_chan * | p, |
| const char * | text | ||
| ) |
Send display text.
| p | Channel to send text over |
| text | Text to send. |
Definition at line 9368 of file sig_pri.c.
References ast_copy_string(), sig_pri_chan::call, sig_pri_chan::pri, sig_pri_span::pri, pri_grab(), and pri_rel().
Referenced by dahdi_sendtext().
| void sig_pri_set_alarm | ( | struct sig_pri_chan * | p, |
| int | in_alarm | ||
| ) |
Definition at line 192 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_chan::inalarm, sig_pri_chan::pri, sig_pri_chan::resetting, sig_pri_callback::set_alarm, sig_pri_callbacks, sig_pri_is_alarm_ignored(), and SIG_PRI_RESET_IDLE.
Referenced by mkintf(), pri_dchannel(), and sig_pri_chan_alarm_notify().
{
if (sig_pri_is_alarm_ignored(p->pri)) {
/* Always set not in alarm */
in_alarm = 0;
}
/*
* Clear the channel restart state when the channel alarm
* changes to prevent the state from getting stuck when the link
* goes down.
*/
p->resetting = SIG_PRI_RESET_IDLE;
p->inalarm = in_alarm;
if (sig_pri_callbacks.set_alarm) {
sig_pri_callbacks.set_alarm(p->chan_pvt, in_alarm);
}
}
| static void sig_pri_set_caller_id | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 267 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::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_name::presentation, ast_party_number::presentation, sig_pri_callback::set_callerid, sig_pri_callbacks, ast_party_name::str, ast_party_number::str, ast_party_subaddress::str, ast_party_id::subaddress, ast_party_id::tag, sig_pri_chan::user_tag, ast_party_name::valid, ast_party_number::valid, and ast_party_subaddress::valid.
Referenced by pri_dchannel(), and sig_pri_handle_subcmds().
{
struct ast_party_caller caller;
if (sig_pri_callbacks.set_callerid) {
ast_party_caller_init(&caller);
caller.id.name.str = p->cid_name;
caller.id.name.presentation = p->callingpres;
caller.id.name.valid = 1;
caller.id.number.str = p->cid_num;
caller.id.number.plan = p->cid_ton;
caller.id.number.presentation = p->callingpres;
caller.id.number.valid = 1;
if (!ast_strlen_zero(p->cid_subaddr)) {
caller.id.subaddress.valid = 1;
//caller.id.subaddress.type = 0;/* nsap */
//caller.id.subaddress.odd_even_indicator = 0;
caller.id.subaddress.str = p->cid_subaddr;
}
caller.id.tag = p->user_tag;
caller.ani.number.str = p->cid_ani;
//caller.ani.number.plan = p->xxx;
//caller.ani.number.presentation = p->xxx;
caller.ani.number.valid = 1;
caller.ani2 = p->cid_ani2;
sig_pri_callbacks.set_callerid(p->chan_pvt, &caller);
}
}
| static void sig_pri_set_dialing | ( | struct sig_pri_chan * | p, |
| int | is_dialing | ||
| ) | [static] |
Definition at line 169 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::set_dialing, and sig_pri_callbacks.
Referenced by pri_dchannel(), sig_pri_answer(), sig_pri_call(), sig_pri_dial_complete(), sig_pri_hangup(), and sig_pri_indicate().
{
if (sig_pri_callbacks.set_dialing) {
sig_pri_callbacks.set_dialing(p->chan_pvt, is_dialing);
}
}
| static void sig_pri_set_digital | ( | struct sig_pri_chan * | p, |
| int | is_digital | ||
| ) | [static] |
Definition at line 176 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_chan::digital, sig_pri_callback::set_digital, and sig_pri_callbacks.
Referenced by sig_pri_call(), sig_pri_hangup(), sig_pri_indicate(), and sig_pri_new_ast_channel().
{
p->digital = is_digital;
if (sig_pri_callbacks.set_digital) {
sig_pri_callbacks.set_digital(p->chan_pvt, is_digital);
}
}
| static void sig_pri_set_dnid | ( | struct sig_pri_chan * | p, |
| const char * | dnid | ||
| ) | [static] |
Definition at line 311 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::set_dnid, and sig_pri_callbacks.
Referenced by pri_dchannel().
{
if (sig_pri_callbacks.set_dnid) {
sig_pri_callbacks.set_dnid(p->chan_pvt, dnid);
}
}
| static int sig_pri_set_echocanceller | ( | struct sig_pri_chan * | p, |
| int | enable | ||
| ) | [static] |
Definition at line 942 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::set_echocanceller, and sig_pri_callbacks.
Referenced by pri_dchannel(), pri_ss_thread(), and sig_pri_dial_complete().
{
if (sig_pri_callbacks.set_echocanceller) {
return sig_pri_callbacks.set_echocanceller(p->chan_pvt, enable);
} else {
return -1;
}
}
| static void sig_pri_set_outgoing | ( | struct sig_pri_chan * | p, |
| int | is_outgoing | ||
| ) | [static] |
Definition at line 184 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_chan::outgoing, sig_pri_callback::set_outgoing, and sig_pri_callbacks.
Referenced by sig_pri_call(), sig_pri_hangup(), and sig_pri_request().
{
p->outgoing = is_outgoing;
if (sig_pri_callbacks.set_outgoing) {
sig_pri_callbacks.set_outgoing(p->chan_pvt, is_outgoing);
}
}
| static void sig_pri_set_rdnis | ( | struct sig_pri_chan * | p, |
| const char * | rdnis | ||
| ) | [static] |
Definition at line 328 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callback::set_rdnis, and sig_pri_callbacks.
Referenced by pri_dchannel().
{
if (sig_pri_callbacks.set_rdnis) {
sig_pri_callbacks.set_rdnis(p->chan_pvt, rdnis);
}
}
| static void sig_pri_set_subaddress | ( | struct ast_party_subaddress * | ast_subaddress, |
| const struct pri_party_subaddress * | pri_subaddress | ||
| ) | [static] |
Definition at line 666 of file sig_pri.c.
References ast_free, ast_malloc, ast_party_subaddress_init(), ast_strdup, len(), ast_party_subaddress::odd_even_indicator, ast_party_subaddress::str, ast_party_subaddress::type, and ast_party_subaddress::valid.
Referenced by pri_dchannel(), and sig_pri_party_id_convert().
{
ast_free(ast_subaddress->str);
if (pri_subaddress->length <= 0) {
ast_party_subaddress_init(ast_subaddress);
return;
}
if (!pri_subaddress->type) {
/* NSAP */
ast_subaddress->str = ast_strdup((char *) pri_subaddress->data);
} else {
char *cnum;
char *ptr;
int x;
int len;
/* User Specified */
cnum = ast_malloc(2 * pri_subaddress->length + 1);
if (!cnum) {
ast_party_subaddress_init(ast_subaddress);
return;
}
ptr = cnum;
len = pri_subaddress->length - 1; /* -1 account for zero based indexing */
for (x = 0; x < len; ++x) {
ptr += sprintf(ptr, "%02x", pri_subaddress->data[x]);
}
if (pri_subaddress->odd_even_indicator) {
/* ODD */
sprintf(ptr, "%01x", (pri_subaddress->data[len]) >> 4);
} else {
/* EVEN */
sprintf(ptr, "%02x", pri_subaddress->data[len]);
}
ast_subaddress->str = cnum;
}
ast_subaddress->type = pri_subaddress->type;
ast_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
ast_subaddress->valid = 1;
}
| static void sig_pri_sort_pri_chans | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 8904 of file sig_pri.c.
References sig_pri_span::numchans, sig_pri_span::pvts, and sig_pri_cmp_pri_chans().
Referenced by sig_pri_start_pri().
{
qsort(&pri->pvts, pri->numchans, sizeof(pri->pvts[0]), sig_pri_cmp_pri_chans);
}
| static void sig_pri_span_devstate_changed | ( | struct sig_pri_span * | pri | ) | [static] |
Definition at line 251 of file sig_pri.c.
References sig_pri_callbacks, 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_hold_ack(), sig_pri_handle_retrieve(), sig_pri_handle_retrieve_ack(), sig_pri_hangup(), sig_pri_kill_call(), and sig_pri_new_ast_channel().
{
if (sig_pri_callbacks.update_span_devstate) {
sig_pri_callbacks.update_span_devstate(pri);
}
}
| int sig_pri_start_pri | ( | struct sig_pri_span * | pri | ) |
Definition at line 8909 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_pthread_create_background, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strip(), ast_strlen_zero(), sig_pri_span::cc_ptmp_recall_mode, sig_pri_span::cc_qsig_signaling_link_req, sig_pri_span::cc_qsig_signaling_link_rsp, sig_pri_mbox::context, DAHDI_CHAN_MAPPING_LOGICAL, DAHDI_OVERLAPDIAL_OUTGOING, sig_pri_span::datetime_send, sig_pri_span::dchans, sig_pri_span::display_flags_receive, sig_pri_span::display_flags_send, sig_pri_span::enable_service_message_support, errno, sig_pri_span::fds, sig_pri_span::inbanddisconnect, sig_pri_span::l2_persistence, sig_pri_span::lock, LOG_ERROR, LOG_WARNING, sig_pri_span::master, sig_pri_span::mbox, sig_pri_span::mwi_mailboxes, sig_pri_span::mwi_vm_numbers, sig_pri_span::nodetype, sig_pri_span::nsf, sig_pri_mbox::number, sig_pri_span::overlapdial, sig_pri_span::pri, pri_dchannel(), sig_pri_span::pritimers, sig_pri_span::qsigchannelmapping, sig_pri_span::resetpos, sig_pri_span::sig, SIG_BRI, SIG_BRI_PTMP, sig_pri_cc_type_name, SIG_PRI_DEBUG_DEFAULT, sig_pri_mwi_cache_update(), sig_pri_mwi_event_cb(), SIG_PRI_NUM_DCHANS, sig_pri_sort_pri_chans(), sig_pri_span::span, sig_pri_mbox::sub, sig_pri_span::switchtype, and sig_pri_mbox::vm_number.
Referenced by setup_dahdi_int().
{
int x;
int i;
#if defined(HAVE_PRI_MWI)
char *saveptr;
char *prev_vm_number;
struct ast_str *mwi_description = ast_str_alloca(64);
#endif /* defined(HAVE_PRI_MWI) */
#if defined(HAVE_PRI_MWI)
/* Prepare the mbox[] for use. */
for (i = 0; i < ARRAY_LEN(pri->mbox); ++i) {
if (pri->mbox[i].sub) {
pri->mbox[i].sub = ast_event_unsubscribe(pri->mbox[i].sub);
}
}
#endif /* defined(HAVE_PRI_MWI) */
ast_mutex_init(&pri->lock);
sig_pri_sort_pri_chans(pri);
#if defined(HAVE_PRI_MWI)
/*
* Split the mwi_vm_numbers configuration string into the mbox[].vm_number:
* vm_number{,vm_number}
*/
prev_vm_number = NULL;
saveptr = pri->mwi_vm_numbers;
for (i = 0; i < ARRAY_LEN(pri->mbox); ++i) {
char *vm_number;
vm_number = strsep(&saveptr, ",");
if (vm_number) {
vm_number = ast_strip(vm_number);
}
if (ast_strlen_zero(vm_number)) {
/* There was no number so reuse the previous number. */
vm_number = prev_vm_number;
} else {
/* We have a new number. */
prev_vm_number = vm_number;
}
pri->mbox[i].vm_number = vm_number;
}
/*
* Split the mwi_mailboxes configuration string into the mbox[]:
* mailbox_number[@context]{,mailbox_number[@context]}
*/
saveptr = pri->mwi_mailboxes;
for (i = 0; i < ARRAY_LEN(pri->mbox); ++i) {
char *mbox_number;
char *mbox_context;
mbox_number = strsep(&saveptr, ",");
if (!mbox_number) {
/* No more defined mailboxes. */
break;
}
/* Split the mailbox_number and context */
mbox_context = strchr(mbox_number, '@');
if (mbox_context) {
*mbox_context++ = '\0';
mbox_context = ast_strip(mbox_context);
}
mbox_number = ast_strip(mbox_number);
if (ast_strlen_zero(mbox_number)) {
/* There is no mailbox number. Skip it. */
continue;
}
if (ast_strlen_zero(mbox_context)) {
/* There was no context so use the default. */
mbox_context = "default";
}
/* Fill the mbox[] element. */
pri->mbox[i].number = mbox_number;
pri->mbox[i].context = mbox_context;
ast_str_set(&mwi_description, -1, "%s span %d[%d] MWI mailbox %s@%s",
sig_pri_cc_type_name, pri->span, i, mbox_number, mbox_context);
pri->mbox[i].sub = ast_event_subscribe(AST_EVENT_MWI, sig_pri_mwi_event_cb,
ast_str_buffer(mwi_description), pri,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox_number,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, mbox_context,
AST_EVENT_IE_END);
if (!pri->mbox[i].sub) {
ast_log(LOG_ERROR, "%s span %d could not subscribe to MWI events for %s@%s.",
sig_pri_cc_type_name, pri->span, mbox_number, mbox_context);
}
#if defined(HAVE_PRI_MWI_V2)
if (ast_strlen_zero(pri->mbox[i].vm_number)) {
ast_log(LOG_WARNING, "%s span %d MWI voicemail number for %s@%s is empty.\n",
sig_pri_cc_type_name, pri->span, mbox_number, mbox_context);
}
#endif /* defined(HAVE_PRI_MWI_V2) */
}
#endif /* defined(HAVE_PRI_MWI) */
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
if (pri->fds[i] == -1) {
break;
}
switch (pri->sig) {
case SIG_BRI:
pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
break;
case SIG_BRI_PTMP:
pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
break;
default:
pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
#if defined(HAVE_PRI_SERVICE_MESSAGES)
if (pri->enable_service_message_support) {
pri_set_service_message_support(pri->dchans[i], 1);
}
#endif /* defined(HAVE_PRI_SERVICE_MESSAGES) */
break;
}
pri_set_overlapdial(pri->dchans[i], (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING) ? 1 : 0);
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
#endif
#ifdef HAVE_PRI_INBANDDISCONNECT
pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
#endif
/* Enslave to master if appropriate */
if (i)
pri_enslave(pri->dchans[0], pri->dchans[i]);
if (!pri->dchans[i]) {
if (pri->fds[i] > 0)
close(pri->fds[i]);
pri->fds[i] = -1;
ast_log(LOG_ERROR, "Unable to create PRI structure\n");
return -1;
}
pri_set_debug(pri->dchans[i], SIG_PRI_DEBUG_DEFAULT);
pri_set_nsf(pri->dchans[i], pri->nsf);
#ifdef PRI_GETSET_TIMERS
for (x = 0; x < PRI_MAX_TIMERS; x++) {
if (pri->pritimers[x] != 0)
pri_set_timer(pri->dchans[i], x, pri->pritimers[x]);
}
#endif
}
/* Assume primary is the one we use */
pri->pri = pri->dchans[0];
#if defined(HAVE_PRI_CALL_HOLD)
pri_hold_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_CALL_HOLD) */
#if defined(HAVE_PRI_CALL_REROUTING)
pri_reroute_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_CALL_REROUTING) */
#if defined(HAVE_PRI_HANGUP_FIX)
pri_hangup_fix_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_HANGUP_FIX) */
#if defined(HAVE_PRI_CCSS)
pri_cc_enable(pri->pri, 1);
pri_cc_recall_mode(pri->pri, pri->cc_ptmp_recall_mode);
pri_cc_retain_signaling_req(pri->pri, pri->cc_qsig_signaling_link_req);
pri_cc_retain_signaling_rsp(pri->pri, pri->cc_qsig_signaling_link_rsp);
#endif /* defined(HAVE_PRI_CCSS) */
#if defined(HAVE_PRI_TRANSFER)
pri_transfer_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_TRANSFER) */
#if defined(HAVE_PRI_AOC_EVENTS)
pri_aoc_events_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_AOC_EVENTS) */
#if defined(HAVE_PRI_CALL_WAITING)
pri_connect_ack_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_CALL_WAITING) */
#if defined(HAVE_PRI_MCID)
pri_mcid_enable(pri->pri, 1);
#endif /* defined(HAVE_PRI_MCID) */
#if defined(HAVE_PRI_DISPLAY_TEXT)
pri_display_options_send(pri->pri, pri->display_flags_send);
pri_display_options_receive(pri->pri, pri->display_flags_receive);
#endif /* defined(HAVE_PRI_DISPLAY_TEXT) */
#if defined(HAVE_PRI_DATETIME_SEND)
pri_date_time_send_option(pri->pri, pri->datetime_send);
#endif /* defined(HAVE_PRI_DATETIME_SEND) */
#if defined(HAVE_PRI_L2_PERSISTENCE)
pri_persistent_layer2_option(pri->pri, pri->l2_persistence);
#endif /* defined(HAVE_PRI_L2_PERSISTENCE) */
pri->resetpos = -1;
if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
if (!pri->dchans[i])
break;
if (pri->fds[i] > 0)
close(pri->fds[i]);
pri->fds[i] = -1;
}
ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
return -1;
}
#if defined(HAVE_PRI_MWI)
/*
* Send the initial MWI indications from the event cache for this span.
*
* If we were loaded after app_voicemail the event would already be in
* the cache. If we were loaded before app_voicemail the event would not
* be in the cache yet and app_voicemail will send the event when it
* gets loaded.
*/
sig_pri_mwi_cache_update(pri);
#endif /* defined(HAVE_PRI_MWI) */
return 0;
}
| void sig_pri_stop_pri | ( | struct sig_pri_span * | pri | ) |
Stop PRI span.
| pri | PRI span control structure. |
Definition at line 8844 of file sig_pri.c.
References ARRAY_LEN, ast_event_unsubscribe(), sig_pri_span::mbox, and sig_pri_mbox::sub.
Referenced by __unload_module().
| static void sig_pri_transfer_rsp | ( | void * | data, |
| int | is_successful | ||
| ) | [static] |
Definition at line 2371 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().
{
struct xfer_rsp_data *rsp = data;
pri_transfer_rsp(rsp->pri->pri, rsp->call, rsp->invoke_id, is_successful);
}
| void sig_pri_unload | ( | void | ) |
Unload the sig_pri submodule.
Definition at line 10007 of file sig_pri.c.
References ao2_ref.
Referenced by __unload_module().
{
#if defined(HAVE_PRI_CCSS)
if (sig_pri_cc_monitors) {
ao2_ref(sig_pri_cc_monitors, -1);
sig_pri_cc_monitors = NULL;
}
#endif /* defined(HAVE_PRI_CCSS) */
}
| static void sig_pri_unlock_private | ( | struct sig_pri_chan * | p | ) | [static] |
Definition at line 335 of file sig_pri.c.
References sig_pri_chan::chan_pvt, sig_pri_callbacks, 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_deadlock_avoidance_private(), sig_pri_handle_hold(), sig_pri_handle_hold_ack(), sig_pri_handle_hold_rej(), sig_pri_handle_retrieve(), sig_pri_handle_retrieve_ack(), sig_pri_handle_retrieve_rej(), sig_pri_handle_subcmds(), sig_pri_kill_call(), and sig_pri_lock_owner().
{
if (sig_pri_callbacks.unlock_private) {
sig_pri_callbacks.unlock_private(p->chan_pvt);
}
}
int pri_gendigittimeout = 8000 [static] |
Definition at line 110 of file sig_pri.c.
Referenced by pri_ss_thread().
int pri_matchdigittimeout = 3000 [static] |
Definition at line 108 of file sig_pri.c.
Referenced by pri_ss_thread().
struct ast_app_option sig_pri_call_opts[128] = { [ 'K' ] = { .flag = OPT_KEYPAD , .arg_index = OPT_ARG_KEYPAD + 1 }, [ 'R' ] = { .flag = OPT_REVERSE_CHARGE }, [ 'A' ] = { .flag = OPT_AOC_REQUEST , .arg_index = OPT_ARG_AOC_REQUEST + 1 }, } [static] |
Definition at line 7735 of file sig_pri.c.
Referenced by sig_pri_call().
struct ao2_container* sig_pri_cc_monitors [static] |
const char* sig_pri_cc_type_name [static] |
Upper level agent/monitor type name.
Definition at line 103 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().
const sig_pri_moh_fsm_state sig_pri_moh_fsm[SIG_PRI_MOH_STATE_NUM] [static] |
MOH FSM state table.
Definition at line 5123 of file sig_pri.c.
Referenced by sig_pri_moh_fsm_event().