the chan_misdn channel driver for Asterisk More...
#include "asterisk.h"#include <pthread.h>#include <sys/socket.h>#include <sys/time.h>#include <arpa/inet.h>#include <fcntl.h>#include <sys/ioctl.h>#include <signal.h>#include <sys/file.h>#include <semaphore.h>#include <ctype.h>#include <time.h>#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/module.h"#include "asterisk/pbx.h"#include "asterisk/io.h"#include "asterisk/frame.h"#include "asterisk/translate.h"#include "asterisk/cli.h"#include "asterisk/musiconhold.h"#include "asterisk/dsp.h"#include "asterisk/file.h"#include "asterisk/callerid.h"#include "asterisk/indications.h"#include "asterisk/app.h"#include "asterisk/features.h"#include "asterisk/term.h"#include "asterisk/sched.h"#include "asterisk/stringfields.h"#include "asterisk/abstract_jb.h"#include "asterisk/causes.h"#include "asterisk/format.h"#include "asterisk/format_cap.h"#include "chan_misdn_config.h"#include "isdn_lib.h"#include "asterisk/strings.h"
Go to the source code of this file.
Data Structures | |
| struct | allowed_bearers |
| struct | chan_list |
| Channel call record structure. More... | |
| struct | hold_info |
| struct | misdn_jb |
| struct | robin_list |
| struct | state_struct |
Defines | |
| #define | chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj)) |
| #define | chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL) |
| #define | MISDN_ASTERISK_TECH_PVT(ast) ast_channel_tech_pvt(ast) |
| #define | MISDN_ASTERISK_TECH_PVT_SET(ast, value) ast_channel_tech_pvt_set(ast, value) |
| #define | ORG_AST 1 |
| #define | ORG_MISDN 2 |
| #define | TRANSFER_ON_HELD_CALL_HANGUP 1 |
Enumerations | |
| enum | misdn_chan_state { MISDN_NOTHING = 0, MISDN_WAITING4DIGS, MISDN_EXTCANTMATCH, MISDN_INCOMING_SETUP, MISDN_DIALING, MISDN_PROGRESS, MISDN_PROCEEDING, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, MISDN_ALERTING, MISDN_BUSY, MISDN_CONNECTED, MISDN_DISCONNECTED, MISDN_CLEANING } |
| enum | misdn_hold_state { MISDN_HOLD_IDLE, MISDN_HOLD_ACTIVE, MISDN_HOLD_TRANSFER, MISDN_HOLD_DISCONNECT } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable) |
| int | add_in_calls (int port) |
| int | add_out_calls (int port) |
| static enum mISDN_NUMBER_PLAN | ast_to_misdn_plan (unsigned ast_number_plan) |
| static int | ast_to_misdn_pres (int presentation) |
| static enum mISDN_REDIRECTING_REASON | ast_to_misdn_reason (const enum AST_REDIRECTING_REASON ast) |
| static int | ast_to_misdn_screen (int screening) |
| static enum mISDN_NUMBER_TYPE | ast_to_misdn_ton (unsigned ast_number_type) |
| static const char * | bearer2str (int cap) |
| static enum event_response_e | cb_events (enum event_e event, struct misdn_bchannel *bc, void *user_data) |
| static void | chan_list_destructor (void *obj) |
| static struct chan_list * | chan_list_init (int orig) |
| int | chan_misdn_jb_empty (struct misdn_bchannel *bc, char *buf, int len) |
| static void | chan_misdn_log (int level, int port, char *tmpl,...) |
| static int | cl_dequeue_chan (struct chan_list *chan) |
| static void | cl_queue_chan (struct chan_list *chan) |
| static char * | complete_ch (struct ast_cli_args *a) |
| static char * | complete_debug_port (struct ast_cli_args *a) |
| static char * | complete_show_config (struct ast_cli_args *a) |
| static void | config_jitterbuffer (struct chan_list *ch) |
| void | debug_numtype (int port, int numtype, char *type) |
| static int | dialtone_indicate (struct chan_list *cl) |
| static void | do_immediate_setup (struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast) |
| static void | export_aoc_vars (int originator, struct ast_channel *ast, struct misdn_bchannel *bc) |
| void | export_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch) |
| Export parameters to the dialplan environment variables. | |
| static struct chan_list * | find_chan_by_bc (struct misdn_bchannel *bc) |
| static struct chan_list * | find_hold_active_call (struct misdn_bchannel *bc) |
| static struct chan_list * | find_hold_call (struct misdn_bchannel *bc) |
| static struct chan_list * | find_hold_call_l3 (unsigned long l3_id) |
| static void | free_robin_list (void) |
| static struct chan_list * | get_chan_by_ast (struct ast_channel *ast) |
| static struct chan_list * | get_chan_by_ast_name (const char *name) |
| static struct robin_list * | get_robin_position (char *group) |
| static char * | handle_cli_misdn_port_block (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_port_down (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_port_unblock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_port_up (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_restart_pid (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_restart_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_send_digit (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_send_display (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_send_facility (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_send_restart (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_set_crypt_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_set_tics (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_show_config (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_show_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_show_ports_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_show_stacks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_misdn_toggle_echocancel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static void | hangup_chan (struct chan_list *ch, struct misdn_bchannel *bc) |
| static void | hanguptone_indicate (struct chan_list *cl) |
| void | import_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch) |
| Import parameters from the dialplan environment variables. | |
| static int | load_module (void) |
| static void | misdn_add_number_prefix (int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size) |
| static int | misdn_answer (struct ast_channel *ast) |
| static int | misdn_attempt_transfer (struct chan_list *active_ch, struct chan_list *held_ch) |
| static enum ast_bridge_result | misdn_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms) |
| static int | misdn_call (struct ast_channel *ast, const char *dest, int timeout) |
| static int | misdn_chan_is_valid (struct chan_list *ch) |
| static int | misdn_check_l2l1 (struct ast_channel *chan, const char *data) |
| static void | misdn_copy_redirecting_from_ast (struct misdn_bchannel *bc, struct ast_channel *ast) |
| static void | misdn_copy_redirecting_to_ast (struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag) |
| static int | misdn_digit_begin (struct ast_channel *chan, char digit) |
| static int | misdn_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
| static int | misdn_facility_exec (struct ast_channel *chan, const char *data) |
| static void | misdn_facility_ie_handler (enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch) |
| static int | misdn_fixup (struct ast_channel *oldast, struct ast_channel *ast) |
| static const char * | misdn_get_ch_state (struct chan_list *p) |
| static void | misdn_get_connected_line (struct ast_channel *ast, struct misdn_bchannel *bc, int originator) |
| static int | misdn_hangup (struct ast_channel *ast) |
| static int | misdn_indication (struct ast_channel *ast, int cond, const void *data, size_t datalen) |
| static int | misdn_is_msn_valid (int port, const struct misdn_party_dialing *dialed) |
| void | misdn_jb_destroy (struct misdn_jb *jb) |
| frees the data and destroys the given jitterbuffer struct | |
| int | misdn_jb_empty (struct misdn_jb *jb, char *data, int len) |
| gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data. | |
| int | misdn_jb_fill (struct misdn_jb *jb, const char *data, int len) |
| fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun). | |
| struct misdn_jb * | misdn_jb_init (int size, int upper_threshold) |
| allocates the jb-structure and initialize the elements | |
| static int | misdn_l1_task (const void *vdata) |
| static struct ast_channel * | misdn_new (struct chan_list *cl, int state, char *exten, char *callerid, struct ast_format_cap *cap, const char *linkedid, int port, int c) |
| static int | misdn_overlap_dial_task (const void *data) |
| static void | misdn_prefix_string (const char *str_prefix, char *str_main, size_t size) |
| static void | misdn_queue_connected_line_update (struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag) |
| static struct ast_frame * | misdn_read (struct ast_channel *ast) |
| static struct ast_channel * | misdn_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause) |
| static int | misdn_send_text (struct ast_channel *chan, const char *text) |
| static int | misdn_set_opt_exec (struct ast_channel *chan, const char *data) |
| static int | misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data) |
| static int | misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data) |
| static void | misdn_tasks_destroy (void) |
| static void | misdn_tasks_init (void) |
| static void | misdn_tasks_remove (int task_id) |
| static void * | misdn_tasks_thread_func (void *data) |
| static void | misdn_tasks_wakeup (void) |
| static int | misdn_to_ast_plan (enum mISDN_NUMBER_PLAN number_plan) |
| static int | misdn_to_ast_pres (int presentation) |
| static enum AST_REDIRECTING_REASON | misdn_to_ast_reason (const enum mISDN_REDIRECTING_REASON q931) |
| static int | misdn_to_ast_screen (int screening) |
| static int | misdn_to_ast_ton (enum mISDN_NUMBER_TYPE number_type) |
| static const char * | misdn_to_str_plan (enum mISDN_NUMBER_PLAN number_plan) |
| static const char * | misdn_to_str_pres (int presentation) |
| static const char * | misdn_to_str_screen (int screening) |
| static const char * | misdn_to_str_ton (enum mISDN_NUMBER_TYPE number_type) |
| static void | misdn_update_caller_id (struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag) |
| static void | misdn_update_connected_line (struct ast_channel *ast, struct misdn_bchannel *bc, int originator) |
| static void | misdn_update_redirecting (struct ast_channel *ast, struct misdn_bchannel *bc, int originator) |
| static void | misdn_update_remote_party (struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag) |
| static int | misdn_write (struct ast_channel *ast, struct ast_frame *frame) |
| static int | pbx_start_chan (struct chan_list *ch) |
| static void | print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc) |
| static void | print_bearer (struct misdn_bchannel *bc) |
| static void | print_facility (const struct FacParm *fac, const struct misdn_bchannel *bc) |
| static struct ast_frame * | process_ast_dsp (struct chan_list *tmp, struct ast_frame *frame) |
| static int | read_config (struct chan_list *ch) |
| static void | release_chan (struct chan_list *ch, struct misdn_bchannel *bc) |
| static void | release_chan_early (struct chan_list *ch) |
| static int | reload (void) |
| static void | reload_config (void) |
| static int | send_cause2ast (struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) |
| static void | send_digit_to_chan (struct chan_list *cl, char digit) |
| static void | show_config_description (int fd, enum misdn_cfg_elements elem) |
| static void | sighandler (int sig) |
| static int | start_bc_tones (struct chan_list *cl) |
| static void | start_pbx (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) |
| static int | stop_bc_tones (struct chan_list *cl) |
| static int | stop_indicate (struct chan_list *cl) |
| static int | unload_module (void) |
| static void | update_config (struct chan_list *ch) |
| Updates caller ID information from config. | |
| static int | update_ec_config (struct misdn_bchannel *bc) |
| static void | update_name (struct ast_channel *tmp, int port, int c) |
| static void | wait_for_digits (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Channel driver for mISDN Support (BRI/PRI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } |
| static struct allowed_bearers | allowed_bearers_array [] |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_cli_entry | chan_misdn_clis [] |
| static struct chan_list * | cl_te = NULL |
| Global channel call record list head. | |
| static ast_mutex_t | cl_te_lock |
| static int | g_config_initialized = 0 |
| static int | glob_channel = 0 |
| static char | global_tracefile [BUFFERSIZE+1] |
| static int | max_ports |
| int | MAXTICS = 8 |
| static int * | misdn_debug |
| static int * | misdn_debug_only |
| static int * | misdn_in_calls |
| static int * | misdn_out_calls |
| static int * | misdn_ports |
| static struct ast_sched_context * | misdn_tasks = NULL |
| the main schedule context for stuff like l1 watcher, overlap dial, ... | |
| static pthread_t | misdn_tasks_thread |
| static struct ast_channel_tech | misdn_tech |
| static struct ast_channel_tech | misdn_tech_wo_bridge |
| static const char | misdn_type [] = "mISDN" |
| static struct ast_format | prefformat |
| Only alaw and mulaw is allowed for now. | |
| static ast_mutex_t | release_lock |
| static struct robin_list * | robin = NULL |
| static struct state_struct | state_array [] |
| static int | tracing = 0 |
the chan_misdn channel driver for Asterisk
Definition in file chan_misdn.c.
| #define chan_list_ref | ( | obj, | |
| debug | |||
| ) | (ao2_t_ref((obj), +1, (debug)), (obj)) |
Definition at line 346 of file chan_misdn.c.
Referenced by cl_queue_chan(), find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), get_chan_by_ast(), get_chan_by_ast_name(), and misdn_new().
| #define chan_list_unref | ( | obj, | |
| debug | |||
| ) | (ao2_t_ref((obj), -1, (debug)), NULL) |
Definition at line 347 of file chan_misdn.c.
Referenced by cb_events(), chan_misdn_jb_empty(), cl_dequeue_chan(), handle_cli_misdn_send_digit(), handle_cli_misdn_send_display(), handle_cli_misdn_send_facility(), handle_cli_misdn_toggle_echocancel(), misdn_bridge(), misdn_hangup(), misdn_request(), release_chan(), and release_chan_early().
| #define MISDN_ASTERISK_TECH_PVT | ( | ast | ) | ast_channel_tech_pvt(ast) |
Definition at line 658 of file chan_misdn.c.
Referenced by cb_events(), do_immediate_setup(), misdn_answer(), misdn_call(), misdn_digit_end(), misdn_facility_exec(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_read(), misdn_send_text(), misdn_set_opt_exec(), misdn_update_connected_line(), misdn_write(), release_chan(), and release_chan_early().
| #define MISDN_ASTERISK_TECH_PVT_SET | ( | ast, | |
| value | |||
| ) | ast_channel_tech_pvt_set(ast, value) |
Definition at line 659 of file chan_misdn.c.
Referenced by misdn_hangup(), misdn_new(), release_chan(), and release_chan_early().
| #define ORG_AST 1 |
Asterisk created the channel (outgoing call)
Definition at line 318 of file chan_misdn.c.
Referenced by cb_events(), export_aoc_vars(), misdn_hangup(), misdn_request(), print_bc_info(), read_config(), release_chan(), and release_chan_early().
| #define ORG_MISDN 2 |
mISDN created the channel (incoming call)
Definition at line 320 of file chan_misdn.c.
Referenced by cb_events(), misdn_get_connected_line(), misdn_indication(), misdn_update_connected_line(), and misdn_update_redirecting().
| #define TRANSFER_ON_HELD_CALL_HANGUP 1 |
Definition at line 8298 of file chan_misdn.c.
| enum misdn_chan_state |
Definition at line 300 of file chan_misdn.c.
{
MISDN_NOTHING = 0, /*!< at beginning */
MISDN_WAITING4DIGS, /*!< when waiting for info */
MISDN_EXTCANTMATCH, /*!< when asterisk couldn't match our ext */
MISDN_INCOMING_SETUP, /*!< for incoming setup */
MISDN_DIALING, /*!< when pbx_start */
MISDN_PROGRESS, /*!< we have progress */
MISDN_PROCEEDING, /*!< we have progress */
MISDN_CALLING, /*!< when misdn_call is called */
MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
MISDN_ALERTING, /*!< when Alerting */
MISDN_BUSY, /*!< when BUSY */
MISDN_CONNECTED, /*!< when connected */
MISDN_DISCONNECTED, /*!< when connected */
MISDN_CLEANING, /*!< when hangup from * but we were connected before */
};
| enum misdn_hold_state |
| MISDN_HOLD_IDLE |
HOLD not active |
| MISDN_HOLD_ACTIVE |
Call is held |
| MISDN_HOLD_TRANSFER |
Held call is being transferred |
| MISDN_HOLD_DISCONNECT |
Held call is being disconnected |
Definition at line 322 of file chan_misdn.c.
{
MISDN_HOLD_IDLE, /*!< HOLD not active */
MISDN_HOLD_ACTIVE, /*!< Call is held */
MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
MISDN_HOLD_DISCONNECT, /*!< Held call is being disconnected */
};
| static void __reg_module | ( | void | ) | [static] |
Definition at line 12803 of file chan_misdn.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 12803 of file chan_misdn.c.
| static int _misdn_tasks_add_variable | ( | int | timeout, |
| ast_sched_cb | callback, | ||
| const void * | data, | ||
| int | variable | ||
| ) | [inline, static] |
Definition at line 3564 of file chan_misdn.c.
References ast_sched_add_variable(), misdn_tasks_init(), and misdn_tasks_wakeup().
Referenced by misdn_tasks_add(), and misdn_tasks_add_variable().
{
int task_id;
if (!misdn_tasks) {
misdn_tasks_init();
}
task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
misdn_tasks_wakeup();
return task_id;
}
| int add_in_calls | ( | int | port | ) |
Definition at line 8844 of file chan_misdn.c.
References ast_log(), LOG_NOTICE, misdn_cfg_get(), and MISDN_CFG_MAX_IN.
Referenced by cb_events().
{
int max_in_calls;
misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
misdn_in_calls[port]++;
if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
return misdn_in_calls[port] - max_in_calls;
}
return 0;
}
| int add_out_calls | ( | int | port | ) |
Definition at line 8859 of file chan_misdn.c.
References ast_log(), LOG_NOTICE, misdn_cfg_get(), and MISDN_CFG_MAX_OUT.
Referenced by misdn_call().
{
int max_out_calls;
misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
return (misdn_out_calls[port] + 1) - max_out_calls;
}
misdn_out_calls[port]++;
return 0;
}
| static enum mISDN_NUMBER_PLAN ast_to_misdn_plan | ( | unsigned | ast_number_plan | ) | [static] |
Definition at line 2018 of file chan_misdn.c.
References NUMPLAN_DATA, NUMPLAN_ISDN, NUMPLAN_NATIONAL, NUMPLAN_PRIVATE, NUMPLAN_TELEX, and NUMPLAN_UNKNOWN.
Referenced by misdn_call(), misdn_copy_redirecting_from_ast(), and misdn_get_connected_line().
{
enum mISDN_NUMBER_PLAN number_plan;
switch (ast_number_plan & 0x0F) {
default:
case NUMPLAN_UNKNOWN:
number_plan = NUMPLAN_UNKNOWN;
break;
case NUMPLAN_ISDN:
number_plan = NUMPLAN_ISDN;
break;
case NUMPLAN_DATA:
number_plan = NUMPLAN_DATA;
break;
case NUMPLAN_TELEX:
number_plan = NUMPLAN_TELEX;
break;
case NUMPLAN_NATIONAL:
number_plan = NUMPLAN_NATIONAL;
break;
case NUMPLAN_PRIVATE:
number_plan = NUMPLAN_PRIVATE;
break;
}
return number_plan;
}
| static int ast_to_misdn_pres | ( | int | presentation | ) | [static] |
Definition at line 2121 of file chan_misdn.c.
References AST_PRES_ALLOWED, AST_PRES_RESTRICTED, AST_PRES_RESTRICTION, and AST_PRES_UNAVAILABLE.
Referenced by misdn_copy_redirecting_from_ast(), misdn_get_connected_line(), and update_config().
{
switch (presentation & AST_PRES_RESTRICTION) {
default:
case AST_PRES_ALLOWED:
presentation = 0;
break;
case AST_PRES_RESTRICTED:
presentation = 1;
break;
case AST_PRES_UNAVAILABLE:
presentation = 2;
break;
}
return presentation;
}
| static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason | ( | const enum AST_REDIRECTING_REASON | ast | ) | [static] |
Definition at line 2250 of file chan_misdn.c.
References ARRAY_LEN, AST_REDIRECTING_REASON_AWAY, AST_REDIRECTING_REASON_CALL_FWD_DTE, AST_REDIRECTING_REASON_DEFLECTION, AST_REDIRECTING_REASON_DO_NOT_DISTURB, AST_REDIRECTING_REASON_FOLLOW_ME, AST_REDIRECTING_REASON_NO_ANSWER, AST_REDIRECTING_REASON_OUT_OF_ORDER, AST_REDIRECTING_REASON_TIME_OF_DAY, AST_REDIRECTING_REASON_UNAVAILABLE, AST_REDIRECTING_REASON_UNCONDITIONAL, AST_REDIRECTING_REASON_UNKNOWN, AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_NO_REPLY, mISDN_REDIRECTING_REASON_OUT_OF_ORDER, and mISDN_REDIRECTING_REASON_UNKNOWN.
Referenced by misdn_copy_redirecting_from_ast().
{
unsigned index;
static const struct misdn_reasons {
enum AST_REDIRECTING_REASON ast;
enum mISDN_REDIRECTING_REASON q931;
} misdn_reason_table[] = {
/* *INDENT-OFF* */
{ AST_REDIRECTING_REASON_UNKNOWN, mISDN_REDIRECTING_REASON_UNKNOWN },
{ AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
{ AST_REDIRECTING_REASON_NO_ANSWER, mISDN_REDIRECTING_REASON_NO_REPLY },
{ AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
{ AST_REDIRECTING_REASON_UNCONDITIONAL, mISDN_REDIRECTING_REASON_CALL_FWD },
{ AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
{ AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
{ AST_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_DEFLECTION },
{ AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
{ AST_REDIRECTING_REASON_OUT_OF_ORDER, mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
{ AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
{ AST_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
/* *INDENT-ON* */
};
for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
if (misdn_reason_table[index].ast == ast) {
return misdn_reason_table[index].q931;
}
}
return mISDN_REDIRECTING_REASON_UNKNOWN;
}
| static int ast_to_misdn_screen | ( | int | screening | ) | [static] |
Definition at line 2218 of file chan_misdn.c.
References AST_PRES_NETWORK_NUMBER, AST_PRES_NUMBER_TYPE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.
Referenced by misdn_copy_redirecting_from_ast(), misdn_get_connected_line(), and update_config().
{
switch (screening & AST_PRES_NUMBER_TYPE) {
default:
case AST_PRES_USER_NUMBER_UNSCREENED:
screening = 0;
break;
case AST_PRES_USER_NUMBER_PASSED_SCREEN:
screening = 1;
break;
case AST_PRES_USER_NUMBER_FAILED_SCREEN:
screening = 2;
break;
case AST_PRES_NETWORK_NUMBER:
screening = 3;
break;
}
return screening;
}
| static enum mISDN_NUMBER_TYPE ast_to_misdn_ton | ( | unsigned | ast_number_type | ) | [static] |
Definition at line 1892 of file chan_misdn.c.
References NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.
Referenced by misdn_call(), misdn_copy_redirecting_from_ast(), and misdn_get_connected_line().
{
enum mISDN_NUMBER_TYPE number_type;
switch ((ast_number_type >> 4) & 0x07) {
default:
case NUMTYPE_UNKNOWN:
number_type = NUMTYPE_UNKNOWN;
break;
case NUMTYPE_INTERNATIONAL:
number_type = NUMTYPE_INTERNATIONAL;
break;
case NUMTYPE_NATIONAL:
number_type = NUMTYPE_NATIONAL;
break;
case NUMTYPE_NETWORK_SPECIFIC:
number_type = NUMTYPE_NETWORK_SPECIFIC;
break;
case NUMTYPE_SUBSCRIBER:
number_type = NUMTYPE_SUBSCRIBER;
break;
case NUMTYPE_ABBREVIATED:
number_type = NUMTYPE_ABBREVIATED;
break;
}
return number_type;
}
| static const char* bearer2str | ( | int | cap | ) | [static] |
Definition at line 2349 of file chan_misdn.c.
References ARRAY_LEN, and allowed_bearers::display.
Referenced by cb_events(), print_bc_info(), and print_bearer().
{
unsigned index;
for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
if (allowed_bearers_array[index].cap == cap) {
return allowed_bearers_array[index].display;
}
}
return "Unknown Bearer";
}
| static enum event_response_e cb_events | ( | enum event_e | event, |
| struct misdn_bchannel * | bc, | ||
| void * | user_data | ||
| ) | [static] |
queue new chan
Supplementary Services
Definition at line 9915 of file chan_misdn.c.
References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, ao2_ref, misdn_bchannel::AOCD_need_export, ARRAY_LEN, chan_list::ast, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_cdr_update(), ast_channel_caller(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_generator(), ast_channel_generatordata(), ast_channel_generatordata_set(), ast_channel_hangupcause_set(), ast_channel_lock, ast_channel_queue_redirecting_update(), ast_channel_redirecting(), ast_channel_rings_set(), ast_channel_transfercapability_set(), ast_channel_unlock, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_deactivate_generator(), ast_exists_extension(), AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_set(), AST_FRAME_DTMF, AST_FRAME_VOICE, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_party_id_reset(), ast_party_redirecting_copy(), ast_party_redirecting_free(), ast_party_redirecting_init(), ast_pickup_call(), ast_pickup_ext(), ast_poll, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_queue_frame(), ast_set_callerid(), ast_setstate(), AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdup, ast_strlen_zero(), ast_transfercapability2str(), ast_tv(), ast_tvnow(), chan_list::bc, misdn_bchannel::bc_state, bc_state2str(), bearer2str(), misdn_bchannel::bframe, misdn_bchannel::bframe_len, misdn_bchannel::caller, misdn_bchannel::capability, misdn_bchannel::cause, cb_log, chan_list_init(), chan_list_unref, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, cl_queue_chan(), misdn_bchannel::connected, chan_list::context, misdn_bchannel::cw, ast_frame::data, ast_frame::datalen, ast_frame::delivery, misdn_bchannel::dialed, do_immediate_setup(), misdn_bchannel::dtmf, misdn_bchannel::dummy, errno, EVENT_ALERTING, EVENT_BCHAN_ACTIVATED, EVENT_BCHAN_DATA, EVENT_BCHAN_ERROR, EVENT_CLEANUP, EVENT_CONNECT, EVENT_CONNECT_ACKNOWLEDGE, EVENT_DISCONNECT, EVENT_DTMF_TONE, EVENT_FACILITY, EVENT_HOLD, EVENT_HOLD_ACKNOWLEDGE, EVENT_HOLD_REJECT, EVENT_INFORMATION, EVENT_NEW_BC, EVENT_NEW_CHANNEL, EVENT_NEW_L3ID, EVENT_NOTIFY, EVENT_PORT_ALARM, EVENT_PROCEEDING, EVENT_PROGRESS, EVENT_REGISTER, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, EVENT_RESTART, EVENT_RETRIEVE, EVENT_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_REJECT, EVENT_SETUP, EVENT_SETUP_ACKNOWLEDGE, EVENT_STATUS, EVENT_TIMEOUT, EVENT_TONE_GENERATE, export_aoc_vars(), export_ch(), misdn_bchannel::fac_in, misdn_bchannel::fac_out, chan_list::far_alerting, find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), ast_frame_subclass::format, ast_frame::frametype, misdn_party_redirecting::from, ast_generator::generate, hangup_chan(), hanguptone_indicate(), chan_list::hold, ast_party_caller::id, chan_list::ignore_dtmf, misdn_bchannel::incoming_cid_tag, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::info_dad, INFO_PI_INBAND_AVAILABLE, misdn_bchannel::infos_pending, ast_frame_subclass::integer, misdn_bchannel::keypad, misdn_bchannel::l3_id, chan_list::l3id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_isdn_get_info(), misdn_add_number_prefix(), MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, misdn_attempt_transfer(), MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, misdn_cap_is_speech(), MISDN_CFG_ALARM_BLOCK, MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, misdn_cfg_get(), MISDN_CFG_HOLD_ALLOWED, MISDN_CFG_IMMEDIATE, MISDN_CFG_REJECT_CAUSE, MISDN_CLEANING, MISDN_CONNECTED, misdn_copy_redirecting_to_ast(), MISDN_DIALING, MISDN_DISCONNECTED, MISDN_EXTCANTMATCH, misdn_facility_ie_handler(), MISDN_GEN_APPEND_DIGITS2EXTEN, misdn_get_ch_state(), MISDN_HOLD_ACTIVE, MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, misdn_inband_avail(), MISDN_INCOMING_SETUP, misdn_is_msn_valid(), misdn_lib_is_ptp(), misdn_lib_log_ies(), misdn_lib_port_block(), misdn_lib_send_event(), misdn_new(), MISDN_NOTHING, mISDN_NOTIFY_CODE_CALL_IS_DIVERTING, mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE, mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING, mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED, mISDN_NOTIFY_CODE_INVALID, misdn_overlap_dial_task(), MISDN_PROCEEDING, MISDN_PROGRESS, mISDN_REDIRECTING_REASON_NO_REPLY, mISDN_REDIRECTING_REASON_UNKNOWN, misdn_tasks_add_variable(), misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_screen(), misdn_to_ast_ton(), misdn_to_str_plan(), misdn_to_str_pres(), misdn_to_str_screen(), misdn_to_str_ton(), misdn_update_remote_party(), MISDN_WAITING4DIGS, misdn_party_id::name, allowed_bearers::name, chan_list::need_busy, misdn_bchannel::need_disconnect, misdn_bchannel::need_more_infos, misdn_bchannel::need_release, misdn_bchannel::need_release_complete, chan_list::noautorespond_on_setup, misdn_bchannel::notify_description_code, misdn_bchannel::nt, chan_list::nttimeout, misdn_party_dialing::number, ast_party_id::number, misdn_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, ast_frame::offset, ORG_AST, ORG_MISDN, chan_list::originator, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_builtin_setvar_helper(), misdn_bchannel::pid, chan_list::pipe, ast_party_number::plan, hold_info::port, misdn_bchannel::port, ast_party_number::presentation, misdn_party_id::presentation, print_bearer(), ast_party_redirecting::priv_from, ast_party_redirecting::priv_orig, ast_party_redirecting::priv_to, misdn_bchannel::progress_indicator, ast_frame::ptr, read_config(), misdn_party_redirecting::reason, misdn_bchannel::redirecting, release_chan(), RESPONSE_ERR, RESPONSE_IGNORE_SETUP, RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE, RESPONSE_OK, RESPONSE_RELEASE_SETUP, ast_frame::samples, misdn_party_id::screening, misdn_bchannel::sending_complete, ast_frame::src, start_bc_tones(), start_pbx(), hold_info::state, chan_list::state, stop_bc_tones(), stop_indicate(), ast_frame::subclass, ast_party_id::tag, misdn_party_redirecting::to, ast_party_redirecting::to, misdn_party_redirecting::to_changed, misdn_bchannel::tone_cnt, update_name(), and wait_for_digits().
Referenced by load_module().
{
#if defined(AST_MISDN_ENHANCEMENTS)
struct misdn_cc_record *cc_record;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
struct chan_list *held_ch;
struct chan_list *ch = find_chan_by_bc(bc);
if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
int debuglevel = 1;
/* Debug Only Non-Bchan */
if (event == EVENT_CLEANUP && !user_data) {
debuglevel = 5;
}
chan_misdn_log(debuglevel, bc->port,
"I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
manager_isdn_get_info(event),
bc->caller.name,
bc->caller.number,
bc->dialed.number,
bc->pid,
ch ? misdn_get_ch_state(ch) : "none");
if (debuglevel == 1) {
misdn_lib_log_ies(bc);
chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
}
}
if (!ch) {
switch(event) {
case EVENT_SETUP:
case EVENT_DISCONNECT:
case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE:
case EVENT_PORT_ALARM:
case EVENT_RETRIEVE:
case EVENT_NEW_BC:
case EVENT_FACILITY:
case EVENT_REGISTER:
break;
case EVENT_CLEANUP:
case EVENT_TONE_GENERATE:
case EVENT_BCHAN_DATA:
return -1;
default:
chan_misdn_log(1, bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n", bc->l3_id, bc, manager_isdn_get_info(event), bc->port, bc->channel);
return -1;
}
} else {
switch (event) {
case EVENT_TONE_GENERATE:
break;
case EVENT_DISCONNECT:
case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE:
case EVENT_CLEANUP:
case EVENT_TIMEOUT:
if (!ch->ast) {
chan_misdn_log(3, bc->port, "ast_hangup already called, so we have no ast ptr anymore in event(%s)\n", manager_isdn_get_info(event));
}
break;
default:
if (!ch->ast || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
if (event != EVENT_BCHAN_DATA) {
ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
}
chan_list_unref(ch, "No Ast or Ast private pointer");
return -1;
}
break;
}
}
switch (event) {
case EVENT_PORT_ALARM:
{
int boa = 0;
misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
if (boa) {
cb_log(1, bc->port, " --> blocking\n");
misdn_lib_port_block(bc->port);
}
}
break;
case EVENT_BCHAN_ACTIVATED:
break;
case EVENT_NEW_CHANNEL:
update_name(ch->ast,bc->port,bc->channel);
break;
case EVENT_NEW_L3ID:
ch->l3id=bc->l3_id;
ch->addr=bc->addr;
break;
case EVENT_NEW_BC:
if (!ch) {
ch = find_hold_call(bc);
}
if (!ch) {
ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
break;
}
if (bc) {
ch->bc = (struct misdn_bchannel *) user_data;
}
break;
case EVENT_DTMF_TONE:
{
/* sending INFOS as DTMF-Frames :) */
struct ast_frame fr;
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_DTMF;
fr.subclass.integer = bc->dtmf ;
fr.src = NULL;
fr.data.ptr = NULL;
fr.datalen = 0;
fr.samples = 0;
fr.mallocd = 0;
fr.offset = 0;
fr.delivery = ast_tv(0,0);
if (!ch->ignore_dtmf) {
chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
ast_queue_frame(ch->ast, &fr);
} else {
chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
}
break;
}
case EVENT_STATUS:
break;
case EVENT_INFORMATION:
if (ch->state != MISDN_CONNECTED) {
stop_indicate(ch);
}
if (!ch->ast) {
break;
}
if (ch->state == MISDN_WAITING4DIGS) {
/* Ok, incomplete Setup, waiting till extension exists */
if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
chan_misdn_log(1, bc->port, " --> using keypad as info\n");
ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
}
strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
ast_channel_exten_set(ch->ast, bc->dialed.number);
/* Check for Pickup Request first */
if (!strcmp(ast_channel_exten(ch->ast), ast_pickup_ext())) {
if (ast_pickup_call(ch->ast)) {
hangup_chan(ch, bc);
} else {
ch->state = MISDN_CALLING_ACKNOWLEDGE;
hangup_chan(ch, bc);
ch->ast = NULL;
break;
}
}
if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
ast_log(LOG_WARNING,
"Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
bc->dialed.number, ch->context, bc->port);
pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
ast_channel_exten_set(ch->ast, "i");
ch->state = MISDN_DIALING;
start_pbx(ch, bc, ch->ast);
break;
}
ast_log(LOG_WARNING,
"Extension '%s@%s' can never match. Disconnecting. port:%d\n"
"\tMaybe you want to add an 'i' extension to catch this case.\n",
bc->dialed.number, ch->context, bc->port);
if (bc->nt) {
hanguptone_indicate(ch);
}
ch->state = MISDN_EXTCANTMATCH;
bc->out_cause = AST_CAUSE_UNALLOCATED;
misdn_lib_send_event(bc, EVENT_DISCONNECT);
break;
}
if (ch->overlap_dial) {
ast_mutex_lock(&ch->overlap_tv_lock);
ch->overlap_tv = ast_tvnow();
ast_mutex_unlock(&ch->overlap_tv_lock);
if (ch->overlap_dial_task == -1) {
ch->overlap_dial_task =
misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
}
break;
}
if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
ch->state = MISDN_DIALING;
start_pbx(ch, bc, ch->ast);
}
} else {
/* sending INFOS as DTMF-Frames :) */
struct ast_frame fr;
int digits;
memset(&fr, 0, sizeof(fr));
fr.frametype = AST_FRAME_DTMF;
fr.subclass.integer = bc->info_dad[0] ;
fr.src = NULL;
fr.data.ptr = NULL;
fr.datalen = 0;
fr.samples = 0;
fr.mallocd = 0;
fr.offset = 0;
fr.delivery = ast_tv(0,0);
misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
if (ch->state != MISDN_CONNECTED) {
if (digits) {
strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
ast_channel_exten_set(ch->ast, bc->dialed.number);
ast_cdr_update(ch->ast);
}
ast_queue_frame(ch->ast, &fr);
}
}
break;
case EVENT_SETUP:
{
struct ast_channel *chan;
int exceed;
int ai;
int im;
int append_msn = 0;
if (ch) {
switch (ch->state) {
case MISDN_NOTHING:
chan_list_unref(ch, "Ignore found ch. Is it for an outgoing call?");
ch = NULL;
break;
default:
chan_list_unref(ch, "Already have a call.");
chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */
}
}
if (!bc->nt && !misdn_is_msn_valid(bc->port, &bc->dialed)) {
chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */
}
if (bc->cw) {
int cause;
chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
return RESPONSE_RELEASE_SETUP;
}
print_bearer(bc);
ch = chan_list_init(ORG_MISDN);
if (!ch) {
chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
return RESPONSE_RELEASE_SETUP;
}
ch->bc = bc;
ch->l3id = bc->l3_id;
ch->addr = bc->addr;
{
struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
struct ast_format tmpfmt;
if (!(cap)) {
return RESPONSE_ERR;
}
ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, bc->port, bc->channel);
cap = ast_format_cap_destroy(cap);
}
if (!chan) {
chan_list_unref(ch, "Failed to create a new channel");
ast_log(LOG_ERROR, "cb_events: misdn_new failed!\n");
return RESPONSE_RELEASE_SETUP;
}
if ((exceed = add_in_calls(bc->port))) {
char tmp[16];
snprintf(tmp, sizeof(tmp), "%d", exceed);
pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
}
read_config(ch);
export_ch(chan, bc, ch);
ast_channel_rings_set(ch->ast, 1);
ast_setstate(ch->ast, AST_STATE_RINGING);
/* Update asterisk channel caller information */
chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
ast_channel_caller(chan)->id.number.plan = misdn_to_ast_ton(bc->caller.number_type)
| misdn_to_ast_plan(bc->caller.number_plan);
chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
ast_channel_caller(chan)->id.number.presentation = misdn_to_ast_pres(bc->caller.presentation)
| misdn_to_ast_screen(bc->caller.screening);
ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
misdn_cfg_get(bc->port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
if (append_msn) {
strncat(bc->incoming_cid_tag, "_", sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
strncat(bc->incoming_cid_tag, bc->dialed.number, sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
}
ast_channel_lock(chan);
ast_channel_caller(chan)->id.tag = ast_strdup(bc->incoming_cid_tag);
ast_channel_unlock(chan);
if (!ast_strlen_zero(bc->redirecting.from.number)) {
/* Add configured prefix to redirecting.from.number */
misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
/* Update asterisk channel redirecting information */
misdn_copy_redirecting_to_ast(chan, &bc->redirecting, bc->incoming_cid_tag);
}
pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
ast_channel_transfercapability_set(chan, bc->capability);
switch (bc->capability) {
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
break;
default:
pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
break;
}
if (!strstr(ch->allowed_bearers, "all")) {
int i;
for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
if (allowed_bearers_array[i].cap == bc->capability) {
if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
/* The bearer capability is allowed */
if (allowed_bearers_array[i].deprecated) {
chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
allowed_bearers_array[i].name);
}
break;
}
}
}
if (i == ARRAY_LEN(allowed_bearers_array)) {
/* We did not find the bearer capability */
chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
bearer2str(bc->capability), bc->capability);
ch->state = MISDN_EXTCANTMATCH;
chan_list_unref(ch, "BC not allowed, releasing call");
bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
return RESPONSE_RELEASE_SETUP;
}
}
/** queue new chan **/
cl_queue_chan(ch);
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
/* Check for Pickup Request first */
if (!strcmp(ast_channel_exten(chan), ast_pickup_ext())) {
if (!ch->noautorespond_on_setup) {
/* Sending SETUP_ACK */
misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
} else {
ch->state = MISDN_INCOMING_SETUP;
}
if (ast_pickup_call(chan)) {
hangup_chan(ch, bc);
} else {
ch->state = MISDN_CALLING_ACKNOWLEDGE;
hangup_chan(ch, bc);
ch->ast = NULL;
break;
}
}
/*
* added support for s extension hope it will help those poor cretains
* which haven't overlap dial.
*/
misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
if (ai) {
do_immediate_setup(bc, ch, chan);
break;
}
/* check if we should jump into s when we have no dialed.number */
misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
if (im && ast_strlen_zero(bc->dialed.number)) {
do_immediate_setup(bc, ch, chan);
break;
}
chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
ast_log(LOG_WARNING,
"Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
bc->dialed.number, ch->context, bc->port);
pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
ast_channel_exten_set(ch->ast, "i");
misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
ch->state = MISDN_DIALING;
start_pbx(ch, bc, chan);
break;
}
ast_log(LOG_WARNING,
"Extension '%s@%s' can never match. Disconnecting. port:%d\n"
"\tMaybe you want to add an 'i' extension to catch this case.\n",
bc->dialed.number, ch->context, bc->port);
if (bc->nt) {
hanguptone_indicate(ch);
}
ch->state = MISDN_EXTCANTMATCH;
bc->out_cause = AST_CAUSE_UNALLOCATED;
misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_RELEASE);
break;
}
/* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
* jump into the dialplan, when the dialed extension does not exist, the 's' extension
* will be used by Asterisk automatically. */
if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
if (!ch->noautorespond_on_setup) {
ch->state=MISDN_DIALING;
misdn_lib_send_event(bc, EVENT_PROCEEDING);
} else {
ch->state = MISDN_INCOMING_SETUP;
}
start_pbx(ch, bc, chan);
break;
}
/*
* When we are NT and overlapdial is set and if
* the number is empty, we wait for the ISDN timeout
* instead of our own timer.
*/
if (ch->overlap_dial && bc->nt && !bc->dialed.number[0]) {
wait_for_digits(ch, bc, chan);
break;
}
/*
* If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
* Infos with a Interdigit Timeout.
* */
if (ch->overlap_dial) {
ast_mutex_lock(&ch->overlap_tv_lock);
ch->overlap_tv = ast_tvnow();
ast_mutex_unlock(&ch->overlap_tv_lock);
wait_for_digits(ch, bc, chan);
if (ch->overlap_dial_task == -1) {
ch->overlap_dial_task =
misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
}
break;
}
/* If the extension does not exist and we're not TE_PTMP we wait for more digits
* without interdigit timeout.
* */
if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
wait_for_digits(ch, bc, chan);
break;
}
/*
* If the extension exists let's just jump into it.
* */
if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
ch->state = MISDN_DIALING;
start_pbx(ch, bc, chan);
break;
}
break;
}
#if defined(AST_MISDN_ENHANCEMENTS)
case EVENT_REGISTER:
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
/*
* Shut down this connection immediately.
* The current design of chan_misdn data structures
* does not allow the proper handling of inbound call records
* without an assigned B channel. Therefore, we cannot
* be the CCBS User-B party in a point-to-point setup.
*/
bc->fac_out.Function = Fac_None;
bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
break;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
case EVENT_SETUP_ACKNOWLEDGE:
ch->state = MISDN_CALLING_ACKNOWLEDGE;
if (bc->channel) {
update_name(ch->ast,bc->port,bc->channel);
}
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
if (!ast_strlen_zero(bc->infos_pending)) {
/* TX Pending Infos */
strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
if (!ch->ast) {
break;
}
ast_channel_exten_set(ch->ast, bc->dialed.number);
ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
misdn_lib_send_event(bc, EVENT_INFORMATION);
}
break;
case EVENT_PROCEEDING:
if (misdn_cap_is_speech(bc->capability) &&
misdn_inband_avail(bc)) {
start_bc_tones(ch);
}
ch->state = MISDN_PROCEEDING;
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
if (!ch->ast) {
break;
}
ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
break;
case EVENT_PROGRESS:
if (bc->channel) {
update_name(ch->ast, bc->port, bc->channel);
}
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
if (!bc->nt) {
if (misdn_cap_is_speech(bc->capability) &&
misdn_inband_avail(bc)) {
start_bc_tones(ch);
}
ch->state = MISDN_PROGRESS;
if (!ch->ast) {
break;
}
ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
}
break;
case EVENT_ALERTING:
ch->state = MISDN_ALERTING;
if (!ch->ast) {
break;
}
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
ast_queue_control(ch->ast, AST_CONTROL_RINGING);
ast_setstate(ch->ast, AST_STATE_RINGING);
cb_log(7, bc->port, " --> Set State Ringing\n");
if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
start_bc_tones(ch);
} else {
cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
if (ch->far_alerting) {
cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
start_bc_tones(ch);
/*tone_indicate(ch, TONE_FAR_ALERTING);*/
}
}
break;
case EVENT_CONNECT:
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
#if defined(AST_MISDN_ENHANCEMENTS)
if (bc->div_leg_3_rx_wanted) {
bc->div_leg_3_rx_wanted = 0;
if (ch->ast) {
struct ast_party_redirecting redirecting;
ast_channel_redirecting(ch->ast)->to.number.presentation =
AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
ast_party_redirecting_init(&redirecting);
ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
/*
* Reset any earlier private redirecting id representations and
* make sure that it is invalidated at the remote end.
*/
ast_party_id_reset(&redirecting.priv_orig);
ast_party_id_reset(&redirecting.priv_from);
ast_party_id_reset(&redirecting.priv_to);
ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
ast_party_redirecting_free(&redirecting);
}
}
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
/* we answer when we've got our very new L3 ID from the NT stack */
misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
if (!ch->ast) {
break;
}
stop_indicate(ch);
#if defined(AST_MISDN_ENHANCEMENTS)
if (ch->record_id != -1) {
/*
* We will delete the associated call completion
* record since we now have a completed call.
* We will not wait/depend on the network to tell
* us to delete it.
*/
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_id(ch->record_id);
if (cc_record) {
if (cc_record->ptp && cc_record->mode.ptp.bc) {
/* Close the call-completion signaling link */
cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
}
misdn_cc_delete(cc_record);
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
ch->record_id = -1;
if (ch->peer) {
misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, "");
ao2_ref(ch->peer, -1);
ch->peer = NULL;
}
}
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
if (!ast_strlen_zero(bc->connected.number)) {
/* Add configured prefix to connected.number */
misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
/* Update the connected line information on the other channel */
misdn_update_remote_party(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, bc->incoming_cid_tag);
}
ch->l3id = bc->l3_id;
ch->addr = bc->addr;
start_bc_tones(ch);
ch->state = MISDN_CONNECTED;
ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
break;
case EVENT_CONNECT_ACKNOWLEDGE:
ch->l3id = bc->l3_id;
ch->addr = bc->addr;
start_bc_tones(ch);
ch->state = MISDN_CONNECTED;
break;
case EVENT_DISCONNECT:
/* we might not have an ch->ast ptr here anymore */
if (ch) {
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
chan_misdn_log(3, bc->port, " --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
/* If there's inband information available (e.g. a
recorded message saying what was wrong with the
dialled number, or perhaps even giving an
alternative number, then play it instead of
immediately releasing the call */
chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
ch->state = MISDN_DISCONNECTED;
start_bc_tones(ch);
if (ch->ast) {
ast_channel_hangupcause_set(ch->ast, bc->cause);
if (bc->cause == AST_CAUSE_USER_BUSY) {
ast_queue_control(ch->ast, AST_CONTROL_BUSY);
}
}
ch->need_busy = 0;
break;
}
bc->need_disconnect = 0;
stop_bc_tones(ch);
/* Check for held channel, to implement transfer */
held_ch = find_hold_call(bc);
if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
hangup_chan(ch, bc);
}
} else {
held_ch = find_hold_call_l3(bc->l3_id);
if (held_ch) {
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, held_ch);
}
if (held_ch->hold.state == MISDN_HOLD_ACTIVE) {
bc->need_disconnect = 0;
#if defined(TRANSFER_ON_HELD_CALL_HANGUP)
/*
* Some phones disconnect the held call and the active call at the
* same time to do the transfer. Unfortunately, either call could
* be disconnected first.
*/
ch = find_hold_active_call(bc);
if (!ch || misdn_attempt_transfer(ch, held_ch)) {
held_ch->hold.state = MISDN_HOLD_DISCONNECT;
hangup_chan(held_ch, bc);
}
#else
hangup_chan(held_ch, bc);
#endif /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
}
}
}
if (held_ch) {
chan_list_unref(held_ch, "Done with held call");
}
bc->out_cause = -1;
if (bc->need_release) {
misdn_lib_send_event(bc, EVENT_RELEASE);
}
break;
case EVENT_RELEASE:
if (!ch) {
ch = find_hold_call_l3(bc->l3_id);
if (!ch) {
chan_misdn_log(1, bc->port,
" --> no Ch, so we've already released. (%s)\n",
manager_isdn_get_info(event));
return -1;
}
}
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
bc->need_disconnect = 0;
bc->need_release = 0;
hangup_chan(ch, bc);
release_chan(ch, bc);
break;
case EVENT_RELEASE_COMPLETE:
if (!ch) {
ch = find_hold_call_l3(bc->l3_id);
}
bc->need_disconnect = 0;
bc->need_release = 0;
bc->need_release_complete = 0;
if (ch) {
if (bc->fac_in.Function != Fac_None) {
misdn_facility_ie_handler(event, bc, ch);
}
stop_bc_tones(ch);
hangup_chan(ch, bc);
release_chan(ch, bc);
} else {
#if defined(AST_MISDN_ENHANCEMENTS)
/*
* A call-completion signaling link established with
* REGISTER does not have a struct chan_list record
* associated with it.
*/
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_bc(bc);
if (cc_record) {
/* The call-completion signaling link is closed. */
misdn_cc_delete(cc_record);
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
chan_misdn_log(1, bc->port,
" --> no Ch, so we've already released. (%s)\n",
manager_isdn_get_info(event));
}
break;
case EVENT_BCHAN_ERROR:
case EVENT_CLEANUP:
stop_bc_tones(ch);
switch (ch->state) {
case MISDN_CALLING:
bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
break;
default:
break;
}
hangup_chan(ch, bc);
release_chan(ch, bc);
break;
case EVENT_TONE_GENERATE:
{
int tone_len = bc->tone_cnt;
struct ast_channel *ast = ch->ast;
void *tmp;
int res;
int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
if (!ast) {
break;
}
if (!ast_channel_generator(ast)) {
break;
}
tmp = ast_channel_generatordata(ast);
ast_channel_generatordata_set(ast, NULL);
generate = ast_channel_generator(ast)->generate;
if (tone_len < 0 || tone_len > 512) {
ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
tone_len = 128;
}
res = generate(ast, tmp, tone_len, tone_len);
ast_channel_generatordata_set(ast, tmp);
if (res) {
ast_log(LOG_WARNING, "Auto-deactivating generator\n");
ast_deactivate_generator(ast);
} else {
bc->tone_cnt = 0;
}
break;
}
case EVENT_BCHAN_DATA:
if (ch->bc->AOCD_need_export) {
export_aoc_vars(ch->originator, ch->ast, ch->bc);
}
if (!misdn_cap_is_speech(ch->bc->capability)) {
struct ast_frame frame;
/* In Data Modes we queue frames */
memset(&frame, 0, sizeof(frame));
frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
ast_format_set(&frame.subclass.format, AST_FORMAT_ALAW, 0);
frame.datalen = bc->bframe_len;
frame.samples = bc->bframe_len;
frame.mallocd = 0;
frame.offset = 0;
frame.delivery = ast_tv(0, 0);
frame.src = NULL;
frame.data.ptr = bc->bframe;
if (ch->ast) {
ast_queue_frame(ch->ast, &frame);
}
} else {
struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
int t;
t = ast_poll(&pfd, 1, 0);
if (t < 0) {
chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
break;
}
if (!t) {
chan_misdn_log(9, bc->port, "poll() timed out\n");
break;
}
if (pfd.revents & POLLOUT) {
chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
stop_bc_tones(ch);
hangup_chan(ch, bc);
release_chan(ch, bc);
}
} else {
chan_misdn_log(1, bc->port, "Write Pipe full!\n");
}
}
break;
case EVENT_TIMEOUT:
if (ch && bc) {
chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
}
switch (ch->state) {
case MISDN_DIALING:
case MISDN_PROGRESS:
if (bc->nt && !ch->nttimeout) {
break;
}
/* fall-through */
case MISDN_CALLING:
case MISDN_ALERTING:
case MISDN_PROCEEDING:
case MISDN_CALLING_ACKNOWLEDGE:
if (bc->nt) {
bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
hanguptone_indicate(ch);
}
bc->out_cause = AST_CAUSE_UNALLOCATED;
misdn_lib_send_event(bc, EVENT_DISCONNECT);
break;
case MISDN_WAITING4DIGS:
if (bc->nt) {
bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
bc->out_cause = AST_CAUSE_UNALLOCATED;
hanguptone_indicate(ch);
misdn_lib_send_event(bc, EVENT_DISCONNECT);
} else {
bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
misdn_lib_send_event(bc, EVENT_RELEASE);
}
break;
case MISDN_CLEANING:
chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
break;
default:
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
break;
}
break;
/****************************/
/** Supplementary Services **/
/****************************/
case EVENT_RETRIEVE:
if (!ch) {
chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
ch = find_hold_call_l3(bc->l3_id);
if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
break;
}
}
/* remember the channel again */
ch->bc = bc;
ch->hold.state = MISDN_HOLD_IDLE;
ch->hold.port = 0;
ch->hold.channel = 0;
ast_queue_control(ch->ast, AST_CONTROL_UNHOLD);
if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
}
break;
case EVENT_HOLD:
{
int hold_allowed;
struct ast_channel *bridged;
misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
if (!hold_allowed) {
chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
break;
}
bridged = ast_bridged_channel(ch->ast);
if (bridged) {
chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", ast_channel_tech(bridged)->type);
ch->l3id = bc->l3_id;
/* forget the channel now */
ch->bc = NULL;
ch->hold.state = MISDN_HOLD_ACTIVE;
ch->hold.port = bc->port;
ch->hold.channel = bc->channel;
ast_queue_control(ch->ast, AST_CONTROL_HOLD);
misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
} else {
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
}
break;
}
case EVENT_NOTIFY:
if (bc->redirecting.to_changed) {
/* Add configured prefix to redirecting.to.number */
misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
}
switch (bc->notify_description_code) {
case mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED:
/* Ignore for now. */
bc->redirecting.to_changed = 0;
break;
case mISDN_NOTIFY_CODE_CALL_IS_DIVERTING:
{
struct ast_party_redirecting redirecting;
if (!bc->redirecting.to_changed) {
break;
}
bc->redirecting.to_changed = 0;
if (!ch || !ch->ast) {
break;
}
switch (ch->state) {
case MISDN_ALERTING:
/* Call is deflecting after we have seen an ALERTING message */
bc->redirecting.reason = mISDN_REDIRECTING_REASON_NO_REPLY;
break;
default:
/* Call is deflecting for call forwarding unconditional or busy reason. */
bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
break;
}
misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
ast_party_redirecting_init(&redirecting);
ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
/*
* Reset any earlier private redirecting id representations and
* make sure that it is invalidated at the remote end.
*/
ast_party_id_reset(&redirecting.priv_orig);
ast_party_id_reset(&redirecting.priv_from);
ast_party_id_reset(&redirecting.priv_to);
ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
ast_party_redirecting_free(&redirecting);
break;
}
case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
/*
* It would be preferable to update the connected line information
* only when the message callStatus is active. However, the
* optional redirection number may not be present in the active
* message if an alerting message were received earlier.
*
* The consequences if we wind up sending two updates is benign.
* The other end will think that it got transferred twice.
*/
if (!bc->redirecting.to_changed) {
break;
}
bc->redirecting.to_changed = 0;
if (!ch || !ch->ast) {
break;
}
misdn_update_remote_party(ch->ast, &bc->redirecting.to,
AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING,
bc->incoming_cid_tag);
break;
case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
if (!bc->redirecting.to_changed) {
break;
}
bc->redirecting.to_changed = 0;
if (!ch || !ch->ast) {
break;
}
misdn_update_remote_party(ch->ast, &bc->redirecting.to,
AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
break;
default:
bc->redirecting.to_changed = 0;
chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
bc->notify_description_code);
break;
}
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
break;
case EVENT_FACILITY:
if (bc->fac_in.Function == Fac_None) {
/* This is a FACILITY message so we MUST have a facility ie */
chan_misdn_log(0, bc->port," --> Missing facility ie or unknown facility ie contents.\n");
} else {
misdn_facility_ie_handler(event, bc, ch);
}
/* In case it came in on a FACILITY message and we did not handle it. */
bc->redirecting.to_changed = 0;
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
break;
case EVENT_RESTART:
if (!bc->dummy) {
stop_bc_tones(ch);
release_chan(ch, bc);
}
break;
default:
chan_misdn_log(1, 0, "Got Unknown Event\n");
break;
}
if (ch) {
chan_list_unref(ch, "cb_event complete OK");
}
return RESPONSE_OK;
}
| static void chan_list_destructor | ( | void * | obj | ) | [static] |
Definition at line 7749 of file chan_misdn.c.
References ao2_ref, ast_dsp_free(), ast_mutex_destroy, chan_list::dsp, chan_list::jb, misdn_jb_destroy(), misdn_tasks_remove(), chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, and chan_list::pipe.
Referenced by chan_list_init().
{
struct chan_list *ch = obj;
#if defined(AST_MISDN_ENHANCEMENTS)
if (ch->peer) {
ao2_ref(ch->peer, -1);
ch->peer = NULL;
}
#endif /* AST_MISDN_ENHANCEMENTS */
if (ch->dsp) {
ast_dsp_free(ch->dsp);
ch->dsp = NULL;
}
/* releasing jitterbuffer */
if (ch->jb) {
misdn_jb_destroy(ch->jb);
ch->jb = NULL;
}
if (ch->overlap_dial) {
if (ch->overlap_dial_task != -1) {
misdn_tasks_remove(ch->overlap_dial_task);
ch->overlap_dial_task = -1;
}
ast_mutex_destroy(&ch->overlap_tv_lock);
}
if (-1 < ch->pipe[0]) {
close(ch->pipe[0]);
}
if (-1 < ch->pipe[1]) {
close(ch->pipe[1]);
}
}
| static struct chan_list* chan_list_init | ( | int | orig | ) | [static, read] |
Returns a reference to the new chan_list.
Definition at line 7788 of file chan_misdn.c.
References ao2_alloc, chan_list_destructor(), chan_misdn_log(), chan_list::need_busy, chan_list::need_hangup, chan_list::need_queue_hangup, chan_list::originator, chan_list::overlap_dial_task, and chan_list::pipe.
Referenced by cb_events(), and misdn_request().
{
struct chan_list *cl;
cl = ao2_alloc(sizeof(*cl), chan_list_destructor);
if (!cl) {
chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
return NULL;
}
cl->originator = orig;
cl->need_queue_hangup = 1;
cl->need_hangup = 1;
cl->need_busy = 1;
cl->overlap_dial_task = -1;
#if defined(AST_MISDN_ENHANCEMENTS)
cl->record_id = -1;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
cl->pipe[0] = -1;
cl->pipe[1] = -1;
return cl;
}
| int chan_misdn_jb_empty | ( | struct misdn_bchannel * | bc, |
| char * | buf, | ||
| int | len | ||
| ) |
Definition at line 12540 of file chan_misdn.c.
References chan_list_unref, find_chan_by_bc(), chan_list::jb, and misdn_jb_empty().
Referenced by load_module().
{
struct chan_list *ch;
int res;
ch = find_chan_by_bc(bc);
if (!ch) {
return 0;
}
if (ch->jb) {
res = misdn_jb_empty(ch->jb, buf, len);
} else {
res = 0;
}
chan_list_unref(ch, "Done emptying jb");
return res;
}
| static void chan_misdn_log | ( | int | level, |
| int | port, | ||
| char * | tmpl, | ||
| ... | |||
| ) | [static] |
Definition at line 12734 of file chan_misdn.c.
References ast_log(), ast_strlen_zero(), ast_verbose(), errno, and LOG_WARNING.
Referenced by cb_events(), chan_list_init(), cl_queue_chan(), config_jitterbuffer(), debug_numtype(), dialtone_indicate(), do_immediate_setup(), export_ch(), find_chan_by_bc(), find_hold_call(), load_module(), misdn_answer(), misdn_attempt_transfer(), misdn_bridge(), misdn_call(), misdn_check_l2l1(), misdn_digit_end(), misdn_facility_exec(), misdn_facility_ie_handler(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_jb_empty(), misdn_jb_fill(), misdn_jb_init(), misdn_l1_task(), misdn_new(), misdn_overlap_dial_task(), misdn_read(), misdn_request(), misdn_set_opt_exec(), misdn_tasks_destroy(), misdn_tasks_init(), misdn_tasks_thread_func(), misdn_write(), print_bearer(), print_facility(), process_ast_dsp(), read_config(), release_chan(), send_cause2ast(), start_pbx(), stop_indicate(), update_config(), and update_name().
{
va_list ap;
char buf[1024];
char port_buf[8];
if (!(0 <= port && port <= max_ports)) {
ast_log(LOG_WARNING, "chan_misdn_log called with out-of-range port number! (%d)\n", port);
port = 0;
level = -1;
} else if (!(level == -1
|| (misdn_debug_only[port]
? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
: level <= misdn_debug[port])
|| (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
/*
* We are not going to print anything so lets not
* go to all the work of generating a string.
*/
return;
}
snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
va_start(ap, tmpl);
vsnprintf(buf, sizeof(buf), tmpl, ap);
va_end(ap);
if (level == -1) {
ast_log(LOG_WARNING, "%s", buf);
} else if (misdn_debug_only[port]
? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
: level <= misdn_debug[port]) {
ast_verbose("%s%s", port_buf, buf);
}
if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
char ctimebuf[30];
time_t tm;
char *tmp;
char *p;
FILE *fp;
fp = fopen(global_tracefile, "a+");
if (!fp) {
ast_verbose("Error opening Tracefile: [ %s ] %s\n", global_tracefile, strerror(errno));
return;
}
tm = time(NULL);
tmp = ctime_r(&tm, ctimebuf);
p = strchr(tmp, '\n');
if (p) {
*p = ':';
}
fputs(tmp, fp);
fputs(" ", fp);
fputs(port_buf, fp);
fputs(" ", fp);
fputs(buf, fp);
fclose(fp);
}
}
| static int cl_dequeue_chan | ( | struct chan_list * | chan | ) | [static] |
Definition at line 8362 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, chan_list_unref, and chan_list::next.
Referenced by release_chan(), and release_chan_early().
{
int found_it;
struct chan_list *help;
ast_mutex_lock(&cl_te_lock);
if (!cl_te) {
/* List is empty. */
ast_mutex_unlock(&cl_te_lock);
return 0;
}
if (cl_te == chan) {
/* What we want is the head of the list. */
cl_te = cl_te->next;
ast_mutex_unlock(&cl_te_lock);
chan_list_unref(chan, "Removed chan_list from list head");
return 1;
}
found_it = 0;
for (help = cl_te; help->next; help = help->next) {
if (help->next == chan) {
/* Found it in the list. */
help->next = help->next->next;
found_it = 1;
break;
}
}
ast_mutex_unlock(&cl_te_lock);
if (found_it) {
chan_list_unref(chan, "Removed chan_list from list");
}
return found_it;
}
| static void cl_queue_chan | ( | struct chan_list * | chan | ) | [static] |
Definition at line 8341 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, chan_list::bc, chan_list_ref, chan_misdn_log(), chan_list::next, and misdn_bchannel::port.
Referenced by cb_events(), and misdn_request().
{
chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
chan_list_ref(chan, "Adding chan_list to list");
ast_mutex_lock(&cl_te_lock);
chan->next = NULL;
if (!cl_te) {
/* List is empty, make head of list. */
cl_te = chan;
} else {
struct chan_list *help;
/* Put at end of list. */
for (help = cl_te; help->next; help = help->next) {
}
help->next = chan;
}
ast_mutex_unlock(&cl_te_lock);
}
| static char * complete_ch | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 5627 of file chan_misdn.c.
References ast_complete_channels(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.
Referenced by handle_cli_misdn_send_digit(), handle_cli_misdn_send_display(), handle_cli_misdn_send_facility(), handle_cli_misdn_show_channel(), and handle_cli_misdn_toggle_echocancel().
{
return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
}
| static char * complete_debug_port | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 5632 of file chan_misdn.c.
References ast_strdup, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.
Referenced by handle_cli_misdn_set_debug().
{
if (a->n) {
return NULL;
}
switch (a->pos) {
case 4:
if (a->word[0] == 'p') {
return ast_strdup("port");
} else if (a->word[0] == 'o') {
return ast_strdup("only");
}
break;
case 6:
if (a->word[0] == 'o') {
return ast_strdup("only");
}
break;
}
return NULL;
}
| static char * complete_show_config | ( | struct ast_cli_args * | a | ) | [static] |
Definition at line 5655 of file chan_misdn.c.
References ast_strdup, BUFFERSIZE, ast_cli_args::line, MISDN_CFG_FIRST, misdn_cfg_get_name(), misdn_cfg_get_next_port(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.
Referenced by handle_cli_misdn_show_config().
{
char buffer[BUFFERSIZE];
enum misdn_cfg_elements elem;
int wordlen = strlen(a->word);
int which = 0;
int port = 0;
switch (a->pos) {
case 3:
if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n)) {
return ast_strdup("description");
}
if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n)) {
return ast_strdup("descriptions");
}
if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n)) {
return ast_strdup("0");
}
while ((port = misdn_cfg_get_next_port(port)) != -1) {
snprintf(buffer, sizeof(buffer), "%d", port);
if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
return ast_strdup(buffer);
}
}
break;
case 4:
if (strstr(a->line, "description ")) {
for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) {
continue;
}
misdn_cfg_get_name(elem, buffer, sizeof(buffer));
if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
if (++which > a->n) {
return ast_strdup(buffer);
}
}
}
} else if (strstr(a->line, "descriptions ")) {
if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n)) {
return ast_strdup("general");
}
if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n)) {
return ast_strdup("ports");
}
}
break;
}
return NULL;
}
| static void config_jitterbuffer | ( | struct chan_list * | ch | ) | [static] |
Definition at line 5790 of file chan_misdn.c.
References chan_list::bc, cb_log, chan_misdn_log(), chan_list::jb, chan_list::jb_len, chan_list::jb_upper_threshold, len(), misdn_jb_destroy(), misdn_jb_init(), misdn_bchannel::nojitter, and misdn_bchannel::port.
Referenced by misdn_set_opt_exec(), and read_config().
{
struct misdn_bchannel *bc = ch->bc;
int len = ch->jb_len;
int threshold = ch->jb_upper_threshold;
chan_misdn_log(5, bc->port, "config_jb: Called\n");
if (!len) {
chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
bc->nojitter = 1;
} else {
if (len <= 100 || len > 8000) {
chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
len = 1000;
}
if (threshold > len) {
chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
}
if (ch->jb) {
cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
misdn_jb_destroy(ch->jb);
ch->jb = NULL;
}
ch->jb = misdn_jb_init(len, threshold);
if (!ch->jb) {
bc->nojitter = 1;
}
}
}
| void debug_numtype | ( | int | port, |
| int | numtype, | ||
| char * | type | ||
| ) |
Definition at line 5826 of file chan_misdn.c.
References chan_misdn_log(), NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.
Referenced by misdn_call(), misdn_get_connected_line(), and read_config().
{
switch (numtype) {
case NUMTYPE_UNKNOWN:
chan_misdn_log(2, port, " --> %s: Unknown\n", type);
break;
case NUMTYPE_INTERNATIONAL:
chan_misdn_log(2, port, " --> %s: International\n", type);
break;
case NUMTYPE_NATIONAL:
chan_misdn_log(2, port, " --> %s: National\n", type);
break;
case NUMTYPE_NETWORK_SPECIFIC:
chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
break;
case NUMTYPE_SUBSCRIBER:
chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
break;
case NUMTYPE_ABBREVIATED:
chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
break;
/* Maybe we should cut off the prefix if present ? */
default:
chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
break;
}
}
| static int dialtone_indicate | ( | struct chan_list * | cl | ) | [static] |
AST INDICATIONS END
Definition at line 7664 of file chan_misdn.c.
References chan_list::ast, ast_channel_zone(), ast_get_indication_tone(), ast_playtones_start(), chan_list::bc, chan_misdn_log(), ast_tone_zone_sound::data, misdn_cfg_get(), MISDN_CFG_NODIALTONE, chan_list::norxtone, chan_list::notxtone, misdn_bchannel::port, and chan_list::ts.
Referenced by wait_for_digits().
{
struct ast_channel *ast = cl->ast;
int nd = 0;
if (!ast) {
chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
return -1;
}
misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
if (nd) {
chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
return 0;
}
chan_misdn_log(3, cl->bc->port, " --> Dial\n");
cl->ts = ast_get_indication_tone(ast_channel_zone(ast), "dial");
if (cl->ts) {
cl->notxtone = 0;
cl->norxtone = 0;
/* This prods us in misdn_write */
ast_playtones_start(ast, 0, cl->ts->data, 0);
}
return 0;
}
| static void do_immediate_setup | ( | struct misdn_bchannel * | bc, |
| struct chan_list * | ch, | ||
| struct ast_channel * | ast | ||
| ) | [static] |
Definition at line 8659 of file chan_misdn.c.
References chan_list::ast, ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_exten_set(), AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), ast_tv(), misdn_bchannel::caller, chan_misdn_log(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_RELEASE_COMPLETE, EVENT_SETUP_ACKNOWLEDGE, ast_frame::frametype, hangup_chan(), hanguptone_indicate(), ast_frame_subclass::integer, ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, MISDN_DIALING, MISDN_INCOMING_SETUP, misdn_lib_is_ptp(), misdn_lib_send_event(), name, chan_list::noautorespond_on_setup, misdn_bchannel::nt, misdn_party_id::number, ast_frame::offset, misdn_bchannel::out_cause, pbx_start_chan(), misdn_bchannel::port, ast_frame::ptr, ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.
Referenced by cb_events().
{
char *predial;
struct ast_frame fr;
predial = ast_strdupa(ast_channel_exten(ast));
ch->state = MISDN_DIALING;
if (!ch->noautorespond_on_setup) {
if (bc->nt) {
misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
} else {
if (misdn_lib_is_ptp(bc->port)) {
misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
} else {
misdn_lib_send_event(bc, EVENT_PROCEEDING);
}
}
} else {
ch->state = MISDN_INCOMING_SETUP;
}
chan_misdn_log(1, bc->port,
"* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
ast_channel_context(ast),
ast_channel_exten(ast),
(ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
? ast_channel_caller(ast)->id.name.str : "",
(ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
? ast_channel_caller(ast)->id.number.str : "");
ast_channel_exten_set(ast, "s");
if (!ast_canmatch_extension(ast, ast_channel_context(ast), ast_channel_exten(ast), 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
ast = NULL;
bc->out_cause = AST_CAUSE_UNALLOCATED;
hangup_chan(ch, bc);
hanguptone_indicate(ch);
misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
}
while (!ast_strlen_zero(predial)) {
fr.frametype = AST_FRAME_DTMF;
fr.subclass.integer = *predial;
fr.src = NULL;
fr.data.ptr = NULL;
fr.datalen = 0;
fr.samples = 0;
fr.mallocd = 0;
fr.offset = 0;
fr.delivery = ast_tv(0,0);
if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
ast_queue_frame(ch->ast, &fr);
}
predial++;
}
}
| static void export_aoc_vars | ( | int | originator, |
| struct ast_channel * | ast, | ||
| struct misdn_bchannel * | bc | ||
| ) | [static] |
Definition at line 3434 of file chan_misdn.c.
References misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, misdn_bchannel::AOCDtype, ast_bridged_channel(), misdn_bchannel::chargingUnit, misdn_bchannel::currency, ORG_AST, and pbx_builtin_setvar_helper().
Referenced by cb_events(), and misdn_facility_ie_handler().
{
char buf[128];
if (!bc->AOCD_need_export || !ast) {
return;
}
if (originator == ORG_AST) {
ast = ast_bridged_channel(ast);
if (!ast) {
return;
}
}
switch (bc->AOCDtype) {
case Fac_AOCDCurrency:
pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
if (bc->AOCD.currency.chargeNotAvailable) {
pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
} else {
pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
if (bc->AOCD.currency.freeOfCharge) {
pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
} else {
pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) {
pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
}
}
}
}
break;
case Fac_AOCDChargingUnit:
pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
if (bc->AOCD.chargingUnit.chargeNotAvailable) {
pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
} else {
pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
if (bc->AOCD.chargingUnit.freeOfCharge) {
pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
} else {
pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) {
pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
}
}
}
}
break;
default:
break;
}
bc->AOCD_need_export = 0;
}
| void export_ch | ( | struct ast_channel * | chan, |
| struct misdn_bchannel * | bc, | ||
| struct chan_list * | ch | ||
| ) |
Export parameters to the dialplan environment variables.
Definition at line 8811 of file chan_misdn.c.
References ast_strlen_zero(), chan_misdn_log(), misdn_bchannel::keypad, pbx_builtin_setvar_helper(), misdn_bchannel::pid, misdn_bchannel::port, misdn_bchannel::sending_complete, misdn_bchannel::urate, misdn_bchannel::uu, and misdn_bchannel::uulen.
Referenced by cb_events().
{
char tmp[32];
/*
* The only use for MISDN_PID is if there is a problem and you
* have to use the "misdn restart pid" CLI command. Otherwise,
* the pid is not used by anyone. The internal use of MISDN_PID
* has been deleted.
*/
chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
snprintf(tmp, sizeof(tmp), "%d", bc->pid);
pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
if (bc->sending_complete) {
snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
}
if (bc->urate) {
snprintf(tmp, sizeof(tmp), "%d", bc->urate);
pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
}
if (bc->uulen) {
pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
}
if (!ast_strlen_zero(bc->keypad)) {
pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
}
}
| static struct chan_list* find_chan_by_bc | ( | struct misdn_bchannel * | bc | ) | [static, read] |
Returns a reference to the found chan_list.
Definition at line 8223 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, chan_list::bc, misdn_bchannel::caller, chan_list_ref, chan_misdn_log(), misdn_bchannel::dialed, misdn_party_id::name, chan_list::next, misdn_party_dialing::number, misdn_party_id::number, and misdn_bchannel::port.
Referenced by cb_events(), and chan_misdn_jb_empty().
{
struct chan_list *help;
ast_mutex_lock(&cl_te_lock);
for (help = cl_te; help; help = help->next) {
if (help->bc == bc) {
chan_list_ref(help, "Found chan_list by bc");
ast_mutex_unlock(&cl_te_lock);
return help;
}
}
ast_mutex_unlock(&cl_te_lock);
chan_misdn_log(6, bc->port,
"$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
bc->dialed.number,
bc->caller.name,
bc->caller.number);
return NULL;
}
| static struct chan_list* find_hold_active_call | ( | struct misdn_bchannel * | bc | ) | [static, read] |
Definition at line 8315 of file chan_misdn.c.
References chan_list::ast, ast_mutex_lock, ast_mutex_unlock, chan_list::bc, chan_list_ref, chan_list::hold, MISDN_ALERTING, MISDN_CONNECTED, MISDN_HOLD_IDLE, MISDN_PROCEEDING, MISDN_PROGRESS, chan_list::next, misdn_bchannel::port, hold_info::state, and chan_list::state.
Referenced by cb_events().
{
struct chan_list *list;
ast_mutex_lock(&cl_te_lock);
for (list = cl_te; list; list = list->next) {
if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
&& list->ast) {
switch (list->state) {
case MISDN_PROCEEDING:
case MISDN_PROGRESS:
case MISDN_ALERTING:
case MISDN_CONNECTED:
chan_list_ref(list, "Found chan_list hold active call");
ast_mutex_unlock(&cl_te_lock);
return list;
default:
break;
}
}
}
ast_mutex_unlock(&cl_te_lock);
return NULL;
}
| static struct chan_list* find_hold_call | ( | struct misdn_bchannel * | bc | ) | [static, read] |
Returns a reference to the found chan_list.
Definition at line 8247 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, misdn_bchannel::caller, chan_list_ref, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, misdn_bchannel::dialed, chan_list::hold, MISDN_HOLD_ACTIVE, misdn_party_id::name, chan_list::next, misdn_party_dialing::number, misdn_party_id::number, hold_info::port, misdn_bchannel::port, misdn_bchannel::pri, and hold_info::state.
Referenced by cb_events().
{
struct chan_list *help;
if (bc->pri) {
return NULL;
}
chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d dialed:%s caller:\"%s\" <%s>\n",
bc->channel,
bc->dialed.number,
bc->caller.name,
bc->caller.number);
ast_mutex_lock(&cl_te_lock);
for (help = cl_te; help; help = help->next) {
chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
chan_list_ref(help, "Found chan_list hold call");
ast_mutex_unlock(&cl_te_lock);
return help;
}
}
ast_mutex_unlock(&cl_te_lock);
chan_misdn_log(6, bc->port,
"$$$ find_hold_call: No channel found for dialed:%s caller:\"%s\" <%s>\n",
bc->dialed.number,
bc->caller.name,
bc->caller.number);
return NULL;
}
| static struct chan_list* find_hold_call_l3 | ( | unsigned long | l3_id | ) | [static, read] |
Returns a reference to the found chan_list.
Definition at line 8281 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, chan_list_ref, chan_list::hold, chan_list::l3id, MISDN_HOLD_IDLE, chan_list::next, and hold_info::state.
Referenced by cb_events().
{
struct chan_list *help;
ast_mutex_lock(&cl_te_lock);
for (help = cl_te; help; help = help->next) {
if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
chan_list_ref(help, "Found chan_list hold call l3");
ast_mutex_unlock(&cl_te_lock);
return help;
}
}
ast_mutex_unlock(&cl_te_lock);
return NULL;
}
| static void free_robin_list | ( | void | ) | [static] |
Definition at line 604 of file chan_misdn.c.
References ast_free, robin_list::group, and robin_list::next.
Referenced by reload_config(), and unload_module().
{
struct robin_list *r;
struct robin_list *next;
for (r = robin, robin = NULL; r; r = next) {
next = r->next;
ast_free(r->group);
ast_free(r);
}
}
| static struct chan_list* get_chan_by_ast | ( | struct ast_channel * | ast | ) | [static, read] |
Returns a reference to the found chan_list.
Definition at line 744 of file chan_misdn.c.
References chan_list::ast, ast_mutex_lock, ast_mutex_unlock, chan_list_ref, and chan_list::next.
Referenced by misdn_bridge().
{
struct chan_list *tmp;
ast_mutex_lock(&cl_te_lock);
for (tmp = cl_te; tmp; tmp = tmp->next) {
if (tmp->ast == ast) {
chan_list_ref(tmp, "Found chan_list by ast");
ast_mutex_unlock(&cl_te_lock);
return tmp;
}
}
ast_mutex_unlock(&cl_te_lock);
return NULL;
}
| static struct chan_list* get_chan_by_ast_name | ( | const char * | name | ) | [static, read] |
Returns a reference to the found chan_list.
Definition at line 762 of file chan_misdn.c.
References chan_list::ast, ast_channel_name(), ast_mutex_lock, ast_mutex_unlock, chan_list_ref, and chan_list::next.
Referenced by handle_cli_misdn_send_digit(), handle_cli_misdn_send_display(), handle_cli_misdn_send_facility(), and handle_cli_misdn_toggle_echocancel().
{
struct chan_list *tmp;
ast_mutex_lock(&cl_te_lock);
for (tmp = cl_te; tmp; tmp = tmp->next) {
if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
chan_list_ref(tmp, "Found chan_list by ast name");
ast_mutex_unlock(&cl_te_lock);
return tmp;
}
}
ast_mutex_unlock(&cl_te_lock);
return NULL;
}
| static struct robin_list* get_robin_position | ( | char * | group | ) | [static, read] |
Definition at line 616 of file chan_misdn.c.
References ast_calloc, ast_free, ast_strdup, robin_list::group, robin_list::next, robin_list::prev, and robin.
Referenced by misdn_request().
{
struct robin_list *new;
struct robin_list *iter = robin;
for (; iter; iter = iter->next) {
if (!strcasecmp(iter->group, group)) {
return iter;
}
}
new = ast_calloc(1, sizeof(*new));
if (!new) {
return NULL;
}
new->group = ast_strdup(group);
if (!new->group) {
ast_free(new);
return NULL;
}
new->channel = 1;
if (robin) {
new->next = robin;
robin->prev = new;
}
robin = new;
return robin;
}
| static char* handle_cli_misdn_port_block | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3803 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_block(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn port block";
e->usage =
"Usage: misdn port block <port>\n"
" Block the specified port by <port>.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
misdn_lib_port_block(atoi(a->argv[3]));
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_port_down | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3913 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_get_port_down(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn port down";
e->usage =
"Usage: misdn port down <port>\n"
" Try to deactivate the L1 on the given port.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
misdn_lib_get_port_down(atoi(a->argv[3]));
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_port_unblock | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3825 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_unblock(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn port unblock";
e->usage =
"Usage: misdn port unblock <port>\n"
" Unblock the port specified by <port>.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
misdn_lib_port_unblock(atoi(a->argv[3]));
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_port_up | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3891 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_get_port_up(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn port up";
e->usage =
"Usage: misdn port up <port>\n"
" Try to establish L1 on the given port.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
misdn_lib_get_port_up(atoi(a->argv[3]));
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_reload | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 4117 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, reload_config(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn reload";
e->usage =
"Usage: misdn reload\n"
" Reload internal mISDN config, read from the config\n"
" file.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 2) {
return CLI_SHOWUSAGE;
}
ast_cli(a->fd, "Reloading mISDN configuration\n");
reload_config();
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_restart_pid | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3869 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_pid_restart(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn restart pid";
e->usage =
"Usage: misdn restart pid <pid>\n"
" Restart the given pid\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
misdn_lib_pid_restart(atoi(a->argv[3]));
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_restart_port | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3847 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_restart(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn restart port";
e->usage =
"Usage: misdn restart port <port>\n"
" Restart the given port.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
misdn_lib_port_restart(atoi(a->argv[3]));
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_send_digit | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 5482 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, chan_list::ast, ast_cli(), ast_dtmf_stream(), chan_list_unref, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, get_chan_by_ast_name(), send_digit_to_chan(), and ast_cli_entry::usage.
{
const char *channame;
const char *msg;
struct chan_list *tmp;
int i, msglen;
switch (cmd) {
case CLI_INIT:
e->command = "misdn send digit";
e->usage =
"Usage: misdn send digit <channel> \"<msg>\" \n"
" Send <digit> to <channel> as DTMF Tone\n"
" when channel is a mISDN channel\n";
return NULL;
case CLI_GENERATE:
return complete_ch(a);
}
if (a->argc != 5) {
return CLI_SHOWUSAGE;
}
channame = a->argv[3];
msg = a->argv[4];
msglen = strlen(msg);
ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
tmp = get_chan_by_ast_name(channame);
if (!tmp) {
ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
return CLI_SUCCESS;
}
#if 1
for (i = 0; i < msglen; i++) {
if (!tmp->ast) {
break;
}
ast_cli(a->fd, "Sending: %c\n", msg[i]);
send_digit_to_chan(tmp, msg[i]);
/* res = ast_safe_sleep(tmp->ast, 250); */
usleep(250000);
/* res = ast_waitfor(tmp->ast,100); */
}
#else
if (tmp->ast) {
ast_dtmf_stream(tmp->ast, NULL, msg, 250);
}
#endif
chan_list_unref(tmp, "Digit(s) sent");
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_send_display | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 5584 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), chan_list::bc, chan_list_unref, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), misdn_bchannel::display, EVENT_INFORMATION, ast_cli_args::fd, get_chan_by_ast_name(), misdn_lib_send_event(), and ast_cli_entry::usage.
{
const char *channame;
const char *msg;
struct chan_list *tmp;
switch (cmd) {
case CLI_INIT:
e->command = "misdn send display";
e->usage =
"Usage: misdn send display <channel> \"<msg>\" \n"
" Send <msg> to <channel> as Display Message\n"
" when channel is a mISDN channel\n";
return NULL;
case CLI_GENERATE:
return complete_ch(a);
}
if (a->argc != 5) {
return CLI_SHOWUSAGE;
}
channame = a->argv[3];
msg = a->argv[4];
ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
tmp = get_chan_by_ast_name(channame);
if (tmp && tmp->bc) {
ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
chan_list_unref(tmp, "Done sending display");
} else {
if (tmp) {
chan_list_unref(tmp, "Display failed");
}
ast_cli(a->fd, "No such channel %s\n", channame);
return CLI_SUCCESS;
}
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_send_facility | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 5156 of file chan_misdn.c.
References ao2_lock, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ARRAY_LEN, ast_copy_string(), ast_verbose(), chan_list::bc, chan_list_unref, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), dummy(), EVENT_FACILITY, EVENT_REGISTER, misdn_bchannel::fac_out, get_chan_by_ast_name(), misdn_lib_port_is_nt(), misdn_lib_send_event(), misdn_make_dummy(), print_facility(), and ast_cli_entry::usage.
{
const char *channame;
const char *nr;
struct chan_list *tmp;
int port;
const char *served_nr;
struct misdn_bchannel dummy, *bc=&dummy;
unsigned max_len;
switch (cmd) {
case CLI_INIT:
e->command = "misdn send facility";
e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
"\t type is one of:\n"
"\t - calldeflect\n"
#if defined(AST_MISDN_ENHANCEMENTS)
"\t - callrerouting\n"
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
"\t - CFActivate\n"
"\t - CFDeactivate\n";
return NULL;
case CLI_GENERATE:
return complete_ch(a);
}
if (a->argc < 5) {
return CLI_SHOWUSAGE;
}
if (strstr(a->argv[3], "calldeflect")) {
if (a->argc < 6) {
ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
return 0;
}
channame = a->argv[4];
nr = a->argv[5];
ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
tmp = get_chan_by_ast_name(channame);
if (!tmp) {
ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
return 0;
}
ao2_lock(tmp);
#if defined(AST_MISDN_ENHANCEMENTS)
max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
if (max_len < strlen(nr)) {
ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
nr, channame, max_len);
ao2_unlock(tmp);
chan_list_unref(tmp, "Number too long");
return 0;
}
tmp->bc->fac_out.Function = Fac_CallDeflection;
tmp->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
tmp->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(nr);
strcpy((char *) tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, nr);
tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
#else /* !defined(AST_MISDN_ENHANCEMENTS) */
max_len = sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
if (max_len < strlen(nr)) {
ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
nr, channame, max_len);
ao2_unlock(tmp);
chan_list_unref(tmp, "Number too long");
return 0;
}
tmp->bc->fac_out.Function = Fac_CD;
tmp->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
//tmp->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
strcpy((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr);
#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
/* Send message */
print_facility(&tmp->bc->fac_out, tmp->bc);
ao2_unlock(tmp);
misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
chan_list_unref(tmp, "Send facility complete");
#if defined(AST_MISDN_ENHANCEMENTS)
} else if (strstr(a->argv[3], "callrerouteing") || strstr(a->argv[3], "callrerouting")) {
if (a->argc < 6) {
ast_verbose("callrerouting requires 1 arg: ToNumber\n\n");
return 0;
}
channame = a->argv[4];
nr = a->argv[5];
ast_verbose("Sending Callrerouting (%s) to %s\n", nr, channame);
tmp = get_chan_by_ast_name(channame);
if (!tmp) {
ast_verbose("Sending Call Rerouting with nr %s to %s failed: Channel does not exist.\n", nr, channame);
return 0;
}
ao2_lock(tmp);
max_len = sizeof(tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
if (max_len < strlen(nr)) {
ast_verbose("Sending Call Rerouting with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
nr, channame, max_len);
ao2_unlock(tmp);
chan_list_unref(tmp, "Number too long");
return 0;
}
tmp->bc->fac_out.Function = Fac_CallRerouteing;
tmp->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
tmp->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(nr);
strcpy((char *) tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, nr);
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
/* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
/* Send message */
print_facility(&tmp->bc->fac_out, tmp->bc);
ao2_unlock(tmp);
misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
chan_list_unref(tmp, "Send facility complete");
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
} else if (strstr(a->argv[3], "CFActivate")) {
if (a->argc < 7) {
ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
return 0;
}
port = atoi(a->argv[4]);
served_nr = a->argv[5];
nr = a->argv[6];
misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
ast_verbose("Sending CFActivate Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
#if defined(AST_MISDN_ENHANCEMENTS)
bc->fac_out.Function = Fac_ActivationDiversion;
bc->fac_out.u.ActivationDiversion.InvokeID = ++misdn_invoke_id;
bc->fac_out.u.ActivationDiversion.ComponentType = FacComponent_Invoke;
bc->fac_out.u.ActivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
bc->fac_out.u.ActivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number,
served_nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number));
bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number);
bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number,
nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number));
bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber =
strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number);
bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 0;/* unknown */
bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Subaddress.Length = 0;
#else /* !defined(AST_MISDN_ENHANCEMENTS) */
bc->fac_out.Function = Fac_CFActivate;
bc->fac_out.u.CFActivate.BasicService = 0; /* All Services */
bc->fac_out.u.CFActivate.Procedure = 0; /* Unconditional */
ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
ast_copy_string((char *) bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
/* Send message */
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
} else if (strstr(a->argv[3], "CFDeactivate")) {
if (a->argc < 6) {
ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
return 0;
}
port = atoi(a->argv[4]);
served_nr = a->argv[5];
misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr);
#if defined(AST_MISDN_ENHANCEMENTS)
bc->fac_out.Function = Fac_DeactivationDiversion;
bc->fac_out.u.DeactivationDiversion.InvokeID = ++misdn_invoke_id;
bc->fac_out.u.DeactivationDiversion.ComponentType = FacComponent_Invoke;
bc->fac_out.u.DeactivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
bc->fac_out.u.DeactivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
ast_copy_string((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number,
served_nr, sizeof(bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number));
bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
strlen((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number);
bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
#else /* !defined(AST_MISDN_ENHANCEMENTS) */
bc->fac_out.Function = Fac_CFDeactivate;
bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
/* Send message */
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
#if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
} else if (strstr(a->argv[3], "test")) {
int msg_number;
if (a->argc < 5) {
ast_verbose("test (<port> [<msg#>]) | (<channel-name> <msg#>)\n\n");
return 0;
}
port = atoi(a->argv[4]);
channame = a->argv[4];
tmp = get_chan_by_ast_name(channame);
if (tmp) {
/* We are going to send this FACILITY message out on an existing connection */
msg_number = atoi(a->argv[5]);
if (msg_number < ARRAY_LEN(Fac_Msgs)) {
ao2_lock(tmp);
tmp->bc->fac_out = Fac_Msgs[msg_number];
/* Send message */
print_facility(&tmp->bc->fac_out, tmp->bc);
ao2_unlock(tmp);
misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
} else {
ast_verbose("test <channel-name> <msg#>\n\n");
}
chan_list_unref(tmp, "Facility test done");
} else if (a->argc < 6) {
for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) {
misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
bc->fac_out = Fac_Msgs[msg_number];
/* Send message */
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
sleep(1);
}
} else {
msg_number = atoi(a->argv[5]);
if (msg_number < ARRAY_LEN(Fac_Msgs)) {
misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
bc->fac_out = Fac_Msgs[msg_number];
/* Send message */
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
} else {
ast_verbose("test <port> [<msg#>]\n\n");
}
}
} else if (strstr(a->argv[3], "register")) {
if (a->argc < 5) {
ast_verbose("register <port>\n\n");
return 0;
}
port = atoi(a->argv[4]);
bc = misdn_lib_get_register_bc(port);
if (!bc) {
ast_verbose("Could not allocate REGISTER bc struct\n\n");
return 0;
}
bc->fac_out = Fac_Msgs[45];
/* Send message */
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_REGISTER);
#endif /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
}
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_send_restart | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 5450 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, misdn_bchannel::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_send_restart(), misdn_bchannel::port, and ast_cli_entry::usage.
{
int port;
int channel;
switch (cmd) {
case CLI_INIT:
e->command = "misdn send restart";
e->usage =
"Usage: misdn send restart [port [channel]]\n"
" Send a restart for every bchannel on the given port.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc < 4 || a->argc > 5) {
return CLI_SHOWUSAGE;
}
port = atoi(a->argv[3]);
if (a->argc == 5) {
channel = atoi(a->argv[4]);
misdn_lib_send_restart(port, channel);
} else {
misdn_lib_send_restart(port, -1);
}
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_set_crypt_debug | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3780 of file chan_misdn.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn set crypt debug";
e->usage =
"Usage: misdn set crypt debug <level>\n"
" Set the crypt debug level of the mISDN channel. Level\n"
" must be 1 or 2.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 5) {
return CLI_SHOWUSAGE;
}
/* XXX Is this supposed to not do anything? XXX */
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_set_debug | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3693 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_debug_port(), ast_cli_args::fd, max_ports, and ast_cli_entry::usage.
{
int level;
switch (cmd) {
case CLI_INIT:
e->command = "misdn set debug [on|off]";
e->usage =
"Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
" Set the debug level of the mISDN channel.\n";
return NULL;
case CLI_GENERATE:
return complete_debug_port(a);
}
if (a->argc < 4 || a->argc > 7) {
return CLI_SHOWUSAGE;
}
if (!strcasecmp(a->argv[3], "on")) {
level = 1;
} else if (!strcasecmp(a->argv[3], "off")) {
level = 0;
} else if (isdigit(a->argv[3][0])) {
level = atoi(a->argv[3]);
} else {
return CLI_SHOWUSAGE;
}
switch (a->argc) {
case 4:
case 5:
{
int i;
int only = 0;
if (a->argc == 5) {
if (strncasecmp(a->argv[4], "only", strlen(a->argv[4]))) {
return CLI_SHOWUSAGE;
} else {
only = 1;
}
}
for (i = 0; i <= max_ports; i++) {
misdn_debug[i] = level;
misdn_debug_only[i] = only;
}
ast_cli(a->fd, "changing debug level for all ports to %d%s\n", misdn_debug[0], only ? " (only)" : "");
}
break;
case 6:
case 7:
{
int port;
if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
return CLI_SHOWUSAGE;
port = atoi(a->argv[5]);
if (port <= 0 || port > max_ports) {
switch (max_ports) {
case 0:
ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
break;
case 1:
ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
break;
default:
ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
}
return 0;
}
if (a->argc == 7) {
if (strncasecmp(a->argv[6], "only", strlen(a->argv[6]))) {
return CLI_SHOWUSAGE;
} else {
misdn_debug_only[port] = 1;
}
} else {
misdn_debug_only[port] = 0;
}
misdn_debug[port] = level;
ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port] ? " (only)" : "", port);
}
}
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_set_tics | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 4312 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "misdn set tics";
e->usage =
"Usage: misdn set tics <value>\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
/* XXX Wow, this does... a whole lot of nothing... XXX */
MAXTICS = atoi(a->argv[3]);
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_show_channel | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 4276 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, chan_list::ast, ast_channel_name(), ast_mutex_lock, ast_mutex_unlock, chan_list::bc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, chan_list::next, print_bc_info(), and ast_cli_entry::usage.
{
struct chan_list *help;
switch (cmd) {
case CLI_INIT:
e->command = "misdn show channel";
e->usage =
"Usage: misdn show channel <channel>\n"
" Show an internal mISDN channel\n.";
return NULL;
case CLI_GENERATE:
return complete_ch(a);
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
ast_mutex_lock(&cl_te_lock);
for (help = cl_te; help; help = help->next) {
struct misdn_bchannel *bc = help->bc;
struct ast_channel *ast = help->ast;
if (bc && ast) {
if (!strcasecmp(ast_channel_name(ast), a->argv[3])) {
print_bc_info(a->fd, help, bc);
break;
}
}
}
ast_mutex_unlock(&cl_te_lock);
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_show_channels | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 4203 of file chan_misdn.c.
References ast_cli_args::argc, chan_list::ast, ast_channel_caller(), ast_channel_exten(), ast_cli(), ast_mutex_lock, ast_mutex_unlock, chan_list::bc, hold_info::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, chan_list::hold, chan_list::l3id, misdn_dump_chanlist(), MISDN_HOLD_IDLE, name, chan_list::next, misdn_bchannel::pid, hold_info::port, print_bc_info(), S_COR, hold_info::state, and ast_cli_entry::usage.
{
struct chan_list *help;
switch (cmd) {
case CLI_INIT:
e->command = "misdn show channels";
e->usage =
"Usage: misdn show channels\n"
" Show the internal mISDN channel list\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3) {
return CLI_SHOWUSAGE;
}
ast_cli(a->fd, "Channel List: %p\n", cl_te);
/*
* Walking the list and dumping the channel information could
* take awhile. With the list locked for the duration, the
* channel driver cannot process signaling messages. However,
* since this is a CLI command it should not be run very often.
*/
ast_mutex_lock(&cl_te_lock);
for (help = cl_te; help; help = help->next) {
struct misdn_bchannel *bc = help->bc;
struct ast_channel *ast = help->ast;
if (!ast) {
if (!bc) {
ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
continue;
}
ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
}
if (misdn_debug[0] > 2) {
ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
}
if (bc) {
print_bc_info(a->fd, help, bc);
} else {
if (help->hold.state != MISDN_HOLD_IDLE) {
ast_cli(a->fd, "ITS A HELD CALL BC:\n");
ast_cli(a->fd, " --> l3_id: %x\n"
" --> dialed:%s\n"
" --> caller:\"%s\" <%s>\n"
" --> hold_port: %d\n"
" --> hold_channel: %d\n",
help->l3id,
ast_channel_exten(ast),
S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, ""),
S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""),
help->hold.port,
help->hold.channel
);
} else {
ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n",
ast_channel_exten(ast),
S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""));
}
}
}
ast_mutex_unlock(&cl_te_lock);
misdn_dump_chanlist();
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_show_config | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3960 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), BUFFERSIZE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_config(), ast_cli_args::fd, MISDN_CFG_FIRST, misdn_cfg_get_config_string(), misdn_cfg_get_elem(), misdn_cfg_get_next_port(), misdn_cfg_is_port_valid(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, show_config_description(), and ast_cli_entry::usage.
{
char buffer[BUFFERSIZE];
enum misdn_cfg_elements elem;
int linebreak;
int onlyport = -1;
int ok = 0;
switch (cmd) {
case CLI_INIT:
e->command = "misdn show config";
e->usage =
"Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
" Use 0 for <port> to only print the general config.\n";
return NULL;
case CLI_GENERATE:
return complete_show_config(a);
}
if (a->argc >= 4) {
if (!strcmp(a->argv[3], "description")) {
if (a->argc == 5) {
enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
if (elem == MISDN_CFG_FIRST) {
ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
} else {
show_config_description(a->fd, elem);
}
return CLI_SUCCESS;
}
return CLI_SHOWUSAGE;
} else if (!strcmp(a->argv[3], "descriptions")) {
if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
show_config_description(a->fd, elem);
ast_cli(a->fd, "\n");
}
ok = 1;
}
if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
show_config_description(a->fd, elem);
ast_cli(a->fd, "\n");
}
ok = 1;
}
return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
} else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
return CLI_SHOWUSAGE;
}
}
if (a->argc == 3 || onlyport == 0) {
ast_cli(a->fd, "mISDN General-Config:\n");
for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
}
ast_cli(a->fd, "\n");
}
if (onlyport < 0) {
int port = misdn_cfg_get_next_port(0);
for (; port > 0; port = misdn_cfg_get_next_port(port)) {
ast_cli(a->fd, "\n[PORT %d]\n", port);
for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
}
ast_cli(a->fd, "\n");
}
}
if (onlyport > 0) {
if (misdn_cfg_is_port_valid(onlyport)) {
ast_cli(a->fd, "[PORT %d]\n", onlyport);
for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
}
ast_cli(a->fd, "\n");
} else {
ast_cli(a->fd, "Port %d is not active!\n", onlyport);
}
}
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_show_port | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 4394 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_show_stack_details(), and ast_cli_entry::usage.
{
int port;
char buf[128];
switch (cmd) {
case CLI_INIT:
e->command = "misdn show port";
e->usage =
"Usage: misdn show port <port>\n"
" Show detailed information for given port.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
port = atoi(a->argv[3]);
ast_cli(a->fd, "BEGIN STACK_LIST:\n");
get_show_stack_details(port, buf);
ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_show_ports_stats | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 4365 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, misdn_cfg_get_next_port(), and ast_cli_entry::usage.
{
int port;
switch (cmd) {
case CLI_INIT:
e->command = "misdn show ports stats";
e->usage =
"Usage: misdn show ports stats\n"
" Show mISDNs channel's call statistics per port.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
for (port = misdn_cfg_get_next_port(0); port > 0;
port = misdn_cfg_get_next_port(port)) {
ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
}
ast_cli(a->fd, "\n");
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_show_stacks | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 4334 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_show_stack_details(), misdn_cfg_get_next_port(), and ast_cli_entry::usage.
{
int port;
switch (cmd) {
case CLI_INIT:
e->command = "misdn show stacks";
e->usage =
"Usage: misdn show stacks\n"
" Show internal mISDN stack_list.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3) {
return CLI_SHOWUSAGE;
}
ast_cli(a->fd, "BEGIN STACK_LIST:\n");
for (port = misdn_cfg_get_next_port(0); port > 0;
port = misdn_cfg_get_next_port(port)) {
char buf[128];
get_show_stack_details(port, buf);
ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
}
return CLI_SUCCESS;
}
| static char* handle_cli_misdn_toggle_echocancel | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 5537 of file chan_misdn.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), chan_list::bc, chan_list_unref, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, get_chan_by_ast_name(), manager_ec_disable(), manager_ec_enable(), chan_list::toggle_ec, update_ec_config(), and ast_cli_entry::usage.
{
const char *channame;
struct chan_list *tmp;
switch (cmd) {
case CLI_INIT:
e->command = "misdn toggle echocancel";
e->usage =
"Usage: misdn toggle echocancel <channel>\n"
" Toggle EchoCancel on mISDN Channel.\n";
return NULL;
case CLI_GENERATE:
return complete_ch(a);
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
channame = a->argv[3];
ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
tmp = get_chan_by_ast_name(channame);
if (!tmp) {
ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
return CLI_SUCCESS;
}
tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
if (tmp->toggle_ec) {
#ifdef MISDN_1_2
update_pipeline_config(tmp->bc);
#else
update_ec_config(tmp->bc);
#endif
manager_ec_enable(tmp->bc);
} else {
manager_ec_disable(tmp->bc);
}
chan_list_unref(tmp, "Done toggling echo cancel");
return CLI_SUCCESS;
}
| static void hangup_chan | ( | struct chan_list * | ch, |
| struct misdn_bchannel * | bc | ||
| ) | [static] |
Definition at line 8411 of file chan_misdn.c.
References chan_list::ast, ast_hangup(), ast_queue_hangup_with_cause(), misdn_bchannel::cause, cb_log, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::port, and send_cause2ast().
Referenced by cb_events(), do_immediate_setup(), local_hangup(), and start_pbx().
{
int port = bc->port;
if (!ch) {
cb_log(1, port, "Cannot hangup chan, no ch\n");
return;
}
cb_log(5, port, "hangup_chan called\n");
if (ch->need_hangup) {
cb_log(2, port, " --> hangup\n");
ch->need_hangup = 0;
ch->need_queue_hangup = 0;
if (ch->ast && send_cause2ast(ch->ast, bc, ch)) {
ast_hangup(ch->ast);
}
return;
}
if (!ch->need_queue_hangup) {
cb_log(2, port, " --> No need to queue hangup\n");
return;
}
ch->need_queue_hangup = 0;
if (ch->ast) {
if (send_cause2ast(ch->ast, bc, ch)) {
ast_queue_hangup_with_cause(ch->ast, bc->cause);
cb_log(2, port, " --> queue_hangup\n");
}
} else {
cb_log(1, port, "Cannot hangup chan, no ast\n");
}
}
| static void hanguptone_indicate | ( | struct chan_list * | cl | ) | [static] |
Definition at line 7695 of file chan_misdn.c.
References chan_list::bc, misdn_lib_send_tone(), and TONE_HANGUP.
Referenced by cb_events(), do_immediate_setup(), misdn_hangup(), misdn_indication(), misdn_overlap_dial_task(), and start_pbx().
{
misdn_lib_send_tone(cl->bc, TONE_HANGUP);
}
| void import_ch | ( | struct ast_channel * | chan, |
| struct misdn_bchannel * | bc, | ||
| struct chan_list * | ch | ||
| ) |
Import parameters from the dialplan environment variables.
Definition at line 8786 of file chan_misdn.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), misdn_bchannel::keypad, LOG_NOTICE, pbx_builtin_getvar_helper(), misdn_bchannel::sending_complete, misdn_bchannel::uu, and misdn_bchannel::uulen.
Referenced by misdn_call().
{
const char *tmp;
ast_channel_lock(chan);
tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
if (tmp && (atoi(tmp) == 1)) {
bc->sending_complete = 1;
}
tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
if (tmp) {
ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
bc->uulen = strlen(bc->uu);
}
tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
if (tmp) {
ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
}
ast_channel_unlock(chan);
}
| static int load_module | ( | void | ) | [static] |
Definition at line 11276 of file chan_misdn.c.
References ast_calloc, ast_channel_register(), ast_cli_register_multiple(), ast_custom_function_register, AST_FORMAT_ALAW, ast_format_cap_add(), ast_format_cap_alloc(), ast_format_set(), ast_free, ast_log(), ast_malloc, AST_MODULE_LOAD_DECLINE, ast_mutex_init, ast_register_application, ast_strlen_zero(), BUFFERSIZE, ast_channel_tech::capabilities, misdn_lib_iface::cb_event, cb_events(), chan_misdn_jb_empty(), chan_misdn_log(), LOG_ERROR, max_ports, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), MISDN_CFG_L1_TIMEOUT, misdn_cfg_update_ptp(), misdn_check_l2l1(), misdn_facility_exec(), MISDN_GEN_DEBUG, MISDN_GEN_NTDEBUGFILE, MISDN_GEN_NTDEBUGFLAGS, MISDN_GEN_NTKEEPCALLS, MISDN_GEN_TRACEFILE, misdn_l1_task(), misdn_lib_init(), misdn_lib_maxports_get(), misdn_lib_nt_debug_init(), misdn_lib_nt_keepcalls(), misdn_set_opt_exec(), misdn_tasks_add(), prefformat, and unload_module().
{
int i, port;
int ntflags = 0, ntkc = 0;
char ports[256] = "";
char tempbuf[BUFFERSIZE + 1];
char ntfile[BUFFERSIZE + 1];
struct misdn_lib_iface iface = {
.cb_event = cb_events,
.cb_log = chan_misdn_log,
.cb_jb_empty = chan_misdn_jb_empty,
};
if (!(misdn_tech.capabilities = ast_format_cap_alloc())) {
return AST_MODULE_LOAD_DECLINE;
}
if (!(misdn_tech_wo_bridge.capabilities = ast_format_cap_alloc())) {
return AST_MODULE_LOAD_DECLINE;
}
ast_format_set(&prefformat, AST_FORMAT_ALAW, 0);
ast_format_cap_add(misdn_tech.capabilities, &prefformat);
ast_format_cap_add(misdn_tech_wo_bridge.capabilities, &prefformat);
max_ports = misdn_lib_maxports_get();
if (max_ports <= 0) {
ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
return AST_MODULE_LOAD_DECLINE;
}
if (misdn_cfg_init(max_ports, 0)) {
ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
return AST_MODULE_LOAD_DECLINE;
}
g_config_initialized = 1;
#if defined(AST_MISDN_ENHANCEMENTS)
misdn_cc_init();
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
if (!misdn_debug) {
ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
return AST_MODULE_LOAD_DECLINE;
}
misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
if (!misdn_ports) {
ast_free(misdn_debug);
ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
return AST_MODULE_LOAD_DECLINE;
}
misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
for (i = 1; i <= max_ports; i++) {
misdn_debug[i] = misdn_debug[0];
misdn_ports[i] = i;
}
*misdn_ports = 0;
misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
if (!misdn_debug_only) {
ast_free(misdn_ports);
ast_free(misdn_debug);
ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
return AST_MODULE_LOAD_DECLINE;
}
misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
if (!ast_strlen_zero(tempbuf)) {
tracing = 1;
}
misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
if (!misdn_in_calls) {
ast_free(misdn_debug_only);
ast_free(misdn_ports);
ast_free(misdn_debug);
ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
return AST_MODULE_LOAD_DECLINE;
}
misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
if (!misdn_out_calls) {
ast_free(misdn_in_calls);
ast_free(misdn_debug_only);
ast_free(misdn_ports);
ast_free(misdn_debug);
ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
return AST_MODULE_LOAD_DECLINE;
}
for (i = 1; i <= max_ports; i++) {
misdn_in_calls[i] = 0;
misdn_out_calls[i] = 0;
}
ast_mutex_init(&cl_te_lock);
ast_mutex_init(&release_lock);
misdn_cfg_update_ptp();
misdn_cfg_get_ports_string(ports);
if (!ast_strlen_zero(ports)) {
chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
}
if (misdn_lib_init(ports, &iface, NULL)) {
chan_misdn_log(0, 0, "No te ports initialized\n");
}
misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
misdn_cfg_get(0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
misdn_lib_nt_keepcalls(ntkc);
misdn_lib_nt_debug_init(ntflags, ntfile);
if (ast_channel_register(&misdn_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
unload_module();
return AST_MODULE_LOAD_DECLINE;
}
ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
"misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
"Sets mISDN opts. and optargs\n"
"\n"
"The available options are:\n"
" a - Have Asterisk detect DTMF tones on called channel\n"
" c - Make crypted outgoing call, optarg is keyindex\n"
" d - Send display text to called phone, text is the optarg\n"
" e - Perform echo cancellation on this channel,\n"
" takes taps as optarg (32,64,128,256)\n"
" e! - Disable echo cancellation on this channel\n"
" f - Enable fax detection\n"
" h - Make digital outgoing call\n"
" h1 - Make HDLC mode digital outgoing call\n"
" i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
" they will be transported inband.\n"
" jb - Set jitter buffer length, optarg is length\n"
" jt - Set jitter buffer upper threshold, optarg is threshold\n"
" jn - Disable jitter buffer\n"
" n - Disable mISDN DSP on channel.\n"
" Disables: echo cancel, DTMF detection, and volume control.\n"
" p - Caller ID presentation,\n"
" optarg is either 'allowed' or 'restricted'\n"
" s - Send Non-inband DTMF as inband\n"
" vr - Rx gain control, optarg is gain\n"
" vt - Tx gain control, optarg is gain\n"
);
ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
"misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
"Sends the Facility Message FACILITY_TYPE with \n"
"the given Arguments to the current ISDN Channel\n"
"Supported Facilities are:\n"
"\n"
"type=calldeflect args=Nr where to deflect\n"
#if defined(AST_MISDN_ENHANCEMENTS)
"type=callrerouting args=Nr where to deflect\n"
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
);
ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
"misdn_check_l2l1(<port>||g:<groupname>,timeout)\n"
"Checks if the L2 and L1 are up on either the given <port> or\n"
"on the ports in the group with <groupname>\n"
"If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
"for <timeout> seconds that this happens. Otherwise, nothing happens\n"
"\n"
"This application, ensures the L1/L2 state of the Ports in a group\n"
"it is intended to make the pmp_l1_check option redundant and to\n"
"fix a buggy switch config from your provider\n"
"\n"
"a sample dialplan would look like:\n\n"
"exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
"exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
);
#if defined(AST_MISDN_ENHANCEMENTS)
ast_register_application(misdn_command_name, misdn_command_exec, misdn_command_name,
"misdn_command(<command>[,<options>])\n"
"The following commands are defined:\n"
"cc-initialize\n"
" Setup mISDN support for call completion\n"
" Must call before doing any Dial() involving call completion.\n"
"ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
" Request Call Completion No Reply activation\n"
"ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
" Request Call Completion Busy Subscriber activation\n"
"cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
" Set the dialplan location to notify when User-B is available but User-A is busy.\n"
" Setting this dialplan location is optional.\n"
"cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>\n"
" Set the busy status of call completion User-A\n"
"cc-deactivate,${MISDN_CC_RECORD_ID}\n"
" Deactivate the identified call completion request\n"
"\n"
"MISDN_CC_RECORD_ID is set when Dial() returns and call completion is possible\n"
"MISDN_CC_STATUS is set to ACTIVATED or ERROR after the call completion\n"
"activation request.\n"
"MISDN_ERROR_MSG is set to a descriptive message on error.\n"
);
ast_custom_function_register(&misdn_cc_function);
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
/* start the l1 watchers */
for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
int l1timeout;
misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
if (l1timeout) {
chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
}
}
chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
return 0;
}
| static void misdn_add_number_prefix | ( | int | port, |
| enum mISDN_NUMBER_TYPE | number_type, | ||
| char * | number, | ||
| size_t | size | ||
| ) | [static] |
Definition at line 3400 of file chan_misdn.c.
References misdn_cfg_get(), MISDN_CFG_TON_PREFIX_ABBREVIATED, MISDN_CFG_TON_PREFIX_INTERNATIONAL, MISDN_CFG_TON_PREFIX_NATIONAL, MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC, MISDN_CFG_TON_PREFIX_SUBSCRIBER, MISDN_CFG_TON_PREFIX_UNKNOWN, MISDN_MAX_NUMBER_LEN, misdn_prefix_string(), NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.
Referenced by cb_events(), misdn_facility_ie_handler(), misdn_is_msn_valid(), and read_config().
{
enum misdn_cfg_elements type_prefix;
char num_prefix[MISDN_MAX_NUMBER_LEN];
/* Get prefix string. */
switch (number_type) {
case NUMTYPE_UNKNOWN:
type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
break;
case NUMTYPE_INTERNATIONAL:
type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
break;
case NUMTYPE_NATIONAL:
type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
break;
case NUMTYPE_NETWORK_SPECIFIC:
type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
break;
case NUMTYPE_SUBSCRIBER:
type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
break;
case NUMTYPE_ABBREVIATED:
type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
break;
default:
/* Type-of-number does not have a prefix that can be added. */
return;
}
misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
misdn_prefix_string(num_prefix, number, size);
}
| static int misdn_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 6787 of file chan_misdn.c.
References AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_PROTOCOL_ERROR, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), ast_queue_hangup_with_cause(), ast_strlen_zero(), ast_true(), chan_list::bc, chan_misdn_log(), misdn_bchannel::connected, misdn_bchannel::crypt_key, misdn_bchannel::dialed, EVENT_CONNECT, misdn_bchannel::fac_out, misdn_bchannel::hdlc, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_lib_send_event(), misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_party_dialing::number, misdn_party_id::number, misdn_party_dialing::number_plan, misdn_party_id::number_plan, misdn_party_dialing::number_type, misdn_party_id::number_type, misdn_bchannel::outgoing_colp, pbx_builtin_getvar_helper(), misdn_bchannel::port, misdn_party_id::presentation, misdn_bchannel::presentation, print_facility(), misdn_party_id::screening, start_bc_tones(), chan_list::state, and stop_indicate().
{
struct chan_list *p;
const char *tmp;
if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
return -1;
}
chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
if (!p) {
ast_log(LOG_WARNING, " --> Channel not connected ??\n");
ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
}
if (!p->bc) {
chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
}
ast_channel_lock(ast);
tmp = pbx_builtin_getvar_helper(ast, "CRYPT_KEY");
if (!ast_strlen_zero(tmp)) {
chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
} else {
chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
}
tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
p->bc->nodsp = 1;
p->bc->hdlc = 0;
p->bc->nojitter = 1;
}
ast_channel_unlock(ast);
p->state = MISDN_CONNECTED;
stop_indicate(p);
if (ast_strlen_zero(p->bc->connected.number)) {
chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
ast_copy_string(p->bc->connected.number, p->bc->dialed.number, sizeof(p->bc->connected.number));
/*
* Use the misdn_set_opt() application to set the presentation
* before we answer or you can use the CONECTEDLINE() function
* to set everything before using the Answer() application.
*/
p->bc->connected.presentation = p->bc->presentation;
p->bc->connected.screening = 0; /* unscreened */
p->bc->connected.number_type = p->bc->dialed.number_type;
p->bc->connected.number_plan = p->bc->dialed.number_plan;
}
switch (p->bc->outgoing_colp) {
case 1:/* restricted */
case 2:/* blocked */
p->bc->connected.presentation = 1;/* restricted */
break;
default:
break;
}
#if defined(AST_MISDN_ENHANCEMENTS)
if (p->bc->div_leg_3_tx_pending) {
p->bc->div_leg_3_tx_pending = 0;
/* Send DivertingLegInformation3 */
p->bc->fac_out.Function = Fac_DivertingLegInformation3;
p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
(p->bc->connected.presentation == 0) ? 1 : 0;
print_facility(&p->bc->fac_out, p->bc);
}
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
misdn_lib_send_event(p->bc, EVENT_CONNECT);
start_bc_tones(p);
return 0;
}
| static int misdn_attempt_transfer | ( | struct chan_list * | active_ch, |
| struct chan_list * | held_ch | ||
| ) | [static] |
Definition at line 8583 of file chan_misdn.c.
References ao2_ref, chan_list::ast, ast_bridged_channel(), ast_channel_connected(), ast_channel_lock_both, ast_channel_name(), ast_channel_transfer_masquerade(), ast_channel_unlock, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_party_id_reset(), chan_misdn_log(), chan_list::hold, MISDN_ALERTING, MISDN_CONNECTED, MISDN_HOLD_TRANSFER, MISDN_PROCEEDING, MISDN_PROGRESS, hold_info::port, ast_party_connected_line::priv, hold_info::state, and chan_list::state.
Referenced by cb_events().
{
int retval;
struct ast_channel *target;
struct ast_channel *transferee;
struct ast_party_connected_line target_colp;
struct ast_party_connected_line transferee_colp;
switch (active_ch->state) {
case MISDN_PROCEEDING:
case MISDN_PROGRESS:
case MISDN_ALERTING:
case MISDN_CONNECTED:
break;
default:
return -1;
}
ast_channel_lock_both(held_ch->ast, active_ch->ast);
transferee = ast_bridged_channel(held_ch->ast);
if (!transferee) {
/*
* Could not transfer. Held channel is not bridged anymore.
* Held party probably got tired of waiting and hung up.
*/
ast_channel_unlock(held_ch->ast);
ast_channel_unlock(active_ch->ast);
return -1;
}
target = active_ch->ast;
chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
ast_channel_name(held_ch->ast), ast_channel_name(target));
ast_party_connected_line_init(&target_colp);
ast_party_connected_line_copy(&target_colp, ast_channel_connected(target));
/* Reset any earlier private connected id representation */
ast_party_id_reset(&target_colp.priv);
ast_party_connected_line_init(&transferee_colp);
ast_party_connected_line_copy(&transferee_colp, ast_channel_connected(held_ch->ast));
/* Reset any earlier private connected id representation*/
ast_party_id_reset(&transferee_colp.priv);
held_ch->hold.state = MISDN_HOLD_TRANSFER;
/*
* Before starting a masquerade, all channel and pvt locks must
* be unlocked. Any recursive channel locks held before
* ast_channel_transfer_masquerade() invalidates deadlock
* avoidance. Since we are unlocking both the pvt and its owner
* channel it is possible for "target" and "transferee" to be
* destroyed by their pbx threads. To prevent this we must give
* "target" and "transferee" a reference before any unlocking
* takes place.
*/
ao2_ref(target, +1);
ao2_ref(transferee, +1);
ast_channel_unlock(held_ch->ast);
ast_channel_unlock(active_ch->ast);
/* Setup transfer masquerade. */
retval = ast_channel_transfer_masquerade(target, &target_colp, 0,
transferee, &transferee_colp, 1);
ast_party_connected_line_free(&target_colp);
ast_party_connected_line_free(&transferee_colp);
ao2_ref(target, -1);
ao2_ref(transferee, -1);
return retval;
}
| static enum ast_bridge_result misdn_bridge | ( | struct ast_channel * | c0, |
| struct ast_channel * | c1, | ||
| int | flags, | ||
| struct ast_frame ** | fo, | ||
| struct ast_channel ** | rc, | ||
| int | timeoutms | ||
| ) | [static] |
Definition at line 7547 of file chan_misdn.c.
References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, ast_channel_exten(), ast_channel_hangupcause_hash_set(), ast_channel_name(), AST_CONTROL_PVT_CAUSE_CODE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_read(), ast_verb, ast_waitfor_n(), ast_write(), chan_list::bc, misdn_bchannel::caller, chan_list_unref, chan_misdn_log(), ast_frame::data, ast_frame::datalen, f, ast_frame::frametype, get_chan_by_ast(), chan_list::ignore_dtmf, ast_frame_subclass::integer, LOG_NOTICE, MISDN_CFG_BRIDGING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_bridge(), misdn_lib_split_bridge(), misdn_party_id::name, misdn_party_id::number, misdn_bchannel::pid, misdn_bchannel::port, ast_frame::ptr, and ast_frame::subclass.
{
struct chan_list *ch1, *ch2;
struct ast_channel *carr[2], *who;
int to = -1;
struct ast_frame *f;
int p1_b, p2_b;
int bridging;
ch1 = get_chan_by_ast(c0);
if (!ch1) {
return -1;
}
ch2 = get_chan_by_ast(c1);
if (!ch2) {
chan_list_unref(ch1, "Failed to find ch2");
return -1;
}
carr[0] = c0;
carr[1] = c1;
misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
if (! p1_b || ! p2_b) {
ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
chan_list_unref(ch1, "Bridge fallback ch1");
chan_list_unref(ch2, "Bridge fallback ch2");
return AST_BRIDGE_FAILED;
}
misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
if (bridging) {
/* trying to make a mISDN_dsp conference */
chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
misdn_lib_bridge(ch1->bc, ch2->bc);
}
ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
ch1->bc->caller.name,
ch1->bc->caller.number,
ch2->bc->caller.name,
ch2->bc->caller.number);
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
ch1->ignore_dtmf = 1;
}
if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
ch2->ignore_dtmf = 1;
}
for (;/*ever*/;) {
to = -1;
who = ast_waitfor_n(carr, 2, &to);
if (!who) {
ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
break;
}
f = ast_read(who);
if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass.integer != AST_CONTROL_PVT_CAUSE_CODE)) {
/* got hangup .. */
if (!f) {
chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
} else {
chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass.integer);
}
*fo = f;
*rc = who;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass.integer, ast_channel_exten(who));
*fo = f;
*rc = who;
break;
}
#if 0
if (f->frametype == AST_FRAME_VOICE) {
chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
continue;
}
#endif
if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr, f->datalen);
} else {
ast_write((who == c0) ? c1 : c0, f);
}
}
chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
misdn_lib_split_bridge(ch1->bc, ch2->bc);
chan_list_unref(ch1, "Bridge complete ch1");
chan_list_unref(ch2, "Bridge complete ch2");
return AST_BRIDGE_COMPLETE;
}
| static int misdn_call | ( | struct ast_channel * | ast, |
| const char * | dest, | ||
| int | timeout | ||
| ) | [static] |
we should have l3id after sending setup
Definition at line 6517 of file chan_misdn.c.
References add_out_calls(), args, AST_APP_ARG, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_channel_caller(), ast_channel_connected_effective_id(), ast_channel_context(), ast_channel_exten_set(), ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_transfercapability(), ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, ast_strdup, ast_strlen_zero(), ast_to_misdn_plan(), ast_to_misdn_ton(), ast_transfercapability2str(), chan_list::bc, misdn_bchannel::caller, misdn_bchannel::capability, chan_misdn_log(), misdn_party_redirecting::count, debug_numtype(), misdn_bchannel::dialed, ENOCHAN, EVENT_SETUP, ext, misdn_bchannel::fac_out, misdn_party_redirecting::from, misdn_bchannel::hdlc, ast_party_caller::id, import_ch(), misdn_bchannel::incoming_cid_tag, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::l3_id, chan_list::l3id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, misdn_cfg_get(), MISDN_CFG_LOCALDIALPLAN, misdn_copy_redirecting_from_ast(), misdn_lib_is_ptp(), misdn_lib_send_event(), misdn_set_opt_exec(), ast_party_id::name, misdn_party_id::name, misdn_bchannel::nt, misdn_party_dialing::number, ast_party_id::number, misdn_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, NUMPLAN_ISDN, NUMTYPE_UNKNOWN, misdn_bchannel::outgoing_colp, pbx_builtin_setvar_helper(), misdn_bchannel::pid, ast_party_number::plan, misdn_bchannel::port, misdn_party_id::presentation, misdn_bchannel::presentation, print_facility(), misdn_party_redirecting::reason, misdn_bchannel::redirecting, misdn_bchannel::sending_complete, misdn_bchannel::set_presentation, chan_list::state, stop_bc_tones(), ast_party_name::str, ast_party_number::str, ast_party_id::tag, update_config(), ast_party_name::valid, and ast_party_number::valid.
{
int port = 0;
int r;
int exceed;
int number_type;
struct chan_list *ch;
struct misdn_bchannel *newbc;
char *dest_cp;
int append_msn = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(intf); /* The interface token is discarded. */
AST_APP_ARG(ext); /* extension token */
AST_APP_ARG(opts); /* options token */
);
if (!ast) {
ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
return -1;
}
if (((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) || !dest) {
ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast_channel_name(ast));
ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
ch = MISDN_ASTERISK_TECH_PVT(ast);
if (!ch) {
ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast_channel_name(ast));
ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
newbc = ch->bc;
if (!newbc) {
ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast_channel_name(ast));
ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
port = newbc->port;
#if defined(AST_MISDN_ENHANCEMENTS)
if ((ch->peer = misdn_cc_caller_get(ast))) {
chan_misdn_log(3, port, " --> Found CC caller data, peer:%s\n",
ch->peer->chan ? "available" : "NULL");
}
if (ch->record_id != -1) {
struct misdn_cc_record *cc_record;
/* This is a call completion retry call */
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_id(ch->record_id);
if (!cc_record) {
AST_LIST_UNLOCK(&misdn_cc_records_db);
ast_log(LOG_WARNING, " --> ! misdn_call called on %s, cc_record==NULL\n", ast_channel_name(ast));
ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
/* Setup calling parameters to retry the call. */
newbc->dialed = cc_record->redial.dialed;
newbc->caller = cc_record->redial.caller;
memset(&newbc->redirecting, 0, sizeof(newbc->redirecting));
newbc->capability = cc_record->redial.capability;
newbc->hdlc = cc_record->redial.hdlc;
newbc->sending_complete = 1;
if (cc_record->ptp) {
newbc->fac_out.Function = Fac_CCBS_T_Call;
newbc->fac_out.u.CCBS_T_Call.InvokeID = ++misdn_invoke_id;
} else {
newbc->fac_out.Function = Fac_CCBSCall;
newbc->fac_out.u.CCBSCall.InvokeID = ++misdn_invoke_id;
newbc->fac_out.u.CCBSCall.CCBSReference = cc_record->mode.ptmp.reference_id;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
ast_channel_exten_set(ast, newbc->dialed.number);
chan_misdn_log(1, port, "* Call completion to: %s\n", newbc->dialed.number);
chan_misdn_log(2, port, " --> * tech:%s context:%s\n", ast_channel_name(ast), ast_channel_context(ast));
} else
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
{
struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
/*
* dest is ---v
* Dial(mISDN/g:group_name[/extension[/options]])
* Dial(mISDN/port[:preselected_channel][/extension[/options]])
*
* The dial extension could be empty if you are using MISDN_KEYPAD
* to control ISDN provider features.
*/
dest_cp = ast_strdupa(dest);
AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
if (!args.ext) {
args.ext = "";
}
chan_misdn_log(1, port, "* CALL: %s\n", dest);
chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast_channel_name(ast), ast_channel_context(ast));
ast_channel_exten_set(ast, args.ext);
ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
if (ast_strlen_zero(newbc->caller.name)
&& connected_id.name.valid
&& !ast_strlen_zero(connected_id.name.str)) {
ast_copy_string(newbc->caller.name, connected_id.name.str, sizeof(newbc->caller.name));
chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
}
if (ast_strlen_zero(newbc->caller.number)
&& connected_id.number.valid
&& !ast_strlen_zero(connected_id.number.str)) {
ast_copy_string(newbc->caller.number, connected_id.number.str, sizeof(newbc->caller.number));
chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
}
misdn_cfg_get(port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
if (append_msn) {
strncat(newbc->incoming_cid_tag, "_", sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
}
ast_channel_caller(ast)->id.tag = ast_strdup(newbc->incoming_cid_tag);
misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
if (number_type < 0) {
if (connected_id.number.valid) {
newbc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan);
newbc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan);
} else {
newbc->caller.number_type = NUMTYPE_UNKNOWN;
newbc->caller.number_plan = NUMPLAN_ISDN;
}
} else {
/* Force us to send in SETUP message */
newbc->caller.number_type = number_type;
newbc->caller.number_plan = NUMPLAN_ISDN;
}
debug_numtype(port, newbc->caller.number_type, "LTON");
newbc->capability = ast_channel_transfercapability(ast);
pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
if (ast_channel_transfercapability(ast) == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
chan_misdn_log(2, port, " --> * Call with flag Digital\n");
}
/* update caller screening and presentation */
update_config(ch);
/* fill in some ies from channel dialplan variables */
import_ch(ast, newbc, ch);
/* Finally The Options Override Everything */
if (!ast_strlen_zero(args.opts)) {
misdn_set_opt_exec(ast, args.opts);
} else {
chan_misdn_log(2, port, "NO OPTS GIVEN\n");
}
if (newbc->set_presentation) {
newbc->caller.presentation = newbc->presentation;
}
misdn_copy_redirecting_from_ast(newbc, ast);
switch (newbc->outgoing_colp) {
case 1:/* restricted */
case 2:/* blocked */
newbc->redirecting.from.presentation = 1;/* restricted */
break;
default:
break;
}
#if defined(AST_MISDN_ENHANCEMENTS)
if (newbc->redirecting.from.number[0] && misdn_lib_is_ptp(port)) {
if (newbc->redirecting.count < 1) {
newbc->redirecting.count = 1;
}
/* Create DivertingLegInformation2 facility */
newbc->fac_out.Function = Fac_DivertingLegInformation2;
newbc->fac_out.u.DivertingLegInformation2.InvokeID = ++misdn_invoke_id;
newbc->fac_out.u.DivertingLegInformation2.DivertingPresent = 1;
misdn_PresentedNumberUnscreened_fill(
&newbc->fac_out.u.DivertingLegInformation2.Diverting,
&newbc->redirecting.from);
switch (newbc->outgoing_colp) {
case 2:/* blocked */
/* Block the number going out */
newbc->fac_out.u.DivertingLegInformation2.Diverting.Type = 1;/* presentationRestricted */
/* Don't tell about any previous diversions or why for that matter. */
newbc->fac_out.u.DivertingLegInformation2.DiversionCounter = 1;
newbc->fac_out.u.DivertingLegInformation2.DiversionReason = 0;/* unknown */
break;
default:
newbc->fac_out.u.DivertingLegInformation2.DiversionCounter =
newbc->redirecting.count;
newbc->fac_out.u.DivertingLegInformation2.DiversionReason =
misdn_to_diversion_reason(newbc->redirecting.reason);
break;
}
newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
if (1 < newbc->fac_out.u.DivertingLegInformation2.DiversionCounter) {
newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;/* numberNotAvailableDueToInterworking */
}
/*
* Expect a DivertingLegInformation3 to update the COLR of the
* redirecting-to party we are attempting to call now.
*/
newbc->div_leg_3_rx_wanted = 1;
}
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
}
exceed = add_out_calls(port);
if (exceed != 0) {
char tmp[16];
snprintf(tmp, sizeof(tmp), "%d", exceed);
pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
#if defined(AST_MISDN_ENHANCEMENTS)
if (newbc->fac_out.Function != Fac_None) {
print_facility(&newbc->fac_out, newbc);
}
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
r = misdn_lib_send_event(newbc, EVENT_SETUP);
/** we should have l3id after sending setup **/
ch->l3id = newbc->l3_id;
if (r == -ENOCHAN) {
chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
ast_setstate(ast, AST_STATE_DIALING);
ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_CLEARING);
if (newbc->nt) {
stop_bc_tones(ch);
}
ch->state = MISDN_CALLING;
return 0;
}
| static int misdn_chan_is_valid | ( | struct chan_list * | ch | ) | [static] |
Definition at line 727 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, and chan_list::next.
Referenced by misdn_hangup().
{
struct chan_list *list;
ast_mutex_lock(&cl_te_lock);
for (list = cl_te; list; list = list->next) {
if (list == ch) {
ast_mutex_unlock(&cl_te_lock);
return 1;
}
}
ast_mutex_unlock(&cl_te_lock);
return 0;
}
| static int misdn_check_l2l1 | ( | struct ast_channel * | chan, |
| const char * | data | ||
| ) | [static] |
Definition at line 12257 of file chan_misdn.c.
References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), ast_safe_sleep(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), BUFFERSIZE, chan_misdn_log(), LOG_WARNING, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_CFG_GROUPNAME, misdn_lib_get_port_up(), misdn_lib_port_up(), and parse().
Referenced by load_module().
{
char *parse;
char group[BUFFERSIZE + 1];
char *port_str;
int port = 0;
int timeout;
int dowait = 0;
int port_up;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(grouppar);
AST_APP_ARG(timeout);
);
if (ast_strlen_zero((char *) data)) {
ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
return -1;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
if (args.argc != 2) {
ast_log(LOG_WARNING, "Wrong argument count\n");
return 0;
}
/*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
timeout = atoi(args.timeout);
port_str = args.grouppar;
if (port_str[0] == 'g' && port_str[1] == ':') {
/* We make a group call lets checkout which ports are in my group */
port_str += 2;
ast_copy_string(group, port_str, sizeof(group));
chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
for (port = misdn_cfg_get_next_port(port);
port > 0;
port = misdn_cfg_get_next_port(port)) {
char cfg_group[BUFFERSIZE + 1];
chan_misdn_log(2, 0, "trying port %d\n", port);
misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
if (!strcasecmp(cfg_group, group)) {
port_up = misdn_lib_port_up(port, 1);
if (!port_up) {
chan_misdn_log(2, 0, " --> port '%d'\n", port);
misdn_lib_get_port_up(port);
dowait = 1;
}
}
}
} else {
port = atoi(port_str);
chan_misdn_log(2, 0, "Checking Port: %d\n", port);
port_up = misdn_lib_port_up(port, 1);
if (!port_up) {
misdn_lib_get_port_up(port);
dowait = 1;
}
}
if (dowait) {
chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
ast_safe_sleep(chan, timeout * 1000);
}
return 0;
}
| static void misdn_copy_redirecting_from_ast | ( | struct misdn_bchannel * | bc, |
| struct ast_channel * | ast | ||
| ) | [static] |
Definition at line 6345 of file chan_misdn.c.
References ast_channel_redirecting(), ast_channel_redirecting_effective_from(), ast_channel_redirecting_effective_to(), ast_copy_string(), ast_to_misdn_plan(), ast_to_misdn_pres(), ast_to_misdn_reason(), ast_to_misdn_screen(), ast_to_misdn_ton(), misdn_party_redirecting::count, ast_party_redirecting::count, misdn_party_redirecting::from, ast_party_id::name, misdn_party_id::name, ast_party_id::number, misdn_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, NUMPLAN_UNKNOWN, NUMTYPE_UNKNOWN, ast_party_number::plan, ast_party_number::presentation, misdn_party_id::presentation, misdn_party_redirecting::reason, misdn_bchannel::redirecting, S_COR, S_OR, misdn_party_id::screening, ast_party_name::str, ast_party_number::str, misdn_party_redirecting::to, ast_party_name::valid, and ast_party_number::valid.
Referenced by misdn_call(), and misdn_update_redirecting().
{
struct ast_party_id from_id = ast_channel_redirecting_effective_from(ast);
struct ast_party_id to_id = ast_channel_redirecting_effective_to(ast);
ast_copy_string(bc->redirecting.from.name,
S_COR(from_id.name.valid, from_id.name.str, ""),
sizeof(bc->redirecting.from.name));
if (from_id.number.valid) {
ast_copy_string(bc->redirecting.from.number, S_OR(from_id.number.str, ""),
sizeof(bc->redirecting.from.number));
bc->redirecting.from.presentation = ast_to_misdn_pres(from_id.number.presentation);
bc->redirecting.from.screening = ast_to_misdn_screen(from_id.number.presentation);
bc->redirecting.from.number_type = ast_to_misdn_ton(from_id.number.plan);
bc->redirecting.from.number_plan = ast_to_misdn_plan(from_id.number.plan);
} else {
bc->redirecting.from.number[0] = '\0';
bc->redirecting.from.presentation = 0;/* Allowed */
bc->redirecting.from.screening = 0;/* Unscreened */
bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
bc->redirecting.from.number_plan = NUMPLAN_UNKNOWN;
}
ast_copy_string(bc->redirecting.to.name,
S_COR(to_id.name.valid, to_id.name.str, ""),
sizeof(bc->redirecting.to.name));
if (to_id.number.valid) {
ast_copy_string(bc->redirecting.to.number, S_OR(to_id.number.str, ""),
sizeof(bc->redirecting.to.number));
bc->redirecting.to.presentation = ast_to_misdn_pres(to_id.number.presentation);
bc->redirecting.to.screening = ast_to_misdn_screen(to_id.number.presentation);
bc->redirecting.to.number_type = ast_to_misdn_ton(to_id.number.plan);
bc->redirecting.to.number_plan = ast_to_misdn_plan(to_id.number.plan);
} else {
bc->redirecting.to.number[0] = '\0';
bc->redirecting.to.presentation = 0;/* Allowed */
bc->redirecting.to.screening = 0;/* Unscreened */
bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
}
bc->redirecting.reason = ast_to_misdn_reason(ast_channel_redirecting(ast)->reason);
bc->redirecting.count = ast_channel_redirecting(ast)->count;
}
| static void misdn_copy_redirecting_to_ast | ( | struct ast_channel * | ast, |
| const struct misdn_party_redirecting * | redirect, | ||
| char * | tag | ||
| ) | [static] |
Definition at line 6400 of file chan_misdn.c.
References ast_channel_redirecting(), ast_channel_set_redirecting(), ast_party_redirecting_set_init(), misdn_party_redirecting::count, ast_party_redirecting::count, misdn_party_redirecting::from, ast_party_redirecting::from, ast_set_party_redirecting::from, misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_reason(), misdn_to_ast_screen(), misdn_to_ast_ton(), ast_party_id::number, misdn_party_id::number, ast_set_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, ast_party_number::plan, ast_party_number::presentation, misdn_party_id::presentation, misdn_party_redirecting::reason, ast_party_redirecting::reason, misdn_party_id::screening, ast_party_number::str, ast_party_id::tag, misdn_party_redirecting::to, ast_party_redirecting::to, ast_set_party_redirecting::to, and ast_party_number::valid.
Referenced by cb_events(), and misdn_facility_ie_handler().
{
struct ast_party_redirecting redirecting;
struct ast_set_party_redirecting update_redirecting;
ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(ast));
memset(&update_redirecting, 0, sizeof(update_redirecting));
update_redirecting.from.number = 1;
redirecting.from.number.valid = 1;
redirecting.from.number.str = (char *) redirect->from.number;
redirecting.from.number.plan =
misdn_to_ast_ton(redirect->from.number_type)
| misdn_to_ast_plan(redirect->from.number_plan);
redirecting.from.number.presentation =
misdn_to_ast_pres(redirect->from.presentation)
| misdn_to_ast_screen(redirect->from.screening);
redirecting.from.tag = tag;
update_redirecting.to.number = 1;
redirecting.to.number.valid = 1;
redirecting.to.number.str = (char *) redirect->to.number;
redirecting.to.number.plan =
misdn_to_ast_ton(redirect->to.number_type)
| misdn_to_ast_plan(redirect->to.number_plan);
redirecting.to.number.presentation =
misdn_to_ast_pres(redirect->to.presentation)
| misdn_to_ast_screen(redirect->to.screening);
redirecting.to.tag = tag;
redirecting.reason = misdn_to_ast_reason(redirect->reason);
redirecting.count = redirect->count;
ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
}
| static int misdn_digit_begin | ( | struct ast_channel * | chan, |
| char | digit | ||
| ) | [static] |
Definition at line 6872 of file chan_misdn.c.
{
/* XXX Modify this callback to support Asterisk controlling the length of DTMF */
return 0;
}
| static int misdn_digit_end | ( | struct ast_channel * | ast, |
| char | digit, | ||
| unsigned int | duration | ||
| ) | [static] |
Definition at line 6878 of file chan_misdn.c.
References chan_list::ast, ast_channel_exten_set(), ast_copy_string(), ast_log(), chan_list::bc, chan_misdn_log(), misdn_bchannel::dialed, EVENT_INFORMATION, misdn_bchannel::info_dad, misdn_bchannel::infos_pending, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, misdn_lib_send_event(), misdn_party_dialing::number, misdn_bchannel::port, send_digit_to_chan(), misdn_bchannel::send_dtmf, and chan_list::state.
{
struct chan_list *p;
struct misdn_bchannel *bc;
char buf[2] = { digit, 0 };
if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
return -1;
}
bc = p->bc;
chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
if (!bc) {
ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
return -1;
}
switch (p->state) {
case MISDN_CALLING:
if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
}
break;
case MISDN_CALLING_ACKNOWLEDGE:
ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
}
ast_channel_exten_set(p->ast, bc->dialed.number);
misdn_lib_send_event(bc, EVENT_INFORMATION);
break;
default:
if (bc->send_dtmf) {
send_digit_to_chan(p, digit);
}
break;
}
return 0;
}
| static int misdn_facility_exec | ( | struct ast_channel * | chan, |
| const char * | data | ||
| ) | [static] |
Definition at line 12134 of file chan_misdn.c.
References args, AST_APP_ARG, ast_channel_tech(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), chan_list::bc, chan_misdn_log(), EVENT_FACILITY, misdn_bchannel::fac_out, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_lib_send_event(), parse(), misdn_bchannel::port, and print_facility().
Referenced by load_module().
{
struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
char *parse;
unsigned max_len;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(facility_type);
AST_APP_ARG(arg)[99];
);
chan_misdn_log(0, 0, "TYPE: %s\n", ast_channel_tech(chan)->type);
if (strcasecmp(ast_channel_tech(chan)->type, misdn_type)) {
ast_log(LOG_WARNING, "misdn_facility only makes sense with %s channels!\n", misdn_type);
return -1;
}
if (ast_strlen_zero((char *) data)) {
ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
return -1;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.facility_type)) {
ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
return -1;
}
if (!strcasecmp(args.facility_type, "calldeflect")) {
if (ast_strlen_zero(args.arg[0])) {
ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
}
#if defined(AST_MISDN_ENHANCEMENTS)
max_len = sizeof(ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
if (max_len < strlen(args.arg[0])) {
ast_log(LOG_WARNING,
"Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
max_len);
return 0;
}
ch->bc->fac_out.Function = Fac_CallDeflection;
ch->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
ch->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(args.arg[0]);
strcpy((char *) ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, args.arg[0]);
ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
#else /* !defined(AST_MISDN_ENHANCEMENTS) */
max_len = sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
if (max_len < strlen(args.arg[0])) {
ast_log(LOG_WARNING,
"Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
max_len);
return 0;
}
ch->bc->fac_out.Function = Fac_CD;
ch->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
//ch->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
strcpy((char *) ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0]);
#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
/* Send message */
print_facility(&ch->bc->fac_out, ch->bc);
misdn_lib_send_event(ch->bc, EVENT_FACILITY);
#if defined(AST_MISDN_ENHANCEMENTS)
} else if (!strcasecmp(args.facility_type, "callrerouteing")
|| !strcasecmp(args.facility_type, "callrerouting")) {
if (ast_strlen_zero(args.arg[0])) {
ast_log(LOG_WARNING, "Facility: Call rerouting requires an argument: Number\n");
}
max_len = sizeof(ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
if (max_len < strlen(args.arg[0])) {
ast_log(LOG_WARNING,
"Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
max_len);
return 0;
}
ch->bc->fac_out.Function = Fac_CallRerouteing;
ch->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
ch->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(args.arg[0]);
strcpy((char *) ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, args.arg[0]);
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
/* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
ch->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
/* Send message */
print_facility(&ch->bc->fac_out, ch->bc);
misdn_lib_send_event(ch->bc, EVENT_FACILITY);
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
} else {
chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
}
return 0;
}
| static void misdn_facility_ie_handler | ( | enum event_e | event, |
| struct misdn_bchannel * | bc, | ||
| struct chan_list * | ch | ||
| ) | [static] |
Definition at line 9093 of file chan_misdn.c.
References misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, misdn_bchannel::AOCDtype, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_channel_queue_redirecting_update(), ast_channel_redirecting(), AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, AST_CONTROL_BUSY, ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_party_id_reset(), ast_party_redirecting_copy(), ast_party_redirecting_free(), ast_party_redirecting_init(), AST_PRES_ALLOWED, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), misdn_bchannel::caller, misdn_bchannel::capability, chan_misdn_log(), misdn_bchannel::chargingUnit, misdn_party_redirecting::count, misdn_bchannel::currency, misdn_bchannel::dialed, EVENT_ALERTING, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, EVENT_SETUP, export_aoc_vars(), misdn_bchannel::fac_in, misdn_bchannel::fac_out, misdn_party_redirecting::from, misdn_bchannel::hdlc, misdn_bchannel::incoming_cid_tag, misdn_add_number_prefix(), misdn_copy_redirecting_to_ast(), misdn_lib_send_event(), mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE, mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING, mISDN_NOTIFY_CODE_INVALID, mISDN_REDIRECTING_REASON_DEFLECTION, misdn_update_remote_party(), misdn_party_id::name, misdn_bchannel::notify_description_code, misdn_party_dialing::number, ast_party_id::number, misdn_party_id::number, misdn_party_dialing::number_plan, misdn_party_id::number_plan, misdn_party_dialing::number_type, misdn_party_id::number_type, NUMPLAN_ISDN, NUMPLAN_UNKNOWN, NUMTYPE_UNKNOWN, chan_list::originator, misdn_bchannel::port, ast_party_number::presentation, misdn_party_id::presentation, print_facility(), ast_party_redirecting::priv_from, ast_party_redirecting::priv_orig, ast_party_redirecting::priv_to, misdn_party_redirecting::reason, misdn_bchannel::redirecting, misdn_party_id::screening, misdn_party_redirecting::to, ast_party_redirecting::to, and misdn_party_redirecting::to_changed.
Referenced by cb_events().
{
#if defined(AST_MISDN_ENHANCEMENTS)
const char *diagnostic_msg;
struct misdn_cc_record *cc_record;
char buf[32];
struct misdn_party_id party_id;
long new_record_id;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
print_facility(&bc->fac_in, bc);
switch (bc->fac_in.Function) {
#if defined(AST_MISDN_ENHANCEMENTS)
case Fac_ActivationDiversion:
switch (bc->fac_in.u.ActivationDiversion.ComponentType) {
case FacComponent_Result:
/* Positive ACK to activation */
/* We don't handle this yet */
break;
default:
chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
case Fac_DeactivationDiversion:
switch (bc->fac_in.u.DeactivationDiversion.ComponentType) {
case FacComponent_Result:
/* Positive ACK to deactivation */
/* We don't handle this yet */
break;
default:
chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
case Fac_ActivationStatusNotificationDiv:
/* Sent to other MSN numbers on the line when a user activates call forwarding. */
/* Sent in the first call control message of an outgoing call from the served user. */
/* We do not have anything to do for this message. */
break;
case Fac_DeactivationStatusNotificationDiv:
/* Sent to other MSN numbers on the line when a user deactivates call forwarding. */
/* We do not have anything to do for this message. */
break;
#if 0 /* We don't handle this yet */
case Fac_InterrogationDiversion:
/* We don't handle this yet */
break;
case Fac_InterrogateServedUserNumbers:
/* We don't handle this yet */
break;
#endif /* We don't handle this yet */
case Fac_DiversionInformation:
/* Sent to the served user when a call is forwarded. */
/* We do not have anything to do for this message. */
break;
case Fac_CallDeflection:
if (ch && ch->ast) {
switch (bc->fac_in.u.CallDeflection.ComponentType) {
case FacComponent_Invoke:
ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
sizeof(bc->redirecting.from.number));
bc->redirecting.from.name[0] = 0;
bc->redirecting.from.number_plan = bc->dialed.number_plan;
bc->redirecting.from.number_type = bc->dialed.number_type;
bc->redirecting.from.screening = 0;/* Unscreened */
if (bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
bc->redirecting.from.presentation =
bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser
? 0 /* Allowed */ : 1 /* Restricted */;
} else {
bc->redirecting.from.presentation = 0;/* Allowed */
}
/* Add configured prefix to the call deflection number */
memset(&party_id, 0, sizeof(party_id));
misdn_PartyNumber_extract(&party_id,
&bc->fac_in.u.CallDeflection.Component.Invoke.Deflection.Party);
misdn_add_number_prefix(bc->port, party_id.number_type,
party_id.number, sizeof(party_id.number));
//party_id.presentation = 0;/* Allowed */
//party_id.screening = 0;/* Unscreened */
bc->redirecting.to = party_id;
++bc->redirecting.count;
bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
ast_channel_call_forward_set(ch->ast, bc->redirecting.to.number);
/* Send back positive ACK */
#if 1
/*
* Since there are no return result arguments it must be a
* generic result message. ETSI 300-196
*/
bc->fac_out.Function = Fac_RESULT;
bc->fac_out.u.RESULT.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
#else
bc->fac_out.Function = Fac_CallDeflection;
bc->fac_out.u.CallDeflection.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Result;
#endif
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_DISCONNECT);
/* This line is BUSY to further attempts by this dialing attempt. */
ast_queue_control(ch->ast, AST_CONTROL_BUSY);
break;
case FacComponent_Result:
/* Positive ACK to call deflection */
/*
* Sent in DISCONNECT or FACILITY message depending upon network option.
* It is in the FACILITY message if the call is still offered to the user
* while trying to alert the deflected to party.
*/
/* Ignore the ACK */
break;
default:
break;
}
}
break;
#if 0 /* We don't handle this yet */
case Fac_CallRerouteing:
/* Private-Public ISDN interworking message */
/* We don't handle this yet */
break;
#endif /* We don't handle this yet */
case Fac_DivertingLegInformation1:
/* Private-Public ISDN interworking message */
bc->div_leg_3_rx_wanted = 0;
if (ch && ch->ast) {
bc->redirecting.reason =
diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation1.DiversionReason);
if (bc->fac_in.u.DivertingLegInformation1.DivertedToPresent) {
misdn_PresentedNumberUnscreened_extract(&bc->redirecting.to,
&bc->fac_in.u.DivertingLegInformation1.DivertedTo);
/* Add configured prefix to redirecting.to.number */
misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
} else {
bc->redirecting.to.number[0] = '\0';
bc->redirecting.to.number_plan = NUMPLAN_ISDN;
bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
bc->redirecting.to.presentation = 1;/* restricted */
bc->redirecting.to.screening = 0;/* unscreened */
}
misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
bc->div_leg_3_rx_wanted = 1;
}
break;
case Fac_DivertingLegInformation2:
/* Private-Public ISDN interworking message */
switch (event) {
case EVENT_SETUP:
/* Comes in on a SETUP with redirecting.from information */
bc->div_leg_3_tx_pending = 1;
if (ch && ch->ast) {
/*
* Setup the redirecting.to informtion so we can identify
* if the user wants to manually supply the COLR for this
* redirected to number if further redirects could happen.
*
* All the user needs to do is set the REDIRECTING(to-pres)
* to the COLR and REDIRECTING(to-num) = ${EXTEN} to be safe
* after determining that the incoming call was redirected by
* checking if there is a REDIRECTING(from-num).
*/
ast_copy_string(bc->redirecting.to.number, bc->dialed.number,
sizeof(bc->redirecting.to.number));
bc->redirecting.to.number_plan = bc->dialed.number_plan;
bc->redirecting.to.number_type = bc->dialed.number_type;
bc->redirecting.to.presentation = 1;/* restricted */
bc->redirecting.to.screening = 0;/* unscreened */
bc->redirecting.reason =
diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation2.DiversionReason);
bc->redirecting.count = bc->fac_in.u.DivertingLegInformation2.DiversionCounter;
if (bc->fac_in.u.DivertingLegInformation2.DivertingPresent) {
/* This information is redundant if there was a redirecting ie in the SETUP. */
misdn_PresentedNumberUnscreened_extract(&bc->redirecting.from,
&bc->fac_in.u.DivertingLegInformation2.Diverting);
/* Add configured prefix to redirecting.from.number */
misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type,
bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
}
#if 0
if (bc->fac_in.u.DivertingLegInformation2.OriginalCalledPresent) {
/* We have no place to put the OriginalCalled number */
}
#endif
misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
}
break;
default:
chan_misdn_log(0, bc->port," --> Expected in a SETUP message: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
case Fac_DivertingLegInformation3:
/* Private-Public ISDN interworking message */
if (bc->div_leg_3_rx_wanted) {
bc->div_leg_3_rx_wanted = 0;
if (ch && ch->ast) {
struct ast_party_redirecting redirecting;
ast_channel_redirecting(ch->ast)->to.number.presentation =
bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
? AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED
: AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
ast_party_redirecting_init(&redirecting);
ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
/*
* Reset any earlier private redirecting id representations and
* make sure that it is invalidated at the remote end.
*/
ast_party_id_reset(&redirecting.priv_orig);
ast_party_id_reset(&redirecting.priv_from);
ast_party_id_reset(&redirecting.priv_to);
ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
ast_party_redirecting_free(&redirecting);
}
}
break;
#else /* !defined(AST_MISDN_ENHANCEMENTS) */
case Fac_CD:
if (ch && ch->ast) {
ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
sizeof(bc->redirecting.from.number));
bc->redirecting.from.name[0] = 0;
bc->redirecting.from.number_plan = bc->dialed.number_plan;
bc->redirecting.from.number_type = bc->dialed.number_type;
bc->redirecting.from.screening = 0;/* Unscreened */
bc->redirecting.from.presentation =
bc->fac_in.u.CDeflection.PresentationAllowed
? 0 /* Allowed */ : 1 /* Restricted */;
ast_copy_string(bc->redirecting.to.number,
(char *) bc->fac_in.u.CDeflection.DeflectedToNumber,
sizeof(bc->redirecting.to.number));
bc->redirecting.to.name[0] = 0;
bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
bc->redirecting.to.presentation = 0;/* Allowed */
bc->redirecting.to.screening = 0;/* Unscreened */
++bc->redirecting.count;
bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
ast_channel_call_forward_set(ch->ast, bc->redirecting.to.number);
misdn_lib_send_event(bc, EVENT_DISCONNECT);
/* This line is BUSY to further attempts by this dialing attempt. */
ast_queue_control(ch->ast, AST_CONTROL_BUSY);
}
break;
#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
case Fac_AOCDCurrency:
if (ch && ch->ast) {
bc->AOCDtype = Fac_AOCDCurrency;
memcpy(&bc->AOCD.currency, &bc->fac_in.u.AOCDcur, sizeof(bc->AOCD.currency));
bc->AOCD_need_export = 1;
export_aoc_vars(ch->originator, ch->ast, bc);
}
break;
case Fac_AOCDChargingUnit:
if (ch && ch->ast) {
bc->AOCDtype = Fac_AOCDChargingUnit;
memcpy(&bc->AOCD.chargingUnit, &bc->fac_in.u.AOCDchu, sizeof(bc->AOCD.chargingUnit));
bc->AOCD_need_export = 1;
export_aoc_vars(ch->originator, ch->ast, bc);
}
break;
#if defined(AST_MISDN_ENHANCEMENTS)
case Fac_ERROR:
diagnostic_msg = misdn_to_str_error_code(bc->fac_in.u.ERROR.errorValue);
chan_misdn_log(1, bc->port, " --> Facility error code: %s\n", diagnostic_msg);
switch (event) {
case EVENT_DISCONNECT:
case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE:
/* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
if (ch && ch->peer) {
misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
}
break;
default:
break;
}
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.ERROR.invokeId);
if (cc_record) {
cc_record->outstanding_message = 0;
cc_record->error_code = bc->fac_in.u.ERROR.errorValue;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
break;
case Fac_REJECT:
diagnostic_msg = misdn_to_str_reject_code(bc->fac_in.u.REJECT.Code);
chan_misdn_log(1, bc->port, " --> Facility reject code: %s\n", diagnostic_msg);
switch (event) {
case EVENT_DISCONNECT:
case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE:
/* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
if (ch && ch->peer) {
misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
}
break;
default:
break;
}
if (bc->fac_in.u.REJECT.InvokeIDPresent) {
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.REJECT.InvokeID);
if (cc_record) {
cc_record->outstanding_message = 0;
cc_record->reject_code = bc->fac_in.u.REJECT.Code;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
}
break;
case Fac_RESULT:
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.RESULT.InvokeID);
if (cc_record) {
cc_record->outstanding_message = 0;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
break;
#if 0 /* We don't handle this yet */
case Fac_EctExecute:
/* We don't handle this yet */
break;
case Fac_ExplicitEctExecute:
/* We don't handle this yet */
break;
case Fac_EctLinkIdRequest:
/* We don't handle this yet */
break;
#endif /* We don't handle this yet */
case Fac_SubaddressTransfer:
/* We do not have anything to do for this message since we do not handle subaddreses. */
break;
case Fac_RequestSubaddress:
/*
* We do not have anything to do for this message since we do not handle subaddreses.
* However, we do care about some other ie's that should be present.
*/
if (bc->redirecting.to_changed) {
/* Add configured prefix to redirecting.to.number */
misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
}
switch (bc->notify_description_code) {
case mISDN_NOTIFY_CODE_INVALID:
/* Notify ie was not present. */
bc->redirecting.to_changed = 0;
break;
case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
/*
* It would be preferable to update the connected line information
* only when the message callStatus is active. However, the
* optional redirection number may not be present in the active
* message if an alerting message were received earlier.
*
* The consequences if we wind up sending two updates is benign.
* The other end will think that it got transferred twice.
*/
if (!bc->redirecting.to_changed) {
break;
}
bc->redirecting.to_changed = 0;
if (!ch || !ch->ast) {
break;
}
misdn_update_remote_party(ch->ast, &bc->redirecting.to,
AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING,
bc->incoming_cid_tag);
break;
case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
if (!bc->redirecting.to_changed) {
break;
}
bc->redirecting.to_changed = 0;
if (!ch || !ch->ast) {
break;
}
misdn_update_remote_party(ch->ast, &bc->redirecting.to,
AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
break;
default:
bc->redirecting.to_changed = 0;
chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
bc->notify_description_code);
break;
}
bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
break;
case Fac_EctInform:
/* Private-Public ISDN interworking message */
if (ch && ch->ast && bc->fac_in.u.EctInform.RedirectionPresent) {
/* Add configured prefix to the redirection number */
memset(&party_id, 0, sizeof(party_id));
misdn_PresentedNumberUnscreened_extract(&party_id,
&bc->fac_in.u.EctInform.Redirection);
misdn_add_number_prefix(bc->port, party_id.number_type,
party_id.number, sizeof(party_id.number));
/*
* It would be preferable to update the connected line information
* only when the message callStatus is active. However, the
* optional redirection number may not be present in the active
* message if an alerting message were received earlier.
*
* The consequences if we wind up sending two updates is benign.
* The other end will think that it got transferred twice.
*/
misdn_update_remote_party(ch->ast, &party_id,
(bc->fac_in.u.EctInform.Status == 0 /* alerting */)
? AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
: AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
bc->incoming_cid_tag);
}
break;
#if 0 /* We don't handle this yet */
case Fac_EctLoopTest:
/* The use of this message is unclear on how it works to detect loops. */
/* We don't handle this yet */
break;
#endif /* We don't handle this yet */
case Fac_CallInfoRetain:
switch (event) {
case EVENT_ALERTING:
case EVENT_DISCONNECT:
/* CCBS/CCNR is available */
if (ch && ch->peer) {
AST_LIST_LOCK(&misdn_cc_records_db);
if (ch->record_id == -1) {
cc_record = misdn_cc_new();
} else {
/*
* We are doing a call-completion attempt
* or the switch is sending us extra call-completion
* availability indications (erroneously?).
*
* Assume that the network request retention option
* is not on and that the current call-completion
* request is disabled.
*/
cc_record = misdn_cc_find_by_id(ch->record_id);
if (cc_record) {
if (cc_record->ptp && cc_record->mode.ptp.bc) {
/*
* What? We are getting mixed messages from the
* switch. We are currently setup for
* point-to-point. Now we are switching to
* point-to-multipoint.
*
* Close the call-completion signaling link
*/
cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
}
/*
* Resetup the existing record for a possible new
* call-completion request.
*/
new_record_id = misdn_cc_record_id_new();
if (new_record_id < 0) {
/* Looks like we must keep the old id anyway. */
} else {
cc_record->record_id = new_record_id;
ch->record_id = new_record_id;
}
cc_record->ptp = 0;
cc_record->port = bc->port;
memset(&cc_record->mode, 0, sizeof(cc_record->mode));
cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
cc_record->invoke_id = ++misdn_invoke_id;
cc_record->activated = 0;
cc_record->outstanding_message = 0;
cc_record->activation_requested = 0;
cc_record->error_code = FacError_None;
cc_record->reject_code = FacReject_None;
memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
cc_record->time_created = time(NULL);
cc_record = NULL;
} else {
/*
* Where did the record go? We will have to recapture
* the call setup information. Unfortunately, some
* setup information may have been changed.
*/
ch->record_id = -1;
cc_record = misdn_cc_new();
}
}
if (cc_record) {
ch->record_id = cc_record->record_id;
cc_record->ptp = 0;
cc_record->port = bc->port;
cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
/* Record call information for possible call-completion attempt. */
cc_record->redial.caller = bc->caller;
cc_record->redial.dialed = bc->dialed;
cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
cc_record->redial.capability = bc->capability;
cc_record->redial.hdlc = bc->hdlc;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
/* Set MISDN_CC_RECORD_ID in original channel */
if (ch->record_id != -1) {
snprintf(buf, sizeof(buf), "%ld", ch->record_id);
} else {
buf[0] = 0;
}
misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
}
break;
default:
chan_misdn_log(0, bc->port,
" --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
case Fac_CCBS_T_Call:
case Fac_CCBSCall:
switch (event) {
case EVENT_SETUP:
/*
* This is a call completion retry call.
* If we had anything to do we would do it here.
*/
break;
default:
chan_misdn_log(0, bc->port, " --> Expected in a SETUP message: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
case Fac_CCBSDeactivate:
switch (bc->fac_in.u.CCBSDeactivate.ComponentType) {
case FacComponent_Result:
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSDeactivate.InvokeID);
if (cc_record) {
cc_record->outstanding_message = 0;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
break;
default:
chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
case Fac_CCBSErase:
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_reference(bc->port, bc->fac_in.u.CCBSErase.CCBSReference);
if (cc_record) {
misdn_cc_delete(cc_record);
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
break;
case Fac_CCBSRemoteUserFree:
misdn_cc_handle_remote_user_free(bc->port, &bc->fac_in);
break;
case Fac_CCBSBFree:
misdn_cc_handle_b_free(bc->port, &bc->fac_in);
break;
case Fac_CCBSStatusRequest:
misdn_cc_handle_ccbs_status_request(bc->port, &bc->fac_in);
break;
case Fac_EraseCallLinkageID:
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_linkage(bc->port,
bc->fac_in.u.EraseCallLinkageID.CallLinkageID);
if (cc_record && !cc_record->activation_requested) {
/*
* The T-RETENTION timer expired before we requested
* call completion activation. Call completion is no
* longer available.
*/
misdn_cc_delete(cc_record);
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
break;
case Fac_CCBSStopAlerting:
/* We do not have anything to do for this message. */
break;
case Fac_CCBSRequest:
case Fac_CCNRRequest:
switch (bc->fac_in.u.CCBSRequest.ComponentType) {
case FacComponent_Result:
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSRequest.InvokeID);
if (cc_record && !cc_record->ptp) {
cc_record->outstanding_message = 0;
cc_record->activated = 1;
cc_record->mode.ptmp.recall_mode = bc->fac_in.u.CCBSRequest.Component.Result.RecallMode;
cc_record->mode.ptmp.reference_id = bc->fac_in.u.CCBSRequest.Component.Result.CCBSReference;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
break;
default:
chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
#if 0 /* We don't handle this yet */
case Fac_CCBSInterrogate:
case Fac_CCNRInterrogate:
/* We don't handle this yet */
break;
case Fac_StatusRequest:
/* We don't handle this yet */
break;
#endif /* We don't handle this yet */
#if 0 /* We don't handle this yet */
case Fac_CCBS_T_Suspend:
case Fac_CCBS_T_Resume:
/* We don't handle this yet */
break;
#endif /* We don't handle this yet */
case Fac_CCBS_T_RemoteUserFree:
misdn_cc_handle_T_remote_user_free(bc);
break;
case Fac_CCBS_T_Available:
switch (event) {
case EVENT_ALERTING:
case EVENT_DISCONNECT:
/* CCBS-T/CCNR-T is available */
if (ch && ch->peer) {
int set_id = 1;
AST_LIST_LOCK(&misdn_cc_records_db);
if (ch->record_id == -1) {
cc_record = misdn_cc_new();
} else {
/*
* We are doing a call-completion attempt
* or the switch is sending us extra call-completion
* availability indications (erroneously?).
*/
cc_record = misdn_cc_find_by_id(ch->record_id);
if (cc_record) {
if (cc_record->ptp && cc_record->mode.ptp.retention_enabled) {
/*
* Call-completion is still activated.
* The user does not have to request it again.
*/
chan_misdn_log(1, bc->port, " --> Call-completion request retention option is enabled\n");
set_id = 0;
} else {
if (cc_record->ptp && cc_record->mode.ptp.bc) {
/*
* The network request retention option
* is not on and the current call-completion
* request is to be disabled.
*
* We should get here only if EVENT_DISCONNECT
*
* Close the call-completion signaling link
*/
cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
}
/*
* Resetup the existing record for a possible new
* call-completion request.
*/
new_record_id = misdn_cc_record_id_new();
if (new_record_id < 0) {
/* Looks like we must keep the old id anyway. */
} else {
cc_record->record_id = new_record_id;
ch->record_id = new_record_id;
}
cc_record->ptp = 1;
cc_record->port = bc->port;
memset(&cc_record->mode, 0, sizeof(cc_record->mode));
cc_record->invoke_id = ++misdn_invoke_id;
cc_record->activated = 0;
cc_record->outstanding_message = 0;
cc_record->activation_requested = 0;
cc_record->error_code = FacError_None;
cc_record->reject_code = FacReject_None;
memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
cc_record->time_created = time(NULL);
}
cc_record = NULL;
} else {
/*
* Where did the record go? We will have to recapture
* the call setup information. Unfortunately, some
* setup information may have been changed.
*/
ch->record_id = -1;
cc_record = misdn_cc_new();
}
}
if (cc_record) {
ch->record_id = cc_record->record_id;
cc_record->ptp = 1;
cc_record->port = bc->port;
/* Record call information for possible call-completion attempt. */
cc_record->redial.caller = bc->caller;
cc_record->redial.dialed = bc->dialed;
cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
cc_record->redial.capability = bc->capability;
cc_record->redial.hdlc = bc->hdlc;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
/* Set MISDN_CC_RECORD_ID in original channel */
if (ch->record_id != -1 && set_id) {
snprintf(buf, sizeof(buf), "%ld", ch->record_id);
} else {
buf[0] = 0;
}
misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
}
break;
default:
chan_misdn_log(0, bc->port,
" --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
case Fac_CCBS_T_Request:
case Fac_CCNR_T_Request:
switch (bc->fac_in.u.CCBS_T_Request.ComponentType) {
case FacComponent_Result:
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBS_T_Request.InvokeID);
if (cc_record && cc_record->ptp) {
cc_record->outstanding_message = 0;
cc_record->activated = 1;
cc_record->mode.ptp.retention_enabled =
cc_record->mode.ptp.requested_retention
? bc->fac_in.u.CCBS_T_Request.Component.Result.RetentionSupported
? 1 : 0
: 0;
}
AST_LIST_UNLOCK(&misdn_cc_records_db);
break;
case FacComponent_Invoke:
/* We cannot be User-B in ptp mode. */
default:
chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
break;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
case Fac_None:
break;
default:
chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
bc->fac_in.Function);
break;
}
}
| static int misdn_fixup | ( | struct ast_channel * | oldast, |
| struct ast_channel * | ast | ||
| ) | [static] |
Definition at line 6921 of file chan_misdn.c.
References chan_list::ast, chan_list::bc, chan_misdn_log(), chan_list::l3id, MISDN_ASTERISK_TECH_PVT, misdn_get_ch_state(), and misdn_bchannel::port.
{
struct chan_list *p;
if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
return -1;
}
chan_misdn_log(1, p->bc ? p->bc->port : 0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
p->ast = ast;
return 0;
}
| static const char* misdn_get_ch_state | ( | struct chan_list * | p | ) | [static] |
Definition at line 4075 of file chan_misdn.c.
References ARRAY_LEN, chan_list::state, state, and state_struct::txt.
Referenced by cb_events(), misdn_fixup(), misdn_hangup(), misdn_write(), and print_bc_info().
{
int i;
static char state[8];
if (!p) {
return NULL;
}
for (i = 0; i < ARRAY_LEN(state_array); i++) {
if (state_array[i].state == p->state) {
return state_array[i].txt;
}
}
snprintf(state, sizeof(state), "%d", p->state) ;
return state;
}
| static void misdn_get_connected_line | ( | struct ast_channel * | ast, |
| struct misdn_bchannel * | bc, | ||
| int | originator | ||
| ) | [static] |
Definition at line 6189 of file chan_misdn.c.
References ast_channel_connected_effective_id(), ast_copy_string(), ast_to_misdn_plan(), ast_to_misdn_pres(), ast_to_misdn_screen(), ast_to_misdn_ton(), misdn_bchannel::caller, misdn_bchannel::connected, debug_numtype(), MISDN_CFG_CPNDIALPLAN, misdn_cfg_get(), MISDN_CFG_LOCALDIALPLAN, ast_party_id::name, misdn_party_id::name, ast_party_id::number, misdn_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, NUMPLAN_ISDN, NUMPLAN_UNKNOWN, NUMTYPE_UNKNOWN, ORG_MISDN, ast_party_number::plan, misdn_bchannel::port, ast_party_number::presentation, misdn_party_id::presentation, S_COR, S_OR, misdn_party_id::screening, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by misdn_update_connected_line().
{
int number_type;
struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
if (originator == ORG_MISDN) {
/* ORIGINATOR MISDN (incoming call) */
ast_copy_string(bc->connected.name,
S_COR(connected_id.name.valid, connected_id.name.str, ""),
sizeof(bc->connected.name));
if (connected_id.number.valid) {
ast_copy_string(bc->connected.number, S_OR(connected_id.number.str, ""),
sizeof(bc->connected.number));
bc->connected.presentation = ast_to_misdn_pres(connected_id.number.presentation);
bc->connected.screening = ast_to_misdn_screen(connected_id.number.presentation);
bc->connected.number_type = ast_to_misdn_ton(connected_id.number.plan);
bc->connected.number_plan = ast_to_misdn_plan(connected_id.number.plan);
} else {
bc->connected.number[0] = '\0';
bc->connected.presentation = 0;/* Allowed */
bc->connected.screening = 0;/* Unscreened */
bc->connected.number_type = NUMTYPE_UNKNOWN;
bc->connected.number_plan = NUMPLAN_UNKNOWN;
}
misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
if (0 <= number_type) {
/* Force us to send in CONNECT message */
bc->connected.number_type = number_type;
bc->connected.number_plan = NUMPLAN_ISDN;
}
debug_numtype(bc->port, bc->connected.number_type, "CTON");
} else {
/* ORIGINATOR Asterisk (outgoing call) */
ast_copy_string(bc->caller.name,
S_COR(connected_id.name.valid, connected_id.name.str, ""),
sizeof(bc->caller.name));
if (connected_id.number.valid) {
ast_copy_string(bc->caller.number, S_OR(connected_id.number.str, ""),
sizeof(bc->caller.number));
bc->caller.presentation = ast_to_misdn_pres(connected_id.number.presentation);
bc->caller.screening = ast_to_misdn_screen(connected_id.number.presentation);
bc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan);
bc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan);
} else {
bc->caller.number[0] = '\0';
bc->caller.presentation = 0;/* Allowed */
bc->caller.screening = 0;/* Unscreened */
bc->caller.number_type = NUMTYPE_UNKNOWN;
bc->caller.number_plan = NUMPLAN_UNKNOWN;
}
misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
if (0 <= number_type) {
/* Force us to send in SETUP message */
bc->caller.number_type = number_type;
bc->caller.number_plan = NUMPLAN_ISDN;
}
debug_numtype(bc->port, bc->caller.number_type, "LTON");
}
}
| static int misdn_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 7079 of file chan_misdn.c.
References chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_hangupcause(), ast_channel_name(), ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, chan_list::bc, misdn_bchannel::cause, chan_list_unref, chan_misdn_log(), EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, hanguptone_indicate(), chan_list::hold, INFO_PI_INBAND_AVAILABLE, chan_list::l3id, LOG_NOTICE, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_ASTERISK_TECH_PVT_SET, MISDN_BUSY, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, misdn_chan_is_valid(), MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, misdn_get_ch_state(), MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, MISDN_INCOMING_SETUP, misdn_lib_find_held_bc(), misdn_lib_release(), misdn_lib_send_event(), MISDN_NOTHING, MISDN_PROCEEDING, MISDN_PROGRESS, name, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, misdn_bchannel::nt, ORG_AST, chan_list::originator, misdn_bchannel::out_cause, pbx_builtin_getvar_helper(), misdn_bchannel::pid, hold_info::port, misdn_bchannel::port, misdn_bchannel::progress_indicator, release_chan(), release_chan_early(), start_bc_tones(), hold_info::state, chan_list::state, stop_bc_tones(), misdn_bchannel::uu, misdn_bchannel::uulen, and var.
{
struct chan_list *p;
struct misdn_bchannel *bc;
const char *var;
if (!ast) {
return -1;
}
ast_debug(1, "misdn_hangup(%s)\n", ast_channel_name(ast));
/* Take the ast_channel's tech_pvt reference. */
ast_mutex_lock(&release_lock);
p = MISDN_ASTERISK_TECH_PVT(ast);
if (!p) {
ast_mutex_unlock(&release_lock);
return -1;
}
MISDN_ASTERISK_TECH_PVT_SET(ast, NULL);
if (!misdn_chan_is_valid(p)) {
ast_mutex_unlock(&release_lock);
chan_list_unref(p, "Release ast_channel reference. Was not active?");
return 0;
}
if (p->hold.state == MISDN_HOLD_IDLE) {
bc = p->bc;
} else {
p->hold.state = MISDN_HOLD_DISCONNECT;
bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
if (!bc) {
chan_misdn_log(4, p->hold.port,
"misdn_hangup: Could not find held bc for (%s)\n", ast_channel_name(ast));
release_chan_early(p);
ast_mutex_unlock(&release_lock);
chan_list_unref(p, "Release ast_channel reference");
return 0;
}
}
if (ast_channel_state(ast) == AST_STATE_RESERVED || p->state == MISDN_NOTHING) {
/* between request and call */
ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
release_chan_early(p);
if (bc) {
misdn_lib_release(bc);
}
ast_mutex_unlock(&release_lock);
chan_list_unref(p, "Release ast_channel reference");
return 0;
}
if (!bc) {
ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
misdn_get_ch_state(p), p->l3id);
release_chan_early(p);
ast_mutex_unlock(&release_lock);
chan_list_unref(p, "Release ast_channel reference");
return 0;
}
p->ast = NULL;
p->need_hangup = 0;
p->need_queue_hangup = 0;
p->need_busy = 0;
if (!bc->nt) {
stop_bc_tones(p);
}
bc->out_cause = ast_channel_hangupcause(ast) ? ast_channel_hangupcause(ast) : AST_CAUSE_NORMAL_CLEARING;
/* Channel lock is already held when we are called. */
//ast_channel_lock(ast);
var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
if (!var) {
var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
}
if (var) {
int tmpcause;
tmpcause = atoi(var);
bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
}
var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
if (var) {
ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
ast_copy_string(bc->uu, var, sizeof(bc->uu));
bc->uulen = strlen(bc->uu);
}
//ast_channel_unlock(ast);
chan_misdn_log(1, bc->port,
"* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
bc->pid,
ast_channel_context(ast),
ast_channel_exten(ast),
(ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
? ast_channel_caller(ast)->id.name.str : "",
(ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
? ast_channel_caller(ast)->id.number.str : "",
misdn_get_ch_state(p));
chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
switch (p->state) {
case MISDN_INCOMING_SETUP:
/*
* This is the only place in misdn_hangup, where we
* can call release_chan, else it might create a lot of trouble.
*/
ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
release_chan(p, bc);
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
ast_mutex_unlock(&release_lock);
chan_list_unref(p, "Release ast_channel reference");
return 0;
case MISDN_DIALING:
if (p->hold.state == MISDN_HOLD_IDLE) {
start_bc_tones(p);
hanguptone_indicate(p);
}
if (bc->need_disconnect) {
misdn_lib_send_event(bc, EVENT_DISCONNECT);
}
break;
case MISDN_CALLING_ACKNOWLEDGE:
if (p->hold.state == MISDN_HOLD_IDLE) {
start_bc_tones(p);
hanguptone_indicate(p);
}
if (bc->need_disconnect) {
misdn_lib_send_event(bc, EVENT_DISCONNECT);
}
break;
case MISDN_CALLING:
case MISDN_ALERTING:
case MISDN_PROGRESS:
case MISDN_PROCEEDING:
if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
hanguptone_indicate(p);
}
if (bc->need_disconnect) {
misdn_lib_send_event(bc, EVENT_DISCONNECT);
}
break;
case MISDN_CONNECTED:
/* Alerting or Disconnect */
if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
start_bc_tones(p);
hanguptone_indicate(p);
bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
}
if (bc->need_disconnect) {
misdn_lib_send_event(bc, EVENT_DISCONNECT);
}
break;
case MISDN_DISCONNECTED:
if (bc->need_release) {
misdn_lib_send_event(bc, EVENT_RELEASE);
}
break;
case MISDN_CLEANING:
ast_mutex_unlock(&release_lock);
chan_list_unref(p, "Release ast_channel reference");
return 0;
case MISDN_BUSY:
break;
default:
if (bc->nt) {
bc->out_cause = -1;
if (bc->need_release) {
misdn_lib_send_event(bc, EVENT_RELEASE);
}
} else {
if (bc->need_disconnect) {
misdn_lib_send_event(bc, EVENT_DISCONNECT);
}
}
break;
}
p->state = MISDN_CLEANING;
chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast_channel_name(ast),
misdn_get_ch_state(p));
ast_mutex_unlock(&release_lock);
chan_list_unref(p, "Release ast_channel reference");
return 0;
}
| static int misdn_indication | ( | struct ast_channel * | ast, |
| int | cond, | ||
| const void * | data, | ||
| size_t | datalen | ||
| ) | [static] |
Definition at line 6938 of file chan_misdn.c.
References AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, ast_channel_name(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_REDIRECTING, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_setstate(), AST_STATE_BUSY, AST_STATE_RING, chan_list::bc, chan_misdn_log(), EVENT_ALERTING, EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_PROGRESS, hanguptone_indicate(), chan_list::hold, chan_list::incoming_early_audio, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, MISDN_HOLD_IDLE, misdn_lib_send_event(), misdn_update_connected_line(), misdn_update_redirecting(), chan_list::mohinterpret, misdn_bchannel::nt, ORG_MISDN, chan_list::originator, misdn_bchannel::out_cause, chan_list::overlap_dial, misdn_bchannel::pid, misdn_bchannel::port, start_bc_tones(), hold_info::state, chan_list::state, and stop_indicate().
{
struct chan_list *p;
if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
return -1;
}
if (!p->bc) {
if (p->hold.state == MISDN_HOLD_IDLE) {
chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
ast_channel_name(ast));
ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
} else {
chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
cond, ast_channel_name(ast));
}
return -1;
}
chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n", cond, ast_channel_name(ast));
switch (cond) {
case AST_CONTROL_BUSY:
chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
ast_setstate(ast, AST_STATE_BUSY);
p->bc->out_cause = AST_CAUSE_USER_BUSY;
if (p->state != MISDN_CONNECTED) {
start_bc_tones(p);
misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
}
return -1;
case AST_CONTROL_RING:
chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
return -1;
case AST_CONTROL_RINGING:
chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
switch (p->state) {
case MISDN_ALERTING:
chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
break;
case MISDN_CONNECTED:
chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc->pid);
return -1;
default:
p->state = MISDN_ALERTING;
chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
misdn_lib_send_event(p->bc, EVENT_ALERTING);
chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
ast_setstate(ast, AST_STATE_RING);
if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
} else {
return -1;
}
}
break;
case AST_CONTROL_ANSWER:
chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
start_bc_tones(p);
break;
case AST_CONTROL_TAKEOFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
return -1;
case AST_CONTROL_OFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
return -1;
case AST_CONTROL_FLASH:
chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
break;
case AST_CONTROL_PROGRESS:
chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
misdn_lib_send_event(p->bc, EVENT_PROGRESS);
break;
case AST_CONTROL_PROCEEDING:
chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
misdn_lib_send_event(p->bc, EVENT_PROCEEDING);
break;
case AST_CONTROL_INCOMPLETE:
chan_misdn_log(1, p->bc->port, " --> *\tincomplete pid:%d\n", p->bc->pid);
if (!p->overlap_dial) {
/* Overlapped dialing not enabled - send hangup */
p->bc->out_cause = AST_CAUSE_INVALID_NUMBER_FORMAT;
start_bc_tones(p);
misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
if (p->bc->nt) {
hanguptone_indicate(p);
}
}
break;
case AST_CONTROL_CONGESTION:
chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
start_bc_tones(p);
misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
if (p->bc->nt) {
hanguptone_indicate(p);
}
break;
case -1 :
chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
stop_indicate(p);
if (p->state == MISDN_CONNECTED) {
start_bc_tones(p);
}
break;
case AST_CONTROL_HOLD:
ast_moh_start(ast, data, p->mohinterpret);
chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
break;
case AST_CONTROL_UNHOLD:
ast_moh_stop(ast);
chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
break;
case AST_CONTROL_CONNECTED_LINE:
chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
misdn_update_connected_line(ast, p->bc, p->originator);
break;
case AST_CONTROL_REDIRECTING:
chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
misdn_update_redirecting(ast, p->bc, p->originator);
break;
default:
chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
/* fallthrough */
case AST_CONTROL_PVT_CAUSE_CODE:
return -1;
}
return 0;
}
| static int misdn_is_msn_valid | ( | int | port, |
| const struct misdn_party_dialing * | dialed | ||
| ) | [static] |
Definition at line 9902 of file chan_misdn.c.
References ast_copy_string(), misdn_add_number_prefix(), misdn_cfg_is_msn_valid(), misdn_party_dialing::number, and misdn_party_dialing::number_type.
Referenced by cb_events().
{
char number[sizeof(dialed->number)];
ast_copy_string(number, dialed->number, sizeof(number));
misdn_add_number_prefix(port, dialed->number_type, number, sizeof(number));
return misdn_cfg_is_msn_valid(port, number);
}
| void misdn_jb_destroy | ( | struct misdn_jb * | jb | ) |
frees the data and destroys the given jitterbuffer struct
Definition at line 12605 of file chan_misdn.c.
References ast_free, ast_mutex_destroy, misdn_jb::mutexjb, misdn_jb::ok, and misdn_jb::samples.
Referenced by chan_list_destructor(), and config_jitterbuffer().
| int misdn_jb_empty | ( | struct misdn_jb * | jb, |
| char * | data, | ||
| int | len | ||
| ) |
gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data.
Definition at line 12682 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, chan_misdn_log(), len(), misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::rp, misdn_jb::samples, misdn_jb::size, misdn_jb::state_buffer, misdn_jb::state_empty, and misdn_jb::wp.
Referenced by chan_misdn_jb_empty().
{
int i;
int wp;
int rp;
int read = 0;
ast_mutex_lock(&jb->mutexjb);
rp = jb->rp;
wp = jb->wp;
if (jb->state_empty) {
for (i = 0; i < len; i++) {
if (wp == rp) {
jb->rp = rp;
jb->state_empty = 0;
ast_mutex_unlock(&jb->mutexjb);
return read;
} else {
if (jb->ok[rp] == 1) {
data[i] = jb->samples[rp];
jb->ok[rp] = 0;
rp = (rp != jb->size - 1) ? rp + 1 : 0;
read += 1;
}
}
}
if (wp >= rp) {
jb->state_buffer = wp - rp;
} else {
jb->state_buffer = jb->size - rp + wp;
}
chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
jb->rp = rp;
} else {
chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
}
ast_mutex_unlock(&jb->mutexjb);
return read;
}
| int misdn_jb_fill | ( | struct misdn_jb * | jb, |
| const char * | data, | ||
| int | len | ||
| ) |
fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).
Definition at line 12616 of file chan_misdn.c.
References ast_mutex_lock, ast_mutex_unlock, misdn_jb::bytes_wrote, chan_misdn_log(), len(), misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::rp, misdn_jb::samples, misdn_jb::size, misdn_jb::state_buffer, misdn_jb::state_empty, misdn_jb::state_full, misdn_jb::upper_threshold, and misdn_jb::wp.
Referenced by misdn_write().
{
int i;
int j;
int rp;
int wp;
if (!jb || ! data) {
return 0;
}
ast_mutex_lock(&jb->mutexjb);
wp = jb->wp;
rp = jb->rp;
for (i = 0; i < len; i++) {
jb->samples[wp] = data[i];
jb->ok[wp] = 1;
wp = (wp != jb->size - 1) ? wp + 1 : 0;
if (wp == jb->rp) {
jb->state_full = 1;
}
}
if (wp >= rp) {
jb->state_buffer = wp - rp;
} else {
jb->state_buffer = jb->size - rp + wp;
}
chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
if (jb->state_full) {
jb->wp = wp;
rp = wp;
for (j = 0; j < jb->upper_threshold; j++) {
rp = (rp != 0) ? rp - 1 : jb->size - 1;
}
jb->rp = rp;
jb->state_full = 0;
jb->state_empty = 1;
ast_mutex_unlock(&jb->mutexjb);
return -1;
}
if (!jb->state_empty) {
jb->bytes_wrote += len;
if (jb->bytes_wrote >= jb->upper_threshold) {
jb->state_empty = 1;
jb->bytes_wrote = 0;
}
}
jb->wp = wp;
ast_mutex_unlock(&jb->mutexjb);
return 0;
}
| struct misdn_jb * misdn_jb_init | ( | int | size, |
| int | upper_threshold | ||
| ) | [read] |
allocates the jb-structure and initialize the elements
Definition at line 12568 of file chan_misdn.c.
References ast_calloc, ast_free, ast_mutex_init, chan_misdn_log(), misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::samples, misdn_jb::size, and misdn_jb::upper_threshold.
Referenced by config_jitterbuffer().
{
struct misdn_jb *jb;
jb = ast_calloc(1, sizeof(*jb));
if (!jb) {
chan_misdn_log(-1, 0, "No free Mem for jb\n");
return NULL;
}
jb->size = size;
jb->upper_threshold = upper_threshold;
//jb->wp = 0;
//jb->rp = 0;
//jb->state_full = 0;
//jb->state_empty = 0;
//jb->bytes_wrote = 0;
jb->samples = ast_calloc(size, sizeof(*jb->samples));
if (!jb->samples) {
ast_free(jb);
chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
return NULL;
}
jb->ok = ast_calloc(size, sizeof(*jb->ok));
if (!jb->ok) {
ast_free(jb->samples);
ast_free(jb);
chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
return NULL;
}
ast_mutex_init(&jb->mutexjb);
return jb;
}
| static int misdn_l1_task | ( | const void * | vdata | ) | [static] |
Definition at line 3592 of file chan_misdn.c.
References chan_misdn_log(), and misdn_lib_isdn_l1watcher().
Referenced by load_module().
{
const int *data = vdata;
misdn_lib_isdn_l1watcher(*data);
chan_misdn_log(5, *data, "L1watcher timeout\n");
return 1;
}
| static struct ast_channel * misdn_new | ( | struct chan_list * | cl, |
| int | state, | ||
| char * | exten, | ||
| char * | callerid, | ||
| struct ast_format_cap * | cap, | ||
| const char * | linkedid, | ||
| int | port, | ||
| int | c | ||
| ) | [static, read] |
Definition at line 8149 of file chan_misdn.c.
References ast_party_caller::ani, chan_list::ast, ast_best_codec(), ast_callerid_parse(), ast_channel_alloc(), ast_channel_caller(), ast_channel_exten_set(), ast_channel_nativeformats(), ast_channel_priority_set(), ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_channel_readformat(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_tech_set(), ast_channel_writeformat(), ast_format_cap_add(), ast_format_copy(), ast_jb_configure(), ast_log(), AST_STATE_RING, ast_strdup, ast_strlen_zero(), chan_list_ref, chan_misdn_log(), cid_name, cid_num, LOG_ERROR, MISDN_ASTERISK_TECH_PVT_SET, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_GEN_BRIDGING, misdn_get_global_jbconf(), misdn_lib_port_is_pri(), ast_party_id::number, chan_list::pipe, prefformat, ast_party_number::str, and ast_party_number::valid.
Referenced by cb_events(), and misdn_request().
{
struct ast_channel *tmp;
char *cid_name = NULL;
char *cid_num = NULL;
int chan_offset = 0;
int tmp_port = misdn_cfg_get_next_port(0);
int bridging;
struct ast_format tmpfmt;
for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
if (tmp_port == port) {
break;
}
chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
}
if (c < 0) {
c = 0;
}
if (callerid) {
ast_callerid_parse(callerid, &cid_name, &cid_num);
}
tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", linkedid, 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
if (tmp) {
chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
ast_best_codec(cap, &tmpfmt);
ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat);
ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
/* Link the channel and private together */
chan_list_ref(chlist, "Give a reference to ast_channel");
MISDN_ASTERISK_TECH_PVT_SET(tmp, chlist);
chlist->ast = tmp;
misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
ast_channel_tech_set(tmp, bridging ? &misdn_tech : &misdn_tech_wo_bridge);
ast_channel_priority_set(tmp, 1);
if (exten) {
ast_channel_exten_set(tmp, exten);
} else {
chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
}
if (!ast_strlen_zero(cid_num)) {
/* Don't use ast_set_callerid() here because it will
* generate a needless NewCallerID event */
ast_channel_caller(tmp)->ani.number.valid = 1;
ast_channel_caller(tmp)->ani.number.str = ast_strdup(cid_num);
}
if (pipe(chlist->pipe) < 0) {
ast_log(LOG_ERROR, "Pipe failed\n");
}
ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
ast_channel_rings_set(tmp, (state == AST_STATE_RING) ? 1 : 0);
ast_jb_configure(tmp, misdn_get_global_jbconf());
} else {
chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
}
return tmp;
}
| static int misdn_overlap_dial_task | ( | const void * | data | ) | [static] |
Definition at line 3601 of file chan_misdn.c.
References chan_list::ast, AST_CAUSE_UNALLOCATED, ast_channel_exten_set(), ast_exists_extension(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), chan_list::bc, misdn_bchannel::caller, chan_misdn_log(), chan_list::context, misdn_bchannel::dialed, EVENT_DISCONNECT, hanguptone_indicate(), MISDN_CLEANING, MISDN_DIALING, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_party_dialing::number, misdn_party_id::number, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_start_chan(), misdn_bchannel::port, chan_list::state, and stop_indicate().
Referenced by cb_events().
{
struct timeval tv_end, tv_now;
int diff;
struct chan_list *ch = (struct chan_list *) data;
char *dad;
chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
if (ch->state != MISDN_WAITING4DIGS) {
ch->overlap_dial_task = -1;
return 0;
}
ast_mutex_lock(&ch->overlap_tv_lock);
tv_end = ch->overlap_tv;
ast_mutex_unlock(&ch->overlap_tv_lock);
tv_end.tv_sec += ch->overlap_dial;
tv_now = ast_tvnow();
diff = ast_tvdiff_ms(tv_end, tv_now);
if (100 < diff) {
return diff;
}
/* if we are 100ms near the timeout, we are satisfied.. */
stop_indicate(ch);
if (ast_strlen_zero(ch->bc->dialed.number)) {
dad = "s";
ast_channel_exten_set(ch->ast, dad);
} else {
dad = ch->bc->dialed.number;
}
if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
ch->state = MISDN_DIALING;
if (pbx_start_chan(ch) < 0) {
chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
goto misdn_overlap_dial_task_disconnect;
}
} else {
misdn_overlap_dial_task_disconnect:
hanguptone_indicate(ch);
ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
ch->state = MISDN_CLEANING;
misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
}
ch->overlap_dial_task = -1;
return 0;
}
| static void misdn_prefix_string | ( | const char * | str_prefix, |
| char * | str_main, | ||
| size_t | size | ||
| ) | [static] |
Definition at line 3357 of file chan_misdn.c.
Referenced by misdn_add_number_prefix().
{
size_t len_over;
size_t len_total;
size_t len_main;
size_t len_prefix;
len_prefix = strlen(str_prefix);
if (!len_prefix) {
/* There is no prefix to prepend. */
return;
}
len_main = strlen(str_main);
len_total = len_prefix + len_main;
if (size <= len_total) {
/* We need to truncate since the buffer is too small. */
len_over = len_total + 1 - size;
if (len_over <= len_main) {
len_main -= len_over;
} else {
len_over -= len_main;
len_main = 0;
len_prefix -= len_over;
}
}
if (len_main) {
memmove(str_main + len_prefix, str_main, len_main);
}
memcpy(str_main, str_prefix, len_prefix);
str_main[len_prefix + len_main] = '\0';
}
| static void misdn_queue_connected_line_update | ( | struct ast_channel * | ast, |
| const struct misdn_party_id * | id, | ||
| enum AST_CONNECTED_LINE_UPDATE_SOURCE | source, | ||
| char * | cid_tag | ||
| ) | [static] |
Definition at line 6098 of file chan_misdn.c.
References ast_channel_queue_connected_line_update(), ast_party_connected_line_init(), ast_set_party_id_all(), ast_party_connected_line::id, ast_set_party_connected_line::id, misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_screen(), misdn_to_ast_ton(), ast_party_id::number, misdn_party_id::number, ast_set_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, ast_party_number::plan, ast_party_number::presentation, misdn_party_id::presentation, ast_set_party_connected_line::priv, misdn_party_id::screening, ast_party_connected_line::source, ast_party_number::str, ast_party_id::tag, and ast_party_number::valid.
Referenced by misdn_update_remote_party().
{
struct ast_party_connected_line connected;
struct ast_set_party_connected_line update_connected;
ast_party_connected_line_init(&connected);
memset(&update_connected, 0, sizeof(update_connected));
update_connected.id.number = 1;
connected.id.number.valid = 1;
connected.id.number.str = (char *) id->number;
connected.id.number.plan = misdn_to_ast_ton(id->number_type)
| misdn_to_ast_plan(id->number_plan);
connected.id.number.presentation = misdn_to_ast_pres(id->presentation)
| misdn_to_ast_screen(id->screening);
/*
* Make sure that any earlier private connected id
* representation at the remote end is invalidated
*/
ast_set_party_id_all(&update_connected.priv);
connected.id.tag = cid_tag;
connected.source = source;
ast_channel_queue_connected_line_update(ast, &connected, &update_connected);
}
| static struct ast_frame* misdn_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 7355 of file chan_misdn.c.
References chan_list::ast_dsp, AST_FORMAT_ALAW, ast_format_set(), AST_FRAME_VOICE, ast_poll, chan_list::ast_rd_buf, ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), chan_list::bc, chan_misdn_log(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, chan_list::faxdetect, chan_list::faxdetect_timeout, chan_list::faxdetect_tv, chan_list::faxhandled, ast_frame_subclass::format, chan_list::frame, ast_frame::frametype, chan_list::hold, len(), ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, MISDN_HOLD_IDLE, ast_frame::offset, chan_list::pipe, misdn_bchannel::port, process_ast_dsp(), ast_frame::ptr, ast_frame::samples, ast_frame::src, hold_info::state, and ast_frame::subclass.
{
struct chan_list *tmp;
int len, t;
struct pollfd pfd = { .fd = -1, .events = POLLIN };
if (!ast) {
chan_misdn_log(1, 0, "misdn_read called without ast\n");
return NULL;
}
if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
return NULL;
}
if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
chan_misdn_log(1, 0, "misdn_read called without bc\n");
return NULL;
}
pfd.fd = tmp->pipe[0];
t = ast_poll(&pfd, 1, 20);
if (t < 0) {
chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
return NULL;
}
if (!t) {
chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
len = 160;
} else if (pfd.revents & POLLIN) {
len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
if (len <= 0) {
/* we hangup here, since our pipe is closed */
chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
return NULL;
}
} else {
return NULL;
}
tmp->frame.frametype = AST_FRAME_VOICE;
ast_format_set(&tmp->frame.subclass.format, AST_FORMAT_ALAW, 0);
tmp->frame.datalen = len;
tmp->frame.samples = len;
tmp->frame.mallocd = 0;
tmp->frame.offset = 0;
tmp->frame.delivery = ast_tv(0, 0);
tmp->frame.src = NULL;
tmp->frame.data.ptr = tmp->ast_rd_buf;
if (tmp->faxdetect && !tmp->faxhandled) {
if (tmp->faxdetect_timeout) {
if (ast_tvzero(tmp->faxdetect_tv)) {
tmp->faxdetect_tv = ast_tvnow();
chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
return process_ast_dsp(tmp, &tmp->frame);
} else {
struct timeval tv_now = ast_tvnow();
int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
if (diff <= (tmp->faxdetect_timeout * 1000)) {
chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
return process_ast_dsp(tmp, &tmp->frame);
} else {
chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
tmp->faxdetect = 0;
return &tmp->frame;
}
}
} else {
chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
return process_ast_dsp(tmp, &tmp->frame);
}
} else {
if (tmp->ast_dsp) {
return process_ast_dsp(tmp, &tmp->frame);
} else {
return &tmp->frame;
}
}
}
| static struct ast_channel* misdn_request | ( | const char * | type, |
| struct ast_format_cap * | cap, | ||
| const struct ast_channel * | requestor, | ||
| const char * | data, | ||
| int * | cause | ||
| ) | [static, read] |
Definition at line 7812 of file chan_misdn.c.
References args, AST_APP_ARG, ast_channel_linkedid(), ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STATE_RESERVED, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, chan_list_init(), chan_list_unref, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, cl_queue_chan(), misdn_bchannel::dec, ext, get_robin_position(), LOG_ERROR, LOG_WARNING, METHOD_ROUND_ROBIN, METHOD_STANDARD_DEC, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_next_port_spin(), MISDN_CFG_GROUPNAME, misdn_cfg_is_group_method(), MISDN_CFG_PMP_L1_CHECK, misdn_lib_get_free_bc(), misdn_lib_get_maxchans(), misdn_lib_port_up(), misdn_lib_release(), misdn_new(), chan_list::need_hangup, ORG_AST, misdn_bchannel::port, robin_list::port, and read_config().
{
struct ast_channel *ast;
char group[BUFFERSIZE + 1] = "";
char dial_str[128];
char *dest_cp;
char *p = NULL;
int channel = 0;
int port = 0;
struct misdn_bchannel *newbc = NULL;
int dec = 0;
#if defined(AST_MISDN_ENHANCEMENTS)
int cc_retry_call = 0; /* TRUE if this is a call completion retry call */
long record_id = -1;
struct misdn_cc_record *cc_record;
const char *err_msg;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
struct chan_list *cl;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(intf); /* interface token */
AST_APP_ARG(ext); /* extension token */
AST_APP_ARG(opts); /* options token */
);
snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, data);
/*
* data is ---v
* Dial(mISDN/g:group_name[/extension[/options]])
* Dial(mISDN/port[:preselected_channel][/extension[/options]])
* Dial(mISDN/cc/cc-record-id)
*
* The dial extension could be empty if you are using MISDN_KEYPAD
* to control ISDN provider features.
*/
dest_cp = ast_strdupa(data);
AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
if (!args.ext) {
args.ext = "";
}
if (!ast_strlen_zero(args.intf)) {
if (args.intf[0] == 'g' && args.intf[1] == ':') {
/* We make a group call lets checkout which ports are in my group */
args.intf += 2;
ast_copy_string(group, args.intf, sizeof(group));
chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
#if defined(AST_MISDN_ENHANCEMENTS)
} else if (strcmp(args.intf, "cc") == 0) {
cc_retry_call = 1;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
} else if ((p = strchr(args.intf, ':'))) {
/* we have a preselected channel */
*p++ = 0;
channel = atoi(p);
port = atoi(args.intf);
chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
} else {
port = atoi(args.intf);
}
} else {
ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
return NULL;
}
#if defined(AST_MISDN_ENHANCEMENTS)
if (cc_retry_call) {
if (ast_strlen_zero(args.ext)) {
ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT cc-record-id, check extensions.conf\n", dial_str);
return NULL;
}
if (!isdigit(*args.ext)) {
ast_log(LOG_WARNING, " --> ! IND : Dial(%s) cc-record-id must be a number.\n", dial_str);
return NULL;
}
record_id = atol(args.ext);
AST_LIST_LOCK(&misdn_cc_records_db);
cc_record = misdn_cc_find_by_id(record_id);
if (!cc_record) {
AST_LIST_UNLOCK(&misdn_cc_records_db);
err_msg = misdn_cc_record_not_found;
ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
return NULL;
}
if (!cc_record->activated) {
AST_LIST_UNLOCK(&misdn_cc_records_db);
err_msg = "Call completion has not been activated";
ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
return NULL;
}
port = cc_record->port;
AST_LIST_UNLOCK(&misdn_cc_records_db);
}
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
dec = 1;
}
if (!ast_strlen_zero(group)) {
char cfg_group[BUFFERSIZE + 1];
struct robin_list *rr = NULL;
/* Group dial */
if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
rr = get_robin_position(group);
}
if (rr) {
int port_start;
int bchan_start;
int port_up;
int check;
int maxbchans;
int wraped = 0;
if (!rr->port) {
rr->port = misdn_cfg_get_next_port_spin(0);
}
if (!rr->channel) {
rr->channel = 1;
}
bchan_start = rr->channel;
port_start = rr->port;
do {
misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
if (strcasecmp(cfg_group, group)) {
wraped = 1;
rr->port = misdn_cfg_get_next_port_spin(rr->port);
rr->channel = 1;
continue;
}
misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
port_up = misdn_lib_port_up(rr->port, check);
if (!port_up) {
chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
rr->port = misdn_cfg_get_next_port_spin(rr->port);
rr->channel = 1;
} else if (port_up < 0) {
ast_log(LOG_WARNING, "This port (%d) is blocked\n", rr->port);
rr->port = misdn_cfg_get_next_port_spin(rr->port);
rr->channel = 1;
} else {
chan_misdn_log(4, rr->port, "portup\n");
maxbchans = misdn_lib_get_maxchans(rr->port);
for (;rr->channel <= maxbchans;rr->channel++) {
/* ive come full circle and can stop now */
if (wraped && (rr->port == port_start) && (rr->channel == bchan_start)) {
break;
}
chan_misdn_log(4, rr->port, "Checking channel %d\n", rr->channel);
if ((newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0))) {
chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
rr->channel++;
break;
}
}
if (wraped && (rr->port == port_start) && (rr->channel <= bchan_start)) {
break;
} else if (!newbc || (rr->channel == maxbchans)) {
rr->port = misdn_cfg_get_next_port_spin(rr->port);
rr->channel = 1;
}
}
wraped = 1;
} while (!newbc && (rr->port > 0));
} else {
for (port = misdn_cfg_get_next_port(0); port > 0;
port = misdn_cfg_get_next_port(port)) {
misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
if (!strcasecmp(cfg_group, group)) {
int port_up;
int check;
misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
port_up = misdn_lib_port_up(port, check);
chan_misdn_log(4, port, "portup:%d\n", port_up);
if (port_up > 0) {
newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
if (newbc) {
break;
}
}
}
}
}
/* Group dial failed ?*/
if (!newbc) {
ast_log(LOG_WARNING,
"Could not Dial out on group '%s'.\n"
"\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
"\tOr there was no free channel on none of the ports\n\n",
group);
return NULL;
}
} else {
/* 'Normal' Port dial * Port dial */
if (channel) {
chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
}
newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
if (!newbc) {
ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
return NULL;
}
}
/* create ast_channel and link all the objects together */
cl = chan_list_init(ORG_AST);
if (!cl) {
misdn_lib_release(newbc);
ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
return NULL;
}
cl->bc = newbc;
ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, cap, requestor ? ast_channel_linkedid(requestor) : NULL, port, channel);
if (!ast) {
chan_list_unref(cl, "Failed to create a new channel");
misdn_lib_release(newbc);
ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
return NULL;
}
#if defined(AST_MISDN_ENHANCEMENTS)
cl->record_id = record_id;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
/* register chan in local list */
cl_queue_chan(cl);
/* fill in the config into the objects */
read_config(cl);
/* important */
cl->need_hangup = 0;
chan_list_unref(cl, "Successful misdn_request()");
return ast;
}
| static int misdn_send_text | ( | struct ast_channel * | chan, |
| const char * | text | ||
| ) | [static] |
Definition at line 8072 of file chan_misdn.c.
References ast_copy_string(), ast_log(), chan_list::bc, misdn_bchannel::display, EVENT_INFORMATION, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, and misdn_lib_send_event().
{
struct chan_list *tmp = MISDN_ASTERISK_TECH_PVT(chan);
if (tmp && tmp->bc) {
ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
} else {
ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
return -1;
}
return 0;
}
| static int misdn_set_opt_exec | ( | struct ast_channel * | chan, |
| const char * | data | ||
| ) | [static] |
Definition at line 12331 of file chan_misdn.c.
References ast_channel_tech(), ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), ast_log(), ast_strlen_zero(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, chan_list::dsp, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, keys, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_GEN_CRYPT_KEYS, misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_bchannel::orig, chan_list::originator, parse(), misdn_bchannel::port, misdn_bchannel::presentation, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, misdn_bchannel::set_presentation, and misdn_bchannel::txgain.
Referenced by load_module(), and misdn_call().
{
struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
char *tok;
char *tokb;
char *parse;
int keyidx = 0;
int rxgain = 0;
int txgain = 0;
int change_jitter = 0;
if (strcasecmp(ast_channel_tech(chan)->type, misdn_type)) {
ast_log(LOG_WARNING, "misdn_set_opt makes sense only with %s channels!\n", misdn_type);
return -1;
}
if (ast_strlen_zero((char *) data)) {
ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
return -1;
}
parse = ast_strdupa(data);
for (tok = strtok_r(parse, ":", &tokb);
tok;
tok = strtok_r(NULL, ":", &tokb)) {
int neglect = 0;
if (tok[0] == '!') {
neglect = 1;
tok++;
}
switch(tok[0]) {
case 'd' :
ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
break;
case 'n':
chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
ch->bc->nodsp = 1;
break;
case 'j':
chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
tok++;
change_jitter = 1;
switch (tok[0]) {
case 'b':
ch->jb_len = atoi(++tok);
chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
break;
case 't' :
ch->jb_upper_threshold = atoi(++tok);
chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
break;
case 'n':
ch->bc->nojitter = 1;
chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
break;
default:
ch->jb_len = 4000;
ch->jb_upper_threshold = 0;
chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
break;
}
break;
case 'v':
tok++;
switch (tok[0]) {
case 'r' :
rxgain = atoi(++tok);
if (rxgain < -8) {
rxgain = -8;
}
if (rxgain > 8) {
rxgain = 8;
}
ch->bc->rxgain = rxgain;
chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
break;
case 't':
txgain = atoi(++tok);
if (txgain < -8) {
txgain = -8;
}
if (txgain > 8) {
txgain = 8;
}
ch->bc->txgain = txgain;
chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
break;
}
break;
case 'c':
keyidx = atoi(++tok);
{
char keys[4096];
char *key = NULL;
char *tmp = keys;
int i;
misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
for (i = 0; i < keyidx; i++) {
key = strsep(&tmp, ",");
}
if (key) {
ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
}
chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
break;
}
case 'e':
chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
if (neglect) {
chan_misdn_log(1, ch->bc->port, " --> disabled\n");
#ifdef MISDN_1_2
*ch->bc->pipeline = 0;
#else
ch->bc->ec_enable = 0;
#endif
} else {
#ifdef MISDN_1_2
update_pipeline_config(ch->bc);
#else
ch->bc->ec_enable = 1;
ch->bc->orig = ch->originator;
tok++;
if (*tok) {
ch->bc->ec_deftaps = atoi(tok);
}
#endif
}
break;
case 'h':
chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
if (strlen(tok) > 1 && tok[1] == '1') {
chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
if (!ch->bc->hdlc) {
ch->bc->hdlc = 1;
}
}
ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
break;
case 's':
chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
ch->bc->send_dtmf = 1;
break;
case 'f':
chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
ch->faxdetect = 1;
misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
break;
case 'a':
chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
ch->ast_dsp = 1;
break;
case 'p':
chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
/* CRICH: callingpres!!! */
if (strstr(tok, "allowed")) {
ch->bc->presentation = 0;
ch->bc->set_presentation = 1;
} else if (strstr(tok, "restricted")) {
ch->bc->presentation = 1;
ch->bc->set_presentation = 1;
} else if (strstr(tok, "not_screened")) {
chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
ch->bc->presentation = 1;
ch->bc->set_presentation = 1;
}
break;
case 'i' :
chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
ch->ignore_dtmf = 1;
break;
default:
break;
}
}
if (change_jitter) {
config_jitterbuffer(ch);
}
if (ch->faxdetect || ch->ast_dsp) {
if (!ch->dsp) {
ch->dsp = ast_dsp_new();
}
if (ch->dsp) {
ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
}
}
if (ch->ast_dsp) {
chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
ch->bc->nodsp = 1;
}
return 0;
}
| static int misdn_tasks_add | ( | int | timeout, |
| ast_sched_cb | callback, | ||
| const void * | data | ||
| ) | [static] |
Definition at line 3577 of file chan_misdn.c.
References _misdn_tasks_add_variable().
Referenced by load_module().
{
return _misdn_tasks_add_variable(timeout, callback, data, 0);
}
| static int misdn_tasks_add_variable | ( | int | timeout, |
| ast_sched_cb | callback, | ||
| const void * | data | ||
| ) | [static] |
Definition at line 3582 of file chan_misdn.c.
References _misdn_tasks_add_variable().
Referenced by cb_events().
{
return _misdn_tasks_add_variable(timeout, callback, data, 1);
}
| static void misdn_tasks_destroy | ( | void | ) | [static] |
Definition at line 3547 of file chan_misdn.c.
References ast_sched_context_destroy(), cb_log, and chan_misdn_log().
Referenced by unload_module().
{
if (misdn_tasks) {
chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
if (pthread_cancel(misdn_tasks_thread) == 0) {
cb_log(4, 0, "Joining misdn_tasks thread\n");
pthread_join(misdn_tasks_thread, NULL);
}
ast_sched_context_destroy(misdn_tasks);
}
}
| static void misdn_tasks_init | ( | void | ) | [static] |
Definition at line 3527 of file chan_misdn.c.
References ast_sched_context_create(), chan_misdn_log(), misdn_tasks_thread_func(), and pthread_create.
Referenced by _misdn_tasks_add_variable().
{
sem_t blocker;
int i = 5;
if (sem_init(&blocker, 0, 0)) {
perror("chan_misdn: Failed to initialize semaphore!");
exit(1);
}
chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
misdn_tasks = ast_sched_context_create();
pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
while (sem_wait(&blocker) && --i) {
}
sem_destroy(&blocker);
}
| static void misdn_tasks_remove | ( | int | task_id | ) | [static] |
Definition at line 3587 of file chan_misdn.c.
References AST_SCHED_DEL.
Referenced by chan_list_destructor().
{
AST_SCHED_DEL(misdn_tasks, task_id);
}
| static void* misdn_tasks_thread_func | ( | void * | data | ) | [static] |
Definition at line 3501 of file chan_misdn.c.
References ast_sched_runq(), ast_sched_wait(), chan_misdn_log(), and sighandler().
Referenced by misdn_tasks_init().
{
int wait;
struct sigaction sa;
sa.sa_handler = sighandler;
sa.sa_flags = SA_NODEFER;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGUSR1);
sigaction(SIGUSR1, &sa, NULL);
sem_post((sem_t *)data);
while (1) {
wait = ast_sched_wait(misdn_tasks);
if (wait < 0) {
wait = 8000;
}
if (poll(NULL, 0, wait) < 0) {
chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
}
ast_sched_runq(misdn_tasks);
}
return NULL;
}
| static void misdn_tasks_wakeup | ( | void | ) | [inline, static] |
Definition at line 3559 of file chan_misdn.c.
Referenced by _misdn_tasks_add_variable().
{
pthread_kill(misdn_tasks_thread, SIGUSR1);
}
| static int misdn_to_ast_plan | ( | enum mISDN_NUMBER_PLAN | number_plan | ) | [static] |
Definition at line 1976 of file chan_misdn.c.
References NUMPLAN_DATA, NUMPLAN_ISDN, NUMPLAN_NATIONAL, NUMPLAN_PRIVATE, NUMPLAN_TELEX, and NUMPLAN_UNKNOWN.
Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().
{
int ast_number_plan;
switch (number_plan) {
default:
case NUMPLAN_UNKNOWN:
ast_number_plan = NUMPLAN_UNKNOWN;
break;
case NUMPLAN_ISDN:
ast_number_plan = NUMPLAN_ISDN;
break;
case NUMPLAN_DATA:
ast_number_plan = NUMPLAN_DATA;
break;
case NUMPLAN_TELEX:
ast_number_plan = NUMPLAN_TELEX;
break;
case NUMPLAN_NATIONAL:
ast_number_plan = NUMPLAN_NATIONAL;
break;
case NUMPLAN_PRIVATE:
ast_number_plan = NUMPLAN_PRIVATE;
break;
}
return ast_number_plan;
}
| static int misdn_to_ast_pres | ( | int | presentation | ) | [static] |
Definition at line 2093 of file chan_misdn.c.
References AST_PRES_ALLOWED, AST_PRES_RESTRICTED, and AST_PRES_UNAVAILABLE.
Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().
{
switch (presentation) {
default:
case 0:
presentation = AST_PRES_ALLOWED;
break;
case 1:
presentation = AST_PRES_RESTRICTED;
break;
case 2:
presentation = AST_PRES_UNAVAILABLE;
break;
}
return presentation;
}
| static enum AST_REDIRECTING_REASON misdn_to_ast_reason | ( | const enum mISDN_REDIRECTING_REASON | q931 | ) | [static] |
Definition at line 2290 of file chan_misdn.c.
References AST_REDIRECTING_REASON_CALL_FWD_DTE, AST_REDIRECTING_REASON_DEFLECTION, AST_REDIRECTING_REASON_NO_ANSWER, AST_REDIRECTING_REASON_OUT_OF_ORDER, AST_REDIRECTING_REASON_UNCONDITIONAL, AST_REDIRECTING_REASON_UNKNOWN, AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_NO_REPLY, mISDN_REDIRECTING_REASON_OUT_OF_ORDER, and mISDN_REDIRECTING_REASON_UNKNOWN.
Referenced by misdn_copy_redirecting_to_ast().
{
enum AST_REDIRECTING_REASON ast;
switch (q931) {
default:
case mISDN_REDIRECTING_REASON_UNKNOWN:
ast = AST_REDIRECTING_REASON_UNKNOWN;
break;
case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
ast = AST_REDIRECTING_REASON_USER_BUSY;
break;
case mISDN_REDIRECTING_REASON_NO_REPLY:
ast = AST_REDIRECTING_REASON_NO_ANSWER;
break;
case mISDN_REDIRECTING_REASON_DEFLECTION:
ast = AST_REDIRECTING_REASON_DEFLECTION;
break;
case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
break;
case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
break;
case mISDN_REDIRECTING_REASON_CALL_FWD:
ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
break;
}
return ast;
}
| static int misdn_to_ast_screen | ( | int | screening | ) | [static] |
Definition at line 2186 of file chan_misdn.c.
References AST_PRES_NETWORK_NUMBER, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.
Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().
{
switch (screening) {
default:
case 0:
screening = AST_PRES_USER_NUMBER_UNSCREENED;
break;
case 1:
screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
break;
case 2:
screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
break;
case 3:
screening = AST_PRES_NETWORK_NUMBER;
break;
}
return screening;
}
| static int misdn_to_ast_ton | ( | enum mISDN_NUMBER_TYPE | number_type | ) | [static] |
Definition at line 1850 of file chan_misdn.c.
References NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.
Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().
{
int ast_number_type;
switch (number_type) {
default:
case NUMTYPE_UNKNOWN:
ast_number_type = NUMTYPE_UNKNOWN << 4;
break;
case NUMTYPE_INTERNATIONAL:
ast_number_type = NUMTYPE_INTERNATIONAL << 4;
break;
case NUMTYPE_NATIONAL:
ast_number_type = NUMTYPE_NATIONAL << 4;
break;
case NUMTYPE_NETWORK_SPECIFIC:
ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
break;
case NUMTYPE_SUBSCRIBER:
ast_number_type = NUMTYPE_SUBSCRIBER << 4;
break;
case NUMTYPE_ABBREVIATED:
ast_number_type = NUMTYPE_ABBREVIATED << 4;
break;
}
return ast_number_type;
}
| static const char* misdn_to_str_plan | ( | enum mISDN_NUMBER_PLAN | number_plan | ) | [static] |
Definition at line 1934 of file chan_misdn.c.
References NUMPLAN_DATA, NUMPLAN_ISDN, NUMPLAN_NATIONAL, NUMPLAN_PRIVATE, NUMPLAN_TELEX, NUMPLAN_UNKNOWN, and str.
Referenced by cb_events().
{
const char *str;
switch (number_plan) {
default:
case NUMPLAN_UNKNOWN:
str = "Unknown";
break;
case NUMPLAN_ISDN:
str = "ISDN";
break;
case NUMPLAN_DATA:
str = "Data";
break;
case NUMPLAN_TELEX:
str = "Telex";
break;
case NUMPLAN_NATIONAL:
str = "National";
break;
case NUMPLAN_PRIVATE:
str = "Private";
break;
}
return str;
}
| static const char* misdn_to_str_pres | ( | int | presentation | ) | [static] |
Definition at line 2060 of file chan_misdn.c.
References str.
Referenced by cb_events(), and update_config().
| static const char* misdn_to_str_screen | ( | int | screening | ) | [static] |
Definition at line 2149 of file chan_misdn.c.
References str.
Referenced by cb_events(), and update_config().
| static const char* misdn_to_str_ton | ( | enum mISDN_NUMBER_TYPE | number_type | ) | [static] |
Definition at line 1808 of file chan_misdn.c.
References NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, NUMTYPE_UNKNOWN, and str.
Referenced by cb_events().
{
const char *str;
switch (number_type) {
default:
case NUMTYPE_UNKNOWN:
str = "Unknown";
break;
case NUMTYPE_INTERNATIONAL:
str = "International";
break;
case NUMTYPE_NATIONAL:
str = "National";
break;
case NUMTYPE_NETWORK_SPECIFIC:
str = "Network Specific";
break;
case NUMTYPE_SUBSCRIBER:
str = "Subscriber";
break;
case NUMTYPE_ABBREVIATED:
str = "Abbreviated";
break;
}
return str;
}
| static void misdn_update_caller_id | ( | struct ast_channel * | ast, |
| const struct misdn_party_id * | id, | ||
| char * | cid_tag | ||
| ) | [static] |
Definition at line 6134 of file chan_misdn.c.
References ast_party_caller::ani, ast_set_party_caller::ani, ast_channel_caller(), ast_channel_lock, ast_channel_set_caller_event(), ast_channel_unlock, ast_party_caller_set_init(), ast_party_caller::id, ast_set_party_caller::id, misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_screen(), misdn_to_ast_ton(), ast_party_id::number, misdn_party_id::number, ast_set_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, ast_party_number::plan, ast_party_number::presentation, misdn_party_id::presentation, misdn_party_id::screening, ast_party_number::str, ast_party_id::tag, and ast_party_number::valid.
Referenced by misdn_update_remote_party().
{
struct ast_party_caller caller;
struct ast_set_party_caller update_caller;
memset(&update_caller, 0, sizeof(update_caller));
update_caller.id.number = 1;
update_caller.ani.number = 1;
ast_channel_lock(ast);
ast_party_caller_set_init(&caller, ast_channel_caller(ast));
caller.id.number.valid = 1;
caller.id.number.str = (char *) id->number;
caller.id.number.plan = misdn_to_ast_ton(id->number_type)
| misdn_to_ast_plan(id->number_plan);
caller.id.number.presentation = misdn_to_ast_pres(id->presentation)
| misdn_to_ast_screen(id->screening);
caller.ani.number = caller.id.number;
caller.id.tag = cid_tag;
caller.ani.tag = cid_tag;
ast_channel_set_caller_event(ast, &caller, &update_caller);
ast_channel_unlock(ast);
}
| static void misdn_update_connected_line | ( | struct ast_channel * | ast, |
| struct misdn_bchannel * | bc, | ||
| int | originator | ||
| ) | [static] |
Definition at line 6263 of file chan_misdn.c.
References misdn_bchannel::caller, misdn_bchannel::connected, EVENT_FACILITY, EVENT_NOTIFY, misdn_bchannel::fac_out, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_get_connected_line(), misdn_lib_is_ptp(), misdn_lib_port_is_nt(), misdn_lib_send_event(), mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE, misdn_bchannel::notify_description_code, ORG_MISDN, misdn_bchannel::outgoing_colp, misdn_bchannel::port, misdn_party_id::presentation, print_facility(), misdn_bchannel::redirecting, chan_list::state, misdn_party_redirecting::to, and misdn_party_redirecting::to_changed.
Referenced by misdn_indication().
{
struct chan_list *ch;
misdn_get_connected_line(ast, bc, originator);
if (originator == ORG_MISDN) {
bc->redirecting.to = bc->connected;
} else {
bc->redirecting.to = bc->caller;
}
switch (bc->outgoing_colp) {
case 1:/* restricted */
bc->redirecting.to.presentation = 1;/* restricted */
break;
case 2:/* blocked */
/* Don't tell the remote party that the call was transferred. */
return;
default:
break;
}
ch = MISDN_ASTERISK_TECH_PVT(ast);
if (ch->state == MISDN_CONNECTED
|| originator != ORG_MISDN) {
int is_ptmp;
is_ptmp = !misdn_lib_is_ptp(bc->port);
if (is_ptmp) {
/*
* We should not send these messages to the network if we are
* the CPE side since phones do not transfer calls within
* themselves. Well... If you consider handing the handset to
* someone else a transfer then how is the network to know?
*/
if (!misdn_lib_port_is_nt(bc->port)) {
return;
}
if (ch->state != MISDN_CONNECTED) {
/* Send NOTIFY(Nie(transfer-active), RDNie(redirecting.to data)) */
bc->redirecting.to_changed = 1;
bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE;
misdn_lib_send_event(bc, EVENT_NOTIFY);
#if defined(AST_MISDN_ENHANCEMENTS)
} else {
/* Send FACILITY(Fie(RequestSubaddress), Nie(transfer-active), RDNie(redirecting.to data)) */
bc->redirecting.to_changed = 1;
bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE;
bc->fac_out.Function = Fac_RequestSubaddress;
bc->fac_out.u.RequestSubaddress.InvokeID = ++misdn_invoke_id;
/* Send message */
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
}
#if defined(AST_MISDN_ENHANCEMENTS)
} else {
/* Send FACILITY(Fie(EctInform(transfer-active, redirecting.to data))) */
bc->fac_out.Function = Fac_EctInform;
bc->fac_out.u.EctInform.InvokeID = ++misdn_invoke_id;
bc->fac_out.u.EctInform.Status = 1;/* active */
bc->fac_out.u.EctInform.RedirectionPresent = 1;/* Must be present when status is active */
misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.EctInform.Redirection,
&bc->redirecting.to);
/* Send message */
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
}
}
}
| static void misdn_update_redirecting | ( | struct ast_channel * | ast, |
| struct misdn_bchannel * | bc, | ||
| int | originator | ||
| ) | [static] |
Definition at line 6446 of file chan_misdn.c.
References ast_channel_exten(), EVENT_FACILITY, EVENT_NOTIFY, misdn_bchannel::fac_out, match(), misdn_copy_redirecting_from_ast(), misdn_lib_is_ptp(), misdn_lib_port_is_nt(), misdn_lib_send_event(), mISDN_NOTIFY_CODE_CALL_IS_DIVERTING, misdn_bchannel::notify_description_code, misdn_party_id::number, ORG_MISDN, misdn_bchannel::outgoing_colp, misdn_bchannel::port, misdn_party_id::presentation, print_facility(), misdn_party_redirecting::reason, misdn_bchannel::redirecting, misdn_party_redirecting::to, and misdn_party_redirecting::to_changed.
Referenced by misdn_indication().
{
int is_ptmp;
misdn_copy_redirecting_from_ast(bc, ast);
switch (bc->outgoing_colp) {
case 1:/* restricted */
bc->redirecting.to.presentation = 1;/* restricted */
break;
case 2:/* blocked */
/* Don't tell the remote party that the call was redirected. */
return;
default:
break;
}
if (originator != ORG_MISDN) {
return;
}
is_ptmp = !misdn_lib_is_ptp(bc->port);
if (is_ptmp) {
/*
* We should not send these messages to the network if we are
* the CPE side since phones do not redirect calls within
* themselves. Well... If you consider someone else picking up
* the handset a redirection then how is the network to know?
*/
if (!misdn_lib_port_is_nt(bc->port)) {
return;
}
/* Send NOTIFY(call-is-diverting, redirecting.to data) */
bc->redirecting.to_changed = 1;
bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_IS_DIVERTING;
misdn_lib_send_event(bc, EVENT_NOTIFY);
#if defined(AST_MISDN_ENHANCEMENTS)
} else {
int match; /* TRUE if the dialed number matches the redirecting to number */
match = (strcmp(ast_channel_exten(ast), bc->redirecting.to.number) == 0) ? 1 : 0;
if (!bc->div_leg_3_tx_pending
|| !match) {
/* Send DivertingLegInformation1 */
bc->fac_out.Function = Fac_DivertingLegInformation1;
bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
bc->fac_out.u.DivertingLegInformation1.DiversionReason =
misdn_to_diversion_reason(bc->redirecting.reason);
bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;/* notificationWithDivertedToNr */
bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
}
bc->div_leg_3_tx_pending = 0;
/* Send DivertingLegInformation3 */
bc->fac_out.Function = Fac_DivertingLegInformation3;
bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
bc->redirecting.to.presentation == 0 ? 1 : 0;
print_facility(&bc->fac_out, bc);
misdn_lib_send_event(bc, EVENT_FACILITY);
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
}
}
| static void misdn_update_remote_party | ( | struct ast_channel * | ast, |
| const struct misdn_party_id * | id, | ||
| enum AST_CONNECTED_LINE_UPDATE_SOURCE | source, | ||
| char * | cid_tag | ||
| ) | [static] |
Definition at line 6173 of file chan_misdn.c.
References misdn_queue_connected_line_update(), and misdn_update_caller_id().
Referenced by cb_events(), and misdn_facility_ie_handler().
{
misdn_update_caller_id(ast, id, cid_tag);
misdn_queue_connected_line_update(ast, id, source, cid_tag);
}
| static int misdn_write | ( | struct ast_channel * | ast, |
| struct ast_frame * | frame | ||
| ) | [static] |
Definition at line 7440 of file chan_misdn.c.
References misdn_bchannel::active, misdn_bchannel::addr, ast_channel_caller(), ast_channel_exten(), ast_debug, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_getformatname(), ast_log(), chan_list::bc, misdn_bchannel::bc_state, BCHAN_ACTIVATED, BCHAN_BRIDGED, misdn_bchannel::capability, cb_log, chan_misdn_log(), ast_frame::data, chan_list::dropped_frame_cnt, ast_frame_subclass::format, chan_list::hold, ast_format::id, chan_list::jb, misdn_bchannel::l3_id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_cap_is_speech(), misdn_get_ch_state(), MISDN_HOLD_IDLE, misdn_jb_fill(), misdn_lib_tone_generator_start(), misdn_lib_tx2misdn_frm(), misdn_bchannel::nojitter, chan_list::notxtone, misdn_bchannel::port, prefformat, ast_frame::ptr, S_COR, ast_frame::samples, ast_frame::src, hold_info::state, ast_frame::subclass, and chan_list::ts.
{
struct chan_list *ch;
if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
return -1;
}
if (ch->hold.state != MISDN_HOLD_IDLE) {
chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
return 0;
}
if (!ch->bc) {
ast_log(LOG_WARNING, "private but no bc\n");
return -1;
}
if (ch->notxtone) {
chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
return 0;
}
if (!frame->subclass.format.id) {
chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
return 0;
}
if (ast_format_cmp(&frame->subclass.format, &prefformat) == AST_FORMAT_CMP_NOT_EQUAL) {
chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(&frame->subclass.format));
return 0;
}
if (!frame->samples) {
chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
if (!strcmp(frame->src,"ast_prod")) {
chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
if (ch->ts) {
chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
misdn_lib_tone_generator_start(ch->bc);
}
return 0;
}
return -1;
}
if (!ch->bc->addr) {
chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
return 0;
}
#ifdef MISDN_DEBUG
{
int i;
int max = 5 > frame->samples ? frame->samples : 5;
ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
for (i = 0; i < max; i++) {
ast_debug(1, "%2.2x ", ((char *) frame->data.ptr)[i]);
}
}
#endif
switch (ch->bc->bc_state) {
case BCHAN_ACTIVATED:
case BCHAN_BRIDGED:
break;
default:
if (!ch->dropped_frame_cnt) {
chan_misdn_log(5, ch->bc->port,
"BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",
frame->samples, ch->bc->addr, ast_channel_exten(ast),
S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""),
misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
}
if (++ch->dropped_frame_cnt > 100) {
ch->dropped_frame_cnt = 0;
chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n", frame->samples, ch->bc->addr);
}
return 0;
}
chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
if (!ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability)) {
/* Buffered Transmit (triggered by read from isdn side)*/
if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
if (ch->bc->active) {
cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
}
}
} else {
/* transmit without jitterbuffer */
misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
}
return 0;
}
| static int pbx_start_chan | ( | struct chan_list * | ch | ) | [static] |
Channel Queue End
Definition at line 8402 of file chan_misdn.c.
References chan_list::ast, ast_pbx_start(), and chan_list::need_hangup.
Referenced by do_immediate_setup(), misdn_overlap_dial_task(), and start_pbx().
{
int ret = ast_pbx_start(ch->ast);
ch->need_hangup = (ret >= 0) ? 0 : 1;
return ret;
}
| static void print_bc_info | ( | int | fd, |
| struct chan_list * | help, | ||
| struct misdn_bchannel * | bc | ||
| ) | [static] |
Definition at line 4140 of file chan_misdn.c.
References misdn_bchannel::active, misdn_bchannel::addr, chan_list::addr, chan_list::ast, ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_name(), ast_cli(), misdn_bchannel::bc_state, bc_state2str(), bearer2str(), misdn_bchannel::capability, misdn_bchannel::channel, misdn_bchannel::display, misdn_bchannel::ec_enable, misdn_party_redirecting::from, misdn_bchannel::holded, misdn_bchannel::l3_id, chan_list::l3id, misdn_get_ch_state(), name, misdn_party_id::name, chan_list::norxtone, chan_list::notxtone, misdn_bchannel::nt, misdn_party_id::number, ORG_AST, chan_list::originator, misdn_bchannel::pid, misdn_bchannel::port, misdn_bchannel::redirecting, and misdn_party_redirecting::to.
Referenced by handle_cli_misdn_show_channel(), and handle_cli_misdn_show_channels().
{
struct ast_channel *ast = help->ast;
ast_cli(fd,
"* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
" --> caller:\"%s\" <%s>\n"
" --> redirecting-from:\"%s\" <%s>\n"
" --> redirecting-to:\"%s\" <%s>\n"
" --> context:%s state:%s\n",
bc->pid,
bc->port,
bc->channel,
bc->nt ? "NT" : "TE",
help->originator == ORG_AST ? "*" : "I",
ast ? ast_channel_exten(ast) : "",
(ast && ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
? ast_channel_caller(ast)->id.name.str : "",
(ast && ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
? ast_channel_caller(ast)->id.number.str : "",
bc->redirecting.from.name,
bc->redirecting.from.number,
bc->redirecting.to.name,
bc->redirecting.to.number,
ast ? ast_channel_context(ast) : "",
misdn_get_ch_state(help));
if (misdn_debug[bc->port] > 0) {
ast_cli(fd,
" --> astname: %s\n"
" --> ch_l3id: %x\n"
" --> ch_addr: %x\n"
" --> bc_addr: %x\n"
" --> bc_l3id: %x\n"
" --> display: %s\n"
" --> activated: %d\n"
" --> state: %s\n"
" --> capability: %s\n"
#ifdef MISDN_1_2
" --> pipeline: %s\n"
#else
" --> echo_cancel: %d\n"
#endif
" --> notone : rx %d tx:%d\n"
" --> bc_hold: %d\n",
ast ? ast_channel_name(ast) : "",
help->l3id,
help->addr,
bc->addr,
bc->l3_id,
bc->display,
bc->active,
bc_state2str(bc->bc_state),
bearer2str(bc->capability),
#ifdef MISDN_1_2
bc->pipeline,
#else
bc->ec_enable,
#endif
help->norxtone, help->notxtone,
bc->holded);
}
}
| static void print_bearer | ( | struct misdn_bchannel * | bc | ) | [static] |
Definition at line 3331 of file chan_misdn.c.
References bearer2str(), misdn_bchannel::capability, chan_misdn_log(), INFO_CODEC_ALAW, INFO_CODEC_ULAW, misdn_bchannel::law, and misdn_bchannel::port.
Referenced by cb_events().
{
chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
switch(bc->law) {
case INFO_CODEC_ALAW:
chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
break;
case INFO_CODEC_ULAW:
chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
break;
}
}
| static void print_facility | ( | const struct FacParm * | fac, |
| const struct misdn_bchannel * | bc | ||
| ) | [static] |
Definition at line 2738 of file chan_misdn.c.
References chan_misdn_log(), and misdn_bchannel::port.
Referenced by handle_cli_misdn_send_facility(), misdn_answer(), misdn_call(), misdn_facility_exec(), misdn_facility_ie_handler(), misdn_update_connected_line(), and misdn_update_redirecting().
{
#if defined(AST_MISDN_ENHANCEMENTS)
unsigned Index;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
switch (fac->Function) {
#if defined(AST_MISDN_ENHANCEMENTS)
case Fac_ActivationDiversion:
chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
fac->u.ActivationDiversion.InvokeID);
switch (fac->u.ActivationDiversion.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
fac->u.ActivationDiversion.Component.Invoke.Procedure,
fac->u.ActivationDiversion.Component.Invoke.BasicService);
chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result\n");
break;
default:
break;
}
break;
case Fac_DeactivationDiversion:
chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
fac->u.DeactivationDiversion.InvokeID);
switch (fac->u.DeactivationDiversion.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
fac->u.DeactivationDiversion.Component.Invoke.Procedure,
fac->u.DeactivationDiversion.Component.Invoke.BasicService);
chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result\n");
break;
default:
break;
}
break;
case Fac_ActivationStatusNotificationDiv:
chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
fac->u.ActivationStatusNotificationDiv.InvokeID,
fac->u.ActivationStatusNotificationDiv.Procedure,
fac->u.ActivationStatusNotificationDiv.BasicService);
chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
break;
case Fac_DeactivationStatusNotificationDiv:
chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
fac->u.DeactivationStatusNotificationDiv.InvokeID,
fac->u.DeactivationStatusNotificationDiv.Procedure,
fac->u.DeactivationStatusNotificationDiv.BasicService);
chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
break;
case Fac_InterrogationDiversion:
chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
fac->u.InterrogationDiversion.InvokeID);
switch (fac->u.InterrogationDiversion.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
fac->u.InterrogationDiversion.Component.Invoke.Procedure,
fac->u.InterrogationDiversion.Component.Invoke.BasicService);
chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result:\n");
if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
chan_misdn_log(1, bc->port, " --> IntResult[%d]:\n", Index);
print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
}
}
break;
default:
break;
}
break;
case Fac_DiversionInformation:
chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
fac->u.DiversionInformation.InvokeID,
fac->u.DiversionInformation.DiversionReason,
fac->u.DiversionInformation.BasicService);
if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
chan_misdn_log(1, bc->port, " --> ServedUserSubaddress:\n");
print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
}
if (fac->u.DiversionInformation.CallingAddressPresent) {
chan_misdn_log(1, bc->port, " --> CallingAddress:\n");
print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
}
if (fac->u.DiversionInformation.OriginalCalledPresent) {
chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
}
if (fac->u.DiversionInformation.LastDivertingPresent) {
chan_misdn_log(1, bc->port, " --> LastDivertingNr:\n");
print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
}
if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
chan_misdn_log(1, bc->port, " --> LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
}
if (fac->u.DiversionInformation.UserInfo.Length) {
chan_misdn_log(1, bc->port, " --> UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
}
break;
case Fac_CallDeflection:
chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
fac->u.CallDeflection.InvokeID);
switch (fac->u.CallDeflection.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke:\n");
if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
}
chan_misdn_log(1, bc->port, " --> DeflectionAddress:\n");
print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result\n");
break;
default:
break;
}
break;
case Fac_CallRerouteing:
chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
fac->u.CallRerouteing.InvokeID);
switch (fac->u.CallRerouteing.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: Reason:%d Counter:%d\n",
fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
chan_misdn_log(1, bc->port, " --> CalledAddress:\n");
print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
chan_misdn_log(1, bc->port, " --> LastReroutingNr:\n");
print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
chan_misdn_log(1, bc->port, " --> SubscriptionOption:%d\n",
fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
chan_misdn_log(1, bc->port, " --> CallingParty:\n");
print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
}
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result\n");
break;
default:
break;
}
break;
case Fac_InterrogateServedUserNumbers:
chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
fac->u.InterrogateServedUserNumbers.InvokeID);
switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke\n");
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result:\n");
if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
chan_misdn_log(1, bc->port, " --> ServedUserNr[%d]:\n", Index);
print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
}
}
break;
default:
break;
}
break;
case Fac_DivertingLegInformation1:
chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
fac->u.DivertingLegInformation1.InvokeID,
fac->u.DivertingLegInformation1.DiversionReason,
fac->u.DivertingLegInformation1.SubscriptionOption);
if (fac->u.DivertingLegInformation1.DivertedToPresent) {
chan_misdn_log(1, bc->port, " --> DivertedToNr:\n");
print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
}
break;
case Fac_DivertingLegInformation2:
chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
fac->u.DivertingLegInformation2.InvokeID,
fac->u.DivertingLegInformation2.DiversionReason,
fac->u.DivertingLegInformation2.DiversionCounter);
if (fac->u.DivertingLegInformation2.DivertingPresent) {
chan_misdn_log(1, bc->port, " --> DivertingNr:\n");
print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
}
if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
}
break;
case Fac_DivertingLegInformation3:
chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
fac->u.DivertingLegInformation3.InvokeID,
fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
break;
#else /* !defined(AST_MISDN_ENHANCEMENTS) */
case Fac_CD:
chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
break;
#endif /* !defined(AST_MISDN_ENHANCEMENTS) */
case Fac_AOCDCurrency:
if (fac->u.AOCDcur.chargeNotAvailable) {
chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
} else if (fac->u.AOCDcur.freeOfCharge) {
chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
} else if (fac->u.AOCDchu.billingId >= 0) {
chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
(fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
} else {
chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
(fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
}
break;
case Fac_AOCDChargingUnit:
if (fac->u.AOCDchu.chargeNotAvailable) {
chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
} else if (fac->u.AOCDchu.freeOfCharge) {
chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
} else if (fac->u.AOCDchu.billingId >= 0) {
chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
} else {
chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
}
break;
#if defined(AST_MISDN_ENHANCEMENTS)
case Fac_ERROR:
chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
break;
case Fac_RESULT:
chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
fac->u.RESULT.InvokeID);
break;
case Fac_REJECT:
if (fac->u.REJECT.InvokeIDPresent) {
chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
} else {
chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
fac->u.REJECT.Code);
}
break;
case Fac_EctExecute:
chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
fac->u.EctExecute.InvokeID);
break;
case Fac_ExplicitEctExecute:
chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
fac->u.ExplicitEctExecute.InvokeID,
fac->u.ExplicitEctExecute.LinkID);
break;
case Fac_RequestSubaddress:
chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
fac->u.RequestSubaddress.InvokeID);
break;
case Fac_SubaddressTransfer:
chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
fac->u.SubaddressTransfer.InvokeID);
print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
break;
case Fac_EctLinkIdRequest:
chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
fac->u.EctLinkIdRequest.InvokeID);
switch (fac->u.EctLinkIdRequest.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke\n");
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: LinkID:%d\n",
fac->u.EctLinkIdRequest.Component.Result.LinkID);
break;
default:
break;
}
break;
case Fac_EctInform:
chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
fac->u.EctInform.InvokeID,
fac->u.EctInform.Status);
if (fac->u.EctInform.RedirectionPresent) {
chan_misdn_log(1, bc->port, " --> Redirection Number\n");
print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
}
break;
case Fac_EctLoopTest:
chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
fac->u.EctLoopTest.InvokeID);
switch (fac->u.EctLoopTest.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: CallTransferID:%d\n",
fac->u.EctLoopTest.Component.Invoke.CallTransferID);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: LoopResult:%d\n",
fac->u.EctLoopTest.Component.Result.LoopResult);
break;
default:
break;
}
break;
case Fac_StatusRequest:
chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
fac->u.StatusRequest.InvokeID);
switch (fac->u.StatusRequest.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: Compatibility:%d\n",
fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: Status:%d\n",
fac->u.StatusRequest.Component.Result.Status);
break;
default:
break;
}
break;
case Fac_CallInfoRetain:
chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
break;
case Fac_CCBSDeactivate:
chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
fac->u.CCBSDeactivate.InvokeID);
switch (fac->u.CCBSDeactivate.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d\n",
fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result\n");
break;
default:
break;
}
break;
case Fac_CCBSErase:
chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
chan_misdn_log(1, bc->port, " --> AddressOfB\n");
print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
break;
case Fac_CCBSRemoteUserFree:
chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
fac->u.CCBSRemoteUserFree.RecallMode);
chan_misdn_log(1, bc->port, " --> AddressOfB\n");
print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
break;
case Fac_CCBSCall:
chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
break;
case Fac_CCBSStatusRequest:
chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
fac->u.CCBSStatusRequest.InvokeID);
switch (fac->u.CCBSStatusRequest.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d RecallMode:%d\n",
fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: Free:%d\n",
fac->u.CCBSStatusRequest.Component.Result.Free);
break;
default:
break;
}
break;
case Fac_CCBSBFree:
chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
fac->u.CCBSBFree.RecallMode);
chan_misdn_log(1, bc->port, " --> AddressOfB\n");
print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
break;
case Fac_EraseCallLinkageID:
chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
break;
case Fac_CCBSStopAlerting:
chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
break;
case Fac_CCBSRequest:
chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
fac->u.CCBSRequest.InvokeID);
switch (fac->u.CCBSRequest.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
fac->u.CCBSRequest.Component.Result.CCBSReference,
fac->u.CCBSRequest.Component.Result.RecallMode);
break;
default:
break;
}
break;
case Fac_CCBSInterrogate:
chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
fac->u.CCBSInterrogate.InvokeID);
switch (fac->u.CCBSInterrogate.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke\n");
if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
}
if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
chan_misdn_log(1, bc->port, " --> AParty\n");
print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
}
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
fac->u.CCBSInterrogate.Component.Result.RecallMode);
if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
}
}
break;
default:
break;
}
break;
case Fac_CCNRRequest:
chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
fac->u.CCNRRequest.InvokeID);
switch (fac->u.CCNRRequest.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
fac->u.CCNRRequest.Component.Result.CCBSReference,
fac->u.CCNRRequest.Component.Result.RecallMode);
break;
default:
break;
}
break;
case Fac_CCNRInterrogate:
chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
fac->u.CCNRInterrogate.InvokeID);
switch (fac->u.CCNRInterrogate.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke\n");
if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
}
if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
chan_misdn_log(1, bc->port, " --> AParty\n");
print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
}
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
fac->u.CCNRInterrogate.Component.Result.RecallMode);
if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
}
}
break;
default:
break;
}
break;
case Fac_CCBS_T_Call:
chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
fac->u.CCBS_T_Call.InvokeID);
break;
case Fac_CCBS_T_Suspend:
chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
fac->u.CCBS_T_Suspend.InvokeID);
break;
case Fac_CCBS_T_Resume:
chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
fac->u.CCBS_T_Resume.InvokeID);
break;
case Fac_CCBS_T_RemoteUserFree:
chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
fac->u.CCBS_T_RemoteUserFree.InvokeID);
break;
case Fac_CCBS_T_Available:
chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
fac->u.CCBS_T_Available.InvokeID);
break;
case Fac_CCBS_T_Request:
chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
fac->u.CCBS_T_Request.InvokeID);
switch (fac->u.CCBS_T_Request.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke\n");
chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
}
if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
}
if (fac->u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Originating, bc);
}
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
fac->u.CCBS_T_Request.Component.Result.RetentionSupported);
break;
default:
break;
}
break;
case Fac_CCNR_T_Request:
chan_misdn_log(1, bc->port, " --> CCNR_T_Request: InvokeID:%d\n",
fac->u.CCNR_T_Request.InvokeID);
switch (fac->u.CCNR_T_Request.ComponentType) {
case FacComponent_Invoke:
chan_misdn_log(1, bc->port, " --> Invoke\n");
chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Destination, bc);
print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCNR_T_Request.Component.Invoke.Q931ie, bc);
if (fac->u.CCNR_T_Request.Component.Invoke.RetentionSupported) {
chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
}
if (fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicator);
}
if (fac->u.CCNR_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Originating, bc);
}
break;
case FacComponent_Result:
chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
fac->u.CCNR_T_Request.Component.Result.RetentionSupported);
break;
default:
break;
}
break;
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
case Fac_None:
/* No facility so print nothing */
break;
default:
chan_misdn_log(1, bc->port, " --> unknown facility\n");
break;
}
}
| static struct ast_frame * process_ast_dsp | ( | struct chan_list * | tmp, |
| struct ast_frame * | frame | ||
| ) | [static, read] |
Definition at line 7280 of file chan_misdn.c.
References chan_list::ast, ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_macrocontext(), ast_channel_name(), ast_debug, chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_log(), ast_verb, chan_list::bc, BUFFERSIZE, chan_misdn_log(), context, chan_list::dsp, misdn_bchannel::ec_enable, f, chan_list::faxdetect, chan_list::faxhandled, ast_frame::frametype, ast_frame_subclass::integer, isdn_lib_stop_dtmf(), isdn_lib_update_ec(), isdn_lib_update_rxgain(), isdn_lib_update_txgain(), LOG_NOTICE, LOG_WARNING, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, S_COR, S_OR, ast_frame::subclass, and misdn_bchannel::txgain.
Referenced by misdn_read().
{
struct ast_frame *f;
if (tmp->dsp) {
f = ast_dsp_process(tmp->ast, tmp->dsp, frame);
} else {
chan_misdn_log(0, tmp->bc->port, "No DSP-Path found\n");
return NULL;
}
if (!f || (f->frametype != AST_FRAME_DTMF)) {
return f;
}
ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass.integer);
if (tmp->faxdetect && (f->subclass.integer == 'f')) {
/* Fax tone -- Handle and return NULL */
if (!tmp->faxhandled) {
struct ast_channel *ast = tmp->ast;
tmp->faxhandled++;
chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast_channel_name(ast));
tmp->bc->rxgain = 0;
isdn_lib_update_rxgain(tmp->bc);
tmp->bc->txgain = 0;
isdn_lib_update_txgain(tmp->bc);
#ifdef MISDN_1_2
*tmp->bc->pipeline = 0;
#else
tmp->bc->ec_enable = 0;
#endif
isdn_lib_update_ec(tmp->bc);
isdn_lib_stop_dtmf(tmp->bc);
switch (tmp->faxdetect) {
case 1:
if (strcmp(ast_channel_exten(ast), "fax")) {
const char *context;
char context_tmp[BUFFERSIZE];
misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
context = S_OR(context_tmp, S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast)));
if (ast_exists_extension(ast, context, "fax", 1,
S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast_channel_name(ast), context);
/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast_channel_exten(ast));
if (ast_async_goto(ast, context, "fax", 1)) {
ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), context);
}
} else {
ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast_channel_exten(ast));
}
} else {
ast_debug(1, "Already in a fax extension, not redirecting\n");
}
break;
case 2:
ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast_channel_name(ast));
break;
default:
break;
}
} else {
ast_debug(1, "Fax already handled\n");
}
}
if (tmp->ast_dsp && (f->subclass.integer != 'f')) {
chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass.integer);
}
return f;
}
| static int read_config | ( | struct chan_list * | ch | ) | [static] |
Definition at line 5895 of file chan_misdn.c.
References chan_list::allowed_bearers, misdn_bchannel::AOCDtype, chan_list::ast, ast_callerid_parse(), ast_channel_callgroup_set(), ast_channel_context_set(), ast_channel_exten_set(), ast_channel_named_callgroups_set(), ast_channel_named_pickupgroups_set(), ast_channel_pickupgroup_set(), ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), ast_free, ast_log(), ast_mutex_init, ast_print_group(), ast_print_namedgroups(), ast_str_create(), ast_str_reset(), ast_strlen_zero(), chan_list::bc, buf2, BUFFERSIZE, misdn_bchannel::caller, misdn_bchannel::capability, chan_misdn_log(), cid_name, cid_num, config_jitterbuffer(), chan_list::context, debug_numtype(), misdn_bchannel::dialed, misdn_bchannel::display_connected, misdn_bchannel::display_setup, chan_list::dsp, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::early_bconnect, chan_list::far_alerting, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, misdn_bchannel::incoming_cid_tag, chan_list::incoming_early_audio, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, misdn_bchannel::keypad, LOG_WARNING, misdn_add_number_prefix(), MISDN_CFG_ALLOWED_BEARERS, MISDN_CFG_ASTDTMF, MISDN_CFG_CALLERID, MISDN_CFG_CALLGROUP, MISDN_CFG_CONTEXT, MISDN_CFG_DIALPLAN, MISDN_CFG_DISPLAY_CONNECTED, MISDN_CFG_DISPLAY_SETUP, MISDN_CFG_EARLY_BCONNECT, MISDN_CFG_FAR_ALERTING, MISDN_CFG_FAXDETECT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_INCOMING_CALLERID_TAG, MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CFG_JITTERBUFFER, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CFG_LANGUAGE, MISDN_CFG_MUSICCLASS, MISDN_CFG_NAMEDCALLGROUP, MISDN_CFG_NAMEDPICKUPGROUP, MISDN_CFG_NEED_MORE_INFOS, MISDN_CFG_NOAUTORESPOND_ON_SETUP, MISDN_CFG_NTTIMEOUT, MISDN_CFG_OUTGOING_COLP, MISDN_CFG_OVERLAP_DIAL, MISDN_CFG_PICKUPGROUP, MISDN_CFG_RXGAIN, MISDN_CFG_SENDDTMF, MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CFG_TXGAIN, chan_list::mohinterpret, misdn_party_id::name, misdn_bchannel::need_more_infos, chan_list::noautorespond_on_setup, chan_list::nttimeout, misdn_party_dialing::number, misdn_party_id::number, misdn_party_dialing::number_plan, misdn_party_dialing::number_type, misdn_party_id::number_type, NUMPLAN_ISDN, ORG_AST, chan_list::originator, misdn_bchannel::outgoing_colp, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, misdn_bchannel::port, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, misdn_bchannel::te_choose_channel, misdn_bchannel::txgain, and update_ec_config().
Referenced by cb_events(), and misdn_request().
{
struct ast_channel *ast;
struct misdn_bchannel *bc;
int port;
int hdlc = 0;
char lang[BUFFERSIZE + 1];
char faxdetect[BUFFERSIZE + 1];
char buf[256];
char buf2[256];
ast_group_t pg;
ast_group_t cg;
struct ast_namedgroups *npg;
struct ast_namedgroups *ncg;
struct ast_str *tmp_str;
if (!ch) {
ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
return -1;
}
ast = ch->ast;
bc = ch->bc;
if (! ast || ! bc) {
ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
return -1;
}
port = bc->port;
chan_misdn_log(1, port, "read_config: Getting Config\n");
misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
ast_channel_language_set(ast, lang);
misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
if (ch->ast_dsp) {
ch->ignore_dtmf = 1;
}
misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
if (hdlc) {
switch (bc->capability) {
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
case INFO_CAPABILITY_DIGITAL_RESTRICTED:
chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
bc->hdlc = 1;
break;
}
}
/*Initialize new Jitterbuffer*/
misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
config_jitterbuffer(ch);
misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
ast_channel_context_set(ast, ch->context);
#ifdef MISDN_1_2
update_pipeline_config(bc);
#else
update_ec_config(bc);
#endif
misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
misdn_cfg_get(port, MISDN_CFG_DISPLAY_CONNECTED, &bc->display_connected, sizeof(bc->display_connected));
misdn_cfg_get(port, MISDN_CFG_DISPLAY_SETUP, &bc->display_setup, sizeof(bc->display_setup));
misdn_cfg_get(port, MISDN_CFG_OUTGOING_COLP, &bc->outgoing_colp, sizeof(bc->outgoing_colp));
misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
ast_channel_pickupgroup_set(ast, pg);
ast_channel_callgroup_set(ast, cg);
misdn_cfg_get(port, MISDN_CFG_NAMEDPICKUPGROUP, &npg, sizeof(npg));
misdn_cfg_get(port, MISDN_CFG_NAMEDCALLGROUP, &ncg, sizeof(ncg));
tmp_str = ast_str_create(1024);
if (tmp_str) {
chan_misdn_log(5, port, " --> * NamedCallGrp:%s\n", ast_print_namedgroups(&tmp_str, ncg));
ast_str_reset(tmp_str);
chan_misdn_log(5, port, " --> * NamedPickupGrp:%s\n", ast_print_namedgroups(&tmp_str, npg));
ast_free(tmp_str);
}
ast_channel_named_pickupgroups_set(ast, npg);
ast_channel_named_callgroups_set(ast, ncg);
if (ch->originator == ORG_AST) {
char callerid[BUFFERSIZE + 1];
/* ORIGINATOR Asterisk (outgoing call) */
misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
ch->faxdetect = strstr(faxdetect, "nojump") ? 2 : 1;
}
misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
if (!ast_strlen_zero(callerid)) {
char *cid_name = NULL;
char *cid_num = NULL;
ast_callerid_parse(callerid, &cid_name, &cid_num);
if (cid_name) {
ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
} else {
bc->caller.name[0] = '\0';
}
if (cid_num) {
ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
} else {
bc->caller.number[0] = '\0';
}
chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
}
misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dialed.number_type, sizeof(bc->dialed.number_type));
bc->dialed.number_plan = NUMPLAN_ISDN;
debug_numtype(port, bc->dialed.number_type, "TON");
ch->overlap_dial = 0;
} else {
/* ORIGINATOR MISDN (incoming call) */
if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
}
/* Add configured prefix to caller.number */
misdn_add_number_prefix(bc->port, bc->caller.number_type, bc->caller.number, sizeof(bc->caller.number));
if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
}
/* Add configured prefix to dialed.number */
misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
ast_channel_exten_set(ast, bc->dialed.number);
misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
ast_mutex_init(&ch->overlap_tv_lock);
} /* ORIG MISDN END */
misdn_cfg_get(port, MISDN_CFG_INCOMING_CALLERID_TAG, bc->incoming_cid_tag, sizeof(bc->incoming_cid_tag));
if (!ast_strlen_zero(bc->incoming_cid_tag)) {
chan_misdn_log(1, port, " --> * Setting incoming caller id tag to \"%s\"\n", bc->incoming_cid_tag);
}
ch->overlap_dial_task = -1;
if (ch->faxdetect || ch->ast_dsp) {
misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
if (!ch->dsp) {
ch->dsp = ast_dsp_new();
}
if (ch->dsp) {
ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | (ch->faxdetect ? DSP_FEATURE_FAX_DETECT : 0));
}
}
/* AOCD initialization */
bc->AOCDtype = Fac_None;
return 0;
}
| static void release_chan | ( | struct chan_list * | ch, |
| struct misdn_bchannel * | bc | ||
| ) | [static] |
Definition at line 8459 of file chan_misdn.c.
References chan_list::ast, ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_trylock, ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_list_unref, chan_misdn_log(), cl_dequeue_chan(), DEADLOCK_AVOIDANCE, misdn_bchannel::l3_id, MISDN_ASTERISK_TECH_PVT, MISDN_ASTERISK_TECH_PVT_SET, MISDN_CLEANING, name, ORG_AST, chan_list::originator, misdn_bchannel::pid, misdn_bchannel::port, S_COR, and chan_list::state.
Referenced by cb_events(), and misdn_hangup().
{
struct ast_channel *ast;
chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
ast_mutex_lock(&release_lock);
for (;;) {
ast = ch->ast;
if (!ast || !ast_channel_trylock(ast)) {
break;
}
DEADLOCK_AVOIDANCE(&release_lock);
}
if (!cl_dequeue_chan(ch)) {
/* Someone already released it. */
if (ast) {
ast_channel_unlock(ast);
}
ast_mutex_unlock(&release_lock);
return;
}
ch->state = MISDN_CLEANING;
ch->ast = NULL;
if (ast) {
struct chan_list *ast_ch;
ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
MISDN_ASTERISK_TECH_PVT_SET(ast, NULL);
chan_misdn_log(1, bc->port,
"* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
bc->pid,
ast_channel_context(ast),
ast_channel_exten(ast),
S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, ""),
S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""));
if (ast_channel_state(ast) != AST_STATE_RESERVED) {
chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
ast_setstate(ast, AST_STATE_DOWN);
}
ast_channel_unlock(ast);
if (ast_ch) {
chan_list_unref(ast_ch, "Release ast_channel reference.");
}
}
if (ch->originator == ORG_AST) {
--misdn_out_calls[bc->port];
} else {
--misdn_in_calls[bc->port];
}
ast_mutex_unlock(&release_lock);
}
| static void release_chan_early | ( | struct chan_list * | ch | ) | [static] |
Definition at line 8525 of file chan_misdn.c.
References chan_list::ast, ast_channel_trylock, ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_list_unref, cl_dequeue_chan(), DEADLOCK_AVOIDANCE, chan_list::hold, MISDN_ASTERISK_TECH_PVT, MISDN_ASTERISK_TECH_PVT_SET, MISDN_CLEANING, MISDN_HOLD_IDLE, ORG_AST, chan_list::originator, hold_info::port, hold_info::state, and chan_list::state.
Referenced by misdn_hangup().
{
struct ast_channel *ast;
ast_mutex_lock(&release_lock);
for (;;) {
ast = ch->ast;
if (!ast || !ast_channel_trylock(ast)) {
break;
}
DEADLOCK_AVOIDANCE(&release_lock);
}
if (!cl_dequeue_chan(ch)) {
/* Someone already released it. */
if (ast) {
ast_channel_unlock(ast);
}
ast_mutex_unlock(&release_lock);
return;
}
ch->state = MISDN_CLEANING;
ch->ast = NULL;
if (ast) {
struct chan_list *ast_ch;
ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
MISDN_ASTERISK_TECH_PVT_SET(ast, NULL);
if (ast_channel_state(ast) != AST_STATE_RESERVED) {
ast_setstate(ast, AST_STATE_DOWN);
}
ast_channel_unlock(ast);
if (ast_ch) {
chan_list_unref(ast_ch, "Release ast_channel reference.");
}
}
if (ch->hold.state != MISDN_HOLD_IDLE) {
if (ch->originator == ORG_AST) {
--misdn_out_calls[ch->hold.port];
} else {
--misdn_in_calls[ch->hold.port];
}
}
ast_mutex_unlock(&release_lock);
}
| static int reload | ( | void | ) | [static] |
Definition at line 11504 of file chan_misdn.c.
References reload_config().
{
reload_config();
return 0;
}
| static void reload_config | ( | void | ) | [static] |
Definition at line 4096 of file chan_misdn.c.
References ast_log(), free_robin_list(), LOG_WARNING, max_ports, misdn_cfg_get(), misdn_cfg_reload(), misdn_cfg_update_ptp(), MISDN_GEN_DEBUG, and MISDN_GEN_TRACEFILE.
Referenced by handle_cli_misdn_reload(), and reload().
{
int i, cfg_debug;
if (!g_config_initialized) {
ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
return ;
}
free_robin_list();
misdn_cfg_reload();
misdn_cfg_update_ptp();
misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
for (i = 0; i <= max_ports; i++) {
misdn_debug[i] = cfg_debug;
misdn_debug_only[i] = 0;
}
}
| static int send_cause2ast | ( | struct ast_channel * | ast, |
| struct misdn_bchannel * | bc, | ||
| struct chan_list * | ch | ||
| ) | [static] |
| -1 | if can hangup after calling. |
| 0 | if cannot hangup after calling. |
Definition at line 8725 of file chan_misdn.c.
References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_ROUTE_TRANSIT_NET, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_channel_hangupcause_set(), AST_CONTROL_BUSY, ast_queue_control(), misdn_bchannel::cause, chan_misdn_log(), MISDN_BUSY, chan_list::need_busy, misdn_bchannel::pid, misdn_bchannel::port, and chan_list::state.
Referenced by hangup_chan().
{
int can_hangup;
if (!ast) {
chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
return 0;
}
if (!bc) {
chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
return 0;
}
if (!ch) {
chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
return 0;
}
ast_channel_hangupcause_set(ast, bc->cause);
can_hangup = -1;
switch (bc->cause) {
case AST_CAUSE_UNALLOCATED:
case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
case AST_CAUSE_NO_ROUTE_DESTINATION:
case 4: /* Send special information tone */
case AST_CAUSE_NUMBER_CHANGED:
case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
/* Congestion Cases */
/*
* Not Queueing the Congestion anymore, since we want to hear
* the inband message
*
chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
ch->state = MISDN_BUSY;
ast_queue_control(ast, AST_CONTROL_CONGESTION);
*/
break;
case AST_CAUSE_CALL_REJECTED:
case AST_CAUSE_USER_BUSY:
ch->state = MISDN_BUSY;
if (!ch->need_busy) {
chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
break;
}
ch->need_busy = 0;
chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
ast_queue_control(ast, AST_CONTROL_BUSY);
/* The BUSY is likely to cause a hangup or the user needs to hear it. */
can_hangup = 0;
break;
}
return can_hangup;
}
| static void send_digit_to_chan | ( | struct chan_list * | cl, |
| char | digit | ||
| ) | [static] |
Definition at line 3654 of file chan_misdn.c.
References chan_list::ast, ast_channel_name(), ast_debug, and ast_playtones_start().
Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().
{
static const char * const dtmf_tones[] = {
/* *INDENT-OFF* */
"!941+1336/100,!0/100", /* 0 */
"!697+1209/100,!0/100", /* 1 */
"!697+1336/100,!0/100", /* 2 */
"!697+1477/100,!0/100", /* 3 */
"!770+1209/100,!0/100", /* 4 */
"!770+1336/100,!0/100", /* 5 */
"!770+1477/100,!0/100", /* 6 */
"!852+1209/100,!0/100", /* 7 */
"!852+1336/100,!0/100", /* 8 */
"!852+1477/100,!0/100", /* 9 */
"!697+1633/100,!0/100", /* A */
"!770+1633/100,!0/100", /* B */
"!852+1633/100,!0/100", /* C */
"!941+1633/100,!0/100", /* D */
"!941+1209/100,!0/100", /* * */
"!941+1477/100,!0/100", /* # */
/* *INDENT-ON* */
};
struct ast_channel *chan = cl->ast;
if (digit >= '0' && digit <='9') {
ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
} else if (digit >= 'A' && digit <= 'D') {
ast_playtones_start(chan, 0, dtmf_tones[digit - 'A' + 10], 0);
} else if (digit == '*') {
ast_playtones_start(chan, 0, dtmf_tones[14], 0);
} else if (digit == '#') {
ast_playtones_start(chan, 0, dtmf_tones[15], 0);
} else {
/* not handled */
ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, ast_channel_name(chan));
}
}
| static void show_config_description | ( | int | fd, |
| enum misdn_cfg_elements | elem | ||
| ) | [inline, static] |
Definition at line 3935 of file chan_misdn.c.
References ast_cli(), BUFFERSIZE, COLOR_BRWHITE, COLOR_YELLOW, desc, misdn_cfg_get_desc(), misdn_cfg_get_name(), MISDN_CFG_LAST, name, and term_color().
Referenced by handle_cli_misdn_show_config().
{
char section[BUFFERSIZE];
char name[BUFFERSIZE];
char desc[BUFFERSIZE];
char def[BUFFERSIZE];
char tmp[BUFFERSIZE];
misdn_cfg_get_name(elem, tmp, sizeof(tmp));
term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
if (elem < MISDN_CFG_LAST) {
term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
} else {
term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
}
if (*def) {
ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
} else {
ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
}
}
| static void sighandler | ( | int | sig | ) | [static] |
| static int start_bc_tones | ( | struct chan_list * | cl | ) | [static] |
Definition at line 7721 of file chan_misdn.c.
References chan_list::bc, misdn_lib_tone_generator_stop(), chan_list::norxtone, and chan_list::notxtone.
Referenced by cb_events(), misdn_answer(), misdn_hangup(), and misdn_indication().
{
misdn_lib_tone_generator_stop(cl->bc);
cl->notxtone = 0;
cl->norxtone = 0;
return 0;
}
| static void start_pbx | ( | struct chan_list * | ch, |
| struct misdn_bchannel * | bc, | ||
| struct ast_channel * | chan | ||
| ) | [static] |
Definition at line 8875 of file chan_misdn.c.
References chan_misdn_log(), EVENT_RELEASE, EVENT_RELEASE_COMPLETE, hangup_chan(), hanguptone_indicate(), misdn_lib_send_event(), misdn_bchannel::nt, pbx_start_chan(), and misdn_bchannel::port.
Referenced by cb_events().
{
if (pbx_start_chan(ch) < 0) {
hangup_chan(ch, bc);
chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
if (bc->nt) {
hanguptone_indicate(ch);
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
} else {
misdn_lib_send_event(bc, EVENT_RELEASE);
}
}
}
| static int stop_bc_tones | ( | struct chan_list * | cl | ) | [static] |
Definition at line 7729 of file chan_misdn.c.
References chan_list::norxtone, and chan_list::notxtone.
Referenced by cb_events(), misdn_call(), and misdn_hangup().
| static int stop_indicate | ( | struct chan_list * | cl | ) | [static] |
Definition at line 7700 of file chan_misdn.c.
References chan_list::ast, ast_playtones_stop(), ast_tone_zone_sound_unref(), chan_list::bc, chan_misdn_log(), misdn_lib_tone_generator_stop(), misdn_bchannel::port, and chan_list::ts.
Referenced by cb_events(), misdn_answer(), misdn_indication(), and misdn_overlap_dial_task().
{
struct ast_channel *ast = cl->ast;
if (!ast) {
chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
return -1;
}
chan_misdn_log(3, cl->bc->port, " --> None\n");
misdn_lib_tone_generator_stop(cl->bc);
ast_playtones_stop(ast);
if (cl->ts) {
cl->ts = ast_tone_zone_sound_unref(cl->ts);
}
return 0;
}
| static int unload_module | ( | void | ) | [static] |
TE STUFF END
Definition at line 11233 of file chan_misdn.c.
References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_format_cap_destroy(), ast_free, ast_unregister_application(), ast_verb, ast_channel_tech::capabilities, free_robin_list(), misdn_cfg_destroy(), misdn_lib_destroy(), and misdn_tasks_destroy().
Referenced by load_module().
{
/* First, take us out of the channel loop */
ast_verb(0, "-- Unregistering mISDN Channel Driver --\n");
misdn_tasks_destroy();
if (!g_config_initialized) {
return 0;
}
ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
/* ast_unregister_application("misdn_crypt"); */
ast_unregister_application("misdn_set_opt");
ast_unregister_application("misdn_facility");
ast_unregister_application("misdn_check_l2l1");
#if defined(AST_MISDN_ENHANCEMENTS)
ast_unregister_application(misdn_command_name);
ast_custom_function_unregister(&misdn_cc_function);
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
ast_channel_unregister(&misdn_tech);
free_robin_list();
misdn_cfg_destroy();
misdn_lib_destroy();
ast_free(misdn_out_calls);
ast_free(misdn_in_calls);
ast_free(misdn_debug_only);
ast_free(misdn_ports);
ast_free(misdn_debug);
#if defined(AST_MISDN_ENHANCEMENTS)
misdn_cc_destroy();
#endif /* defined(AST_MISDN_ENHANCEMENTS) */
misdn_tech.capabilities = ast_format_cap_destroy(misdn_tech.capabilities);
misdn_tech_wo_bridge.capabilities = ast_format_cap_destroy(misdn_tech_wo_bridge.capabilities);
return 0;
}
| static void update_config | ( | struct chan_list * | ch | ) | [static] |
Updates caller ID information from config.
Definition at line 5734 of file chan_misdn.c.
References chan_list::ast, ast_channel_connected(), ast_log(), ast_to_misdn_pres(), ast_to_misdn_screen(), chan_list::bc, misdn_bchannel::caller, misdn_bchannel::capability, chan_misdn_log(), misdn_bchannel::hdlc, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, LOG_WARNING, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_PRES, MISDN_CFG_SCREEN, misdn_to_str_pres(), misdn_to_str_screen(), misdn_bchannel::port, misdn_party_id::presentation, and misdn_party_id::screening.
Referenced by misdn_call().
{
struct ast_channel *ast;
struct misdn_bchannel *bc;
int port;
int hdlc = 0;
int pres;
int screen;
if (!ch) {
ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
return;
}
ast = ch->ast;
bc = ch->bc;
if (! ast || ! bc) {
ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
return;
}
port = bc->port;
chan_misdn_log(7, port, "update_config: Getting Config\n");
misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
if (hdlc) {
switch (bc->capability) {
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
case INFO_CAPABILITY_DIGITAL_RESTRICTED:
chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
bc->hdlc = 1;
break;
}
}
misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
if (pres < 0 || screen < 0) {
chan_misdn_log(2, port, " --> pres: %x\n", ast_channel_connected(ast)->id.number.presentation);
bc->caller.presentation = ast_to_misdn_pres(ast_channel_connected(ast)->id.number.presentation);
chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
bc->caller.screening = ast_to_misdn_screen(ast_channel_connected(ast)->id.number.presentation);
chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
} else {
bc->caller.screening = screen;
bc->caller.presentation = pres;
}
}
| static int update_ec_config | ( | struct misdn_bchannel * | bc | ) | [static] |
Definition at line 5876 of file chan_misdn.c.
References misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, MISDN_CFG_ECHOCANCEL, misdn_cfg_get(), and misdn_bchannel::port.
Referenced by handle_cli_misdn_toggle_echocancel(), and read_config().
{
int ec;
int port = bc->port;
misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
if (ec == 1) {
bc->ec_enable = 1;
} else if (ec > 1) {
bc->ec_enable = 1;
bc->ec_deftaps = ec;
}
return 0;
}
| static void update_name | ( | struct ast_channel * | tmp, |
| int | port, | ||
| int | c | ||
| ) | [static] |
Definition at line 8125 of file chan_misdn.c.
References ast_change_name(), ast_channel_name(), chan_misdn_log(), misdn_cfg_get_next_port(), and misdn_lib_port_is_pri().
Referenced by cb_events().
{
int chan_offset = 0;
int tmp_port = misdn_cfg_get_next_port(0);
char newname[255];
for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
if (tmp_port == port) {
break;
}
chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
}
if (c < 0) {
c = 0;
}
snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
if (strncmp(ast_channel_name(tmp), newname, strlen(newname))) {
snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
ast_change_name(tmp, newname);
chan_misdn_log(3, port, " --> updating channel name to [%s]\n", ast_channel_name(tmp));
}
}
| static void wait_for_digits | ( | struct chan_list * | ch, |
| struct misdn_bchannel * | bc, | ||
| struct ast_channel * | chan | ||
| ) | [static] |
Definition at line 8889 of file chan_misdn.c.
References misdn_bchannel::dialed, dialtone_indicate(), EVENT_SETUP_ACKNOWLEDGE, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::nt, misdn_party_dialing::number, and chan_list::state.
Referenced by cb_events().
{
ch->state = MISDN_WAITING4DIGS;
misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
if (bc->nt && !bc->dialed.number[0]) {
dialtone_indicate(ch);
}
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Channel driver for mISDN Support (BRI/PRI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static] |
Definition at line 12803 of file chan_misdn.c.
struct allowed_bearers allowed_bearers_array[] [static] |
Definition at line 2338 of file chan_misdn.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 12803 of file chan_misdn.c.
struct ast_cli_entry chan_misdn_clis[] [static] |
Definition at line 5707 of file chan_misdn.c.
Global channel call record list head.
Definition at line 682 of file chan_misdn.c.
ast_mutex_t cl_te_lock [static] |
Definition at line 683 of file chan_misdn.c.
int g_config_initialized = 0 [static] |
Definition at line 104 of file chan_misdn.c.
int glob_channel = 0 [static] |
Definition at line 8123 of file chan_misdn.c.
char global_tracefile[BUFFERSIZE+1] [static] |
Definition at line 102 of file chan_misdn.c.
int max_ports [static] |
Definition at line 674 of file chan_misdn.c.
Referenced by handle_cli_misdn_set_debug(), load_module(), and reload_config().
| int MAXTICS = 8 |
Definition at line 587 of file chan_misdn.c.
int* misdn_debug [static] |
Definition at line 672 of file chan_misdn.c.
int* misdn_debug_only [static] |
Definition at line 673 of file chan_misdn.c.
int* misdn_in_calls [static] |
Definition at line 676 of file chan_misdn.c.
int* misdn_out_calls [static] |
Definition at line 677 of file chan_misdn.c.
int* misdn_ports [static] |
Definition at line 648 of file chan_misdn.c.
struct ast_sched_context* misdn_tasks = NULL [static] |
the main schedule context for stuff like l1 watcher, overlap dial, ...
Definition at line 645 of file chan_misdn.c.
pthread_t misdn_tasks_thread [static] |
Definition at line 646 of file chan_misdn.c.
struct ast_channel_tech misdn_tech [static] |
Definition at line 8087 of file chan_misdn.c.
struct ast_channel_tech misdn_tech_wo_bridge [static] |
Definition at line 8105 of file chan_misdn.c.
const char misdn_type[] = "mISDN" [static] |
Definition at line 665 of file chan_misdn.c.
struct ast_format prefformat [static] |
Only alaw and mulaw is allowed for now.
Definition at line 670 of file chan_misdn.c.
Referenced by load_module(), misdn_new(), and misdn_write().
ast_mutex_t release_lock [static] |
Definition at line 298 of file chan_misdn.c.
struct robin_list* robin = NULL [static] |
Definition at line 601 of file chan_misdn.c.
Referenced by get_robin_position().
struct state_struct state_array[] [static] |
Definition at line 4056 of file chan_misdn.c.
int tracing = 0 [static] |
Definition at line 667 of file chan_misdn.c.