chan_misdn.c File Reference

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 "asterisk/features_config.h"
#include "asterisk/bridge.h"
#include "asterisk/pickup.h"
#include "asterisk/format_cache.h"
#include "chan_misdn_config.h"
#include "isdn_lib.h"
#include "asterisk/strings.h"

Include dependency graph for chan_misdn.c:

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_listchan_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_listfind_chan_by_bc (struct misdn_bchannel *bc)
static struct chan_listfind_hold_active_call (struct misdn_bchannel *bc)
static struct chan_listfind_hold_call (struct misdn_bchannel *bc)
static struct chan_listfind_hold_call_l3 (unsigned long l3_id)
static void free_robin_list (void)
static struct chan_listget_chan_by_ast_name (const char *name)
static struct robin_listget_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)
 Load the module.
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 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_jbmisdn_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_channelmisdn_new (struct chan_list *cl, int state, char *exten, char *callerid, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, 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_framemisdn_read (struct ast_channel *ast)
static struct ast_channelmisdn_request (const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, 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_frameprocess_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, .support_level = AST_MODULE_SUPPORT_EXTENDED, .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_infoast_module_info = &__mod_info
static struct ast_cli_entry chan_misdn_clis []
static struct chan_listcl_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_contextmisdn_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 const char misdn_type [] = "mISDN"
static ast_mutex_t release_lock
static struct robin_listrobin = NULL
static struct state_struct state_array []
static int tracing = 0


Detailed Description

the chan_misdn channel driver for Asterisk

Author:
Christian Richter <crich@beronet.com>
MISDN http://www.misdn.org/

Definition in file chan_misdn.c.


Define Documentation

#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)

Definition at line 685 of file chan_misdn.c.

Referenced by misdn_hangup(), misdn_new(), release_chan(), and release_chan_early().

#define ORG_AST   1

#define ORG_MISDN   2

mISDN created the channel (incoming call)

Definition at line 346 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 8335 of file chan_misdn.c.


Enumeration Type Documentation

Enumerator:
MISDN_NOTHING  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

Definition at line 326 of file chan_misdn.c.

00326                       {
00327    MISDN_NOTHING = 0,         /*!< at beginning */
00328    MISDN_WAITING4DIGS,        /*!< when waiting for info */
00329    MISDN_EXTCANTMATCH,        /*!< when asterisk couldn't match our ext */
00330    MISDN_INCOMING_SETUP,      /*!< for incoming setup */
00331    MISDN_DIALING,             /*!< when pbx_start */
00332    MISDN_PROGRESS,            /*!< we have progress */
00333    MISDN_PROCEEDING,          /*!< we have progress */
00334    MISDN_CALLING,             /*!< when misdn_call is called */
00335    MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
00336    MISDN_ALERTING,            /*!< when Alerting */
00337    MISDN_BUSY,                /*!< when BUSY */
00338    MISDN_CONNECTED,           /*!< when connected */
00339    MISDN_DISCONNECTED,        /*!< when connected */
00340    MISDN_CLEANING,            /*!< when hangup from * but we were connected before */
00341 };

Enumerator:
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 348 of file chan_misdn.c.

00348                       {
00349    MISDN_HOLD_IDLE,     /*!< HOLD not active */
00350    MISDN_HOLD_ACTIVE,      /*!< Call is held */
00351    MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
00352    MISDN_HOLD_DISCONNECT,  /*!< Held call is being disconnected */
00353 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 12839 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

03593 {
03594    int task_id;
03595 
03596    if (!misdn_tasks) {
03597       misdn_tasks_init();
03598    }
03599    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
03600    misdn_tasks_wakeup();
03601 
03602    return task_id;
03603 }

int add_in_calls ( int  port  ) 

Definition at line 8845 of file chan_misdn.c.

References ast_log, LOG_NOTICE, misdn_cfg_get(), and MISDN_CFG_MAX_IN.

Referenced by cb_events().

08846 {
08847    int max_in_calls;
08848 
08849    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
08850    misdn_in_calls[port]++;
08851 
08852    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
08853       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
08854       return misdn_in_calls[port] - max_in_calls;
08855    }
08856 
08857    return 0;
08858 }

int add_out_calls ( int  port  ) 

Definition at line 8860 of file chan_misdn.c.

References ast_log, LOG_NOTICE, misdn_cfg_get(), and MISDN_CFG_MAX_OUT.

Referenced by misdn_call().

08861 {
08862    int max_out_calls;
08863 
08864    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
08865 
08866    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
08867       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
08868       return (misdn_out_calls[port] + 1) - max_out_calls;
08869    }
08870 
08871    misdn_out_calls[port]++;
08872 
08873    return 0;
08874 }

static enum mISDN_NUMBER_PLAN ast_to_misdn_plan ( unsigned  ast_number_plan  )  [static]

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

02044 {
02045    enum mISDN_NUMBER_PLAN number_plan;
02046 
02047    switch (ast_number_plan & 0x0F) {
02048    default:
02049    case NUMPLAN_UNKNOWN:
02050       number_plan = NUMPLAN_UNKNOWN;
02051       break;
02052 
02053    case NUMPLAN_ISDN:
02054       number_plan = NUMPLAN_ISDN;
02055       break;
02056 
02057    case NUMPLAN_DATA:
02058       number_plan = NUMPLAN_DATA;
02059       break;
02060 
02061    case NUMPLAN_TELEX:
02062       number_plan = NUMPLAN_TELEX;
02063       break;
02064 
02065    case NUMPLAN_NATIONAL:
02066       number_plan = NUMPLAN_NATIONAL;
02067       break;
02068 
02069    case NUMPLAN_PRIVATE:
02070       number_plan = NUMPLAN_PRIVATE;
02071       break;
02072    }
02073 
02074    return number_plan;
02075 }

static int ast_to_misdn_pres ( int  presentation  )  [static]

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

02147 {
02148    switch (presentation & AST_PRES_RESTRICTION) {
02149    default:
02150    case AST_PRES_ALLOWED:
02151       presentation = 0;
02152       break;
02153 
02154    case AST_PRES_RESTRICTED:
02155       presentation = 1;
02156       break;
02157 
02158    case AST_PRES_UNAVAILABLE:
02159       presentation = 2;
02160       break;
02161    }
02162 
02163    return presentation;
02164 }

static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason ( const enum AST_REDIRECTING_REASON  ast  )  [static]

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

static int ast_to_misdn_screen ( int  screening  )  [static]

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

02244 {
02245    switch (screening & AST_PRES_NUMBER_TYPE) {
02246    default:
02247    case AST_PRES_USER_NUMBER_UNSCREENED:
02248       screening = 0;
02249       break;
02250 
02251    case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02252       screening = 1;
02253       break;
02254 
02255    case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02256       screening = 2;
02257       break;
02258 
02259    case AST_PRES_NETWORK_NUMBER:
02260       screening = 3;
02261       break;
02262    }
02263 
02264    return screening;
02265 }

static enum mISDN_NUMBER_TYPE ast_to_misdn_ton ( unsigned  ast_number_type  )  [static]

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

01918 {
01919    enum mISDN_NUMBER_TYPE number_type;
01920 
01921    switch ((ast_number_type >> 4) & 0x07) {
01922    default:
01923    case NUMTYPE_UNKNOWN:
01924       number_type = NUMTYPE_UNKNOWN;
01925       break;
01926 
01927    case NUMTYPE_INTERNATIONAL:
01928       number_type = NUMTYPE_INTERNATIONAL;
01929       break;
01930 
01931    case NUMTYPE_NATIONAL:
01932       number_type = NUMTYPE_NATIONAL;
01933       break;
01934 
01935    case NUMTYPE_NETWORK_SPECIFIC:
01936       number_type = NUMTYPE_NETWORK_SPECIFIC;
01937       break;
01938 
01939    case NUMTYPE_SUBSCRIBER:
01940       number_type = NUMTYPE_SUBSCRIBER;
01941       break;
01942 
01943    case NUMTYPE_ABBREVIATED:
01944       number_type = NUMTYPE_ABBREVIATED;
01945       break;
01946    }
01947 
01948    return number_type;
01949 }

static const char* bearer2str ( int  cap  )  [static]

Definition at line 2374 of file chan_misdn.c.

References ARRAY_LEN, and allowed_bearers::display.

Referenced by cb_events(), misdn_lib_log_ies(), print_bc_info(), and print_bearer().

02375 {
02376    unsigned index;
02377 
02378    for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
02379       if (allowed_bearers_array[index].cap == cap) {
02380          return allowed_bearers_array[index].display;
02381       }
02382    }
02383 
02384    return "Unknown Bearer";
02385 }

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 9918 of file chan_misdn.c.

References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, ao2_cleanup, ao2_ref, misdn_bchannel::AOCD_need_export, ARRAY_LEN, chan_list::ast, 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_channel_bridge_peer(), ast_channel_caller(), ast_channel_cleanup, 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_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_copy_string(), ast_deactivate_generator(), ast_exists_extension(), ast_format_alaw, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_get_chan_features_pickup_config(), 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_poll, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_queue_frame(), ast_queue_hold(), ast_queue_unhold(), ast_set_callerid(), ast_setstate(), AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdup, ast_strdupa, 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, allowed_bearers::name, misdn_party_id::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, NULL, ast_party_id::number, misdn_party_dialing::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, RAII_VAR, 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().

09919 {
09920 #if defined(AST_MISDN_ENHANCEMENTS)
09921    struct misdn_cc_record *cc_record;
09922 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
09923    struct chan_list *held_ch;
09924    struct chan_list *ch = find_chan_by_bc(bc);
09925 
09926    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
09927       int debuglevel = 1;
09928 
09929       /*  Debug Only Non-Bchan */
09930       if (event == EVENT_CLEANUP && !user_data) {
09931          debuglevel = 5;
09932       }
09933 
09934       chan_misdn_log(debuglevel, bc->port,
09935          "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
09936          manager_isdn_get_info(event),
09937          bc->caller.name,
09938          bc->caller.number,
09939          bc->dialed.number,
09940          bc->pid,
09941          ch ? misdn_get_ch_state(ch) : "none");
09942       if (debuglevel == 1) {
09943          misdn_lib_log_ies(bc);
09944          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
09945       }
09946    }
09947 
09948    if (!ch) {
09949       switch(event) {
09950       case EVENT_SETUP:
09951       case EVENT_DISCONNECT:
09952       case EVENT_RELEASE:
09953       case EVENT_RELEASE_COMPLETE:
09954       case EVENT_PORT_ALARM:
09955       case EVENT_RETRIEVE:
09956       case EVENT_NEW_BC:
09957       case EVENT_FACILITY:
09958       case EVENT_REGISTER:
09959          break;
09960       case EVENT_CLEANUP:
09961       case EVENT_TONE_GENERATE:
09962       case EVENT_BCHAN_DATA:
09963          return -1;
09964       default:
09965          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);
09966          return -1;
09967       }
09968    } else {
09969       switch (event) {
09970       case EVENT_TONE_GENERATE:
09971          break;
09972       case EVENT_DISCONNECT:
09973       case EVENT_RELEASE:
09974       case EVENT_RELEASE_COMPLETE:
09975       case EVENT_CLEANUP:
09976       case EVENT_TIMEOUT:
09977          if (!ch->ast) {
09978             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));
09979          }
09980          break;
09981       default:
09982          if (!ch->ast || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
09983             if (event != EVENT_BCHAN_DATA) {
09984                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
09985             }
09986             chan_list_unref(ch, "No Ast or Ast private pointer");
09987             return -1;
09988          }
09989          break;
09990       }
09991    }
09992 
09993 
09994    switch (event) {
09995    case EVENT_PORT_ALARM:
09996       {
09997          int boa = 0;
09998          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
09999          if (boa) {
10000             cb_log(1, bc->port, " --> blocking\n");
10001             misdn_lib_port_block(bc->port);
10002          }
10003       }
10004       break;
10005    case EVENT_BCHAN_ACTIVATED:
10006       break;
10007 
10008    case EVENT_NEW_CHANNEL:
10009       update_name(ch->ast,bc->port,bc->channel);
10010       break;
10011 
10012    case EVENT_NEW_L3ID:
10013       ch->l3id=bc->l3_id;
10014       ch->addr=bc->addr;
10015       break;
10016 
10017    case EVENT_NEW_BC:
10018       if (!ch) {
10019          ch = find_hold_call(bc);
10020       }
10021 
10022       if (!ch) {
10023          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
10024          break;
10025       }
10026 
10027       if (bc) {
10028          ch->bc = (struct misdn_bchannel *) user_data;
10029       }
10030       break;
10031 
10032    case EVENT_DTMF_TONE:
10033    {
10034       /*  sending INFOS as DTMF-Frames :) */
10035       struct ast_frame fr;
10036 
10037       memset(&fr, 0, sizeof(fr));
10038       fr.frametype = AST_FRAME_DTMF;
10039       fr.subclass.integer = bc->dtmf ;
10040       fr.src = NULL;
10041       fr.data.ptr = NULL;
10042       fr.datalen = 0;
10043       fr.samples = 0;
10044       fr.mallocd = 0;
10045       fr.offset = 0;
10046       fr.delivery = ast_tv(0,0);
10047 
10048       if (!ch->ignore_dtmf) {
10049          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
10050          ast_queue_frame(ch->ast, &fr);
10051       } else {
10052          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
10053       }
10054       break;
10055    }
10056    case EVENT_STATUS:
10057       break;
10058 
10059    case EVENT_INFORMATION:
10060       if (ch->state != MISDN_CONNECTED) {
10061          stop_indicate(ch);
10062       }
10063 
10064       if (!ch->ast) {
10065          break;
10066       }
10067 
10068       if (ch->state == MISDN_WAITING4DIGS) {
10069          RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
10070          const char *pickupexten;
10071 
10072          /*  Ok, incomplete Setup, waiting till extension exists */
10073          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
10074             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
10075             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
10076          }
10077 
10078          strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10079          ast_channel_exten_set(ch->ast, bc->dialed.number);
10080 
10081          ast_channel_lock(ch->ast);
10082          pickup_cfg = ast_get_chan_features_pickup_config(ch->ast);
10083          if (!pickup_cfg) {
10084             ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
10085             pickupexten = "";
10086          } else {
10087             pickupexten = ast_strdupa(pickup_cfg->pickupexten);
10088          }
10089          ast_channel_unlock(ch->ast);
10090 
10091          /* Check for Pickup Request first */
10092          if (!strcmp(ast_channel_exten(ch->ast), pickupexten)) {
10093             if (ast_pickup_call(ch->ast)) {
10094                hangup_chan(ch, bc);
10095             } else {
10096                ch->state = MISDN_CALLING_ACKNOWLEDGE;
10097                hangup_chan(ch, bc);
10098                ch->ast = NULL;
10099                break;
10100             }
10101          }
10102 
10103          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10104             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10105                ast_log(LOG_WARNING,
10106                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10107                   bc->dialed.number, ch->context, bc->port);
10108                pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10109                ast_channel_exten_set(ch->ast, "i");
10110                ch->state = MISDN_DIALING;
10111                start_pbx(ch, bc, ch->ast);
10112                break;
10113             }
10114 
10115             ast_log(LOG_WARNING,
10116                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10117                "\tMaybe you want to add an 'i' extension to catch this case.\n",
10118                bc->dialed.number, ch->context, bc->port);
10119 
10120             if (bc->nt) {
10121                hanguptone_indicate(ch);
10122             }
10123             ch->state = MISDN_EXTCANTMATCH;
10124             bc->out_cause = AST_CAUSE_UNALLOCATED;
10125 
10126             misdn_lib_send_event(bc, EVENT_DISCONNECT);
10127             break;
10128          }
10129 
10130          if (ch->overlap_dial) {
10131             ast_mutex_lock(&ch->overlap_tv_lock);
10132             ch->overlap_tv = ast_tvnow();
10133             ast_mutex_unlock(&ch->overlap_tv_lock);
10134             if (ch->overlap_dial_task == -1) {
10135                ch->overlap_dial_task =
10136                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
10137             }
10138             break;
10139          }
10140 
10141          if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number))  {
10142             ch->state = MISDN_DIALING;
10143             start_pbx(ch, bc, ch->ast);
10144          }
10145       } else {
10146          /*  sending INFOS as DTMF-Frames :) */
10147          struct ast_frame fr;
10148          int digits;
10149 
10150          memset(&fr, 0, sizeof(fr));
10151          fr.frametype = AST_FRAME_DTMF;
10152          fr.subclass.integer = bc->info_dad[0] ;
10153          fr.src = NULL;
10154          fr.data.ptr = NULL;
10155          fr.datalen = 0;
10156          fr.samples = 0;
10157          fr.mallocd = 0;
10158          fr.offset = 0;
10159          fr.delivery = ast_tv(0,0);
10160 
10161          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
10162          if (ch->state != MISDN_CONNECTED) {
10163             if (digits) {
10164                strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10165                ast_channel_exten_set(ch->ast, bc->dialed.number);
10166             }
10167 
10168             ast_queue_frame(ch->ast, &fr);
10169          }
10170       }
10171       break;
10172    case EVENT_SETUP:
10173    {
10174       struct ast_channel *chan;
10175       int exceed;
10176       int ai;
10177       int im;
10178       int append_msn = 0;
10179       RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
10180       const char *pickupexten;
10181 
10182       if (ch) {
10183          switch (ch->state) {
10184          case MISDN_NOTHING:
10185             chan_list_unref(ch, "Ignore found ch.  Is it for an outgoing call?");
10186             ch = NULL;
10187             break;
10188          default:
10189             chan_list_unref(ch, "Already have a call.");
10190             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
10191             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
10192          }
10193       }
10194 
10195       if (!bc->nt && !misdn_is_msn_valid(bc->port, &bc->dialed)) {
10196          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
10197          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
10198       }
10199 
10200       if (bc->cw) {
10201          int cause;
10202          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
10203          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
10204          bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
10205          return RESPONSE_RELEASE_SETUP;
10206       }
10207 
10208       print_bearer(bc);
10209 
10210       ch = chan_list_init(ORG_MISDN);
10211       if (!ch) {
10212          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
10213          return RESPONSE_RELEASE_SETUP;
10214       }
10215 
10216       ch->bc = bc;
10217       ch->l3id = bc->l3_id;
10218       ch->addr = bc->addr;
10219 
10220       {
10221          struct ast_format_cap *cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
10222          if (!(cap)) {
10223             return RESPONSE_ERR;
10224          }
10225          ast_format_cap_append(cap, ast_format_alaw, 0);
10226          chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, NULL, bc->port, bc->channel);
10227          ao2_ref(cap, -1);
10228       }
10229       if (!chan) {
10230          chan_list_unref(ch, "Failed to create a new channel");
10231          ast_log(LOG_ERROR, "cb_events: misdn_new failed!\n");
10232          return RESPONSE_RELEASE_SETUP;
10233       }
10234 
10235       ast_channel_lock(chan);
10236       pickup_cfg = ast_get_chan_features_pickup_config(chan);
10237       if (!pickup_cfg) {
10238          ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
10239          pickupexten = "";
10240       } else {
10241          pickupexten = ast_strdupa(pickup_cfg->pickupexten);
10242       }
10243       ast_channel_unlock(chan);
10244 
10245       if ((exceed = add_in_calls(bc->port))) {
10246          char tmp[16];
10247          snprintf(tmp, sizeof(tmp), "%d", exceed);
10248          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
10249       }
10250 
10251       read_config(ch);
10252 
10253       export_ch(chan, bc, ch);
10254 
10255       ast_channel_lock(ch->ast);
10256       ast_channel_rings_set(ch->ast, 1);
10257       ast_setstate(ch->ast, AST_STATE_RINGING);
10258       ast_channel_unlock(ch->ast);
10259 
10260       /* Update asterisk channel caller information */
10261       chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
10262       chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
10263       ast_channel_caller(chan)->id.number.plan = misdn_to_ast_ton(bc->caller.number_type)
10264          | misdn_to_ast_plan(bc->caller.number_plan);
10265 
10266       chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
10267       chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
10268       ast_channel_caller(chan)->id.number.presentation = misdn_to_ast_pres(bc->caller.presentation)
10269          | misdn_to_ast_screen(bc->caller.screening);
10270 
10271       ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
10272 
10273       misdn_cfg_get(bc->port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
10274       if (append_msn) {
10275          strncat(bc->incoming_cid_tag, "_", sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10276          strncat(bc->incoming_cid_tag, bc->dialed.number, sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10277       }
10278 
10279       ast_channel_lock(chan);
10280       ast_channel_caller(chan)->id.tag = ast_strdup(bc->incoming_cid_tag);
10281       ast_channel_unlock(chan);
10282 
10283       if (!ast_strlen_zero(bc->redirecting.from.number)) {
10284          /* Add configured prefix to redirecting.from.number */
10285          misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
10286 
10287          /* Update asterisk channel redirecting information */
10288          misdn_copy_redirecting_to_ast(chan, &bc->redirecting, bc->incoming_cid_tag);
10289       }
10290 
10291       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
10292       ast_channel_transfercapability_set(chan, bc->capability);
10293 
10294       switch (bc->capability) {
10295       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
10296          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
10297          break;
10298       default:
10299          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
10300          break;
10301       }
10302 
10303       if (!strstr(ch->allowed_bearers, "all")) {
10304          int i;
10305 
10306          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
10307             if (allowed_bearers_array[i].cap == bc->capability) {
10308                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
10309                   /* The bearer capability is allowed */
10310                   if (allowed_bearers_array[i].deprecated) {
10311                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
10312                         allowed_bearers_array[i].name);
10313                   }
10314                   break;
10315                }
10316             }
10317          }
10318          if (i == ARRAY_LEN(allowed_bearers_array)) {
10319             /* We did not find the bearer capability */
10320             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
10321                bearer2str(bc->capability), bc->capability);
10322 
10323             ch->state = MISDN_EXTCANTMATCH;
10324             chan_list_unref(ch, "BC not allowed, releasing call");
10325             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
10326             return RESPONSE_RELEASE_SETUP;
10327          }
10328       }
10329 
10330       /** queue new chan **/
10331       cl_queue_chan(ch);
10332 
10333       if (bc->fac_in.Function != Fac_None) {
10334          misdn_facility_ie_handler(event, bc, ch);
10335       }
10336 
10337       /* Check for Pickup Request first */
10338       if (!strcmp(ast_channel_exten(chan), pickupexten)) {
10339          if (!ch->noautorespond_on_setup) {
10340             /* Sending SETUP_ACK */
10341             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
10342          } else {
10343             ch->state = MISDN_INCOMING_SETUP;
10344          }
10345          if (ast_pickup_call(chan)) {
10346             hangup_chan(ch, bc);
10347          } else {
10348             ch->state = MISDN_CALLING_ACKNOWLEDGE;
10349             hangup_chan(ch, bc);
10350             ch->ast = NULL;
10351             break;
10352          }
10353       }
10354 
10355       /*
10356        * added support for s extension hope it will help those poor cretains
10357        * which haven't overlap dial.
10358        */
10359       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
10360       if (ai) {
10361          do_immediate_setup(bc, ch, chan);
10362          break;
10363       }
10364 
10365       /* check if we should jump into s when we have no dialed.number */
10366       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
10367       if (im && ast_strlen_zero(bc->dialed.number)) {
10368          do_immediate_setup(bc, ch, chan);
10369          break;
10370       }
10371 
10372       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
10373       if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10374          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10375             ast_log(LOG_WARNING,
10376                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10377                bc->dialed.number, ch->context, bc->port);
10378             pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10379             ast_channel_exten_set(ch->ast, "i");
10380             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
10381             ch->state = MISDN_DIALING;
10382             start_pbx(ch, bc, chan);
10383             break;
10384          }
10385 
10386          ast_log(LOG_WARNING,
10387             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10388             "\tMaybe you want to add an 'i' extension to catch this case.\n",
10389             bc->dialed.number, ch->context, bc->port);
10390          if (bc->nt) {
10391             hanguptone_indicate(ch);
10392          }
10393 
10394          ch->state = MISDN_EXTCANTMATCH;
10395          bc->out_cause = AST_CAUSE_UNALLOCATED;
10396 
10397          misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_RELEASE);
10398          break;
10399       }
10400 
10401       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
10402        * jump into the dialplan, when the dialed extension does not exist, the 's' extension
10403        * will be used by Asterisk automatically. */
10404       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
10405          if (!ch->noautorespond_on_setup) {
10406             ch->state=MISDN_DIALING;
10407             misdn_lib_send_event(bc, EVENT_PROCEEDING);
10408          } else {
10409             ch->state = MISDN_INCOMING_SETUP;
10410          }
10411          start_pbx(ch, bc, chan);
10412          break;
10413       }
10414 
10415 
10416       /*
10417        * When we are NT and overlapdial is set and if
10418        * the number is empty, we wait for the ISDN timeout
10419        * instead of our own timer.
10420        */
10421       if (ch->overlap_dial && bc->nt && !bc->dialed.number[0]) {
10422          wait_for_digits(ch, bc, chan);
10423          break;
10424       }
10425 
10426       /*
10427        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
10428        * Infos with a Interdigit Timeout.
10429        * */
10430       if (ch->overlap_dial) {
10431          ast_mutex_lock(&ch->overlap_tv_lock);
10432          ch->overlap_tv = ast_tvnow();
10433          ast_mutex_unlock(&ch->overlap_tv_lock);
10434 
10435          wait_for_digits(ch, bc, chan);
10436          if (ch->overlap_dial_task == -1) {
10437             ch->overlap_dial_task =
10438                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
10439          }
10440          break;
10441       }
10442 
10443       /* If the extension does not exist and we're not TE_PTMP we wait for more digits
10444        * without interdigit timeout.
10445        * */
10446       if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number))  {
10447          wait_for_digits(ch, bc, chan);
10448          break;
10449       }
10450 
10451       /*
10452        * If the extension exists let's just jump into it.
10453        * */
10454       if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10455          misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
10456          ch->state = MISDN_DIALING;
10457          start_pbx(ch, bc, chan);
10458          break;
10459       }
10460       break;
10461    }
10462 #if defined(AST_MISDN_ENHANCEMENTS)
10463    case EVENT_REGISTER:
10464       if (bc->fac_in.Function != Fac_None) {
10465          misdn_facility_ie_handler(event, bc, ch);
10466       }
10467       /*
10468        * Shut down this connection immediately.
10469        * The current design of chan_misdn data structures
10470        * does not allow the proper handling of inbound call records
10471        * without an assigned B channel.  Therefore, we cannot
10472        * be the CCBS User-B party in a point-to-point setup.
10473        */
10474       bc->fac_out.Function = Fac_None;
10475       bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10476       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
10477       break;
10478 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10479    case EVENT_SETUP_ACKNOWLEDGE:
10480       ch->state = MISDN_CALLING_ACKNOWLEDGE;
10481 
10482       if (bc->channel) {
10483          update_name(ch->ast,bc->port,bc->channel);
10484       }
10485 
10486       if (bc->fac_in.Function != Fac_None) {
10487          misdn_facility_ie_handler(event, bc, ch);
10488       }
10489 
10490       if (!ast_strlen_zero(bc->infos_pending)) {
10491          /* TX Pending Infos */
10492          strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10493 
10494          if (!ch->ast) {
10495             break;
10496          }
10497          ast_channel_exten_set(ch->ast, bc->dialed.number);
10498          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
10499          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
10500 
10501          misdn_lib_send_event(bc, EVENT_INFORMATION);
10502       }
10503       break;
10504    case EVENT_PROCEEDING:
10505       if (misdn_cap_is_speech(bc->capability) &&
10506          misdn_inband_avail(bc)) {
10507          start_bc_tones(ch);
10508       }
10509 
10510       ch->state = MISDN_PROCEEDING;
10511 
10512       if (bc->fac_in.Function != Fac_None) {
10513          misdn_facility_ie_handler(event, bc, ch);
10514       }
10515 
10516       if (!ch->ast) {
10517          break;
10518       }
10519 
10520       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
10521       break;
10522    case EVENT_PROGRESS:
10523       if (bc->channel) {
10524          update_name(ch->ast, bc->port, bc->channel);
10525       }
10526 
10527       if (bc->fac_in.Function != Fac_None) {
10528          misdn_facility_ie_handler(event, bc, ch);
10529       }
10530 
10531       if (!bc->nt) {
10532          if (misdn_cap_is_speech(bc->capability) &&
10533             misdn_inband_avail(bc)) {
10534             start_bc_tones(ch);
10535          }
10536 
10537          ch->state = MISDN_PROGRESS;
10538 
10539          if (!ch->ast) {
10540             break;
10541          }
10542          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
10543       }
10544       break;
10545    case EVENT_ALERTING:
10546       ch->state = MISDN_ALERTING;
10547 
10548       if (!ch->ast) {
10549          break;
10550       }
10551 
10552       if (bc->fac_in.Function != Fac_None) {
10553          misdn_facility_ie_handler(event, bc, ch);
10554       }
10555 
10556       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
10557       ast_channel_lock(ch->ast);
10558       ast_setstate(ch->ast, AST_STATE_RINGING);
10559       ast_channel_unlock(ch->ast);
10560 
10561       cb_log(7, bc->port, " --> Set State Ringing\n");
10562 
10563       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
10564          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
10565          start_bc_tones(ch);
10566       } else {
10567          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
10568          if (ch->far_alerting) {
10569             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
10570             start_bc_tones(ch);
10571             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
10572          }
10573       }
10574       break;
10575    case EVENT_CONNECT:
10576       if (bc->fac_in.Function != Fac_None) {
10577          misdn_facility_ie_handler(event, bc, ch);
10578       }
10579 #if defined(AST_MISDN_ENHANCEMENTS)
10580       if (bc->div_leg_3_rx_wanted) {
10581          bc->div_leg_3_rx_wanted = 0;
10582 
10583          if (ch->ast) {
10584             struct ast_party_redirecting redirecting;
10585 
10586             ast_channel_redirecting(ch->ast)->to.number.presentation =
10587                AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
10588             ast_party_redirecting_init(&redirecting);
10589             ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
10590 
10591             /*
10592              * Reset any earlier private redirecting id representations and
10593              * make sure that it is invalidated at the remote end.
10594              */
10595             ast_party_id_reset(&redirecting.priv_orig);
10596             ast_party_id_reset(&redirecting.priv_from);
10597             ast_party_id_reset(&redirecting.priv_to);
10598 
10599             ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
10600             ast_party_redirecting_free(&redirecting);
10601          }
10602       }
10603 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10604 
10605       /* we answer when we've got our very new L3 ID from the NT stack */
10606       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
10607 
10608       if (!ch->ast) {
10609          break;
10610       }
10611 
10612       stop_indicate(ch);
10613 
10614 #if defined(AST_MISDN_ENHANCEMENTS)
10615       if (ch->record_id != -1) {
10616          /*
10617           * We will delete the associated call completion
10618           * record since we now have a completed call.
10619           * We will not wait/depend on the network to tell
10620           * us to delete it.
10621           */
10622          AST_LIST_LOCK(&misdn_cc_records_db);
10623          cc_record = misdn_cc_find_by_id(ch->record_id);
10624          if (cc_record) {
10625             if (cc_record->ptp && cc_record->mode.ptp.bc) {
10626                /* Close the call-completion signaling link */
10627                cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
10628                cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10629                misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
10630             }
10631             misdn_cc_delete(cc_record);
10632          }
10633          AST_LIST_UNLOCK(&misdn_cc_records_db);
10634          ch->record_id = -1;
10635          if (ch->peer) {
10636             misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, "");
10637 
10638             ao2_ref(ch->peer, -1);
10639             ch->peer = NULL;
10640          }
10641       }
10642 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10643 
10644       if (!ast_strlen_zero(bc->connected.number)) {
10645          /* Add configured prefix to connected.number */
10646          misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
10647 
10648          /* Update the connected line information on the other channel */
10649          misdn_update_remote_party(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, bc->incoming_cid_tag);
10650       }
10651 
10652       ch->l3id = bc->l3_id;
10653       ch->addr = bc->addr;
10654 
10655       start_bc_tones(ch);
10656 
10657       ch->state = MISDN_CONNECTED;
10658 
10659       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
10660       break;
10661    case EVENT_CONNECT_ACKNOWLEDGE:
10662       ch->l3id = bc->l3_id;
10663       ch->addr = bc->addr;
10664 
10665       start_bc_tones(ch);
10666 
10667       ch->state = MISDN_CONNECTED;
10668       break;
10669    case EVENT_DISCONNECT:
10670       /* we might not have an ch->ast ptr here anymore */
10671       if (ch) {
10672          if (bc->fac_in.Function != Fac_None) {
10673             misdn_facility_ie_handler(event, bc, ch);
10674          }
10675 
10676          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);
10677          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
10678             /* If there's inband information available (e.g. a
10679                recorded message saying what was wrong with the
10680                dialled number, or perhaps even giving an
10681                alternative number, then play it instead of
10682                immediately releasing the call */
10683             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
10684 
10685             ch->state = MISDN_DISCONNECTED;
10686             start_bc_tones(ch);
10687 
10688             if (ch->ast) {
10689                ast_channel_hangupcause_set(ch->ast, bc->cause);
10690                if (bc->cause == AST_CAUSE_USER_BUSY) {
10691                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
10692                }
10693             }
10694             ch->need_busy = 0;
10695             break;
10696          }
10697 
10698          bc->need_disconnect = 0;
10699          stop_bc_tones(ch);
10700 
10701          /* Check for held channel, to implement transfer */
10702          held_ch = find_hold_call(bc);
10703          if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
10704             hangup_chan(ch, bc);
10705          }
10706       } else {
10707          held_ch = find_hold_call_l3(bc->l3_id);
10708          if (held_ch) {
10709             if (bc->fac_in.Function != Fac_None) {
10710                misdn_facility_ie_handler(event, bc, held_ch);
10711             }
10712 
10713             if (held_ch->hold.state == MISDN_HOLD_ACTIVE) {
10714                bc->need_disconnect = 0;
10715 
10716 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
10717                /*
10718                 * Some phones disconnect the held call and the active call at the
10719                 * same time to do the transfer.  Unfortunately, either call could
10720                 * be disconnected first.
10721                 */
10722                ch = find_hold_active_call(bc);
10723                if (!ch || misdn_attempt_transfer(ch, held_ch)) {
10724                   held_ch->hold.state = MISDN_HOLD_DISCONNECT;
10725                   hangup_chan(held_ch, bc);
10726                }
10727 #else
10728                hangup_chan(held_ch, bc);
10729 #endif   /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
10730             }
10731          }
10732       }
10733       if (held_ch) {
10734          chan_list_unref(held_ch, "Done with held call");
10735       }
10736       bc->out_cause = -1;
10737       if (bc->need_release) {
10738          misdn_lib_send_event(bc, EVENT_RELEASE);
10739       }
10740       break;
10741    case EVENT_RELEASE:
10742       if (!ch) {
10743          ch = find_hold_call_l3(bc->l3_id);
10744          if (!ch) {
10745             chan_misdn_log(1, bc->port,
10746                " --> no Ch, so we've already released. (%s)\n",
10747                manager_isdn_get_info(event));
10748             return -1;
10749          }
10750       }
10751       if (bc->fac_in.Function != Fac_None) {
10752          misdn_facility_ie_handler(event, bc, ch);
10753       }
10754 
10755       bc->need_disconnect = 0;
10756       bc->need_release = 0;
10757 
10758       hangup_chan(ch, bc);
10759       release_chan(ch, bc);
10760       break;
10761    case EVENT_RELEASE_COMPLETE:
10762       if (!ch) {
10763          ch = find_hold_call_l3(bc->l3_id);
10764       }
10765 
10766       bc->need_disconnect = 0;
10767       bc->need_release = 0;
10768       bc->need_release_complete = 0;
10769 
10770       if (ch) {
10771          if (bc->fac_in.Function != Fac_None) {
10772             misdn_facility_ie_handler(event, bc, ch);
10773          }
10774 
10775          stop_bc_tones(ch);
10776          hangup_chan(ch, bc);
10777          release_chan(ch, bc);
10778       } else {
10779 #if defined(AST_MISDN_ENHANCEMENTS)
10780          /*
10781           * A call-completion signaling link established with
10782           * REGISTER does not have a struct chan_list record
10783           * associated with it.
10784           */
10785          AST_LIST_LOCK(&misdn_cc_records_db);
10786          cc_record = misdn_cc_find_by_bc(bc);
10787          if (cc_record) {
10788             /* The call-completion signaling link is closed. */
10789             misdn_cc_delete(cc_record);
10790          }
10791          AST_LIST_UNLOCK(&misdn_cc_records_db);
10792 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10793 
10794          chan_misdn_log(1, bc->port,
10795             " --> no Ch, so we've already released. (%s)\n",
10796             manager_isdn_get_info(event));
10797       }
10798       break;
10799    case EVENT_BCHAN_ERROR:
10800    case EVENT_CLEANUP:
10801       stop_bc_tones(ch);
10802 
10803       switch (ch->state) {
10804       case MISDN_CALLING:
10805          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
10806          break;
10807       default:
10808          break;
10809       }
10810 
10811       hangup_chan(ch, bc);
10812       release_chan(ch, bc);
10813       break;
10814    case EVENT_TONE_GENERATE:
10815    {
10816       int tone_len = bc->tone_cnt;
10817       struct ast_channel *ast = ch->ast;
10818       void *tmp;
10819       int res;
10820       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
10821 
10822       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
10823 
10824       if (!ast) {
10825          break;
10826       }
10827 
10828       if (!ast_channel_generator(ast)) {
10829          break;
10830       }
10831 
10832       tmp = ast_channel_generatordata(ast);
10833       ast_channel_generatordata_set(ast, NULL);
10834       generate = ast_channel_generator(ast)->generate;
10835 
10836       if (tone_len < 0 || tone_len > 512) {
10837          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
10838          tone_len = 128;
10839       }
10840 
10841       res = generate(ast, tmp, tone_len, tone_len);
10842       ast_channel_generatordata_set(ast, tmp);
10843 
10844       if (res) {
10845          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
10846          ast_deactivate_generator(ast);
10847       } else {
10848          bc->tone_cnt = 0;
10849       }
10850       break;
10851    }
10852    case EVENT_BCHAN_DATA:
10853       if (ch->bc->AOCD_need_export) {
10854          export_aoc_vars(ch->originator, ch->ast, ch->bc);
10855       }
10856       if (!misdn_cap_is_speech(ch->bc->capability)) {
10857          struct ast_frame frame;
10858 
10859          /* In Data Modes we queue frames */
10860          memset(&frame, 0, sizeof(frame));
10861          frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
10862          frame.subclass.format = ast_format_alaw;
10863          frame.datalen = bc->bframe_len;
10864          frame.samples = bc->bframe_len;
10865          frame.mallocd = 0;
10866          frame.offset = 0;
10867          frame.delivery = ast_tv(0, 0);
10868          frame.src = NULL;
10869          frame.data.ptr = bc->bframe;
10870 
10871          if (ch->ast) {
10872             ast_queue_frame(ch->ast, &frame);
10873          }
10874       } else {
10875          struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
10876          int t;
10877 
10878          t = ast_poll(&pfd, 1, 0);
10879 
10880          if (t < 0) {
10881             chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
10882             break;
10883          }
10884          if (!t) {
10885             chan_misdn_log(9, bc->port, "poll() timed out\n");
10886             break;
10887          }
10888 
10889          if (pfd.revents & POLLOUT) {
10890             chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
10891             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
10892                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
10893 
10894                stop_bc_tones(ch);
10895                hangup_chan(ch, bc);
10896                release_chan(ch, bc);
10897             }
10898          } else {
10899             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
10900          }
10901       }
10902       break;
10903    case EVENT_TIMEOUT:
10904       if (ch && bc) {
10905          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
10906       }
10907 
10908       switch (ch->state) {
10909       case MISDN_DIALING:
10910       case MISDN_PROGRESS:
10911          if (bc->nt && !ch->nttimeout) {
10912             break;
10913          }
10914          /* fall-through */
10915       case MISDN_CALLING:
10916       case MISDN_ALERTING:
10917       case MISDN_PROCEEDING:
10918       case MISDN_CALLING_ACKNOWLEDGE:
10919          if (bc->nt) {
10920             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
10921             hanguptone_indicate(ch);
10922          }
10923 
10924          bc->out_cause = AST_CAUSE_UNALLOCATED;
10925          misdn_lib_send_event(bc, EVENT_DISCONNECT);
10926          break;
10927       case MISDN_WAITING4DIGS:
10928          if (bc->nt) {
10929             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
10930             bc->out_cause = AST_CAUSE_UNALLOCATED;
10931             hanguptone_indicate(ch);
10932             misdn_lib_send_event(bc, EVENT_DISCONNECT);
10933          } else {
10934             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10935             misdn_lib_send_event(bc, EVENT_RELEASE);
10936          }
10937          break;
10938       case MISDN_CLEANING:
10939          chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
10940          break;
10941       default:
10942          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
10943          break;
10944       }
10945       break;
10946 
10947    /****************************/
10948    /** Supplementary Services **/
10949    /****************************/
10950    case EVENT_RETRIEVE:
10951       if (!ch) {
10952          chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
10953          ch = find_hold_call_l3(bc->l3_id);
10954          if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
10955             ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
10956             misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
10957             break;
10958          }
10959       }
10960 
10961       /* remember the channel again */
10962       ch->bc = bc;
10963 
10964       ch->hold.state = MISDN_HOLD_IDLE;
10965       ch->hold.port = 0;
10966       ch->hold.channel = 0;
10967 
10968       ast_queue_unhold(ch->ast);
10969 
10970       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
10971          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
10972          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
10973       }
10974       break;
10975    case EVENT_HOLD:
10976    {
10977       int hold_allowed;
10978       RAII_VAR(struct ast_channel *, bridged, NULL, ast_channel_cleanup);
10979 
10980       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
10981       if (!hold_allowed) {
10982          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
10983          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
10984          break;
10985       }
10986 
10987       bridged = ast_channel_bridge_peer(ch->ast);
10988       if (bridged) {
10989          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", ast_channel_tech(bridged)->type);
10990          ch->l3id = bc->l3_id;
10991 
10992          /* forget the channel now */
10993          ch->bc = NULL;
10994          ch->hold.state = MISDN_HOLD_ACTIVE;
10995          ch->hold.port = bc->port;
10996          ch->hold.channel = bc->channel;
10997 
10998          ast_queue_hold(ch->ast, NULL);
10999 
11000          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
11001       } else {
11002          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
11003          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
11004       }
11005       break;
11006    }
11007    case EVENT_NOTIFY:
11008       if (bc->redirecting.to_changed) {
11009          /* Add configured prefix to redirecting.to.number */
11010          misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
11011             bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
11012       }
11013       switch (bc->notify_description_code) {
11014       case mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED:
11015          /* Ignore for now. */
11016          bc->redirecting.to_changed = 0;
11017          break;
11018       case mISDN_NOTIFY_CODE_CALL_IS_DIVERTING:
11019       {
11020          struct ast_party_redirecting redirecting;
11021 
11022          if (!bc->redirecting.to_changed) {
11023             break;
11024          }
11025          bc->redirecting.to_changed = 0;
11026          if (!ch || !ch->ast) {
11027             break;
11028          }
11029          switch (ch->state) {
11030          case MISDN_ALERTING:
11031             /* Call is deflecting after we have seen an ALERTING message */
11032             bc->redirecting.reason = mISDN_REDIRECTING_REASON_NO_REPLY;
11033             break;
11034          default:
11035             /* Call is deflecting for call forwarding unconditional or busy reason. */
11036             bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
11037             break;
11038          }
11039          misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
11040          ast_party_redirecting_init(&redirecting);
11041          ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
11042 
11043          /*
11044           * Reset any earlier private redirecting id representations and
11045           * make sure that it is invalidated at the remote end.
11046           */
11047          ast_party_id_reset(&redirecting.priv_orig);
11048          ast_party_id_reset(&redirecting.priv_from);
11049          ast_party_id_reset(&redirecting.priv_to);
11050 
11051          ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
11052          ast_party_redirecting_free(&redirecting);
11053          break;
11054       }
11055       case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
11056          /*
11057           * It would be preferable to update the connected line information
11058           * only when the message callStatus is active.  However, the
11059           * optional redirection number may not be present in the active
11060           * message if an alerting message were received earlier.
11061           *
11062           * The consequences if we wind up sending two updates is benign.
11063           * The other end will think that it got transferred twice.
11064           */
11065          if (!bc->redirecting.to_changed) {
11066             break;
11067          }
11068          bc->redirecting.to_changed = 0;
11069          if (!ch || !ch->ast) {
11070             break;
11071          }
11072          misdn_update_remote_party(ch->ast, &bc->redirecting.to,
11073             AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING,
11074             bc->incoming_cid_tag);
11075          break;
11076       case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
11077          if (!bc->redirecting.to_changed) {
11078             break;
11079          }
11080          bc->redirecting.to_changed = 0;
11081          if (!ch || !ch->ast) {
11082             break;
11083          }
11084          misdn_update_remote_party(ch->ast, &bc->redirecting.to,
11085             AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
11086          break;
11087       default:
11088          bc->redirecting.to_changed = 0;
11089          chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
11090             bc->notify_description_code);
11091          break;
11092       }
11093       bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
11094       break;
11095    case EVENT_FACILITY:
11096       if (bc->fac_in.Function == Fac_None) {
11097          /* This is a FACILITY message so we MUST have a facility ie */
11098          chan_misdn_log(0, bc->port," --> Missing facility ie or unknown facility ie contents.\n");
11099       } else {
11100          misdn_facility_ie_handler(event, bc, ch);
11101       }
11102 
11103       /* In case it came in on a FACILITY message and we did not handle it. */
11104       bc->redirecting.to_changed = 0;
11105       bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
11106       break;
11107    case EVENT_RESTART:
11108       if (!bc->dummy) {
11109          stop_bc_tones(ch);
11110          release_chan(ch, bc);
11111       }
11112       break;
11113    default:
11114       chan_misdn_log(1, 0, "Got Unknown Event\n");
11115       break;
11116    }
11117 
11118    if (ch) {
11119       chan_list_unref(ch, "cb_event complete OK");
11120    }
11121    return RESPONSE_OK;
11122 }

static void chan_list_destructor ( void *  obj  )  [static]

Definition at line 7793 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(), NULL, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, and chan_list::pipe.

Referenced by chan_list_init().

07794 {
07795    struct chan_list *ch = obj;
07796 
07797 #if defined(AST_MISDN_ENHANCEMENTS)
07798    if (ch->peer) {
07799       ao2_ref(ch->peer, -1);
07800       ch->peer = NULL;
07801    }
07802 #endif /* AST_MISDN_ENHANCEMENTS */
07803 
07804    if (ch->dsp) {
07805       ast_dsp_free(ch->dsp);
07806       ch->dsp = NULL;
07807    }
07808 
07809    /* releasing jitterbuffer */
07810    if (ch->jb) {
07811       misdn_jb_destroy(ch->jb);
07812       ch->jb = NULL;
07813    }
07814 
07815    if (ch->overlap_dial) {
07816       if (ch->overlap_dial_task != -1) {
07817          misdn_tasks_remove(ch->overlap_dial_task);
07818          ch->overlap_dial_task = -1;
07819       }
07820       ast_mutex_destroy(&ch->overlap_tv_lock);
07821    }
07822 
07823    if (-1 < ch->pipe[0]) {
07824       close(ch->pipe[0]);
07825    }
07826    if (-1 < ch->pipe[1]) {
07827       close(ch->pipe[1]);
07828    }
07829 }

static struct chan_list* chan_list_init ( int  orig  )  [static, read]

Returns a reference to the new chan_list.

Definition at line 7832 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, NULL, chan_list::originator, chan_list::overlap_dial_task, and chan_list::pipe.

Referenced by cb_events(), and misdn_request().

07833 {
07834    struct chan_list *cl;
07835 
07836    cl = ao2_alloc(sizeof(*cl), chan_list_destructor);
07837    if (!cl) {
07838       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
07839       return NULL;
07840    }
07841 
07842    cl->originator = orig;
07843    cl->need_queue_hangup = 1;
07844    cl->need_hangup = 1;
07845    cl->need_busy = 1;
07846    cl->overlap_dial_task = -1;
07847 #if defined(AST_MISDN_ENHANCEMENTS)
07848    cl->record_id = -1;
07849 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
07850    cl->pipe[0] = -1;
07851    cl->pipe[1] = -1;
07852 
07853    return cl;
07854 }

int chan_misdn_jb_empty ( struct misdn_bchannel bc,
char *  buf,
int  len 
)

Definition at line 12575 of file chan_misdn.c.

References chan_list_unref, find_chan_by_bc(), chan_list::jb, and misdn_jb_empty().

Referenced by load_module().

12576 {
12577    struct chan_list *ch;
12578    int res;
12579 
12580    ch = find_chan_by_bc(bc);
12581    if (!ch) {
12582       return 0;
12583    }
12584 
12585    if (ch->jb) {
12586       res = misdn_jb_empty(ch->jb, buf, len);
12587    } else {
12588       res = 0;
12589    }
12590    chan_list_unref(ch, "Done emptying jb");
12591 
12592    return res;
12593 }

static void chan_misdn_log ( int  level,
int  port,
char *  tmpl,
  ... 
) [static]

Definition at line 12769 of file chan_misdn.c.

References ast_log, ast_strlen_zero, ast_verbose, errno, LOG_WARNING, and NULL.

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

12770 {
12771    va_list ap;
12772    char buf[1024];
12773    char port_buf[8];
12774 
12775    if (!(0 <= port && port <= max_ports)) {
12776       ast_log(LOG_WARNING, "chan_misdn_log called with out-of-range port number! (%d)\n", port);
12777       port = 0;
12778       level = -1;
12779    } else if (!(level == -1
12780       || (misdn_debug_only[port]
12781          ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12782          : level <= misdn_debug[port])
12783       || (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
12784       /*
12785        * We are not going to print anything so lets not
12786        * go to all the work of generating a string.
12787        */
12788       return;
12789    }
12790 
12791    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
12792    va_start(ap, tmpl);
12793    vsnprintf(buf, sizeof(buf), tmpl, ap);
12794    va_end(ap);
12795 
12796    if (level == -1) {
12797       ast_log(LOG_WARNING, "%s", buf);
12798    } else if (misdn_debug_only[port]
12799       ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12800       : level <= misdn_debug[port]) {
12801       ast_verbose("%s%s", port_buf, buf);
12802    }
12803 
12804    if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
12805       char ctimebuf[30];
12806       time_t tm;
12807       char *tmp;
12808       char *p;
12809       FILE *fp;
12810 
12811       fp = fopen(global_tracefile, "a+");
12812       if (!fp) {
12813          ast_verbose("Error opening Tracefile: [ %s ] %s\n", global_tracefile, strerror(errno));
12814          return;
12815       }
12816 
12817       tm = time(NULL);
12818       tmp = ctime_r(&tm, ctimebuf);
12819       p = strchr(tmp, '\n');
12820       if (p) {
12821          *p = ':';
12822       }
12823       fputs(tmp, fp);
12824       fputs(" ", fp);
12825       fputs(port_buf, fp);
12826       fputs(" ", fp);
12827       fputs(buf, fp);
12828 
12829       fclose(fp);
12830    }
12831 }

static int cl_dequeue_chan ( struct chan_list chan  )  [static]

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

08400 {
08401    int found_it;
08402    struct chan_list *help;
08403 
08404    ast_mutex_lock(&cl_te_lock);
08405    if (!cl_te) {
08406       /* List is empty. */
08407       ast_mutex_unlock(&cl_te_lock);
08408       return 0;
08409    }
08410 
08411    if (cl_te == chan) {
08412       /* What we want is the head of the list. */
08413       cl_te = cl_te->next;
08414       ast_mutex_unlock(&cl_te_lock);
08415       chan_list_unref(chan, "Removed chan_list from list head");
08416       return 1;
08417    }
08418 
08419    found_it = 0;
08420    for (help = cl_te; help->next; help = help->next) {
08421       if (help->next == chan) {
08422          /* Found it in the list. */
08423          help->next = help->next->next;
08424          found_it = 1;
08425          break;
08426       }
08427    }
08428 
08429    ast_mutex_unlock(&cl_te_lock);
08430    if (found_it) {
08431       chan_list_unref(chan, "Removed chan_list from list");
08432    }
08433    return found_it;
08434 }

static void cl_queue_chan ( struct chan_list chan  )  [static]

Definition at line 8378 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, chan_list::bc, chan_list_ref, chan_misdn_log(), chan_list::next, NULL, and misdn_bchannel::port.

Referenced by cb_events(), and misdn_request().

08379 {
08380    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
08381 
08382    chan_list_ref(chan, "Adding chan_list to list");
08383    ast_mutex_lock(&cl_te_lock);
08384    chan->next = NULL;
08385    if (!cl_te) {
08386       /* List is empty, make head of list. */
08387       cl_te = chan;
08388    } else {
08389       struct chan_list *help;
08390 
08391       /* Put at end of list. */
08392       for (help = cl_te; help->next; help = help->next) {
08393       }
08394       help->next = chan;
08395    }
08396    ast_mutex_unlock(&cl_te_lock);
08397 }

static char * complete_ch ( struct ast_cli_args a  )  [static]

static char * complete_debug_port ( struct ast_cli_args a  )  [static]

Definition at line 5660 of file chan_misdn.c.

References ast_strdup, ast_cli_args::n, NULL, ast_cli_args::pos, and ast_cli_args::word.

Referenced by handle_cli_misdn_set_debug().

05661 {
05662    if (a->n) {
05663       return NULL;
05664    }
05665 
05666    switch (a->pos) {
05667    case 4:
05668       if (a->word[0] == 'p') {
05669          return ast_strdup("port");
05670       } else if (a->word[0] == 'o') {
05671          return ast_strdup("only");
05672       }
05673       break;
05674    case 6:
05675       if (a->word[0] == 'o') {
05676          return ast_strdup("only");
05677       }
05678       break;
05679    }
05680    return NULL;
05681 }

static char * complete_show_config ( struct ast_cli_args a  )  [static]

Definition at line 5683 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, NULL, ast_cli_args::pos, and ast_cli_args::word.

Referenced by handle_cli_misdn_show_config().

05684 {
05685    char buffer[BUFFERSIZE];
05686    enum misdn_cfg_elements elem;
05687    int wordlen = strlen(a->word);
05688    int which = 0;
05689    int port = 0;
05690 
05691    switch (a->pos) {
05692    case 3:
05693       if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n)) {
05694          return ast_strdup("description");
05695       }
05696       if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n)) {
05697          return ast_strdup("descriptions");
05698       }
05699       if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n)) {
05700          return ast_strdup("0");
05701       }
05702       while ((port = misdn_cfg_get_next_port(port)) != -1) {
05703          snprintf(buffer, sizeof(buffer), "%d", port);
05704          if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
05705             return ast_strdup(buffer);
05706          }
05707       }
05708       break;
05709    case 4:
05710       if (strstr(a->line, "description ")) {
05711          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
05712             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) {
05713                continue;
05714             }
05715             misdn_cfg_get_name(elem, buffer, sizeof(buffer));
05716             if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
05717                if (++which > a->n) {
05718                   return ast_strdup(buffer);
05719                }
05720             }
05721          }
05722       } else if (strstr(a->line, "descriptions ")) {
05723          if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n)) {
05724             return ast_strdup("general");
05725          }
05726          if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n)) {
05727             return ast_strdup("ports");
05728          }
05729       }
05730       break;
05731    }
05732    return NULL;
05733 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

Definition at line 5818 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, NULL, and misdn_bchannel::port.

Referenced by misdn_set_opt_exec(), and read_config().

05819 {
05820    struct misdn_bchannel *bc = ch->bc;
05821    int len = ch->jb_len;
05822    int threshold = ch->jb_upper_threshold;
05823 
05824    chan_misdn_log(5, bc->port, "config_jb: Called\n");
05825 
05826    if (!len) {
05827       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
05828       bc->nojitter = 1;
05829    } else {
05830       if (len <= 100 || len > 8000) {
05831          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
05832          len = 1000;
05833       }
05834 
05835       if (threshold > len) {
05836          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
05837       }
05838 
05839       if (ch->jb) {
05840          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
05841          misdn_jb_destroy(ch->jb);
05842          ch->jb = NULL;
05843       }
05844 
05845       ch->jb = misdn_jb_init(len, threshold);
05846 
05847       if (!ch->jb) {
05848          bc->nojitter = 1;
05849       }
05850    }
05851 }

void debug_numtype ( int  port,
int  numtype,
char *  type 
)

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

05855 {
05856    switch (numtype) {
05857    case NUMTYPE_UNKNOWN:
05858       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
05859       break;
05860    case NUMTYPE_INTERNATIONAL:
05861       chan_misdn_log(2, port, " --> %s: International\n", type);
05862       break;
05863    case NUMTYPE_NATIONAL:
05864       chan_misdn_log(2, port, " --> %s: National\n", type);
05865       break;
05866    case NUMTYPE_NETWORK_SPECIFIC:
05867       chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
05868       break;
05869    case NUMTYPE_SUBSCRIBER:
05870       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
05871       break;
05872    case NUMTYPE_ABBREVIATED:
05873       chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
05874       break;
05875       /* Maybe we should cut off the prefix if present ? */
05876    default:
05877       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
05878       break;
05879    }
05880 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

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

07709 {
07710    struct ast_channel *ast = cl->ast;
07711    int nd = 0;
07712 
07713    if (!ast) {
07714       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
07715       return -1;
07716    }
07717 
07718    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
07719 
07720    if (nd) {
07721       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
07722       return 0;
07723    }
07724 
07725    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
07726 
07727    cl->ts = ast_get_indication_tone(ast_channel_zone(ast), "dial");
07728 
07729    if (cl->ts) {
07730       cl->notxtone = 0;
07731       cl->norxtone = 0;
07732       /* This prods us in misdn_write */
07733       ast_playtones_start(ast, 0, cl->ts->data, 0);
07734    }
07735 
07736    return 0;
07737 }

static void do_immediate_setup ( struct misdn_bchannel bc,
struct chan_list ch,
struct ast_channel ast 
) [static]

Definition at line 8660 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_strdupa, 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, NULL, 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().

08661 {
08662    char *predial;
08663    struct ast_frame fr;
08664 
08665    predial = ast_strdupa(ast_channel_exten(ast));
08666 
08667    ch->state = MISDN_DIALING;
08668 
08669    if (!ch->noautorespond_on_setup) {
08670       if (bc->nt) {
08671          misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08672       } else {
08673          if (misdn_lib_is_ptp(bc->port)) {
08674             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08675          } else {
08676             misdn_lib_send_event(bc, EVENT_PROCEEDING);
08677          }
08678       }
08679    } else {
08680       ch->state = MISDN_INCOMING_SETUP;
08681    }
08682 
08683    chan_misdn_log(1, bc->port,
08684       "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
08685       ast_channel_context(ast),
08686       ast_channel_exten(ast),
08687       (ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
08688          ? ast_channel_caller(ast)->id.name.str : "",
08689       (ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
08690          ? ast_channel_caller(ast)->id.number.str : "");
08691 
08692    ast_channel_exten_set(ast, "s");
08693 
08694    if (!ast_canmatch_extension(ast, ast_channel_context(ast), ast_channel_exten(ast), 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
08695       ast = NULL;
08696       bc->out_cause = AST_CAUSE_UNALLOCATED;
08697       hangup_chan(ch, bc);
08698       hanguptone_indicate(ch);
08699 
08700       misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
08701    }
08702 
08703 
08704    while (!ast_strlen_zero(predial)) {
08705       fr.frametype = AST_FRAME_DTMF;
08706       fr.subclass.integer = *predial;
08707       fr.src = NULL;
08708       fr.data.ptr = NULL;
08709       fr.datalen = 0;
08710       fr.samples = 0;
08711       fr.mallocd = 0;
08712       fr.offset = 0;
08713       fr.delivery = ast_tv(0,0);
08714 
08715       if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
08716          ast_queue_frame(ch->ast, &fr);
08717       }
08718       predial++;
08719    }
08720 }

static void export_aoc_vars ( int  originator,
struct ast_channel ast,
struct misdn_bchannel bc 
) [static]

Definition at line 3459 of file chan_misdn.c.

References misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, misdn_bchannel::AOCDtype, ast_channel_bridge_peer(), ast_channel_cleanup, ast_channel_ref, buf, misdn_bchannel::chargingUnit, misdn_bchannel::currency, NULL, ORG_AST, pbx_builtin_setvar_helper(), and RAII_VAR.

Referenced by cb_events(), and misdn_facility_ie_handler().

03460 {
03461    RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
03462    char buf[128];
03463 
03464    if (!bc->AOCD_need_export || !ast) {
03465       return;
03466    }
03467 
03468    if (originator == ORG_AST) {
03469       chan = ast_channel_bridge_peer(ast);
03470       if (!chan) {
03471          return;
03472       }
03473    } else {
03474       chan = ast_channel_ref(ast);
03475    }
03476 
03477    switch (bc->AOCDtype) {
03478    case Fac_AOCDCurrency:
03479       pbx_builtin_setvar_helper(chan, "AOCD_Type", "currency");
03480       if (bc->AOCD.currency.chargeNotAvailable) {
03481          pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "no");
03482       } else {
03483          pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "yes");
03484          if (bc->AOCD.currency.freeOfCharge) {
03485             pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "yes");
03486          } else {
03487             pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "no");
03488             if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
03489                pbx_builtin_setvar_helper(chan, "AOCD_Amount", buf);
03490                if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) {
03491                   pbx_builtin_setvar_helper(chan, "AOCD_BillingId", buf);
03492                }
03493             }
03494          }
03495       }
03496       break;
03497    case Fac_AOCDChargingUnit:
03498       pbx_builtin_setvar_helper(chan, "AOCD_Type", "charging_unit");
03499       if (bc->AOCD.chargingUnit.chargeNotAvailable) {
03500          pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "no");
03501       } else {
03502          pbx_builtin_setvar_helper(chan, "AOCD_ChargeAvailable", "yes");
03503          if (bc->AOCD.chargingUnit.freeOfCharge) {
03504             pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "yes");
03505          } else {
03506             pbx_builtin_setvar_helper(chan, "AOCD_FreeOfCharge", "no");
03507             if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
03508                pbx_builtin_setvar_helper(chan, "AOCD_RecordedUnits", buf);
03509                if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) {
03510                   pbx_builtin_setvar_helper(chan, "AOCD_BillingId", buf);
03511                }
03512             }
03513          }
03514       }
03515       break;
03516    default:
03517       break;
03518    }
03519 
03520    bc->AOCD_need_export = 0;
03521 }

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

08813 {
08814    char tmp[32];
08815 
08816    /*
08817     * The only use for MISDN_PID is if there is a problem and you
08818     * have to use the "misdn restart pid" CLI command.  Otherwise,
08819     * the pid is not used by anyone.  The internal use of MISDN_PID
08820     * has been deleted.
08821     */
08822    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
08823    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
08824    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
08825 
08826    if (bc->sending_complete) {
08827       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
08828       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
08829    }
08830 
08831    if (bc->urate) {
08832       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
08833       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
08834    }
08835 
08836    if (bc->uulen) {
08837       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
08838    }
08839 
08840    if (!ast_strlen_zero(bc->keypad)) {
08841       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
08842    }
08843 }

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 8260 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, NULL, misdn_party_id::number, misdn_party_dialing::number, and misdn_bchannel::port.

Referenced by cb_events(), and chan_misdn_jb_empty().

08261 {
08262    struct chan_list *help;
08263 
08264    ast_mutex_lock(&cl_te_lock);
08265    for (help = cl_te; help; help = help->next) {
08266       if (help->bc == bc) {
08267          chan_list_ref(help, "Found chan_list by bc");
08268          ast_mutex_unlock(&cl_te_lock);
08269          return help;
08270       }
08271    }
08272    ast_mutex_unlock(&cl_te_lock);
08273 
08274    chan_misdn_log(6, bc->port,
08275       "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08276       bc->dialed.number,
08277       bc->caller.name,
08278       bc->caller.number);
08279 
08280    return NULL;
08281 }

static struct chan_list* find_hold_active_call ( struct misdn_bchannel bc  )  [static, read]

Definition at line 8352 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, NULL, misdn_bchannel::port, chan_list::state, and hold_info::state.

Referenced by cb_events().

08353 {
08354    struct chan_list *list;
08355 
08356    ast_mutex_lock(&cl_te_lock);
08357    for (list = cl_te; list; list = list->next) {
08358       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
08359          && list->ast) {
08360          switch (list->state) {
08361          case MISDN_PROCEEDING:
08362          case MISDN_PROGRESS:
08363          case MISDN_ALERTING:
08364          case MISDN_CONNECTED:
08365             chan_list_ref(list, "Found chan_list hold active call");
08366             ast_mutex_unlock(&cl_te_lock);
08367             return list;
08368          default:
08369             break;
08370          }
08371       }
08372    }
08373    ast_mutex_unlock(&cl_te_lock);
08374    return NULL;
08375 }

static struct chan_list* find_hold_call ( struct misdn_bchannel bc  )  [static, read]

Returns a reference to the found chan_list.

Definition at line 8284 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, NULL, misdn_party_id::number, misdn_party_dialing::number, hold_info::port, misdn_bchannel::port, misdn_bchannel::pri, and hold_info::state.

Referenced by cb_events().

08285 {
08286    struct chan_list *help;
08287 
08288    if (bc->pri) {
08289       return NULL;
08290    }
08291 
08292    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d dialed:%s caller:\"%s\" <%s>\n",
08293       bc->channel,
08294       bc->dialed.number,
08295       bc->caller.name,
08296       bc->caller.number);
08297    ast_mutex_lock(&cl_te_lock);
08298    for (help = cl_te; help; help = help->next) {
08299       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
08300       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
08301          chan_list_ref(help, "Found chan_list hold call");
08302          ast_mutex_unlock(&cl_te_lock);
08303          return help;
08304       }
08305    }
08306    ast_mutex_unlock(&cl_te_lock);
08307    chan_misdn_log(6, bc->port,
08308       "$$$ find_hold_call: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08309       bc->dialed.number,
08310       bc->caller.name,
08311       bc->caller.number);
08312 
08313    return NULL;
08314 }

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 8318 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, NULL, and hold_info::state.

Referenced by cb_events().

08319 {
08320    struct chan_list *help;
08321 
08322    ast_mutex_lock(&cl_te_lock);
08323    for (help = cl_te; help; help = help->next) {
08324       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
08325          chan_list_ref(help, "Found chan_list hold call l3");
08326          ast_mutex_unlock(&cl_te_lock);
08327          return help;
08328       }
08329    }
08330    ast_mutex_unlock(&cl_te_lock);
08331 
08332    return NULL;
08333 }

static void free_robin_list ( void   )  [static]

Definition at line 630 of file chan_misdn.c.

References ast_free, robin_list::group, robin_list::next, and NULL.

Referenced by reload_config(), and unload_module().

00631 {
00632    struct robin_list *r;
00633    struct robin_list *next;
00634 
00635    for (r = robin, robin = NULL; r; r = next) {
00636       next = r->next;
00637       ast_free(r->group);
00638       ast_free(r);
00639    }
00640 }

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 787 of file chan_misdn.c.

References chan_list::ast, ast_channel_name(), ast_mutex_lock, ast_mutex_unlock, chan_list_ref, chan_list::next, and NULL.

Referenced by handle_cli_misdn_send_digit(), handle_cli_misdn_send_display(), handle_cli_misdn_send_facility(), and handle_cli_misdn_toggle_echocancel().

00788 {
00789    struct chan_list *tmp;
00790 
00791    ast_mutex_lock(&cl_te_lock);
00792    for (tmp = cl_te; tmp; tmp = tmp->next) {
00793       if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
00794          chan_list_ref(tmp, "Found chan_list by ast name");
00795          ast_mutex_unlock(&cl_te_lock);
00796          return tmp;
00797       }
00798    }
00799    ast_mutex_unlock(&cl_te_lock);
00800 
00801    return NULL;
00802 }

static struct robin_list* get_robin_position ( char *  group  )  [static, read]

Definition at line 642 of file chan_misdn.c.

References ast_calloc, ast_free, ast_strdup, robin_list::group, robin_list::next, NULL, and robin_list::prev.

Referenced by misdn_request().

00643 {
00644    struct robin_list *new;
00645    struct robin_list *iter = robin;
00646    for (; iter; iter = iter->next) {
00647       if (!strcasecmp(iter->group, group)) {
00648          return iter;
00649       }
00650    }
00651    new = ast_calloc(1, sizeof(*new));
00652    if (!new) {
00653       return NULL;
00654    }
00655    new->group = ast_strdup(group);
00656    if (!new->group) {
00657       ast_free(new);
00658       return NULL;
00659    }
00660    new->channel = 1;
00661    if (robin) {
00662       new->next = robin;
00663       robin->prev = new;
00664    }
00665    robin = new;
00666    return robin;
00667 }

static char* handle_cli_misdn_port_block ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3831 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(), NULL, and ast_cli_entry::usage.

03832 {
03833    switch (cmd) {
03834    case CLI_INIT:
03835       e->command = "misdn port block";
03836       e->usage =
03837          "Usage: misdn port block <port>\n"
03838          "       Block the specified port by <port>.\n";
03839       return NULL;
03840    case CLI_GENERATE:
03841       return NULL;
03842    }
03843 
03844    if (a->argc != 4) {
03845       return CLI_SHOWUSAGE;
03846    }
03847 
03848    misdn_lib_port_block(atoi(a->argv[3]));
03849 
03850    return CLI_SUCCESS;
03851 }

static char* handle_cli_misdn_port_down ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3941 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(), NULL, and ast_cli_entry::usage.

03942 {
03943    switch (cmd) {
03944    case CLI_INIT:
03945       e->command = "misdn port down";
03946       e->usage =
03947          "Usage: misdn port down <port>\n"
03948          "       Try to deactivate the L1 on the given port.\n";
03949       return NULL;
03950    case CLI_GENERATE:
03951       return NULL;
03952    }
03953 
03954    if (a->argc != 4) {
03955       return CLI_SHOWUSAGE;
03956    }
03957 
03958    misdn_lib_get_port_down(atoi(a->argv[3]));
03959 
03960    return CLI_SUCCESS;
03961 }

static char* handle_cli_misdn_port_unblock ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3853 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(), NULL, and ast_cli_entry::usage.

03854 {
03855    switch (cmd) {
03856    case CLI_INIT:
03857       e->command = "misdn port unblock";
03858       e->usage =
03859          "Usage: misdn port unblock <port>\n"
03860          "       Unblock the port specified by <port>.\n";
03861       return NULL;
03862    case CLI_GENERATE:
03863       return NULL;
03864    }
03865 
03866    if (a->argc != 4) {
03867       return CLI_SHOWUSAGE;
03868    }
03869 
03870    misdn_lib_port_unblock(atoi(a->argv[3]));
03871 
03872    return CLI_SUCCESS;
03873 }

static char* handle_cli_misdn_port_up ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3919 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(), NULL, and ast_cli_entry::usage.

03920 {
03921    switch (cmd) {
03922    case CLI_INIT:
03923       e->command = "misdn port up";
03924       e->usage =
03925          "Usage: misdn port up <port>\n"
03926          "       Try to establish L1 on the given port.\n";
03927       return NULL;
03928    case CLI_GENERATE:
03929       return NULL;
03930    }
03931 
03932    if (a->argc != 4) {
03933       return CLI_SHOWUSAGE;
03934    }
03935 
03936    misdn_lib_get_port_up(atoi(a->argv[3]));
03937 
03938    return CLI_SUCCESS;
03939 }

static char* handle_cli_misdn_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4145 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, NULL, reload_config(), and ast_cli_entry::usage.

04146 {
04147    switch (cmd) {
04148    case CLI_INIT:
04149       e->command = "misdn reload";
04150       e->usage =
04151          "Usage: misdn reload\n"
04152          "       Reload internal mISDN config, read from the config\n"
04153          "       file.\n";
04154       return NULL;
04155    case CLI_GENERATE:
04156       return NULL;
04157    }
04158 
04159    if (a->argc != 2) {
04160       return CLI_SHOWUSAGE;
04161    }
04162 
04163    ast_cli(a->fd, "Reloading mISDN configuration\n");
04164    reload_config();
04165    return CLI_SUCCESS;
04166 }

static char* handle_cli_misdn_restart_pid ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3897 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(), NULL, and ast_cli_entry::usage.

03898 {
03899    switch (cmd) {
03900    case CLI_INIT:
03901       e->command = "misdn restart pid";
03902       e->usage =
03903          "Usage: misdn restart pid <pid>\n"
03904          "       Restart the given pid\n";
03905       return NULL;
03906    case CLI_GENERATE:
03907       return NULL;
03908    }
03909 
03910    if (a->argc != 4) {
03911       return CLI_SHOWUSAGE;
03912    }
03913 
03914    misdn_lib_pid_restart(atoi(a->argv[3]));
03915 
03916    return CLI_SUCCESS;
03917 }

static char* handle_cli_misdn_restart_port ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3875 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(), NULL, and ast_cli_entry::usage.

03876 {
03877    switch (cmd) {
03878    case CLI_INIT:
03879       e->command = "misdn restart port";
03880       e->usage =
03881          "Usage: misdn restart port <port>\n"
03882          "       Restart the given port.\n";
03883       return NULL;
03884    case CLI_GENERATE:
03885       return NULL;
03886    }
03887 
03888    if (a->argc != 4) {
03889       return CLI_SHOWUSAGE;
03890    }
03891 
03892    misdn_lib_port_restart(atoi(a->argv[3]));
03893 
03894    return CLI_SUCCESS;
03895 }

static char* handle_cli_misdn_send_digit ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5510 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(), NULL, send_digit_to_chan(), and ast_cli_entry::usage.

05511 {
05512    const char *channame;
05513    const char *msg;
05514    struct chan_list *tmp;
05515    int i, msglen;
05516 
05517    switch (cmd) {
05518    case CLI_INIT:
05519       e->command = "misdn send digit";
05520       e->usage =
05521          "Usage: misdn send digit <channel> \"<msg>\" \n"
05522          "       Send <digit> to <channel> as DTMF Tone\n"
05523          "       when channel is a mISDN channel\n";
05524       return NULL;
05525    case CLI_GENERATE:
05526       return complete_ch(a);
05527    }
05528 
05529    if (a->argc != 5) {
05530       return CLI_SHOWUSAGE;
05531    }
05532 
05533    channame = a->argv[3];
05534    msg = a->argv[4];
05535    msglen = strlen(msg);
05536 
05537    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
05538 
05539    tmp = get_chan_by_ast_name(channame);
05540    if (!tmp) {
05541       ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
05542       return CLI_SUCCESS;
05543    }
05544 #if 1
05545    for (i = 0; i < msglen; i++) {
05546       if (!tmp->ast) {
05547          break;
05548       }
05549       ast_cli(a->fd, "Sending: %c\n", msg[i]);
05550       send_digit_to_chan(tmp, msg[i]);
05551       /* res = ast_safe_sleep(tmp->ast, 250); */
05552       usleep(250000);
05553       /* res = ast_waitfor(tmp->ast,100); */
05554    }
05555 #else
05556    if (tmp->ast) {
05557       ast_dtmf_stream(tmp->ast, NULL, msg, 250);
05558    }
05559 #endif
05560    chan_list_unref(tmp, "Digit(s) sent");
05561 
05562    return CLI_SUCCESS;
05563 }

static char* handle_cli_misdn_send_display ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5612 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(), NULL, and ast_cli_entry::usage.

05613 {
05614    const char *channame;
05615    const char *msg;
05616    struct chan_list *tmp;
05617 
05618    switch (cmd) {
05619    case CLI_INIT:
05620       e->command = "misdn send display";
05621       e->usage =
05622          "Usage: misdn send display <channel> \"<msg>\" \n"
05623          "       Send <msg> to <channel> as Display Message\n"
05624          "       when channel is a mISDN channel\n";
05625       return NULL;
05626    case CLI_GENERATE:
05627       return complete_ch(a);
05628    }
05629 
05630    if (a->argc != 5) {
05631       return CLI_SHOWUSAGE;
05632    }
05633 
05634    channame = a->argv[3];
05635    msg = a->argv[4];
05636 
05637    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
05638 
05639    tmp = get_chan_by_ast_name(channame);
05640    if (tmp && tmp->bc) {
05641       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
05642       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
05643       chan_list_unref(tmp, "Done sending display");
05644    } else {
05645       if (tmp) {
05646          chan_list_unref(tmp, "Display failed");
05647       }
05648       ast_cli(a->fd, "No such channel %s\n", channame);
05649       return CLI_SUCCESS;
05650    }
05651 
05652    return CLI_SUCCESS;
05653 }

static char* handle_cli_misdn_send_facility ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5184 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(), 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(), NULL, print_facility(), and ast_cli_entry::usage.

05185 {
05186    const char *channame;
05187    const char *nr;
05188    struct chan_list *tmp;
05189    int port;
05190    const char *served_nr;
05191    struct misdn_bchannel dummy, *bc=&dummy;
05192    unsigned max_len;
05193 
05194    switch (cmd) {
05195    case CLI_INIT:
05196       e->command = "misdn send facility";
05197       e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
05198       "\t type is one of:\n"
05199       "\t - calldeflect\n"
05200 #if defined(AST_MISDN_ENHANCEMENTS)
05201       "\t - callrerouting\n"
05202 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
05203       "\t - CFActivate\n"
05204       "\t - CFDeactivate\n";
05205 
05206       return NULL;
05207    case CLI_GENERATE:
05208       return complete_ch(a);
05209    }
05210 
05211    if (a->argc < 5) {
05212       return CLI_SHOWUSAGE;
05213    }
05214 
05215    if (strstr(a->argv[3], "calldeflect")) {
05216       if (a->argc < 6) {
05217          ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
05218          return 0;
05219       }
05220       channame = a->argv[4];
05221       nr = a->argv[5];
05222 
05223       ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
05224       tmp = get_chan_by_ast_name(channame);
05225       if (!tmp) {
05226          ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
05227          return 0;
05228       }
05229       ao2_lock(tmp);
05230 
05231 #if defined(AST_MISDN_ENHANCEMENTS)
05232       max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
05233       if (max_len < strlen(nr)) {
05234          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05235             nr, channame, max_len);
05236          ao2_unlock(tmp);
05237          chan_list_unref(tmp, "Number too long");
05238          return 0;
05239       }
05240       tmp->bc->fac_out.Function = Fac_CallDeflection;
05241       tmp->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
05242       tmp->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
05243       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
05244       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
05245       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
05246       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(nr);
05247       strcpy((char *) tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, nr);
05248       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
05249 
05250 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
05251 
05252       max_len = sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
05253       if (max_len < strlen(nr)) {
05254          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05255             nr, channame, max_len);
05256          ao2_unlock(tmp);
05257          chan_list_unref(tmp, "Number too long");
05258          return 0;
05259       }
05260       tmp->bc->fac_out.Function = Fac_CD;
05261       tmp->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
05262       //tmp->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
05263       strcpy((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr);
05264 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
05265 
05266       /* Send message */
05267       print_facility(&tmp->bc->fac_out, tmp->bc);
05268       ao2_unlock(tmp);
05269       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05270       chan_list_unref(tmp, "Send facility complete");
05271 #if defined(AST_MISDN_ENHANCEMENTS)
05272    } else if (strstr(a->argv[3], "callrerouteing") || strstr(a->argv[3], "callrerouting")) {
05273       if (a->argc < 6) {
05274          ast_verbose("callrerouting requires 1 arg: ToNumber\n\n");
05275          return 0;
05276       }
05277       channame = a->argv[4];
05278       nr = a->argv[5];
05279 
05280       ast_verbose("Sending Callrerouting (%s) to %s\n", nr, channame);
05281       tmp = get_chan_by_ast_name(channame);
05282       if (!tmp) {
05283          ast_verbose("Sending Call Rerouting with nr %s to %s failed: Channel does not exist.\n", nr, channame);
05284          return 0;
05285       }
05286       ao2_lock(tmp);
05287 
05288       max_len = sizeof(tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
05289       if (max_len < strlen(nr)) {
05290          ast_verbose("Sending Call Rerouting with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05291             nr, channame, max_len);
05292          ao2_unlock(tmp);
05293          chan_list_unref(tmp, "Number too long");
05294          return 0;
05295       }
05296       tmp->bc->fac_out.Function = Fac_CallRerouteing;
05297       tmp->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
05298       tmp->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
05299 
05300       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
05301       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
05302 
05303       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
05304       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(nr);
05305       strcpy((char *) tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, nr);
05306       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
05307 
05308       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
05309 
05310       /* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
05311       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
05312       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
05313       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
05314       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
05315       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
05316       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
05317       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
05318 
05319       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
05320       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
05321 
05322       /* Send message */
05323       print_facility(&tmp->bc->fac_out, tmp->bc);
05324       ao2_unlock(tmp);
05325       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05326       chan_list_unref(tmp, "Send facility complete");
05327 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
05328    } else if (strstr(a->argv[3], "CFActivate")) {
05329       if (a->argc < 7) {
05330          ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
05331          return 0;
05332       }
05333       port = atoi(a->argv[4]);
05334       served_nr = a->argv[5];
05335       nr = a->argv[6];
05336 
05337       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05338 
05339       ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
05340 
05341 #if defined(AST_MISDN_ENHANCEMENTS)
05342       bc->fac_out.Function = Fac_ActivationDiversion;
05343       bc->fac_out.u.ActivationDiversion.InvokeID = ++misdn_invoke_id;
05344       bc->fac_out.u.ActivationDiversion.ComponentType = FacComponent_Invoke;
05345       bc->fac_out.u.ActivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
05346       bc->fac_out.u.ActivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
05347       ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number,
05348          served_nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number));
05349       bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
05350          strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number);
05351       bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
05352       ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number,
05353          nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number));
05354       bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber =
05355          strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number);
05356       bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 0;/* unknown */
05357       bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Subaddress.Length = 0;
05358 
05359 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
05360 
05361       bc->fac_out.Function = Fac_CFActivate;
05362       bc->fac_out.u.CFActivate.BasicService = 0; /* All Services */
05363       bc->fac_out.u.CFActivate.Procedure = 0; /* Unconditional */
05364       ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
05365       ast_copy_string((char *) bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
05366 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
05367 
05368       /* Send message */
05369       print_facility(&bc->fac_out, bc);
05370       misdn_lib_send_event(bc, EVENT_FACILITY);
05371    } else if (strstr(a->argv[3], "CFDeactivate")) {
05372       if (a->argc < 6) {
05373          ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
05374          return 0;
05375       }
05376       port = atoi(a->argv[4]);
05377       served_nr = a->argv[5];
05378 
05379       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05380       ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
05381 
05382 #if defined(AST_MISDN_ENHANCEMENTS)
05383       bc->fac_out.Function = Fac_DeactivationDiversion;
05384       bc->fac_out.u.DeactivationDiversion.InvokeID = ++misdn_invoke_id;
05385       bc->fac_out.u.DeactivationDiversion.ComponentType = FacComponent_Invoke;
05386       bc->fac_out.u.DeactivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
05387       bc->fac_out.u.DeactivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
05388       ast_copy_string((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number,
05389          served_nr, sizeof(bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number));
05390       bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
05391          strlen((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number);
05392       bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
05393 
05394 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
05395 
05396       bc->fac_out.Function = Fac_CFDeactivate;
05397       bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
05398       bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
05399       ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
05400 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
05401 
05402       /* Send message */
05403       print_facility(&bc->fac_out, bc);
05404       misdn_lib_send_event(bc, EVENT_FACILITY);
05405 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
05406    } else if (strstr(a->argv[3], "test")) {
05407       int msg_number;
05408 
05409       if (a->argc < 5) {
05410          ast_verbose("test (<port> [<msg#>]) | (<channel-name> <msg#>)\n\n");
05411          return 0;
05412       }
05413       port = atoi(a->argv[4]);
05414 
05415       channame = a->argv[4];
05416       tmp = get_chan_by_ast_name(channame);
05417       if (tmp) {
05418          /* We are going to send this FACILITY message out on an existing connection */
05419          msg_number = atoi(a->argv[5]);
05420          if (msg_number < ARRAY_LEN(Fac_Msgs)) {
05421             ao2_lock(tmp);
05422             tmp->bc->fac_out = Fac_Msgs[msg_number];
05423 
05424             /* Send message */
05425             print_facility(&tmp->bc->fac_out, tmp->bc);
05426             ao2_unlock(tmp);
05427             misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05428          } else {
05429             ast_verbose("test <channel-name> <msg#>\n\n");
05430          }
05431          chan_list_unref(tmp, "Facility test done");
05432       } else if (a->argc < 6) {
05433          for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) {
05434             misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05435             bc->fac_out = Fac_Msgs[msg_number];
05436 
05437             /* Send message */
05438             print_facility(&bc->fac_out, bc);
05439             misdn_lib_send_event(bc, EVENT_FACILITY);
05440             sleep(1);
05441          }
05442       } else {
05443          msg_number = atoi(a->argv[5]);
05444          if (msg_number < ARRAY_LEN(Fac_Msgs)) {
05445             misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05446             bc->fac_out = Fac_Msgs[msg_number];
05447 
05448             /* Send message */
05449             print_facility(&bc->fac_out, bc);
05450             misdn_lib_send_event(bc, EVENT_FACILITY);
05451          } else {
05452             ast_verbose("test <port> [<msg#>]\n\n");
05453          }
05454       }
05455    } else if (strstr(a->argv[3], "register")) {
05456       if (a->argc < 5) {
05457          ast_verbose("register <port>\n\n");
05458          return 0;
05459       }
05460       port = atoi(a->argv[4]);
05461 
05462       bc = misdn_lib_get_register_bc(port);
05463       if (!bc) {
05464          ast_verbose("Could not allocate REGISTER bc struct\n\n");
05465          return 0;
05466       }
05467       bc->fac_out = Fac_Msgs[45];
05468 
05469       /* Send message */
05470       print_facility(&bc->fac_out, bc);
05471       misdn_lib_send_event(bc, EVENT_REGISTER);
05472 #endif   /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
05473    }
05474 
05475    return CLI_SUCCESS;
05476 }

static char* handle_cli_misdn_send_restart ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5478 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_send_restart(), NULL, and ast_cli_entry::usage.

05479 {
05480    int port;
05481    int channel;
05482 
05483    switch (cmd) {
05484    case CLI_INIT:
05485       e->command = "misdn send restart";
05486       e->usage =
05487          "Usage: misdn send restart [port [channel]]\n"
05488          "       Send a restart for every bchannel on the given port.\n";
05489       return NULL;
05490    case CLI_GENERATE:
05491       return NULL;
05492    }
05493 
05494    if (a->argc < 4 || a->argc > 5) {
05495       return CLI_SHOWUSAGE;
05496    }
05497 
05498    port = atoi(a->argv[3]);
05499 
05500    if (a->argc == 5) {
05501       channel = atoi(a->argv[4]);
05502       misdn_lib_send_restart(port, channel);
05503    } else {
05504       misdn_lib_send_restart(port, -1);
05505    }
05506 
05507    return CLI_SUCCESS;
05508 }

static char* handle_cli_misdn_set_crypt_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3808 of file chan_misdn.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

03809 {
03810    switch (cmd) {
03811    case CLI_INIT:
03812       e->command = "misdn set crypt debug";
03813       e->usage =
03814          "Usage: misdn set crypt debug <level>\n"
03815          "       Set the crypt debug level of the mISDN channel. Level\n"
03816          "       must be 1 or 2.\n";
03817       return NULL;
03818    case CLI_GENERATE:
03819       return NULL;
03820    }
03821 
03822    if (a->argc != 5) {
03823       return CLI_SHOWUSAGE;
03824    }
03825 
03826    /* XXX Is this supposed to not do anything? XXX */
03827 
03828    return CLI_SUCCESS;
03829 }

static char* handle_cli_misdn_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3721 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, NULL, and ast_cli_entry::usage.

03722 {
03723    int level;
03724 
03725    switch (cmd) {
03726    case CLI_INIT:
03727       e->command = "misdn set debug [on|off]";
03728       e->usage =
03729          "Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
03730          "       Set the debug level of the mISDN channel.\n";
03731       return NULL;
03732    case CLI_GENERATE:
03733       return complete_debug_port(a);
03734    }
03735 
03736    if (a->argc < 4 || a->argc > 7) {
03737       return CLI_SHOWUSAGE;
03738    }
03739 
03740    if (!strcasecmp(a->argv[3], "on")) {
03741       level = 1;
03742    } else if (!strcasecmp(a->argv[3], "off")) {
03743       level = 0;
03744    } else if (isdigit(a->argv[3][0])) {
03745       level = atoi(a->argv[3]);
03746    } else {
03747       return CLI_SHOWUSAGE;
03748    }
03749 
03750    switch (a->argc) {
03751    case 4:
03752    case 5:
03753       {
03754          int i;
03755          int only = 0;
03756          if (a->argc == 5) {
03757             if (strncasecmp(a->argv[4], "only", strlen(a->argv[4]))) {
03758                return CLI_SHOWUSAGE;
03759             } else {
03760                only = 1;
03761             }
03762          }
03763 
03764          for (i = 0; i <= max_ports; i++) {
03765             misdn_debug[i] = level;
03766             misdn_debug_only[i] = only;
03767          }
03768          ast_cli(a->fd, "changing debug level for all ports to %d%s\n", misdn_debug[0], only ? " (only)" : "");
03769       }
03770       break;
03771    case 6:
03772    case 7:
03773       {
03774          int port;
03775          if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
03776             return CLI_SHOWUSAGE;
03777          port = atoi(a->argv[5]);
03778          if (port <= 0 || port > max_ports) {
03779             switch (max_ports) {
03780             case 0:
03781                ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
03782                break;
03783             case 1:
03784                ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
03785                break;
03786             default:
03787                ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
03788             }
03789             return 0;
03790          }
03791          if (a->argc == 7) {
03792             if (strncasecmp(a->argv[6], "only", strlen(a->argv[6]))) {
03793                return CLI_SHOWUSAGE;
03794             } else {
03795                misdn_debug_only[port] = 1;
03796             }
03797          } else {
03798             misdn_debug_only[port] = 0;
03799          }
03800          misdn_debug[port] = level;
03801          ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port] ? " (only)" : "", port);
03802       }
03803    }
03804 
03805    return CLI_SUCCESS;
03806 }

static char* handle_cli_misdn_set_tics ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4340 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, NULL, and ast_cli_entry::usage.

04341 {
04342    switch (cmd) {
04343    case CLI_INIT:
04344       e->command = "misdn set tics";
04345       e->usage =
04346          "Usage: misdn set tics <value>\n";
04347       return NULL;
04348    case CLI_GENERATE:
04349       return NULL;
04350    }
04351 
04352    if (a->argc != 4) {
04353       return CLI_SHOWUSAGE;
04354    }
04355 
04356    /* XXX Wow, this does... a whole lot of nothing... XXX */
04357    MAXTICS = atoi(a->argv[3]);
04358 
04359    return CLI_SUCCESS;
04360 }

static char* handle_cli_misdn_show_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4304 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, NULL, print_bc_info(), and ast_cli_entry::usage.

04305 {
04306    struct chan_list *help;
04307 
04308    switch (cmd) {
04309    case CLI_INIT:
04310       e->command = "misdn show channel";
04311       e->usage =
04312          "Usage: misdn show channel <channel>\n"
04313          "       Show an internal mISDN channel\n.";
04314       return NULL;
04315    case CLI_GENERATE:
04316       return complete_ch(a);
04317    }
04318 
04319    if (a->argc != 4) {
04320       return CLI_SHOWUSAGE;
04321    }
04322 
04323    ast_mutex_lock(&cl_te_lock);
04324    for (help = cl_te; help; help = help->next) {
04325       struct misdn_bchannel *bc = help->bc;
04326       struct ast_channel *ast = help->ast;
04327 
04328       if (bc && ast) {
04329          if (!strcasecmp(ast_channel_name(ast), a->argv[3])) {
04330             print_bc_info(a->fd, help, bc);
04331             break;
04332          }
04333       }
04334    }
04335    ast_mutex_unlock(&cl_te_lock);
04336 
04337    return CLI_SUCCESS;
04338 }

static char* handle_cli_misdn_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4231 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, NULL, misdn_bchannel::pid, hold_info::port, print_bc_info(), S_COR, hold_info::state, and ast_cli_entry::usage.

04232 {
04233    struct chan_list *help;
04234 
04235    switch (cmd) {
04236    case CLI_INIT:
04237       e->command = "misdn show channels";
04238       e->usage =
04239          "Usage: misdn show channels\n"
04240          "       Show the internal mISDN channel list\n";
04241       return NULL;
04242    case CLI_GENERATE:
04243       return NULL;
04244    }
04245 
04246    if (a->argc != 3) {
04247       return CLI_SHOWUSAGE;
04248    }
04249 
04250    ast_cli(a->fd, "Channel List: %p\n", cl_te);
04251 
04252    /*
04253     * Walking the list and dumping the channel information could
04254     * take awhile.  With the list locked for the duration, the
04255     * channel driver cannot process signaling messages.  However,
04256     * since this is a CLI command it should not be run very often.
04257     */
04258    ast_mutex_lock(&cl_te_lock);
04259    for (help = cl_te; help; help = help->next) {
04260       struct misdn_bchannel *bc = help->bc;
04261       struct ast_channel *ast = help->ast;
04262       if (!ast) {
04263          if (!bc) {
04264             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
04265             continue;
04266          }
04267          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
04268       }
04269 
04270       if (misdn_debug[0] > 2) {
04271          ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
04272       }
04273       if (bc) {
04274          print_bc_info(a->fd, help, bc);
04275       } else {
04276          if (help->hold.state != MISDN_HOLD_IDLE) {
04277             ast_cli(a->fd, "ITS A HELD CALL BC:\n");
04278             ast_cli(a->fd, " --> l3_id: %x\n"
04279                " --> dialed:%s\n"
04280                " --> caller:\"%s\" <%s>\n"
04281                " --> hold_port: %d\n"
04282                " --> hold_channel: %d\n",
04283                help->l3id,
04284                ast_channel_exten(ast),
04285                S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, ""),
04286                S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""),
04287                help->hold.port,
04288                help->hold.channel
04289                );
04290          } else {
04291             ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n",
04292                ast_channel_exten(ast),
04293                S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""));
04294          }
04295       }
04296    }
04297    ast_mutex_unlock(&cl_te_lock);
04298 
04299    misdn_dump_chanlist();
04300 
04301    return CLI_SUCCESS;
04302 }

static char* handle_cli_misdn_show_config ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3988 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, NULL, show_config_description(), and ast_cli_entry::usage.

03989 {
03990    char buffer[BUFFERSIZE];
03991    enum misdn_cfg_elements elem;
03992    int linebreak;
03993    int onlyport = -1;
03994    int ok = 0;
03995 
03996    switch (cmd) {
03997    case CLI_INIT:
03998       e->command = "misdn show config";
03999       e->usage =
04000          "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
04001          "       Use 0 for <port> to only print the general config.\n";
04002       return NULL;
04003    case CLI_GENERATE:
04004       return complete_show_config(a);
04005    }
04006 
04007    if (a->argc >= 4) {
04008       if (!strcmp(a->argv[3], "description")) {
04009          if (a->argc == 5) {
04010             enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
04011             if (elem == MISDN_CFG_FIRST) {
04012                ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
04013             } else {
04014                show_config_description(a->fd, elem);
04015             }
04016             return CLI_SUCCESS;
04017          }
04018          return CLI_SHOWUSAGE;
04019       } else if (!strcmp(a->argv[3], "descriptions")) {
04020          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
04021             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
04022                show_config_description(a->fd, elem);
04023                ast_cli(a->fd, "\n");
04024             }
04025             ok = 1;
04026          }
04027          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
04028             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
04029                show_config_description(a->fd, elem);
04030                ast_cli(a->fd, "\n");
04031             }
04032             ok = 1;
04033          }
04034          return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
04035       } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
04036          ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
04037          return CLI_SHOWUSAGE;
04038       }
04039    }
04040 
04041    if (a->argc == 3 || onlyport == 0) {
04042       ast_cli(a->fd, "mISDN General-Config:\n");
04043       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
04044          misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
04045          ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04046       }
04047       ast_cli(a->fd, "\n");
04048    }
04049 
04050    if (onlyport < 0) {
04051       int port = misdn_cfg_get_next_port(0);
04052 
04053       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
04054          ast_cli(a->fd, "\n[PORT %d]\n", port);
04055          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
04056             misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
04057             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04058          }
04059          ast_cli(a->fd, "\n");
04060       }
04061    }
04062 
04063    if (onlyport > 0) {
04064       if (misdn_cfg_is_port_valid(onlyport)) {
04065          ast_cli(a->fd, "[PORT %d]\n", onlyport);
04066          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
04067             misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
04068             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04069          }
04070          ast_cli(a->fd, "\n");
04071       } else {
04072          ast_cli(a->fd, "Port %d is not active!\n", onlyport);
04073       }
04074    }
04075 
04076    return CLI_SUCCESS;
04077 }

static char* handle_cli_misdn_show_port ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4422 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_show_stack_details(), NULL, and ast_cli_entry::usage.

04423 {
04424    int port;
04425    char buf[128];
04426 
04427    switch (cmd) {
04428    case CLI_INIT:
04429       e->command = "misdn show port";
04430       e->usage =
04431          "Usage: misdn show port <port>\n"
04432          "       Show detailed information for given port.\n";
04433       return NULL;
04434    case CLI_GENERATE:
04435       return NULL;
04436    }
04437 
04438    if (a->argc != 4) {
04439       return CLI_SHOWUSAGE;
04440    }
04441 
04442    port = atoi(a->argv[3]);
04443 
04444    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
04445    get_show_stack_details(port, buf);
04446    ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
04447 
04448    return CLI_SUCCESS;
04449 }

static char* handle_cli_misdn_show_ports_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4393 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(), NULL, and ast_cli_entry::usage.

04394 {
04395    int port;
04396 
04397    switch (cmd) {
04398    case CLI_INIT:
04399       e->command = "misdn show ports stats";
04400       e->usage =
04401          "Usage: misdn show ports stats\n"
04402          "       Show mISDNs channel's call statistics per port.\n";
04403       return NULL;
04404    case CLI_GENERATE:
04405       return NULL;
04406    }
04407 
04408    if (a->argc != 4) {
04409       return CLI_SHOWUSAGE;
04410    }
04411 
04412    ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
04413    for (port = misdn_cfg_get_next_port(0); port > 0;
04414       port = misdn_cfg_get_next_port(port)) {
04415       ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
04416    }
04417    ast_cli(a->fd, "\n");
04418 
04419    return CLI_SUCCESS;
04420 }

static char* handle_cli_misdn_show_stacks ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 4362 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli(), buf, 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(), NULL, and ast_cli_entry::usage.

04363 {
04364    int port;
04365 
04366    switch (cmd) {
04367    case CLI_INIT:
04368       e->command = "misdn show stacks";
04369       e->usage =
04370          "Usage: misdn show stacks\n"
04371          "       Show internal mISDN stack_list.\n";
04372       return NULL;
04373    case CLI_GENERATE:
04374       return NULL;
04375    }
04376 
04377    if (a->argc != 3) {
04378       return CLI_SHOWUSAGE;
04379    }
04380 
04381    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
04382    for (port = misdn_cfg_get_next_port(0); port > 0;
04383       port = misdn_cfg_get_next_port(port)) {
04384       char buf[128];
04385 
04386       get_show_stack_details(port, buf);
04387       ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
04388    }
04389 
04390    return CLI_SUCCESS;
04391 }

static char* handle_cli_misdn_toggle_echocancel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 5565 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(), NULL, chan_list::toggle_ec, update_ec_config(), and ast_cli_entry::usage.

05566 {
05567    const char *channame;
05568    struct chan_list *tmp;
05569 
05570    switch (cmd) {
05571    case CLI_INIT:
05572       e->command = "misdn toggle echocancel";
05573       e->usage =
05574          "Usage: misdn toggle echocancel <channel>\n"
05575          "       Toggle EchoCancel on mISDN Channel.\n";
05576       return NULL;
05577    case CLI_GENERATE:
05578       return complete_ch(a);
05579    }
05580 
05581    if (a->argc != 4) {
05582       return CLI_SHOWUSAGE;
05583    }
05584 
05585    channame = a->argv[3];
05586 
05587    ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
05588 
05589    tmp = get_chan_by_ast_name(channame);
05590    if (!tmp) {
05591       ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
05592       return CLI_SUCCESS;
05593    }
05594 
05595    tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
05596 
05597    if (tmp->toggle_ec) {
05598 #ifdef MISDN_1_2
05599       update_pipeline_config(tmp->bc);
05600 #else
05601       update_ec_config(tmp->bc);
05602 #endif
05603       manager_ec_enable(tmp->bc);
05604    } else {
05605       manager_ec_disable(tmp->bc);
05606    }
05607    chan_list_unref(tmp, "Done toggling echo cancel");
05608 
05609    return CLI_SUCCESS;
05610 }

static void hangup_chan ( struct chan_list ch,
struct misdn_bchannel bc 
) [static]

Definition at line 8448 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 ast_unreal_hangup(), cb_events(), do_immediate_setup(), start_pbx(), and wait_event().

08449 {
08450    int port = bc->port;
08451 
08452    if (!ch) {
08453       cb_log(1, port, "Cannot hangup chan, no ch\n");
08454       return;
08455    }
08456 
08457    cb_log(5, port, "hangup_chan called\n");
08458 
08459    if (ch->need_hangup) {
08460       cb_log(2, port, " --> hangup\n");
08461       ch->need_hangup = 0;
08462       ch->need_queue_hangup = 0;
08463       if (ch->ast && send_cause2ast(ch->ast, bc, ch)) {
08464          ast_hangup(ch->ast);
08465       }
08466       return;
08467    }
08468 
08469    if (!ch->need_queue_hangup) {
08470       cb_log(2, port, " --> No need to queue hangup\n");
08471       return;
08472    }
08473 
08474    ch->need_queue_hangup = 0;
08475    if (ch->ast) {
08476       if (send_cause2ast(ch->ast, bc, ch)) {
08477          ast_queue_hangup_with_cause(ch->ast, bc->cause);
08478          cb_log(2, port, " --> queue_hangup\n");
08479       }
08480    } else {
08481       cb_log(1, port, "Cannot hangup chan, no ast\n");
08482    }
08483 }

static void hanguptone_indicate ( struct chan_list cl  )  [static]

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

08788 {
08789    const char *tmp;
08790 
08791    ast_channel_lock(chan);
08792    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
08793    if (tmp && (atoi(tmp) == 1)) {
08794       bc->sending_complete = 1;
08795    }
08796 
08797    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
08798    if (tmp) {
08799       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
08800       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
08801       bc->uulen = strlen(bc->uu);
08802    }
08803 
08804    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
08805    if (tmp) {
08806       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
08807    }
08808    ast_channel_unlock(chan);
08809 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 11316 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_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, 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, 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(), NULL, and unload_module.

11317 {
11318    int i, port;
11319    int ntflags = 0, ntkc = 0;
11320    char ports[256] = "";
11321    char tempbuf[BUFFERSIZE + 1];
11322    char ntfile[BUFFERSIZE + 1];
11323    struct misdn_lib_iface iface = {
11324       .cb_event = cb_events,
11325       .cb_log = chan_misdn_log,
11326       .cb_jb_empty = chan_misdn_jb_empty,
11327    };
11328 
11329 
11330    if (!(misdn_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
11331       return AST_MODULE_LOAD_DECLINE;
11332    }
11333    ast_format_cap_append(misdn_tech.capabilities, ast_format_alaw, 0);
11334 
11335    max_ports = misdn_lib_maxports_get();
11336 
11337    if (max_ports <= 0) {
11338       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
11339       return AST_MODULE_LOAD_DECLINE;
11340    }
11341 
11342    if (misdn_cfg_init(max_ports, 0)) {
11343       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
11344       return AST_MODULE_LOAD_DECLINE;
11345    }
11346    g_config_initialized = 1;
11347 
11348 #if defined(AST_MISDN_ENHANCEMENTS)
11349    misdn_cc_init();
11350 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11351 
11352    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
11353    if (!misdn_debug) {
11354       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
11355       return AST_MODULE_LOAD_DECLINE;
11356    }
11357    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
11358    if (!misdn_ports) {
11359       ast_free(misdn_debug);
11360       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
11361       return AST_MODULE_LOAD_DECLINE;
11362    }
11363    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
11364    for (i = 1; i <= max_ports; i++) {
11365       misdn_debug[i] = misdn_debug[0];
11366       misdn_ports[i] = i;
11367    }
11368    *misdn_ports = 0;
11369    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
11370    if (!misdn_debug_only) {
11371       ast_free(misdn_ports);
11372       ast_free(misdn_debug);
11373       ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
11374       return AST_MODULE_LOAD_DECLINE;
11375    }
11376 
11377    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
11378    if (!ast_strlen_zero(tempbuf)) {
11379       tracing = 1;
11380    }
11381 
11382    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11383    if (!misdn_in_calls) {
11384       ast_free(misdn_debug_only);
11385       ast_free(misdn_ports);
11386       ast_free(misdn_debug);
11387       ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
11388       return AST_MODULE_LOAD_DECLINE;
11389    }
11390    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11391    if (!misdn_out_calls) {
11392       ast_free(misdn_in_calls);
11393       ast_free(misdn_debug_only);
11394       ast_free(misdn_ports);
11395       ast_free(misdn_debug);
11396       ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
11397       return AST_MODULE_LOAD_DECLINE;
11398    }
11399 
11400    for (i = 1; i <= max_ports; i++) {
11401       misdn_in_calls[i] = 0;
11402       misdn_out_calls[i] = 0;
11403    }
11404 
11405    ast_mutex_init(&cl_te_lock);
11406    ast_mutex_init(&release_lock);
11407 
11408    misdn_cfg_update_ptp();
11409    misdn_cfg_get_ports_string(ports);
11410 
11411    if (!ast_strlen_zero(ports)) {
11412       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
11413    }
11414    if (misdn_lib_init(ports, &iface, NULL)) {
11415       chan_misdn_log(0, 0, "No te ports initialized\n");
11416    }
11417 
11418    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
11419    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
11420    misdn_cfg_get(0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
11421 
11422    misdn_lib_nt_keepcalls(ntkc);
11423    misdn_lib_nt_debug_init(ntflags, ntfile);
11424 
11425    if (ast_channel_register(&misdn_tech)) {
11426       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
11427       unload_module();
11428       return AST_MODULE_LOAD_DECLINE;
11429    }
11430 
11431    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11432 
11433    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
11434       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
11435       "Sets mISDN opts. and optargs\n"
11436       "\n"
11437       "The available options are:\n"
11438       "    a - Have Asterisk detect DTMF tones on called channel\n"
11439       "    c - Make crypted outgoing call, optarg is keyindex\n"
11440       "    d - Send display text to called phone, text is the optarg\n"
11441       "    e - Perform echo cancellation on this channel,\n"
11442       "        takes taps as optarg (32,64,128,256)\n"
11443       "   e! - Disable echo cancellation on this channel\n"
11444       "    f - Enable fax detection\n"
11445       "    h - Make digital outgoing call\n"
11446       "   h1 - Make HDLC mode digital outgoing call\n"
11447       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
11448       "        they will be transported inband.\n"
11449       "   jb - Set jitter buffer length, optarg is length\n"
11450       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
11451       "   jn - Disable jitter buffer\n"
11452       "    n - Disable mISDN DSP on channel.\n"
11453       "        Disables: echo cancel, DTMF detection, and volume control.\n"
11454       "    p - Caller ID presentation,\n"
11455       "        optarg is either 'allowed' or 'restricted'\n"
11456       "    s - Send Non-inband DTMF as inband\n"
11457       "   vr - Rx gain control, optarg is gain\n"
11458       "   vt - Tx gain control, optarg is gain\n"
11459       );
11460 
11461 
11462    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
11463       "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
11464       "Sends the Facility Message FACILITY_TYPE with \n"
11465       "the given Arguments to the current ISDN Channel\n"
11466       "Supported Facilities are:\n"
11467       "\n"
11468       "type=calldeflect args=Nr where to deflect\n"
11469 #if defined(AST_MISDN_ENHANCEMENTS)
11470       "type=callrerouting args=Nr where to deflect\n"
11471 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11472       );
11473 
11474 
11475    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
11476       "misdn_check_l2l1(<port>||g:<groupname>,timeout)\n"
11477       "Checks if the L2 and L1 are up on either the given <port> or\n"
11478       "on the ports in the group with <groupname>\n"
11479       "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
11480       "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
11481       "\n"
11482       "This application, ensures the L1/L2 state of the Ports in a group\n"
11483       "it is intended to make the pmp_l1_check option redundant and to\n"
11484       "fix a buggy switch config from your provider\n"
11485       "\n"
11486       "a sample dialplan would look like:\n\n"
11487       "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
11488       "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
11489       );
11490 
11491 #if defined(AST_MISDN_ENHANCEMENTS)
11492    ast_register_application(misdn_command_name, misdn_command_exec, misdn_command_name,
11493       "misdn_command(<command>[,<options>])\n"
11494       "The following commands are defined:\n"
11495       "cc-initialize\n"
11496       "  Setup mISDN support for call completion\n"
11497       "  Must call before doing any Dial() involving call completion.\n"
11498       "ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11499       "  Request Call Completion No Reply activation\n"
11500       "ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11501       "  Request Call Completion Busy Subscriber activation\n"
11502       "cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11503       "  Set the dialplan location to notify when User-B is available but User-A is busy.\n"
11504       "  Setting this dialplan location is optional.\n"
11505       "cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>\n"
11506       "  Set the busy status of call completion User-A\n"
11507       "cc-deactivate,${MISDN_CC_RECORD_ID}\n"
11508       "  Deactivate the identified call completion request\n"
11509       "\n"
11510       "MISDN_CC_RECORD_ID is set when Dial() returns and call completion is possible\n"
11511       "MISDN_CC_STATUS is set to ACTIVATED or ERROR after the call completion\n"
11512       "activation request.\n"
11513       "MISDN_ERROR_MSG is set to a descriptive message on error.\n"
11514       );
11515 
11516    ast_custom_function_register(&misdn_cc_function);
11517 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11518 
11519    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
11520 
11521    /* start the l1 watchers */
11522 
11523    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
11524       int l1timeout;
11525       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
11526       if (l1timeout) {
11527          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
11528          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
11529       }
11530    }
11531 
11532    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
11533 
11534    return 0;
11535 }

static void misdn_add_number_prefix ( int  port,
enum mISDN_NUMBER_TYPE  number_type,
char *  number,
size_t  size 
) [static]

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

03426 {
03427    enum misdn_cfg_elements type_prefix;
03428    char num_prefix[MISDN_MAX_NUMBER_LEN];
03429 
03430    /* Get prefix string. */
03431    switch (number_type) {
03432    case NUMTYPE_UNKNOWN:
03433       type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
03434       break;
03435    case NUMTYPE_INTERNATIONAL:
03436       type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
03437       break;
03438    case NUMTYPE_NATIONAL:
03439       type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
03440       break;
03441    case NUMTYPE_NETWORK_SPECIFIC:
03442       type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
03443       break;
03444    case NUMTYPE_SUBSCRIBER:
03445       type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
03446       break;
03447    case NUMTYPE_ABBREVIATED:
03448       type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
03449       break;
03450    default:
03451       /* Type-of-number does not have a prefix that can be added. */
03452       return;
03453    }
03454    misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
03455 
03456    misdn_prefix_string(num_prefix, number, size);
03457 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 6825 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_bchannel::presentation, misdn_party_id::presentation, print_facility(), misdn_party_id::screening, start_bc_tones(), chan_list::state, and stop_indicate().

06826 {
06827    struct chan_list *p;
06828    const char *tmp;
06829 
06830    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06831       return -1;
06832    }
06833 
06834    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
06835 
06836    if (!p) {
06837       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
06838       ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
06839    }
06840 
06841    if (!p->bc) {
06842       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
06843 
06844       ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
06845    }
06846 
06847    ast_channel_lock(ast);
06848    tmp = pbx_builtin_getvar_helper(ast, "CRYPT_KEY");
06849    if (!ast_strlen_zero(tmp)) {
06850       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
06851       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
06852    } else {
06853       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
06854    }
06855 
06856    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
06857    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
06858       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
06859       p->bc->nodsp = 1;
06860       p->bc->hdlc = 0;
06861       p->bc->nojitter = 1;
06862    }
06863    ast_channel_unlock(ast);
06864 
06865    p->state = MISDN_CONNECTED;
06866    stop_indicate(p);
06867 
06868    if (ast_strlen_zero(p->bc->connected.number)) {
06869       chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
06870       ast_copy_string(p->bc->connected.number, p->bc->dialed.number, sizeof(p->bc->connected.number));
06871 
06872       /*
06873        * Use the misdn_set_opt() application to set the presentation
06874        * before we answer or you can use the CONECTEDLINE() function
06875        * to set everything before using the Answer() application.
06876        */
06877       p->bc->connected.presentation = p->bc->presentation;
06878       p->bc->connected.screening = 0;  /* unscreened */
06879       p->bc->connected.number_type = p->bc->dialed.number_type;
06880       p->bc->connected.number_plan = p->bc->dialed.number_plan;
06881    }
06882 
06883    switch (p->bc->outgoing_colp) {
06884    case 1:/* restricted */
06885    case 2:/* blocked */
06886       p->bc->connected.presentation = 1;/* restricted */
06887       break;
06888    default:
06889       break;
06890    }
06891 
06892 #if defined(AST_MISDN_ENHANCEMENTS)
06893    if (p->bc->div_leg_3_tx_pending) {
06894       p->bc->div_leg_3_tx_pending = 0;
06895 
06896       /* Send DivertingLegInformation3 */
06897       p->bc->fac_out.Function = Fac_DivertingLegInformation3;
06898       p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
06899       p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
06900          (p->bc->connected.presentation == 0) ? 1 : 0;
06901       print_facility(&p->bc->fac_out, p->bc);
06902    }
06903 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06904    misdn_lib_send_event(p->bc, EVENT_CONNECT);
06905    start_bc_tones(p);
06906 
06907    return 0;
06908 }

static int misdn_attempt_transfer ( struct chan_list active_ch,
struct chan_list held_ch 
) [static]

Definition at line 8620 of file chan_misdn.c.

References chan_list::ast, ast_bridge_transfer_attended(), AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_lock_both, ast_channel_name(), ast_channel_ref, ast_channel_unlock, ast_channel_unref, chan_misdn_log(), chan_list::hold, MISDN_ALERTING, MISDN_CONNECTED, MISDN_HOLD_TRANSFER, MISDN_PROCEEDING, MISDN_PROGRESS, hold_info::port, retval, hold_info::state, and chan_list::state.

Referenced by cb_events().

08621 {
08622    int retval;
08623    enum ast_transfer_result xfer_res;
08624    struct ast_channel *to_target;
08625    struct ast_channel *to_transferee;
08626 
08627    switch (active_ch->state) {
08628    case MISDN_PROCEEDING:
08629    case MISDN_PROGRESS:
08630    case MISDN_ALERTING:
08631    case MISDN_CONNECTED:
08632       break;
08633    default:
08634       return -1;
08635    }
08636 
08637    ast_channel_lock_both(held_ch->ast, active_ch->ast);
08638    to_target = active_ch->ast;
08639    to_transferee = held_ch->ast;
08640    chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
08641       ast_channel_name(to_transferee), ast_channel_name(to_target));
08642    held_ch->hold.state = MISDN_HOLD_TRANSFER;
08643    ast_channel_ref(to_target);
08644    ast_channel_ref(to_transferee);
08645    ast_channel_unlock(to_target);
08646    ast_channel_unlock(to_transferee);
08647 
08648    retval = 0;
08649    xfer_res = ast_bridge_transfer_attended(to_transferee, to_target);
08650    if (xfer_res != AST_BRIDGE_TRANSFER_SUCCESS) {
08651       retval = -1;
08652    }
08653 
08654    ast_channel_unref(to_target);
08655    ast_channel_unref(to_transferee);
08656    return retval;
08657 }

static int misdn_call ( struct ast_channel ast,
const char *  dest,
int  timeout 
) [static]

we should have l3id after sending setup

Definition at line 6555 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_strdupa, 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, ast_party_id::number, misdn_party_id::number, misdn_party_dialing::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_bchannel::presentation, misdn_party_id::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_number::str, ast_party_name::str, ast_party_id::tag, update_config(), ast_party_number::valid, and ast_party_name::valid.

06556 {
06557    int port = 0;
06558    int r;
06559    int exceed;
06560    int number_type;
06561    struct chan_list *ch;
06562    struct misdn_bchannel *newbc;
06563    char *dest_cp;
06564    int append_msn = 0;
06565 
06566    AST_DECLARE_APP_ARGS(args,
06567       AST_APP_ARG(intf);   /* The interface token is discarded. */
06568       AST_APP_ARG(ext); /* extension token */
06569       AST_APP_ARG(opts);   /* options token */
06570    );
06571 
06572    if (!ast) {
06573       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
06574       return -1;
06575    }
06576 
06577    if (((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) || !dest) {
06578       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast_channel_name(ast));
06579       ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06580       ast_setstate(ast, AST_STATE_DOWN);
06581       return -1;
06582    }
06583 
06584    ch = MISDN_ASTERISK_TECH_PVT(ast);
06585    if (!ch) {
06586       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast_channel_name(ast));
06587       ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06588       ast_setstate(ast, AST_STATE_DOWN);
06589       return -1;
06590    }
06591 
06592    newbc = ch->bc;
06593    if (!newbc) {
06594       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast_channel_name(ast));
06595       ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06596       ast_setstate(ast, AST_STATE_DOWN);
06597       return -1;
06598    }
06599 
06600    port = newbc->port;
06601 
06602 #if defined(AST_MISDN_ENHANCEMENTS)
06603    if ((ch->peer = misdn_cc_caller_get(ast))) {
06604       chan_misdn_log(3, port, " --> Found CC caller data, peer:%s\n",
06605          ch->peer->chan ? "available" : "NULL");
06606    }
06607 
06608    if (ch->record_id != -1) {
06609       struct misdn_cc_record *cc_record;
06610 
06611       /* This is a call completion retry call */
06612       AST_LIST_LOCK(&misdn_cc_records_db);
06613       cc_record = misdn_cc_find_by_id(ch->record_id);
06614       if (!cc_record) {
06615          AST_LIST_UNLOCK(&misdn_cc_records_db);
06616          ast_log(LOG_WARNING, " --> ! misdn_call called on %s, cc_record==NULL\n", ast_channel_name(ast));
06617          ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06618          ast_setstate(ast, AST_STATE_DOWN);
06619          return -1;
06620       }
06621 
06622       /* Setup calling parameters to retry the call. */
06623       newbc->dialed = cc_record->redial.dialed;
06624       newbc->caller = cc_record->redial.caller;
06625       memset(&newbc->redirecting, 0, sizeof(newbc->redirecting));
06626       newbc->capability = cc_record->redial.capability;
06627       newbc->hdlc = cc_record->redial.hdlc;
06628       newbc->sending_complete = 1;
06629 
06630       if (cc_record->ptp) {
06631          newbc->fac_out.Function = Fac_CCBS_T_Call;
06632          newbc->fac_out.u.CCBS_T_Call.InvokeID = ++misdn_invoke_id;
06633       } else {
06634          newbc->fac_out.Function = Fac_CCBSCall;
06635          newbc->fac_out.u.CCBSCall.InvokeID = ++misdn_invoke_id;
06636          newbc->fac_out.u.CCBSCall.CCBSReference = cc_record->mode.ptmp.reference_id;
06637       }
06638       AST_LIST_UNLOCK(&misdn_cc_records_db);
06639 
06640       ast_channel_exten_set(ast, newbc->dialed.number);
06641 
06642       chan_misdn_log(1, port, "* Call completion to: %s\n", newbc->dialed.number);
06643       chan_misdn_log(2, port, " --> * tech:%s context:%s\n", ast_channel_name(ast), ast_channel_context(ast));
06644    } else
06645 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06646    {
06647       struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
06648 
06649       /*
06650        * dest is ---v
06651        * Dial(mISDN/g:group_name[/extension[/options]])
06652        * Dial(mISDN/port[:preselected_channel][/extension[/options]])
06653        *
06654        * The dial extension could be empty if you are using MISDN_KEYPAD
06655        * to control ISDN provider features.
06656        */
06657       dest_cp = ast_strdupa(dest);
06658       AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
06659       if (!args.ext) {
06660          args.ext = "";
06661       }
06662 
06663       chan_misdn_log(1, port, "* CALL: %s\n", dest);
06664       chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast_channel_name(ast), ast_channel_context(ast));
06665 
06666       ast_channel_exten_set(ast, args.ext);
06667       ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
06668 
06669       if (ast_strlen_zero(newbc->caller.name)
06670          && connected_id.name.valid
06671          && !ast_strlen_zero(connected_id.name.str)) {
06672          ast_copy_string(newbc->caller.name, connected_id.name.str, sizeof(newbc->caller.name));
06673          chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
06674       }
06675       if (ast_strlen_zero(newbc->caller.number)
06676          && connected_id.number.valid
06677          && !ast_strlen_zero(connected_id.number.str)) {
06678          ast_copy_string(newbc->caller.number, connected_id.number.str, sizeof(newbc->caller.number));
06679          chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
06680       }
06681 
06682       misdn_cfg_get(port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
06683       if (append_msn) {
06684          strncat(newbc->incoming_cid_tag, "_", sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
06685          strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
06686       }
06687 
06688       ast_channel_caller(ast)->id.tag = ast_strdup(newbc->incoming_cid_tag);
06689 
06690       misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
06691       if (number_type < 0) {
06692          if (connected_id.number.valid) {
06693             newbc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan);
06694             newbc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan);
06695          } else {
06696             newbc->caller.number_type = NUMTYPE_UNKNOWN;
06697             newbc->caller.number_plan = NUMPLAN_ISDN;
06698          }
06699       } else {
06700          /* Force us to send in SETUP message */
06701          newbc->caller.number_type = number_type;
06702          newbc->caller.number_plan = NUMPLAN_ISDN;
06703       }
06704       debug_numtype(port, newbc->caller.number_type, "LTON");
06705 
06706       newbc->capability = ast_channel_transfercapability(ast);
06707       pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
06708       if (ast_channel_transfercapability(ast) == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
06709          chan_misdn_log(2, port, " --> * Call with flag Digital\n");
06710       }
06711 
06712       /* update caller screening and presentation */
06713       update_config(ch);
06714 
06715       /* fill in some ies from channel dialplan variables */
06716       import_ch(ast, newbc, ch);
06717 
06718       /* Finally The Options Override Everything */
06719       if (!ast_strlen_zero(args.opts)) {
06720          misdn_set_opt_exec(ast, args.opts);
06721       } else {
06722          chan_misdn_log(2, port, "NO OPTS GIVEN\n");
06723       }
06724       if (newbc->set_presentation) {
06725          newbc->caller.presentation = newbc->presentation;
06726       }
06727 
06728       misdn_copy_redirecting_from_ast(newbc, ast);
06729       switch (newbc->outgoing_colp) {
06730       case 1:/* restricted */
06731       case 2:/* blocked */
06732          newbc->redirecting.from.presentation = 1;/* restricted */
06733          break;
06734       default:
06735          break;
06736       }
06737 #if defined(AST_MISDN_ENHANCEMENTS)
06738       if (newbc->redirecting.from.number[0] && misdn_lib_is_ptp(port)) {
06739          if (newbc->redirecting.count < 1) {
06740             newbc->redirecting.count = 1;
06741          }
06742 
06743          /* Create DivertingLegInformation2 facility */
06744          newbc->fac_out.Function = Fac_DivertingLegInformation2;
06745          newbc->fac_out.u.DivertingLegInformation2.InvokeID = ++misdn_invoke_id;
06746          newbc->fac_out.u.DivertingLegInformation2.DivertingPresent = 1;
06747          misdn_PresentedNumberUnscreened_fill(
06748             &newbc->fac_out.u.DivertingLegInformation2.Diverting,
06749             &newbc->redirecting.from);
06750          switch (newbc->outgoing_colp) {
06751          case 2:/* blocked */
06752             /* Block the number going out */
06753             newbc->fac_out.u.DivertingLegInformation2.Diverting.Type = 1;/* presentationRestricted */
06754 
06755             /* Don't tell about any previous diversions or why for that matter. */
06756             newbc->fac_out.u.DivertingLegInformation2.DiversionCounter = 1;
06757             newbc->fac_out.u.DivertingLegInformation2.DiversionReason = 0;/* unknown */
06758             break;
06759          default:
06760             newbc->fac_out.u.DivertingLegInformation2.DiversionCounter =
06761                newbc->redirecting.count;
06762             newbc->fac_out.u.DivertingLegInformation2.DiversionReason =
06763                misdn_to_diversion_reason(newbc->redirecting.reason);
06764             break;
06765          }
06766          newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
06767          if (1 < newbc->fac_out.u.DivertingLegInformation2.DiversionCounter) {
06768             newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
06769             newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;/* numberNotAvailableDueToInterworking */
06770          }
06771 
06772          /*
06773           * Expect a DivertingLegInformation3 to update the COLR of the
06774           * redirecting-to party we are attempting to call now.
06775           */
06776          newbc->div_leg_3_rx_wanted = 1;
06777       }
06778 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06779    }
06780 
06781    exceed = add_out_calls(port);
06782    if (exceed != 0) {
06783       char tmp[16];
06784 
06785       snprintf(tmp, sizeof(tmp), "%d", exceed);
06786       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
06787       ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06788       ast_setstate(ast, AST_STATE_DOWN);
06789       return -1;
06790    }
06791 
06792 #if defined(AST_MISDN_ENHANCEMENTS)
06793    if (newbc->fac_out.Function != Fac_None) {
06794       print_facility(&newbc->fac_out, newbc);
06795    }
06796 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06797    r = misdn_lib_send_event(newbc, EVENT_SETUP);
06798 
06799    /** we should have l3id after sending setup **/
06800    ch->l3id = newbc->l3_id;
06801 
06802    if (r == -ENOCHAN) {
06803       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
06804       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
06805       ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
06806       ast_setstate(ast, AST_STATE_DOWN);
06807       return -1;
06808    }
06809 
06810    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
06811 
06812    ast_setstate(ast, AST_STATE_DIALING);
06813    ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_CLEARING);
06814 
06815    if (newbc->nt) {
06816       stop_bc_tones(ch);
06817    }
06818 
06819    ch->state = MISDN_CALLING;
06820 
06821    return 0;
06822 }

static int misdn_chan_is_valid ( struct chan_list ch  )  [static]

Definition at line 750 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, and chan_list::next.

Referenced by misdn_hangup().

00751 {
00752    struct chan_list *list;
00753 
00754    ast_mutex_lock(&cl_te_lock);
00755    for (list = cl_te; list; list = list->next) {
00756       if (list == ch) {
00757          ast_mutex_unlock(&cl_te_lock);
00758          return 1;
00759       }
00760    }
00761    ast_mutex_unlock(&cl_te_lock);
00762 
00763    return 0;
00764 }

static int misdn_check_l2l1 ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 12292 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_strdupa, 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 timeout.

Referenced by load_module().

12293 {
12294    char *parse;
12295    char group[BUFFERSIZE + 1];
12296    char *port_str;
12297    int port = 0;
12298    int timeout;
12299    int dowait = 0;
12300    int port_up;
12301 
12302    AST_DECLARE_APP_ARGS(args,
12303       AST_APP_ARG(grouppar);
12304       AST_APP_ARG(timeout);
12305    );
12306 
12307    if (ast_strlen_zero((char *) data)) {
12308       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
12309       return -1;
12310    }
12311 
12312    parse = ast_strdupa(data);
12313    AST_STANDARD_APP_ARGS(args, parse);
12314 
12315    if (args.argc != 2) {
12316       ast_log(LOG_WARNING, "Wrong argument count\n");
12317       return 0;
12318    }
12319 
12320    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
12321    timeout = atoi(args.timeout);
12322    port_str = args.grouppar;
12323 
12324    if (port_str[0] == 'g' && port_str[1] == ':') {
12325       /* We make a group call lets checkout which ports are in my group */
12326       port_str += 2;
12327       ast_copy_string(group, port_str, sizeof(group));
12328       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
12329 
12330       for (port = misdn_cfg_get_next_port(port);
12331          port > 0;
12332          port = misdn_cfg_get_next_port(port)) {
12333          char cfg_group[BUFFERSIZE + 1];
12334 
12335          chan_misdn_log(2, 0, "trying port %d\n", port);
12336 
12337          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
12338 
12339          if (!strcasecmp(cfg_group, group)) {
12340             port_up = misdn_lib_port_up(port, 1);
12341             if (!port_up) {
12342                chan_misdn_log(2, 0, " --> port '%d'\n", port);
12343                misdn_lib_get_port_up(port);
12344                dowait = 1;
12345             }
12346          }
12347       }
12348    } else {
12349       port = atoi(port_str);
12350       chan_misdn_log(2, 0, "Checking Port: %d\n", port);
12351       port_up = misdn_lib_port_up(port, 1);
12352       if (!port_up) {
12353          misdn_lib_get_port_up(port);
12354          dowait = 1;
12355       }
12356    }
12357 
12358    if (dowait) {
12359       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
12360       ast_safe_sleep(chan, timeout * 1000);
12361    }
12362 
12363    return 0;
12364 }

static void misdn_copy_redirecting_from_ast ( struct misdn_bchannel bc,
struct ast_channel ast 
) [static]

Definition at line 6383 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(), ast_party_redirecting::count, misdn_party_redirecting::count, misdn_party_redirecting::from, ast_party_id::name, misdn_party_id::name, misdn_party_id::number, ast_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_number::str, ast_party_name::str, misdn_party_redirecting::to, ast_party_number::valid, and ast_party_name::valid.

Referenced by misdn_call(), and misdn_update_redirecting().

06384 {
06385    struct ast_party_id from_id = ast_channel_redirecting_effective_from(ast);
06386    struct ast_party_id to_id = ast_channel_redirecting_effective_to(ast);
06387 
06388    ast_copy_string(bc->redirecting.from.name,
06389       S_COR(from_id.name.valid, from_id.name.str, ""),
06390       sizeof(bc->redirecting.from.name));
06391    if (from_id.number.valid) {
06392       ast_copy_string(bc->redirecting.from.number, S_OR(from_id.number.str, ""),
06393          sizeof(bc->redirecting.from.number));
06394       bc->redirecting.from.presentation = ast_to_misdn_pres(from_id.number.presentation);
06395       bc->redirecting.from.screening = ast_to_misdn_screen(from_id.number.presentation);
06396       bc->redirecting.from.number_type = ast_to_misdn_ton(from_id.number.plan);
06397       bc->redirecting.from.number_plan = ast_to_misdn_plan(from_id.number.plan);
06398    } else {
06399       bc->redirecting.from.number[0] = '\0';
06400       bc->redirecting.from.presentation = 0;/* Allowed */
06401       bc->redirecting.from.screening = 0;/* Unscreened */
06402       bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
06403       bc->redirecting.from.number_plan = NUMPLAN_UNKNOWN;
06404    }
06405 
06406    ast_copy_string(bc->redirecting.to.name,
06407       S_COR(to_id.name.valid, to_id.name.str, ""),
06408       sizeof(bc->redirecting.to.name));
06409    if (to_id.number.valid) {
06410       ast_copy_string(bc->redirecting.to.number, S_OR(to_id.number.str, ""),
06411          sizeof(bc->redirecting.to.number));
06412       bc->redirecting.to.presentation = ast_to_misdn_pres(to_id.number.presentation);
06413       bc->redirecting.to.screening = ast_to_misdn_screen(to_id.number.presentation);
06414       bc->redirecting.to.number_type = ast_to_misdn_ton(to_id.number.plan);
06415       bc->redirecting.to.number_plan = ast_to_misdn_plan(to_id.number.plan);
06416    } else {
06417       bc->redirecting.to.number[0] = '\0';
06418       bc->redirecting.to.presentation = 0;/* Allowed */
06419       bc->redirecting.to.screening = 0;/* Unscreened */
06420       bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
06421       bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
06422    }
06423 
06424    bc->redirecting.reason = ast_to_misdn_reason(ast_channel_redirecting(ast)->reason.code);
06425    bc->redirecting.count = ast_channel_redirecting(ast)->count;
06426 }

static void misdn_copy_redirecting_to_ast ( struct ast_channel ast,
const struct misdn_party_redirecting redirect,
char *  tag 
) [static]

Definition at line 6438 of file chan_misdn.c.

References ast_channel_redirecting(), ast_channel_set_redirecting(), ast_party_redirecting_set_init(), ast_party_redirecting_reason::code, 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(), misdn_party_id::number, ast_party_id::number, ast_set_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, ast_party_number::plan, misdn_party_id::presentation, ast_party_number::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().

06439 {
06440    struct ast_party_redirecting redirecting;
06441    struct ast_set_party_redirecting update_redirecting;
06442 
06443    ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(ast));
06444    memset(&update_redirecting, 0, sizeof(update_redirecting));
06445 
06446    update_redirecting.from.number = 1;
06447    redirecting.from.number.valid = 1;
06448    redirecting.from.number.str = (char *) redirect->from.number;
06449    redirecting.from.number.plan =
06450       misdn_to_ast_ton(redirect->from.number_type)
06451       | misdn_to_ast_plan(redirect->from.number_plan);
06452    redirecting.from.number.presentation =
06453       misdn_to_ast_pres(redirect->from.presentation)
06454       | misdn_to_ast_screen(redirect->from.screening);
06455    redirecting.from.tag = tag;
06456 
06457    update_redirecting.to.number = 1;
06458    redirecting.to.number.valid = 1;
06459    redirecting.to.number.str = (char *) redirect->to.number;
06460    redirecting.to.number.plan =
06461       misdn_to_ast_ton(redirect->to.number_type)
06462       | misdn_to_ast_plan(redirect->to.number_plan);
06463    redirecting.to.number.presentation =
06464       misdn_to_ast_pres(redirect->to.presentation)
06465       | misdn_to_ast_screen(redirect->to.screening);
06466    redirecting.to.tag = tag;
06467 
06468    redirecting.reason.code = misdn_to_ast_reason(redirect->reason);
06469    redirecting.count = redirect->count;
06470 
06471    ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
06472 }

static int misdn_digit_begin ( struct ast_channel chan,
char  digit 
) [static]

Definition at line 6910 of file chan_misdn.c.

06911 {
06912    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
06913    return 0;
06914 }

static int misdn_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 6916 of file chan_misdn.c.

References chan_list::ast, ast_channel_exten_set(), ast_copy_string(), ast_log, chan_list::bc, buf, 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.

06917 {
06918    struct chan_list *p;
06919    struct misdn_bchannel *bc;
06920    char buf[2] = { digit, 0 };
06921 
06922    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06923       return -1;
06924    }
06925 
06926    bc = p->bc;
06927    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
06928 
06929    if (!bc) {
06930       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
06931       return -1;
06932    }
06933 
06934    switch (p->state) {
06935    case MISDN_CALLING:
06936       if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
06937          strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
06938       }
06939       break;
06940    case MISDN_CALLING_ACKNOWLEDGE:
06941       ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
06942       if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
06943          strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
06944       }
06945       ast_channel_exten_set(p->ast, bc->dialed.number);
06946       misdn_lib_send_event(bc, EVENT_INFORMATION);
06947       break;
06948    default:
06949       if (bc->send_dtmf) {
06950          send_digit_to_chan(p, digit);
06951       }
06952       break;
06953    }
06954 
06955    return 0;
06956 }

static int misdn_facility_exec ( struct ast_channel chan,
const char *  data 
) [static]

Definition at line 12169 of file chan_misdn.c.

References args, AST_APP_ARG, ast_channel_tech(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, 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(), misdn_bchannel::port, and print_facility().

Referenced by load_module().

12170 {
12171    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12172    char *parse;
12173    unsigned max_len;
12174 
12175    AST_DECLARE_APP_ARGS(args,
12176       AST_APP_ARG(facility_type);
12177       AST_APP_ARG(arg)[99];
12178    );
12179 
12180    chan_misdn_log(0, 0, "TYPE: %s\n", ast_channel_tech(chan)->type);
12181 
12182    if (strcasecmp(ast_channel_tech(chan)->type, misdn_type)) {
12183       ast_log(LOG_WARNING, "misdn_facility only makes sense with %s channels!\n", misdn_type);
12184       return -1;
12185    }
12186 
12187    if (ast_strlen_zero((char *) data)) {
12188       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12189       return -1;
12190    }
12191 
12192    parse = ast_strdupa(data);
12193    AST_STANDARD_APP_ARGS(args, parse);
12194 
12195    if (ast_strlen_zero(args.facility_type)) {
12196       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12197       return -1;
12198    }
12199 
12200    if (!strcasecmp(args.facility_type, "calldeflect")) {
12201       if (