Wed Aug 18 22:34:11 2010

Asterisk developer's documentation


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

Go to the source code of this file.

Data Structures

struct  allowed_bearers
struct  chan_list
 Channel call record structure. More...
struct  hold_info
struct  misdn_jb
struct  robin_list
struct  state_struct

Defines

#define MISDN_ASTERISK_PVT(ast)   1
#define MISDN_ASTERISK_TECH_PVT(ast)   ast->tech_pvt
#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 const char * bearer2str (int cap)
static enum event_response_e cb_events (enum event_e event, struct misdn_bchannel *bc, void *user_data)
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 void cl_dequeue_chan (struct chan_list **list, struct chan_list *chan)
static void cl_queue_chan (struct chan_list **list, 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_numplan (int port, int numplan, 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 chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_chan_by_pid (struct chan_list *list, int pid)
static struct chan_listfind_hold_active_call (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_hold_call (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_hold_call_l3 (struct chan_list *list, unsigned long l3_id)
static void free_robin_list (void)
static struct chan_listget_chan_by_ast (struct ast_channel *ast)
static struct chan_listget_chan_by_ast_name (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 struct chan_listinit_chan_list (int orig)
static int load_module (void)
static int misdn_answer (struct ast_channel *ast)
static int misdn_attempt_transfer (struct chan_list *active_ch, struct chan_list *held_ch)
static enum ast_bridge_result misdn_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int misdn_call (struct ast_channel *ast, char *dest, int timeout)
static int misdn_check_l2l1 (struct ast_channel *chan, void *data)
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, void *data)
static int misdn_fixup (struct ast_channel *oldast, struct ast_channel *ast)
static const char * misdn_get_ch_state (struct chan_list *p)
static int misdn_hangup (struct ast_channel *ast)
static int misdn_indication (struct ast_channel *ast, int cond, const void *data, size_t datalen)
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).
misdn_jbmisdn_jb_init (int size, int upper_threshold)
 allocates the jb-structure and initialize the elements
static int misdn_l1_task (const void *data)
static struct ast_channelmisdn_new (struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c)
static int misdn_overlap_dial_task (const void *data)
static struct ast_framemisdn_read (struct ast_channel *ast)
static struct ast_channelmisdn_request (const char *type, int format, void *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, void *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_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 (struct FacParm *fac, 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, int orig)
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 void 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 int update_config (struct chan_list *ch, int orig)
 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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct allowed_bearers allowed_bearers_array []
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry chan_misdn_clis []
chan_listcl_te = NULL
 Global channel call record list head.
ast_mutex_t cl_te_lock
chan_list dummy_cl
static int g_config_initialized = 0
static int glob_channel = 0
char global_tracefile [BUFFERSIZE+1]
ast_mutex_t lock
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 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 struct ast_channel_tech misdn_tech_wo_bridge
static const char misdn_type [] = "mISDN"
static int prefformat = AST_FORMAT_ALAW
 Only alaw and mulaw is allowed for now.
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>
ExtRef:
MISDN http://www.misdn.org/

Definition in file chan_misdn.c.


Define Documentation

#define MISDN_ASTERISK_PVT ( ast   )     1

Definition at line 483 of file chan_misdn.c.

Referenced by cb_events(), and do_immediate_setup().

#define MISDN_ASTERISK_TECH_PVT ( ast   )     ast->tech_pvt

Definition at line 482 of file chan_misdn.c.

Referenced by cb_events(), do_immediate_setup(), misdn_answer(), misdn_call(), misdn_digit_end(), misdn_facility_exec(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_read(), misdn_set_opt_exec(), misdn_write(), release_chan(), and release_chan_early().

#define ORG_AST   1

Definition at line 133 of file chan_misdn.c.

Referenced by cb_events(), export_aoc_vars(), misdn_call(), misdn_hangup(), misdn_request(), print_bc_info(), read_config(), release_chan(), and release_chan_early().

#define ORG_MISDN   2

Definition at line 134 of file chan_misdn.c.

Referenced by cb_events(), and misdn_indication().

#define TRANSFER_ON_HELD_CALL_HANGUP   1

Definition at line 3753 of file chan_misdn.c.


Enumeration Type Documentation

enum misdn_chan_state

Enumerator:
MISDN_NOTHING  at beginning
MISDN_WAITING4DIGS  when waiting for infos
MISDN_EXTCANTMATCH  when asterisk couldn't match our ext
MISDN_INCOMING_SETUP  for incoming setups
MISDN_DIALING  when pbx_start
MISDN_PROGRESS  we got a progress
MISDN_PROCEEDING  we got a 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 116 of file chan_misdn.c.

00116                       {
00117    MISDN_NOTHING=0,  /*!< at beginning */
00118    MISDN_WAITING4DIGS, /*!<  when waiting for infos */
00119    MISDN_EXTCANTMATCH, /*!<  when asterisk couldn't match our ext */
00120    MISDN_INCOMING_SETUP, /*!<  for incoming setups*/
00121    MISDN_DIALING, /*!<  when pbx_start */
00122    MISDN_PROGRESS, /*!<  we got a progress */
00123    MISDN_PROCEEDING, /*!<  we got a progress */
00124    MISDN_CALLING, /*!<  when misdn_call is called */
00125    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
00126    MISDN_ALERTING, /*!<  when Alerting */
00127    MISDN_BUSY, /*!<  when BUSY */
00128    MISDN_CONNECTED, /*!<  when connected */
00129    MISDN_DISCONNECTED, /*!<  when connected */
00130    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00131 };

enum misdn_hold_state

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

00136                       {
00137    MISDN_HOLD_IDLE,     /*!< HOLD not active */
00138    MISDN_HOLD_ACTIVE,      /*!< Call is held */
00139    MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
00140    MISDN_HOLD_DISCONNECT,  /*!< Held call is being disconnected */
00141 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 6116 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

References ast_sched_add_variable(), misdn_tasks, misdn_tasks_init(), and misdn_tasks_wakeup().

Referenced by misdn_tasks_add(), and misdn_tasks_add_variable().

00803 {
00804    int task_id;
00805 
00806    if (!misdn_tasks) {
00807       misdn_tasks_init();
00808    }
00809    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00810    misdn_tasks_wakeup();
00811 
00812    return task_id;
00813 }

int add_in_calls ( int  port  ) 

Definition at line 4238 of file chan_misdn.c.

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

Referenced by cb_events().

04239 {
04240    int max_in_calls;
04241    
04242    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04243    misdn_in_calls[port]++;
04244 
04245    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04246       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04247       return misdn_in_calls[port] - max_in_calls;
04248    }
04249    
04250    return 0;
04251 }

int add_out_calls ( int  port  ) 

Definition at line 4253 of file chan_misdn.c.

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

Referenced by misdn_call().

04254 {
04255    int max_out_calls;
04256    
04257    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04258 
04259    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04260       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04261       return (misdn_out_calls[port] + 1) - max_out_calls;
04262    }
04263 
04264    misdn_out_calls[port]++;
04265    
04266    return 0;
04267 }

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

Definition at line 600 of file chan_misdn.c.

References allowed_bearers_array, ARRAY_LEN, and allowed_bearers::display.

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

00601 {
00602    unsigned index;
00603 
00604    for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
00605       if (allowed_bearers_array[index].cap == cap) {
00606          return allowed_bearers_array[index].display;
00607       }
00608    }
00609 
00610    return "Unknown Bearer";
00611 }

static enum event_response_e cb_events ( enum event_e  event,
struct misdn_bchannel bc,
void *  user_data 
) [static]

Definition at line 4293 of file chan_misdn.c.

References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, allowed_bearers_array, misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, misdn_bchannel::AOCDtype, ARRAY_LEN, chan_list::ast, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_cdr_update(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_deactivate_generator(), ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pickup_call(), ast_pickup_ext(), AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_queue_frame(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, 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::cad, misdn_bchannel::capability, misdn_bchannel::cause, cb_log, chan, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, misdn_bchannel::chargingUnit, ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), cl_te, chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::currency, misdn_bchannel::cw, misdn_bchannel::dad, 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_PORT_ALARM, EVENT_PROCEEDING, EVENT_PROGRESS, 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(), ast_channel::exten, misdn_bchannel::fac_in, chan_list::far_alerting, find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), ast_generator::generate, ast_channel::generator, ast_channel::generatordata, hangup_chan(), ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::info_dad, INFO_PI_INBAND_AVAILABLE, misdn_bchannel::infos_pending, init_chan_list(), misdn_bchannel::keypad, misdn_bchannel::l3_id, chan_list::l3id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, manager_isdn_get_info(), MISDN_ALERTING, MISDN_ASTERISK_PVT, 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_get(), MISDN_CFG_HOLD_ALLOWED, MISDN_CFG_IMMEDIATE, misdn_cfg_is_msn_valid(), MISDN_CFG_REJECT_CAUSE, MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, MISDN_EXTCANTMATCH, MISDN_GEN_APPEND_DIGITS2EXTEN, misdn_get_ch_state(), MISDN_HOLD_ACTIVE, MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, misdn_inband_avail(), MISDN_INCOMING_SETUP, misdn_lib_is_ptp(), misdn_lib_log_ies(), misdn_lib_port_block(), misdn_lib_send_event(), misdn_new(), MISDN_NOTHING, misdn_overlap_dial_task(), MISDN_PROCEEDING, MISDN_PROGRESS, misdn_tasks_add_variable(), MISDN_WAITING4DIGS, allowed_bearers::name, chan_list::need_busy, misdn_bchannel::need_disconnect, misdn_bchannel::need_more_infos, misdn_bchannel::need_release, misdn_bchannel::need_release_complete, chan_list::noautorespond_on_setup, misdn_bchannel::nt, chan_list::nttimeout, misdn_bchannel::oad, 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(), pbx_start_chan(), misdn_bchannel::pid, chan_list::pipe, hold_info::port, misdn_bchannel::port, misdn_bchannel::pres, print_bearer(), print_facility(), misdn_bchannel::progress_indicator, read_config(), release_chan(), RESPONSE_IGNORE_SETUP, RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE, RESPONSE_OK, RESPONSE_RELEASE_SETUP, ast_channel::rings, misdn_bchannel::screen, misdn_bchannel::sending_complete, start_bc_tones(), start_pbx(), hold_info::state, chan_list::state, stop_bc_tones(), stop_indicate(), ast_channel::tech, misdn_bchannel::tone_cnt, ast_channel::transfercapability, ast_channel_tech::type, update_name(), and wait_for_digits().

Referenced by load_module().

04294 {
04295    int msn_valid;
04296    struct chan_list *held_ch;
04297    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04298    
04299    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
04300       int debuglevel = 1;
04301       if ( event == EVENT_CLEANUP && !user_data)
04302          debuglevel = 5;
04303 
04304       chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch ? misdn_get_ch_state(ch) : "none");
04305       if (debuglevel == 1) {
04306          misdn_lib_log_ies(bc);
04307          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04308       }
04309    }
04310    
04311    if (!ch) {
04312       switch(event) {
04313       case EVENT_SETUP:
04314       case EVENT_DISCONNECT:
04315       case EVENT_RELEASE:
04316       case EVENT_RELEASE_COMPLETE:
04317       case EVENT_PORT_ALARM:
04318       case EVENT_RETRIEVE:
04319       case EVENT_NEW_BC:
04320       case EVENT_FACILITY:
04321          break;
04322       case EVENT_CLEANUP:
04323       case EVENT_TONE_GENERATE:
04324       case EVENT_BCHAN_DATA:
04325          return -1;
04326       default:
04327          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);
04328          return -1;
04329       }
04330    }
04331    
04332    if (ch) {
04333       switch (event) {
04334       case EVENT_TONE_GENERATE:
04335          break;
04336       case EVENT_DISCONNECT:
04337       case EVENT_RELEASE:
04338       case EVENT_RELEASE_COMPLETE:
04339       case EVENT_CLEANUP:
04340       case EVENT_TIMEOUT:
04341          if (!ch->ast)
04342             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));
04343          break;
04344       default:
04345          if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04346             if (event != EVENT_BCHAN_DATA)
04347                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04348             return -1;
04349          }
04350       }
04351    }
04352    
04353    
04354    switch (event) {
04355    case EVENT_PORT_ALARM:
04356       {
04357          int boa = 0;
04358          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
04359          if (boa) {
04360             cb_log(1, bc->port, " --> blocking\n");
04361             misdn_lib_port_block(bc->port); 
04362          }
04363       }
04364       break;
04365    case EVENT_BCHAN_ACTIVATED:
04366       break;
04367       
04368    case EVENT_NEW_CHANNEL:
04369       update_name(ch->ast,bc->port,bc->channel);
04370       break;
04371       
04372    case EVENT_NEW_L3ID:
04373       ch->l3id=bc->l3_id;
04374       ch->addr=bc->addr;
04375       break;
04376 
04377    case EVENT_NEW_BC:
04378       if (!ch) {
04379          ch = find_hold_call(cl_te,bc);
04380       }
04381       
04382       if (!ch) {
04383          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04384          break;
04385       }
04386 
04387       if (bc)
04388          ch->bc = (struct misdn_bchannel *)user_data;
04389       break;
04390       
04391    case EVENT_DTMF_TONE:
04392    {
04393       /*  sending INFOS as DTMF-Frames :) */
04394       struct ast_frame fr;
04395 
04396       memset(&fr, 0, sizeof(fr));
04397       fr.frametype = AST_FRAME_DTMF;
04398       fr.subclass = bc->dtmf ;
04399       fr.src = NULL;
04400       fr.data.ptr = NULL;
04401       fr.datalen = 0;
04402       fr.samples = 0;
04403       fr.mallocd = 0;
04404       fr.offset = 0;
04405       fr.delivery = ast_tv(0,0);
04406       
04407       if (!ch->ignore_dtmf) {
04408          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04409          ast_queue_frame(ch->ast, &fr);
04410       } else {
04411          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04412       }
04413    }
04414       break;
04415    case EVENT_STATUS:
04416       break;
04417     
04418    case EVENT_INFORMATION:
04419    {
04420       if ( ch->state != MISDN_CONNECTED ) 
04421          stop_indicate(ch);
04422    
04423       if (!ch->ast)
04424          break;
04425 
04426       if (ch->state == MISDN_WAITING4DIGS ) {
04427          /*  Ok, incomplete Setup, waiting till extension exists */
04428          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04429             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04430             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04431          }
04432 
04433          strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04434          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04435 
04436          /* Check for Pickup Request first */
04437          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04438             if (ast_pickup_call(ch->ast)) {
04439                hangup_chan(ch, bc);
04440             } else {
04441                struct ast_channel *chan = ch->ast;
04442                ch->state = MISDN_CALLING_ACKNOWLEDGE;
04443                ast_setstate(chan, AST_STATE_DOWN);
04444                hangup_chan(ch, bc);
04445                ch->ast = NULL;
04446                break;
04447             }
04448          }
04449          
04450          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04451             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04452                ast_log(LOG_WARNING,
04453                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04454                   bc->dad, ch->context, bc->port);
04455                strcpy(ch->ast->exten, "i");
04456 
04457                ch->state = MISDN_DIALING;
04458                start_pbx(ch, bc, ch->ast);
04459                break;
04460             }
04461 
04462             ast_log(LOG_WARNING,
04463                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04464                "\tMaybe you want to add an 'i' extension to catch this case.\n",
04465                bc->dad, ch->context, bc->port);
04466 
04467             if (bc->nt)
04468                hanguptone_indicate(ch);
04469             ch->state = MISDN_EXTCANTMATCH;
04470             bc->out_cause = AST_CAUSE_UNALLOCATED;
04471 
04472             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04473             break;
04474          }
04475 
04476          if (ch->overlap_dial) {
04477             ast_mutex_lock(&ch->overlap_tv_lock);
04478             ch->overlap_tv = ast_tvnow();
04479             ast_mutex_unlock(&ch->overlap_tv_lock);
04480             if (ch->overlap_dial_task == -1) {
04481                ch->overlap_dial_task = 
04482                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04483             }
04484             break;
04485          }
04486 
04487          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04488             
04489             ch->state = MISDN_DIALING;
04490             start_pbx(ch, bc, ch->ast);
04491          }
04492       } else {
04493          /*  sending INFOS as DTMF-Frames :) */
04494          struct ast_frame fr;
04495          int digits;
04496 
04497          memset(&fr, 0, sizeof(fr));
04498          fr.frametype = AST_FRAME_DTMF;
04499          fr.subclass = bc->info_dad[0] ;
04500          fr.src = NULL;
04501          fr.data.ptr = NULL;
04502          fr.datalen = 0;
04503          fr.samples = 0;
04504          fr.mallocd = 0;
04505          fr.offset = 0;
04506          fr.delivery = ast_tv(0,0);
04507 
04508          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
04509          if (ch->state != MISDN_CONNECTED ) {
04510             if (digits) {
04511                strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04512                ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04513                ast_cdr_update(ch->ast);
04514             }
04515             
04516             ast_queue_frame(ch->ast, &fr);
04517          }
04518       }
04519    }
04520       break;
04521    case EVENT_SETUP:
04522    {
04523       struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04524       struct ast_channel *chan;
04525       int exceed;
04526       int pres, screen;
04527       int ai;
04528       int im;
04529 
04530       if (ch) {
04531          switch (ch->state) {
04532          case MISDN_NOTHING:
04533             ch = NULL;
04534             break;
04535          default:
04536             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04537             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
04538          }
04539       }
04540 
04541       msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04542       if (!bc->nt && ! msn_valid) {
04543          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04544          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04545       }
04546 
04547       if (bc->cw) {
04548          int cause;
04549          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04550          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04551          bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
04552          return RESPONSE_RELEASE_SETUP;
04553       }
04554 
04555       print_bearer(bc);
04556 
04557       ch = init_chan_list(ORG_MISDN);
04558 
04559       if (!ch) {
04560          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
04561          return 0;
04562       }
04563 
04564       ch->bc = bc;
04565       ch->l3id = bc->l3_id;
04566       ch->addr = bc->addr;
04567       ch->originator = ORG_MISDN;
04568 
04569       chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04570       if (!chan) {
04571          ast_free(ch);
04572          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04573          ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); 
04574          return 0;
04575       }
04576 
04577       ch->ast = chan;
04578 
04579       if ((exceed = add_in_calls(bc->port))) {
04580          char tmp[16];
04581          snprintf(tmp, sizeof(tmp), "%d", exceed);
04582          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
04583       }
04584 
04585       read_config(ch, ORG_MISDN);
04586 
04587       export_ch(chan, bc, ch);
04588 
04589       ch->ast->rings = 1;
04590       ast_setstate(ch->ast, AST_STATE_RINGING);
04591 
04592       switch (bc->pres) {
04593       case 1:
04594          pres = AST_PRES_RESTRICTED;
04595          chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
04596          break;
04597       case 2:
04598          pres = AST_PRES_UNAVAILABLE;
04599          chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
04600          break;
04601       default:
04602          pres = AST_PRES_ALLOWED;
04603          chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
04604          break;
04605       }
04606 
04607       switch (bc->screen) {
04608       default:
04609       case 0:
04610          screen = AST_PRES_USER_NUMBER_UNSCREENED;
04611          chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
04612          break;
04613       case 1:
04614          screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
04615          chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
04616          break;
04617       case 2:
04618          screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
04619          chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
04620          break;
04621       case 3:
04622          screen = AST_PRES_NETWORK_NUMBER;
04623          chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
04624          break;
04625       }
04626 
04627       chan->cid.cid_pres = pres | screen;
04628 
04629       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04630       chan->transfercapability = bc->capability;
04631 
04632       switch (bc->capability) {
04633       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04634          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
04635          break;
04636       default:
04637          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
04638       }
04639 
04640       /** queue new chan **/
04641       cl_queue_chan(&cl_te, ch);
04642 
04643       if (!strstr(ch->allowed_bearers, "all")) {
04644          int i;
04645 
04646          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
04647             if (allowed_bearers_array[i].cap == bc->capability) {
04648                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
04649                   /* The bearer capability is allowed */
04650                   if (allowed_bearers_array[i].deprecated) {
04651                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
04652                         allowed_bearers_array[i].name);
04653                   }
04654                   break;
04655                }
04656             }
04657          }  /* end for */
04658          if (i == ARRAY_LEN(allowed_bearers_array)) {
04659             /* We did not find the bearer capability */
04660             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
04661                bearer2str(bc->capability), bc->capability);
04662             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
04663 
04664             ch->state = MISDN_EXTCANTMATCH;
04665             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04666             return RESPONSE_OK;
04667          }
04668       }
04669 
04670       /* Check for Pickup Request first */
04671       if (!strcmp(chan->exten, ast_pickup_ext())) {
04672          if (!ch->noautorespond_on_setup) {
04673             int ret;/** Sending SETUP_ACK**/
04674             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04675          } else {
04676             ch->state = MISDN_INCOMING_SETUP;
04677          }
04678          if (ast_pickup_call(chan)) {
04679             hangup_chan(ch, bc);
04680          } else {
04681             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04682             ast_setstate(chan, AST_STATE_DOWN);
04683             hangup_chan(ch, bc);
04684             ch->ast = NULL;
04685             break;
04686          }
04687       }
04688 
04689       /*
04690        * added support for s extension hope it will help those poor cretains
04691        * which haven't overlap dial.
04692        */
04693       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04694       if (ai) {
04695          do_immediate_setup(bc, ch, chan);
04696          break;
04697       }
04698 
04699       /* check if we should jump into s when we have no dad */
04700       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04701       if (im && ast_strlen_zero(bc->dad)) {
04702          do_immediate_setup(bc, ch, chan);
04703          break;
04704       }
04705 
04706       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
04707       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04708          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04709             ast_log(LOG_WARNING,
04710                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04711                bc->dad, ch->context, bc->port);
04712             strcpy(ch->ast->exten, "i");
04713             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04714             ch->state = MISDN_DIALING;
04715             start_pbx(ch, bc, chan);
04716             break;
04717          }
04718 
04719          ast_log(LOG_WARNING,
04720             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04721             "\tMaybe you want to add an 'i' extension to catch this case.\n",
04722             bc->dad, ch->context, bc->port);
04723          if (bc->nt)
04724             hanguptone_indicate(ch);
04725 
04726          ch->state = MISDN_EXTCANTMATCH;
04727          bc->out_cause = AST_CAUSE_UNALLOCATED;
04728 
04729          if (bc->nt)
04730             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04731          else
04732             misdn_lib_send_event(bc, EVENT_RELEASE );
04733 
04734          break;
04735       }
04736 
04737       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
04738        * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
04739        * will be used by Asterisk automatically. */
04740       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04741          if (!ch->noautorespond_on_setup) {
04742             ch->state=MISDN_DIALING;
04743             misdn_lib_send_event(bc, EVENT_PROCEEDING );
04744          } else {
04745             ch->state = MISDN_INCOMING_SETUP;
04746          }
04747          start_pbx(ch, bc, chan);
04748          break;
04749       }
04750 
04751 
04752       /*
04753        * When we are NT and overlapdial is set and if 
04754        * the number is empty, we wait for the ISDN timeout
04755        * instead of our own timer.
04756        */
04757       if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04758          wait_for_digits(ch, bc, chan);
04759          break;
04760       }
04761 
04762       /* 
04763        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
04764        * Infos with a Interdigit Timeout.
04765        * */
04766       if (ch->overlap_dial) {
04767          ast_mutex_lock(&ch->overlap_tv_lock);
04768          ch->overlap_tv = ast_tvnow();
04769          ast_mutex_unlock(&ch->overlap_tv_lock);
04770 
04771          wait_for_digits(ch, bc, chan);
04772          if (ch->overlap_dial_task == -1) 
04773             ch->overlap_dial_task = 
04774                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04775 
04776          break;
04777       }
04778 
04779       /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
04780        * without interdigit timeout.
04781        * */
04782       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04783          wait_for_digits(ch, bc, chan);
04784          break;
04785       }
04786 
04787       /*
04788        * If the extension exists let's just jump into it.
04789        * */
04790       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04791          if (bc->need_more_infos)
04792             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04793          else
04794             misdn_lib_send_event(bc, EVENT_PROCEEDING);
04795 
04796          ch->state = MISDN_DIALING;
04797          start_pbx(ch, bc, chan);
04798          break;
04799       }
04800    }
04801    break;
04802 
04803    case EVENT_SETUP_ACKNOWLEDGE:
04804    {
04805       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04806 
04807       if (bc->channel) 
04808          update_name(ch->ast,bc->port,bc->channel);
04809       
04810       if (!ast_strlen_zero(bc->infos_pending)) {
04811          /* TX Pending Infos */
04812          strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04813 
04814          if (!ch->ast)
04815             break;
04816          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04817          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04818          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04819 
04820          misdn_lib_send_event(bc, EVENT_INFORMATION);
04821       }
04822    }
04823    break;
04824    case EVENT_PROCEEDING:
04825    {
04826       if (misdn_cap_is_speech(bc->capability) &&
04827            misdn_inband_avail(bc) ) {
04828          start_bc_tones(ch);
04829       }
04830 
04831       ch->state = MISDN_PROCEEDING;
04832       
04833       if (!ch->ast)
04834          break;
04835 
04836       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04837    }
04838    break;
04839    case EVENT_PROGRESS:
04840 
04841       if (bc->channel) 
04842          update_name(ch->ast, bc->port, bc->channel);
04843 
04844       if (!bc->nt ) {
04845          if ( misdn_cap_is_speech(bc->capability) &&
04846               misdn_inband_avail(bc)
04847             ) {
04848             start_bc_tones(ch);
04849          }
04850          
04851          ch->state = MISDN_PROGRESS;
04852 
04853          if (!ch->ast)
04854             break;
04855          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04856       }
04857       break;
04858       
04859       
04860    case EVENT_ALERTING:
04861    {
04862       ch->state = MISDN_ALERTING;
04863       
04864       if (!ch->ast)
04865          break;
04866 
04867       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04868       ast_setstate(ch->ast, AST_STATE_RINGING);
04869       
04870       cb_log(7, bc->port, " --> Set State Ringing\n");
04871       
04872       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04873          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04874          start_bc_tones(ch);
04875       } else {
04876          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04877          if (ch->far_alerting) {
04878             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04879             start_bc_tones(ch);
04880             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04881          }
04882       }
04883    }
04884    break;
04885    case EVENT_CONNECT:
04886    {
04887       struct ast_channel *bridged;
04888 
04889       /*we answer when we've got our very new L3 ID from the NT stack */
04890       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04891 
04892       if (!ch->ast)
04893          break;
04894 
04895       bridged = ast_bridged_channel(ch->ast);
04896       stop_indicate(ch);
04897 
04898       if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04899          struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04900 
04901          chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04902          if (bridged_ch) {
04903             bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04904             ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04905          }
04906       }
04907    }
04908    ch->l3id=bc->l3_id;
04909    ch->addr=bc->addr;
04910 
04911    start_bc_tones(ch);
04912    
04913    ch->state = MISDN_CONNECTED;
04914    
04915    ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04916    break;
04917    case EVENT_CONNECT_ACKNOWLEDGE:
04918    {
04919       ch->l3id = bc->l3_id;
04920       ch->addr = bc->addr;
04921 
04922       start_bc_tones(ch);
04923 
04924       ch->state = MISDN_CONNECTED;
04925    }
04926    break;
04927    case EVENT_DISCONNECT:
04928       /*we might not have an ch->ast ptr here anymore*/
04929       if (ch) {
04930          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);
04931          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04932             /* If there's inband information available (e.g. a
04933                recorded message saying what was wrong with the
04934                dialled number, or perhaps even giving an
04935                alternative number, then play it instead of
04936                immediately releasing the call */
04937             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04938       
04939             ch->state = MISDN_DISCONNECTED;
04940             start_bc_tones(ch);
04941 
04942             if (ch->ast) {
04943                ch->ast->hangupcause = bc->cause;
04944                if (bc->cause == AST_CAUSE_USER_BUSY)
04945                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04946             }
04947             ch->need_busy = 0;
04948             break;
04949          }
04950 
04951          bc->need_disconnect = 0;
04952          stop_bc_tones(ch);
04953 
04954          /* Check for held channel, to implement transfer */
04955          held_ch = find_hold_call(cl_te, bc);
04956          if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
04957             hangup_chan(ch, bc);
04958          }
04959       } else {
04960          held_ch = find_hold_call_l3(cl_te, bc->l3_id);
04961          if (held_ch && held_ch->hold.state == MISDN_HOLD_ACTIVE) {
04962             bc->need_disconnect = 0;
04963 
04964 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
04965             /*
04966              * Some phones disconnect the held call and the active call at the
04967              * same time to do the transfer.  Unfortunately, either call could
04968              * be disconnected first.
04969              */
04970             ch = find_hold_active_call(cl_te, bc);
04971             if (!ch || misdn_attempt_transfer(ch, held_ch)) {
04972                held_ch->hold.state = MISDN_HOLD_DISCONNECT;
04973                hangup_chan(held_ch, bc);
04974             }
04975 #else
04976             hangup_chan(held_ch, bc);
04977 #endif   /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
04978          }
04979       }
04980       bc->out_cause = -1;
04981       if (bc->need_release)
04982          misdn_lib_send_event(bc, EVENT_RELEASE);
04983       break;
04984    
04985    case EVENT_RELEASE:
04986       if (!ch) {
04987          ch = find_hold_call_l3(cl_te, bc->l3_id);
04988          if (!ch) {
04989             chan_misdn_log(1, bc->port,
04990                " --> no Ch, so we've already released. (%s)\n",
04991                manager_isdn_get_info(event));
04992             return -1;
04993          }
04994       }
04995 
04996       bc->need_disconnect = 0;
04997       bc->need_release = 0;
04998 
04999       hangup_chan(ch, bc);
05000       release_chan(ch, bc);
05001       break;
05002    case EVENT_RELEASE_COMPLETE:
05003       if (!ch) {
05004          ch = find_hold_call_l3(cl_te, bc->l3_id);
05005          if (!ch) {
05006             chan_misdn_log(1, bc->port,
05007                " --> no Ch, so we've already released. (%s)\n",
05008                manager_isdn_get_info(event));
05009             break;
05010          }
05011       }
05012 
05013       bc->need_disconnect = 0;
05014       bc->need_release = 0;
05015       bc->need_release_complete = 0;
05016 
05017       stop_bc_tones(ch);
05018       hangup_chan(ch, bc);
05019       release_chan(ch, bc);
05020       break;
05021    case EVENT_BCHAN_ERROR:
05022    case EVENT_CLEANUP:
05023    {
05024       stop_bc_tones(ch);
05025       
05026       switch (ch->state) {
05027       case MISDN_CALLING:
05028          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
05029          break;
05030       default:
05031          break;
05032       }
05033       
05034       hangup_chan(ch, bc);
05035       release_chan(ch, bc);
05036    }
05037    break;
05038 
05039    case EVENT_TONE_GENERATE:
05040    {
05041       int tone_len = bc->tone_cnt;
05042       struct ast_channel *ast = ch->ast;
05043       void *tmp;
05044       int res;
05045       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
05046 
05047       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
05048 
05049       if (!ast)
05050          break;
05051 
05052       if (!ast->generator)
05053          break;
05054 
05055       tmp = ast->generatordata;
05056       ast->generatordata = NULL;
05057       generate = ast->generator->generate;
05058 
05059       if (tone_len < 0 || tone_len > 512 ) {
05060          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
05061          tone_len = 128;
05062       }
05063 
05064       res = generate(ast, tmp, tone_len, tone_len);
05065       ast->generatordata = tmp;
05066       
05067       if (res) {
05068          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
05069          ast_deactivate_generator(ast);
05070       } else {
05071          bc->tone_cnt = 0;
05072       }
05073    }
05074    break;
05075 
05076    case EVENT_BCHAN_DATA:
05077    {
05078       if (ch->bc->AOCD_need_export)
05079          export_aoc_vars(ch->originator, ch->ast, ch->bc);
05080       if (!misdn_cap_is_speech(ch->bc->capability)) {
05081          struct ast_frame frame;
05082          /*In Data Modes we queue frames*/
05083          memset(&frame, 0, sizeof(frame));
05084          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
05085          frame.subclass = AST_FORMAT_ALAW;
05086          frame.datalen = bc->bframe_len;
05087          frame.samples = bc->bframe_len;
05088          frame.mallocd = 0;
05089          frame.offset = 0;
05090          frame.delivery = ast_tv(0,0);
05091          frame.src = NULL;
05092          frame.data.ptr = bc->bframe;
05093 
05094          if (ch->ast) 
05095             ast_queue_frame(ch->ast, &frame);
05096       } else {
05097          fd_set wrfs;
05098          struct timeval tv = { 0, 0 };
05099          int t;
05100 
05101          FD_ZERO(&wrfs);
05102          FD_SET(ch->pipe[1], &wrfs);
05103 
05104          t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
05105 
05106          if (!t) {
05107             chan_misdn_log(9, bc->port, "Select Timed out\n");
05108             break;
05109          }
05110          
05111          if (t < 0) {
05112             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
05113             break;
05114          }
05115          
05116          if (FD_ISSET(ch->pipe[1], &wrfs)) {
05117             chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
05118             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
05119                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
05120 
05121                stop_bc_tones(ch);
05122                hangup_chan(ch, bc);
05123                release_chan(ch, bc);
05124             }
05125          } else {
05126             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
05127          }
05128       }
05129    }
05130    break;
05131    case EVENT_TIMEOUT:
05132    {
05133       if (ch && bc)
05134          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
05135 
05136       switch (ch->state) {
05137       case MISDN_DIALING:
05138       case MISDN_PROGRESS:
05139          if (bc->nt && !ch->nttimeout)
05140             break;
05141          
05142       case MISDN_CALLING:
05143       case MISDN_ALERTING:
05144       case MISDN_PROCEEDING:
05145       case MISDN_CALLING_ACKNOWLEDGE:
05146          if (bc->nt) {
05147             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
05148             hanguptone_indicate(ch);
05149          }
05150             
05151          bc->out_cause = AST_CAUSE_UNALLOCATED;
05152          misdn_lib_send_event(bc, EVENT_DISCONNECT);
05153          break;
05154 
05155       case MISDN_WAITING4DIGS:
05156          if (bc->nt) {
05157             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
05158             bc->out_cause = AST_CAUSE_UNALLOCATED;
05159             hanguptone_indicate(ch);
05160             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05161          } else {
05162             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
05163             misdn_lib_send_event(bc, EVENT_RELEASE);
05164          }
05165             
05166          break;
05167 
05168       case MISDN_CLEANING: 
05169          chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
05170          break;
05171 
05172       default:
05173          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
05174       }
05175    }
05176    break;
05177 
05178     
05179    /****************************/
05180    /** Supplementary Services **/
05181    /****************************/
05182    case EVENT_RETRIEVE:
05183       if (!ch) {
05184          chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
05185          ch = find_hold_call_l3(cl_te, bc->l3_id);
05186          if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
05187             ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
05188             misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05189             break;
05190          }
05191       }
05192 
05193       /* remember the channel again */
05194       ch->bc = bc;
05195 
05196       ch->hold.state = MISDN_HOLD_IDLE;
05197       ch->hold.port = 0;
05198       ch->hold.channel = 0;
05199 
05200       ast_queue_control(ch->ast, AST_CONTROL_UNHOLD);
05201    
05202       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
05203          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
05204          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05205       }
05206       break;
05207     
05208    case EVENT_HOLD:
05209    {
05210       int hold_allowed;
05211       struct ast_channel *bridged;
05212 
05213       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
05214       if (!hold_allowed) {
05215          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
05216          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05217          break;
05218       }
05219 
05220       bridged = ast_bridged_channel(ch->ast);
05221       if (bridged) {
05222          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
05223          ch->l3id = bc->l3_id;
05224 
05225          /* forget the channel now */
05226          ch->bc = NULL;
05227          ch->hold.state = MISDN_HOLD_ACTIVE;
05228          ch->hold.port = bc->port;
05229          ch->hold.channel = bc->channel;
05230 
05231          ast_queue_control(ch->ast, AST_CONTROL_HOLD);
05232          
05233          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
05234       } else {
05235          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05236          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
05237       }
05238    } 
05239    break;
05240    
05241    case EVENT_FACILITY:
05242       print_facility(&(bc->fac_in), bc);
05243       
05244       switch (bc->fac_in.Function) {
05245 #ifdef HAVE_MISDN_FAC_RESULT
05246       case Fac_RESULT:
05247       break;
05248 #endif
05249       case Fac_CD:
05250          if (ch) {
05251             struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05252             struct chan_list *ch_br;
05253             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
05254                ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
05255                /*ch->state = MISDN_FACILITY_DEFLECTED;*/
05256                if (ch_br->bc) {
05257                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
05258                      ch_br->state = MISDN_DIALING;
05259                      if (pbx_start_chan(ch_br) < 0) {
05260                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
05261                      }
05262                   }
05263                }
05264             }
05265             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05266          } 
05267          break;
05268       case Fac_AOCDCurrency:
05269          if (ch) {
05270             bc->AOCDtype = Fac_AOCDCurrency;
05271             memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
05272             bc->AOCD_need_export = 1;
05273             export_aoc_vars(ch->originator, ch->ast, bc);
05274          }
05275          break;
05276       case Fac_AOCDChargingUnit:
05277          if (ch) {
05278             bc->AOCDtype = Fac_AOCDChargingUnit;
05279             memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
05280             bc->AOCD_need_export = 1;
05281             export_aoc_vars(ch->originator, ch->ast, bc);
05282          }
05283          break;
05284       case Fac_None:
05285 #ifdef HAVE_MISDN_FAC_ERROR
05286       case Fac_ERROR:
05287 #endif
05288       break;
05289       default:
05290          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
05291       }
05292       
05293       break;
05294 
05295    case EVENT_RESTART:
05296 
05297       if (!bc->dummy) {
05298          stop_bc_tones(ch);
05299          release_chan(ch, bc);
05300       }
05301       break;
05302 
05303    default:
05304       chan_misdn_log(1, 0, "Got Unknown Event\n");
05305       break;
05306    }
05307    
05308    return RESPONSE_OK;
05309 }

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

Definition at line 5869 of file chan_misdn.c.

References chan_list::bc, cl_te, find_chan_by_bc(), chan_list::jb, and misdn_jb_empty().

Referenced by load_module().

05870 {
05871    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05872    
05873    if (ch && ch->jb) {
05874       return misdn_jb_empty(ch->jb, buf, len);
05875    }
05876    
05877    return -1;
05878 }

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

Definition at line 6052 of file chan_misdn.c.

References ast_console_puts(), ast_log(), ast_strlen_zero(), buf, errno, LOG_WARNING, max_ports, misdn_debug, and misdn_debug_only.

Referenced by cb_events(), cl_queue_chan(), config_jitterbuffer(), debug_numplan(), dialtone_indicate(), do_immediate_setup(), export_ch(), find_chan_by_bc(), find_chan_by_pid(), find_hold_call(), import_ch(), init_chan_list(), load_module(), misdn_answer(), misdn_attempt_transfer(), misdn_bridge(), misdn_call(), misdn_check_l2l1(), misdn_digit_end(), misdn_facility_exec(), 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().

06053 {
06054    va_list ap;
06055    char buf[1024];
06056    char port_buf[8];
06057 
06058    if (! ((0 <= port) && (port <= max_ports))) {
06059       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
06060       port = 0;
06061       level = -1;
06062    }
06063 
06064    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
06065 
06066    va_start(ap, tmpl);
06067    vsnprintf(buf, sizeof(buf), tmpl, ap);
06068    va_end(ap);
06069 
06070    if (level == -1)
06071       ast_log(LOG_WARNING, "%s", buf);
06072 
06073    else if (misdn_debug_only[port] ? 
06074          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
06075        : level <= misdn_debug[port]) {
06076       
06077       ast_console_puts(port_buf);
06078       ast_console_puts(buf);
06079    }
06080    
06081    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
06082       char ctimebuf[30];
06083       time_t tm = time(NULL);
06084       char *tmp = ctime_r(&tm, ctimebuf), *p;
06085 
06086       FILE *fp = fopen(global_tracefile, "a+");
06087 
06088       p = strchr(tmp, '\n');
06089       if (p)
06090          *p = ':';
06091       
06092       if (!fp) {
06093          ast_console_puts("Error opening Tracefile: [ ");
06094          ast_console_puts(global_tracefile);
06095          ast_console_puts(" ] ");
06096          
06097          ast_console_puts(strerror(errno));
06098          ast_console_puts("\n");
06099          return ;
06100       }
06101       
06102       fputs(tmp, fp);
06103       fputs(" ", fp);
06104       fputs(port_buf, fp);
06105       fputs(" ", fp);
06106       fputs(buf, fp);
06107 
06108       fclose(fp);
06109    }
06110 }

static void cl_dequeue_chan ( struct chan_list **  list,
struct chan_list chan 
) [static]

Definition at line 3805 of file chan_misdn.c.

References ast_dsp_free(), ast_mutex_lock(), ast_mutex_unlock(), chan, cl_te_lock, and chan_list::next.

Referenced by release_chan(), and release_chan_early().

03806 {
03807    struct chan_list *help;
03808 
03809    if (chan->dsp) 
03810       ast_dsp_free(chan->dsp);
03811 
03812    ast_mutex_lock(&cl_te_lock);
03813    if (!*list) {
03814       ast_mutex_unlock(&cl_te_lock);
03815       return;
03816    }
03817   
03818    if (*list == chan) {
03819       *list = (*list)->next;
03820       ast_mutex_unlock(&cl_te_lock);
03821       return;
03822    }
03823   
03824    for (help = *list; help->next; help = help->next) {
03825       if (help->next == chan) {
03826          help->next = help->next->next;
03827          ast_mutex_unlock(&cl_te_lock);
03828          return;
03829       }
03830    }
03831    
03832    ast_mutex_unlock(&cl_te_lock);
03833 }

static void cl_queue_chan ( struct chan_list **  list,
struct chan_list chan 
) [static]

Definition at line 3789 of file chan_misdn.c.

References ast_mutex_lock(), ast_mutex_unlock(), chan, chan_misdn_log(), cl_te_lock, ast_channel::next, and chan_list::next.

Referenced by cb_events(), and misdn_request().

03790 {
03791    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03792   
03793    ast_mutex_lock(&cl_te_lock);
03794    if (!*list) {
03795       *list = chan;
03796    } else {
03797       struct chan_list *help = *list;
03798       for (; help->next; help = help->next); 
03799       help->next = chan;
03800    }
03801    chan->next = NULL;
03802    ast_mutex_unlock(&cl_te_lock);
03803 }

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

Definition at line 1852 of file chan_misdn.c.

References ast_complete_channels(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.

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

01853 {
01854    return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
01855 }

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

Definition at line 1857 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_set_debug().

01858 {
01859    if (a->n)
01860       return NULL;
01861 
01862    switch (a->pos) {
01863    case 4:
01864       if (a->word[0] == 'p')
01865          return ast_strdup("port");
01866       else if (a->word[0] == 'o')
01867          return ast_strdup("only");
01868       break;
01869    case 6:
01870       if (a->word[0] == 'o')
01871          return ast_strdup("only");
01872       break;
01873    }
01874    return NULL;
01875 }

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

Definition at line 1877 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_GEN_FIRST, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.

Referenced by handle_cli_misdn_show_config().

01878 {
01879    char buffer[BUFFERSIZE];
01880    enum misdn_cfg_elements elem;
01881    int wordlen = strlen(a->word);
01882    int which = 0;
01883    int port = 0;
01884 
01885    switch (a->pos) {
01886    case 3:
01887       if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n))
01888          return ast_strdup("description");
01889       if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n))
01890          return ast_strdup("descriptions");
01891       if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n))
01892          return ast_strdup("0");
01893       while ((port = misdn_cfg_get_next_port(port)) != -1) {
01894          snprintf(buffer, sizeof(buffer), "%d", port);
01895          if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
01896             return ast_strdup(buffer);
01897          }
01898       }
01899       break;
01900    case 4:
01901       if (strstr(a->line, "description ")) {
01902          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01903             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
01904                continue;
01905             misdn_cfg_get_name(elem, buffer, sizeof(buffer));
01906             if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
01907                if (++which > a->n)
01908                   return ast_strdup(buffer);
01909             }
01910          }
01911       } else if (strstr(a->line, "descriptions ")) {
01912          if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n))
01913             return ast_strdup("general");
01914          if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n))
01915             return ast_strdup("ports");
01916       }
01917       break;
01918    }
01919    return NULL;
01920 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

Definition at line 2032 of file chan_misdn.c.

References chan_list::bc, cb_log, chan_misdn_log(), chan_list::jb, chan_list::jb_len, chan_list::jb_upper_threshold, len(), misdn_jb_destroy(), misdn_jb_init(), misdn_bchannel::nojitter, and misdn_bchannel::port.

Referenced by misdn_set_opt_exec(), and read_config().

02033 {
02034    struct misdn_bchannel *bc = ch->bc;
02035    int len = ch->jb_len, threshold = ch->jb_upper_threshold;
02036    
02037    chan_misdn_log(5, bc->port, "config_jb: Called\n");
02038    
02039    if (! len) {
02040       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
02041       bc->nojitter=1;
02042    } else {
02043       if (len <= 100 || len > 8000) {
02044          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
02045          len = 1000;
02046       }
02047 
02048       if ( threshold > len ) {
02049          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
02050       }
02051 
02052       if ( ch->jb) {
02053          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
02054          misdn_jb_destroy(ch->jb);
02055          ch->jb = NULL;
02056       }
02057 
02058       ch->jb=misdn_jb_init(len, threshold);
02059 
02060       if (!ch->jb ) 
02061          bc->nojitter = 1;
02062    }
02063 }

void debug_numplan ( int  port,
int  numplan,
char *  type 
)

Definition at line 2066 of file chan_misdn.c.

References chan_misdn_log(), NUMPLAN_INTERNATIONAL, NUMPLAN_NATIONAL, NUMPLAN_SUBSCRIBER, and NUMPLAN_UNKNOWN.

Referenced by read_config().

02067 {
02068    switch (numplan) {
02069    case NUMPLAN_INTERNATIONAL:
02070       chan_misdn_log(2, port, " --> %s: International\n", type);
02071       break;
02072    case NUMPLAN_NATIONAL:
02073       chan_misdn_log(2, port, " --> %s: National\n", type);
02074       break;
02075    case NUMPLAN_SUBSCRIBER:
02076       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
02077       break;
02078    case NUMPLAN_UNKNOWN:
02079       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
02080       break;
02081       /* Maybe we should cut off the prefix if present ? */
02082    default:
02083       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
02084       break;
02085    }
02086 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

Definition at line 3260 of file chan_misdn.c.

References chan_list::ast, ast_get_indication_tone(), ast_playtones_start(), chan_list::bc, chan_misdn_log(), tone_zone_sound::data, misdn_cfg_get(), MISDN_CFG_NODIALTONE, chan_list::norxtone, chan_list::notxtone, misdn_bchannel::port, chan_list::ts, and ast_channel::zone.

Referenced by wait_for_digits().

03261 {
03262    const struct tone_zone_sound *ts = NULL;
03263    struct ast_channel *ast = cl->ast;
03264    int nd = 0;
03265 
03266    if (!ast) {
03267       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03268       return -1;
03269    }
03270 
03271    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03272 
03273    if (nd) {
03274       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03275       return 0;
03276    }
03277    
03278    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03279    ts = ast_get_indication_tone(ast->zone, "dial");
03280    cl->ts = ts;   
03281    
03282    if (ts) {
03283       cl->notxtone = 0;
03284       cl->norxtone = 0;
03285       /* This prods us in misdn_write */
03286       ast_playtones_start(ast, 0, ts->data, 0);
03287    }
03288 
03289    return 0;
03290 }

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

Definition at line 4061 of file chan_misdn.c.

References chan_list::ast, ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_FRAME_DTMF, ast_queue_frame(), ast_strdupa, ast_strlen_zero(), ast_tv(), chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_frame::data, ast_frame::datalen, ast_frame::delivery, EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_RELEASE_COMPLETE, EVENT_SETUP_ACKNOWLEDGE, ast_channel::exten, ast_frame::frametype, hangup_chan(), hanguptone_indicate(), ast_frame::mallocd, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_DIALING, MISDN_INCOMING_SETUP, misdn_lib_is_ptp(), misdn_lib_send_event(), chan_list::noautorespond_on_setup, misdn_bchannel::nt, misdn_bchannel::oad, 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().

04062 {
04063    char *predial;
04064    struct ast_frame fr;
04065 
04066    predial = ast_strdupa(ast->exten);
04067 
04068    ch->state = MISDN_DIALING;
04069 
04070    if (!ch->noautorespond_on_setup) {
04071       if (bc->nt) {
04072          int ret; 
04073          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04074       } else {
04075          int ret;
04076          if ( misdn_lib_is_ptp(bc->port)) {
04077             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04078          } else {
04079             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
04080          }
04081       }
04082    } else {
04083       ch->state = MISDN_INCOMING_SETUP;
04084    }
04085 
04086    chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, ast->cid.cid_num);
04087   
04088    strcpy(ast->exten, "s");
04089   
04090    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
04091       ast = NULL;
04092       bc->out_cause = AST_CAUSE_UNALLOCATED;
04093       hangup_chan(ch, bc);
04094       hanguptone_indicate(ch);
04095 
04096       if (bc->nt)
04097          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04098       else
04099          misdn_lib_send_event(bc, EVENT_DISCONNECT );
04100    }
04101   
04102   
04103    while (!ast_strlen_zero(predial) ) {
04104       fr.frametype = AST_FRAME_DTMF;
04105       fr.subclass = *predial;
04106       fr.src = NULL;
04107       fr.data.ptr = NULL;
04108       fr.datalen = 0;
04109       fr.samples = 0;
04110       fr.mallocd = 0;
04111       fr.offset = 0;
04112       fr.delivery = ast_tv(0,0);
04113 
04114       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04115          ast_queue_frame(ch->ast, &fr);
04116       }
04117       predial++;
04118    }
04119 }

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

Definition at line 680 of file chan_misdn.c.

References misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, misdn_bchannel::AOCDtype, ast_bridged_channel(), buf, misdn_bchannel::chargingUnit, misdn_bchannel::currency, ORG_AST, and pbx_builtin_setvar_helper().

Referenced by cb_events().

00681 {
00682    char buf[128];
00683 
00684    if (!bc->AOCD_need_export || !ast)
00685       return;
00686 
00687    if (originator == ORG_AST) {
00688       ast = ast_bridged_channel(ast);
00689       if (!ast)
00690          return;
00691    }
00692 
00693    switch (bc->AOCDtype) {
00694    case Fac_AOCDCurrency:
00695       pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
00696       if (bc->AOCD.currency.chargeNotAvailable)
00697          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00698       else {
00699          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00700          if (bc->AOCD.currency.freeOfCharge)
00701             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00702          else {
00703             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00704             if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
00705                pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
00706                if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
00707                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00708             }
00709          }
00710       }
00711       break;
00712    case Fac_AOCDChargingUnit:
00713       pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
00714       if (bc->AOCD.chargingUnit.chargeNotAvailable)
00715          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00716       else {
00717          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00718          if (bc->AOCD.chargingUnit.freeOfCharge)
00719             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00720          else {
00721             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00722             if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
00723                pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
00724                if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
00725                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00726             }
00727          }
00728       }
00729       break;
00730    default:
00731       break;
00732    }
00733    
00734    bc->AOCD_need_export = 0;
00735 }

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

References ast_strlen_zero(), chan, 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().

04215 {
04216    char tmp[32];
04217    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04218    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04219    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04220 
04221    if (bc->sending_complete) {
04222       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04223       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04224    }
04225 
04226    if (bc->urate) {
04227       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04228       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04229    }
04230 
04231    if (bc->uulen)
04232       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04233 
04234    if (!ast_strlen_zero(bc->keypad)) 
04235       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04236 }

static struct chan_list * find_chan_by_bc ( struct chan_list list,
struct misdn_bchannel bc 
) [static]

Definition at line 3699 of file chan_misdn.c.

References chan_list::bc, chan_misdn_log(), misdn_bchannel::dad, chan_list::next, misdn_bchannel::oad, and misdn_bchannel::port.

Referenced by cb_events(), and chan_misdn_jb_empty().

03700 {
03701    struct chan_list *help = list;
03702    for (; help; help = help->next) {
03703       if (help->bc == bc) return help;
03704    }
03705 
03706    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03707 
03708    return NULL;
03709 }

static struct chan_list * find_chan_by_pid ( struct chan_list list,
int  pid 
) [static]

Definition at line 3711 of file chan_misdn.c.

References chan_list::bc, chan_misdn_log(), chan_list::next, and misdn_bchannel::pid.

Referenced by import_ch().

03712 {
03713    struct chan_list *help = list;
03714    for (; help; help = help->next) {
03715       if ( help->bc && (help->bc->pid == pid) ) return help;
03716    }
03717 
03718    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03719 
03720    return NULL;
03721 }

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

Definition at line 3769 of file chan_misdn.c.

References chan_list::ast, chan_list::bc, chan_list::hold, MISDN_ALERTING, MISDN_CONNECTED, MISDN_HOLD_IDLE, MISDN_PROCEEDING, MISDN_PROGRESS, chan_list::next, misdn_bchannel::port, chan_list::state, and hold_info::state.

Referenced by cb_events().

03770 {
03771    for (; list; list = list->next) {
03772       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
03773          && list->ast) {
03774          switch (list->state) {
03775          case MISDN_PROCEEDING:
03776          case MISDN_PROGRESS:
03777          case MISDN_ALERTING:
03778          case MISDN_CONNECTED:
03779             return list;
03780          default:
03781             break;
03782          }
03783       }
03784    }
03785    return NULL;
03786 }

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

Definition at line 3723 of file chan_misdn.c.

References chan_list::bc, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, misdn_bchannel::dad, chan_list::hold, MISDN_HOLD_ACTIVE, chan_list::next, misdn_bchannel::oad, hold_info::port, misdn_bchannel::port, misdn_bchannel::pri, and hold_info::state.

Referenced by cb_events().

03724 {
03725    struct chan_list *help = list;
03726 
03727    if (bc->pri) return NULL;
03728 
03729    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03730    for (;help; help = help->next) {
03731       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
03732       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port)
03733          return help;
03734    }
03735    chan_misdn_log(6, bc->port, "$$$ find_hold_call: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03736 
03737    return NULL;
03738 }

static struct chan_list* find_hold_call_l3 ( struct chan_list list,
unsigned long  l3_id 
) [static]

Definition at line 3741 of file chan_misdn.c.

References chan_list::hold, chan_list::l3id, MISDN_HOLD_IDLE, chan_list::next, and hold_info::state.

Referenced by cb_events().

03742 {
03743    struct chan_list *help = list;
03744 
03745    for (; help; help = help->next) {
03746       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id)
03747          return help;
03748    }
03749 
03750    return NULL;
03751 }

static void free_robin_list ( void   )  [static]

Definition at line 428 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

00429 {
00430    struct robin_list *r;
00431    struct robin_list *next;
00432 
00433    for (r = robin, robin = NULL; r; r = next) {
00434       next = r->next;
00435       ast_free(r->group);
00436       ast_free(r);
00437    }
00438 }

static struct chan_list* get_chan_by_ast ( struct ast_channel ast  )  [static]

Definition at line 557 of file chan_misdn.c.

References chan_list::ast, cl_te, and chan_list::next.

Referenced by misdn_bridge().

00558 {
00559    struct chan_list *tmp;
00560   
00561    for (tmp=cl_te; tmp; tmp = tmp->next) {
00562       if ( tmp->ast == ast ) return tmp;
00563    }
00564   
00565    return NULL;
00566 }

static struct chan_list* get_chan_by_ast_name ( char *  name  )  [static]

Definition at line 568 of file chan_misdn.c.

References chan_list::ast, cl_te, ast_channel::name, and chan_list::next.

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

00569 {
00570    struct chan_list *tmp;
00571   
00572    for (tmp=cl_te; tmp; tmp = tmp->next) {
00573       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
00574    }
00575   
00576    return NULL;
00577 }

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

Definition at line 440 of file chan_misdn.c.

References robin_list::group, robin_list::next, and robin.

Referenced by misdn_request().

00441 {
00442    struct robin_list *new;
00443    struct robin_list *iter = robin;
00444    for (; iter; iter = iter->next) {
00445       if (!strcasecmp(iter->group, group)) {
00446          return iter;
00447       }
00448    }
00449    new = ast_calloc(1, sizeof(*new));
00450    if (!new) {
00451       return NULL;
00452    }
00453    new->group = ast_strdup(group);
00454    if (!new->group) {
00455       ast_free(new);
00456       return NULL;
00457    }
00458    new->channel = 1;
00459    if (robin) {
00460       new->next = robin;
00461       robin->prev = new;
00462    }
00463    robin = new;
00464    return robin;
00465 }

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

Definition at line 1021 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_block(), and ast_cli_entry::usage.

01022 {
01023    switch (cmd) {
01024    case CLI_INIT:
01025       e->command = "misdn port block";
01026       e->usage =
01027          "Usage: misdn port block <port>\n"
01028          "       Block the specified port by <port>.\n";
01029       return NULL;
01030    case CLI_GENERATE:
01031       return NULL;
01032    }
01033 
01034    if (a->argc != 4)
01035       return CLI_SHOWUSAGE;
01036 
01037    misdn_lib_port_block(atoi(a->argv[3]));
01038 
01039    return CLI_SUCCESS;
01040 }

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

Definition at line 1126 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_get_port_down(), and ast_cli_entry::usage.

01127 {
01128    switch (cmd) {
01129    case CLI_INIT:
01130       e->command = "misdn port down";
01131       e->usage =
01132          "Usage: misdn port down <port>\n"
01133          "       Try to deactivate the L1 on the given port.\n";
01134       return NULL;
01135    case CLI_GENERATE:
01136       return NULL;
01137    }
01138 
01139    if (a->argc != 4)
01140       return CLI_SHOWUSAGE;
01141 
01142    misdn_lib_get_port_down(atoi(a->argv[3]));
01143 
01144    return CLI_SUCCESS;
01145 }

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

Definition at line 1042 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_unblock(), and ast_cli_entry::usage.

01043 {
01044    switch (cmd) {
01045    case CLI_INIT:
01046       e->command = "misdn port unblock";
01047       e->usage =
01048          "Usage: misdn port unblock <port>\n"
01049          "       Unblock the port specified by <port>.\n";
01050       return NULL;
01051    case CLI_GENERATE:
01052       return NULL;
01053    }
01054 
01055    if (a->argc != 4)
01056       return CLI_SHOWUSAGE;
01057 
01058    misdn_lib_port_unblock(atoi(a->argv[3]));
01059 
01060    return CLI_SUCCESS;
01061 }

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

Definition at line 1105 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_get_port_up(), and ast_cli_entry::usage.

01106 {
01107    switch (cmd) {
01108    case CLI_INIT:
01109       e->command = "misdn port up";
01110       e->usage =
01111          "Usage: misdn port up <port>\n"
01112          "       Try to establish L1 on the given port.\n";
01113       return NULL;
01114    case CLI_GENERATE:
01115       return NULL;
01116    }
01117 
01118    if (a->argc != 4)
01119       return CLI_SHOWUSAGE;
01120 
01121    misdn_lib_get_port_up(atoi(a->argv[3]));
01122 
01123    return CLI_SUCCESS;
01124 }

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

Definition at line 1319 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, reload_config(), and ast_cli_entry::usage.

01320 {
01321    switch (cmd) {
01322    case CLI_INIT:
01323       e->command = "misdn reload";
01324       e->usage =
01325          "Usage: misdn reload\n"
01326          "       Reload internal mISDN config, read from the config\n"
01327          "       file.\n";
01328       return NULL;
01329    case CLI_GENERATE:
01330       return NULL;
01331    }
01332 
01333    if (a->argc != 2)
01334       return CLI_SHOWUSAGE;
01335 
01336    ast_cli(a->fd, "Reloading mISDN configuration\n");
01337    reload_config();
01338    return CLI_SUCCESS;
01339 }

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

Definition at line 1084 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_pid_restart(), and ast_cli_entry::usage.

01085 {
01086    switch (cmd) {
01087    case CLI_INIT:
01088       e->command = "misdn restart pid";
01089       e->usage =
01090          "Usage: misdn restart pid <pid>\n"
01091          "       Restart the given pid\n";
01092       return NULL;
01093    case CLI_GENERATE:
01094       return NULL;
01095    }
01096 
01097    if (a->argc != 4)
01098       return CLI_SHOWUSAGE;
01099 
01100    misdn_lib_pid_restart(atoi(a->argv[3]));
01101 
01102    return CLI_SUCCESS;
01103 }

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

Definition at line 1063 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_restart(), and ast_cli_entry::usage.

01064 {
01065    switch (cmd) {
01066    case CLI_INIT:
01067       e->command = "misdn restart port";
01068       e->usage =
01069          "Usage: misdn restart port <port>\n"
01070          "       Restart the given port.\n";
01071       return NULL;
01072    case CLI_GENERATE:
01073       return NULL;
01074    }
01075 
01076    if (a->argc != 4)
01077       return CLI_SHOWUSAGE;
01078 
01079    misdn_lib_port_restart(atoi(a->argv[3]));
01080 
01081    return CLI_SUCCESS;
01082 }

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

Definition at line 1721 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, chan_list::ast, ast_cli(), ast_dtmf_stream(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, get_chan_by_ast_name(), msg, msglen, send_digit_to_chan(), and ast_cli_entry::usage.

01722 {
01723    char *channame; 
01724    char *msg; 
01725    struct chan_list *tmp;
01726    int i, msglen;
01727 
01728    switch (cmd) {
01729    case CLI_INIT:
01730       e->command = "misdn send digit";
01731       e->usage =
01732          "Usage: misdn send digit <channel> \"<msg>\" \n"
01733          "       Send <digit> to <channel> as DTMF Tone\n"
01734          "       when channel is a mISDN channel\n";
01735       return NULL;
01736    case CLI_GENERATE:
01737       return complete_ch(a);
01738    }
01739 
01740    if (a->argc != 5)
01741       return CLI_SHOWUSAGE;
01742 
01743    channame = a->argv[3];
01744    msg = a->argv[4];
01745    msglen = strlen(msg);
01746 
01747    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01748 
01749    tmp = get_chan_by_ast_name(channame);
01750    if (!tmp) {
01751       ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
01752       return CLI_SUCCESS; 
01753    }
01754 #if 1
01755    for (i = 0; i < msglen; i++) {
01756       ast_cli(a->fd, "Sending: %c\n", msg[i]);
01757       send_digit_to_chan(tmp, msg[i]);
01758       /* res = ast_safe_sleep(tmp->ast, 250); */
01759       usleep(250000);
01760       /* res = ast_waitfor(tmp->ast,100); */
01761    }
01762 #else
01763    ast_dtmf_stream(tmp->ast, NULL, msg, 250);
01764 #endif
01765 
01766    return CLI_SUCCESS;
01767 }

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

Definition at line 1814 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), chan_list::bc, 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(), msg, and ast_cli_entry::usage.

01815 {
01816    char *channame;
01817    char *msg;
01818    struct chan_list *tmp;
01819 
01820    switch (cmd) {
01821    case CLI_INIT:
01822       e->command = "misdn send display";
01823       e->usage =
01824          "Usage: misdn send display <channel> \"<msg>\" \n"
01825          "       Send <msg> to <channel> as Display Message\n"
01826          "       when channel is a mISDN channel\n";
01827       return NULL;
01828    case CLI_GENERATE:
01829       return complete_ch(a);
01830    }
01831 
01832    if (a->argc != 5)
01833       return CLI_SHOWUSAGE;
01834 
01835    channame = a->argv[3];
01836    msg = a->argv[4];
01837 
01838    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01839    tmp = get_chan_by_ast_name(channame);
01840     
01841    if (tmp && tmp->bc) {
01842       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01843       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01844    } else {
01845       ast_cli(a->fd, "No such channel %s\n", channame);
01846       return CLI_SUCCESS;
01847    }
01848 
01849    return CLI_SUCCESS;
01850 }

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

Definition at line 1601 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_copy_string(), ast_verbose, chan_list::bc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), dummy(), EVENT_FACILITY, misdn_bchannel::fac_out, get_chan_by_ast_name(), misdn_lib_port_is_nt(), misdn_lib_send_event(), misdn_make_dummy(), and ast_cli_entry::usage.

01602 {
01603    char *channame; 
01604    char *nr;
01605    struct chan_list *tmp;
01606    int port; 
01607    char *served_nr;
01608    struct misdn_bchannel dummy, *bc=&dummy;
01609  
01610    switch (cmd) {
01611    case CLI_INIT:
01612       e->command = "misdn send facility";
01613       e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
01614       "\t type is one of:\n"
01615       "\t - calldeflect\n"
01616       "\t - CFActivate\n"
01617       "\t - CFDeactivate\n";
01618 
01619       return NULL;
01620    case CLI_GENERATE:
01621       return complete_ch(a);
01622    }
01623 
01624    if (a->argc < 5)
01625       return CLI_SHOWUSAGE;
01626  
01627    if (strstr(a->argv[3], "calldeflect")) {
01628       if (a->argc < 6) {
01629          ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
01630          return 0;
01631       }
01632       channame = a->argv[4];
01633       nr = a->argv[5];
01634 
01635       ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
01636       tmp = get_chan_by_ast_name(channame);
01637       if (!tmp) {
01638          ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
01639          return 0; 
01640       }
01641 
01642       if (strlen(nr) >= 15) {
01643          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
01644          return 0; 
01645       }
01646       tmp->bc->fac_out.Function = Fac_CD;
01647       ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
01648       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
01649    } else if (strstr(a->argv[3],"CFActivate")) {
01650       if (a->argc < 7) {
01651          ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
01652          return 0;
01653       }
01654       port = atoi(a->argv[4]);
01655       served_nr = a->argv[5];
01656       nr = a->argv[6];
01657 
01658       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01659 
01660       ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
01661 
01662       bc->fac_out.Function = Fac_CFActivate;
01663       bc->fac_out.u.CFActivate.BasicService = 0; //All Services
01664       bc->fac_out.u.CFActivate.Procedure = 0; //Unconditional
01665       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01666       ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
01667 
01668       misdn_lib_send_event(bc, EVENT_FACILITY);
01669    } else if (strstr(a->argv[3],"CFDeactivate")) {
01670       if (a->argc < 6) {
01671          ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
01672          return 0;
01673       }
01674       port = atoi(a->argv[4]);
01675       served_nr = a->argv[5];
01676       
01677       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01678       ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
01679 
01680       bc->fac_out.Function = Fac_CFDeactivate;
01681       bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
01682       bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
01683       
01684       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01685       misdn_lib_send_event(bc, EVENT_FACILITY);
01686    }
01687 
01688    return CLI_SUCCESS;
01689 }

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

Definition at line 1691 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, misdn_bchannel::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_send_restart(), and ast_cli_entry::usage.

01692 {
01693    int port;
01694    int channel;
01695 
01696    switch (cmd) {
01697    case CLI_INIT:
01698       e->command = "misdn send restart";
01699       e->usage =
01700          "Usage: misdn send restart [port [channel]]\n"
01701          "       Send a restart for every bchannel on the given port.\n";
01702       return NULL;
01703    case CLI_GENERATE:
01704       return NULL;
01705    }
01706 
01707    if (a->argc < 4 || a->argc > 5)
01708       return CLI_SHOWUSAGE;
01709 
01710    port = atoi(a->argv[3]);
01711    if (a->argc == 5) {
01712       channel = atoi(a->argv[4]);
01713       misdn_lib_send_restart(port, channel);
01714    } else {
01715       misdn_lib_send_restart(port, -1);
01716    }
01717 
01718    return CLI_SUCCESS;
01719 }

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

Definition at line 999 of file chan_misdn.c.

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

01000 {
01001    switch (cmd) {
01002    case CLI_INIT:
01003       e->command = "misdn set crypt debug";
01004       e->usage =
01005          "Usage: misdn set crypt debug <level>\n"
01006          "       Set the crypt debug level of the mISDN channel. Level\n"
01007          "       must be 1 or 2.\n";
01008       return NULL;
01009    case CLI_GENERATE:
01010       return NULL;
01011    }
01012 
01013    if (a->argc != 5)
01014       return CLI_SHOWUSAGE;
01015 
01016    /* Is this supposed to not do anything? */
01017 
01018    return CLI_SUCCESS;
01019 }

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

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

00925 {
00926    int level;
00927 
00928    switch (cmd) {
00929    case CLI_INIT:
00930       e->command = "misdn set debug";
00931       e->usage =
00932          "Usage: misdn set debug <level> [only] | [port <port> [only]]\n"
00933          "       Set the debug level of the mISDN channel.\n";
00934       return NULL;
00935    case CLI_GENERATE:
00936       return complete_debug_port(a);
00937    }
00938 
00939    if (a->argc < 4 || a->argc > 7)
00940       return CLI_SHOWUSAGE;
00941 
00942    level = atoi(a->argv[3]);
00943 
00944    switch (a->argc) {
00945    case 4:
00946    case 5:
00947       {
00948          int i;
00949          int only = 0;
00950          if (a->argc == 5) {
00951             if (strncasecmp(a->argv[4], "only", strlen(a->argv[4])))
00952                return CLI_SHOWUSAGE;
00953             else
00954                only = 1;
00955          }
00956    
00957          for (i = 0; i <= max_ports; i++) {
00958             misdn_debug[i] = level;
00959             misdn_debug_only[i] = only;
00960          }
00961          ast_cli(a->fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00962       }
00963       break;
00964    case 6:
00965    case 7:
00966       {
00967          int port;
00968          if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
00969             return CLI_SHOWUSAGE;
00970          port = atoi(a->argv[5]);
00971          if (port <= 0 || port > max_ports) {
00972             switch (max_ports) {
00973             case 0:
00974                ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00975                break;
00976             case 1:
00977                ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
00978                break;
00979             default:
00980                ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00981             }
00982             return 0;
00983          }
00984          if (a->argc == 7) {
00985             if (strncasecmp(a->argv[6], "only", strlen(a->argv[6])))
00986                return CLI_SHOWUSAGE;
00987             else
00988                misdn_debug_only[port] = 1;
00989          } else
00990             misdn_debug_only[port] = 0;
00991          misdn_debug[port] = level;
00992          ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
00993       }
00994    }
00995 
00996    return CLI_SUCCESS;
00997 }

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

Definition at line 1496 of file chan_misdn.c.

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

01497 {
01498    switch (cmd) {
01499    case CLI_INIT:
01500       e->command = "misdn set tics";
01501       e->usage =
01502          "Usage: misdn set tics <value>\n";
01503       return NULL;
01504    case CLI_GENERATE:
01505       return NULL;
01506    }
01507 
01508    if (a->argc != 4)
01509       return CLI_SHOWUSAGE;
01510 
01511    MAXTICS = atoi(a->argv[3]);
01512 
01513    return CLI_SUCCESS;
01514 }

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

Definition at line 1458 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, chan_list::ast, chan_list::bc, cl_te, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, ast_channel::name, chan_list::next, print_bc_info(), and ast_cli_entry::usage.

01459 {
01460    struct chan_list *help;
01461 
01462    switch (cmd) {
01463    case CLI_INIT:
01464       e->command = "misdn show channel";
01465       e->usage =
01466          "Usage: misdn show channel <channel>\n"
01467          "       Show an internal mISDN channel\n.";
01468       return NULL;
01469    case CLI_GENERATE:
01470       return complete_ch(a);
01471    }
01472 
01473    if (a->argc != 4)
01474       return CLI_SHOWUSAGE;
01475 
01476    help = cl_te;
01477 
01478    for (; help; help = help->next) {
01479       struct misdn_bchannel *bc = help->bc;   
01480       struct ast_channel *ast = help->ast;
01481     
01482       if (bc && ast) {
01483          if (!strcasecmp(ast->name, a->argv[3])) {
01484             print_bc_info(a->fd, help, bc);
01485             break; 
01486          }
01487       } 
01488    }
01489 
01490    return CLI_SUCCESS;
01491 }

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

Definition at line 1396 of file chan_misdn.c.

References ast_cli_args::argc, chan_list::ast, ast_cli(), chan_list::bc, hold_info::channel, ast_channel::cid, ast_callerid::cid_num, cl_te, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel::exten, ast_cli_args::fd, chan_list::hold, chan_list::l3id, misdn_debug, misdn_dump_chanlist(), MISDN_HOLD_IDLE, chan_list::next, misdn_bchannel::pid, hold_info::port, print_bc_info(), hold_info::state, and ast_cli_entry::usage.

01397 {
01398    struct chan_list *help;
01399 
01400    switch (cmd) {
01401    case CLI_INIT:
01402       e->command = "misdn show channels";
01403       e->usage =
01404          "Usage: misdn show channels\n"
01405          "       Show the internal mISDN channel list\n";
01406       return NULL;
01407    case CLI_GENERATE:
01408       return NULL;
01409    }
01410 
01411    if (a->argc != 3)
01412       return CLI_SHOWUSAGE;
01413 
01414    help = cl_te;
01415   
01416    ast_cli(a->fd, "Channel List: %p\n", cl_te);
01417 
01418    for (; help; help = help->next) {
01419       struct misdn_bchannel *bc = help->bc;   
01420       struct ast_channel *ast = help->ast;
01421       if (!ast) {
01422          if (!bc) {
01423             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
01424             continue;
01425          }
01426          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
01427          continue;
01428       }
01429 
01430       if (misdn_debug[0] > 2)
01431          ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
01432       if (bc) {
01433          print_bc_info(a->fd, help, bc);
01434       } else {
01435          if (help->hold.state != MISDN_HOLD_IDLE) {
01436             ast_cli(a->fd, "ITS A HELD CALL BC:\n");
01437             ast_cli(a->fd, " --> l3_id: %x\n"
01438                   " --> dad:%s oad:%s\n"
01439                   " --> hold_port: %d\n"
01440                   " --> hold_channel: %d\n",
01441                   help->l3id,
01442                   ast->exten,
01443                   ast->cid.cid_num,
01444                   help->hold.port,
01445                   help->hold.channel
01446                   );
01447          } else {
01448             ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
01449          }
01450       }
01451    }
01452 
01453    misdn_dump_chanlist();
01454 
01455    return CLI_SUCCESS;
01456 }

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

Definition at line 1170 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_elem(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, show_config_description(), and ast_cli_entry::usage.

01171 {
01172    char buffer[BUFFERSIZE];
01173    enum misdn_cfg_elements elem;
01174    int linebreak;
01175    int onlyport = -1;
01176    int ok = 0;
01177 
01178    switch (cmd) {
01179    case CLI_INIT:
01180       e->command = "misdn show config";
01181       e->usage =
01182          "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
01183          "       Use 0 for <port> to only print the general config.\n";
01184       return NULL;
01185    case CLI_GENERATE:
01186       return complete_show_config(a);
01187    }
01188 
01189    if (a->argc >= 4) {
01190       if (!strcmp(a->argv[3], "description")) {
01191          if (a->argc == 5) {
01192             enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
01193             if (elem == MISDN_CFG_FIRST)
01194                ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
01195             else
01196                show_config_description(a->fd, elem);
01197             return CLI_SUCCESS;
01198          }
01199          return CLI_SHOWUSAGE;
01200       } else if (!strcmp(a->argv[3], "descriptions")) {
01201          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
01202             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01203                show_config_description(a->fd, elem);
01204                ast_cli(a->fd, "\n");
01205             }
01206             ok = 1;
01207          }
01208          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
01209             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
01210                show_config_description(a->fd, elem);
01211                ast_cli(a->fd, "\n");
01212             }
01213             ok = 1;
01214          }
01215          return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
01216       } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
01217          ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
01218          return CLI_SHOWUSAGE;
01219       }
01220    } else if (a->argc == 3 || onlyport == 0) {
01221       ast_cli(a->fd, "mISDN General-Config:\n");
01222       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
01223          misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
01224          ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01225       }
01226       ast_cli(a->fd, "\n");
01227    }
01228 
01229    if (onlyport < 0) {
01230       int port = misdn_cfg_get_next_port(0);
01231       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
01232          ast_cli(a->fd, "\n[PORT %d]\n", port);
01233          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01234             misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
01235             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01236          }  
01237          ast_cli(a->fd, "\n");
01238       }
01239    }
01240    
01241    if (onlyport > 0) {
01242       if (misdn_cfg_is_port_valid(onlyport)) {
01243          ast_cli(a->fd, "[PORT %d]\n", onlyport);
01244          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01245             misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
01246             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01247          }  
01248          ast_cli(a->fd, "\n");
01249       } else {
01250          ast_cli(a->fd, "Port %d is not active!\n", onlyport);
01251       }
01252    }
01253 
01254    return CLI_SUCCESS;
01255 }

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

Definition at line 1573 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(), misdn_debug, misdn_debug_only, and ast_cli_entry::usage.

01574 {
01575    int port;
01576    char buf[128];
01577 
01578    switch (cmd) {
01579    case CLI_INIT:
01580       e->command = "misdn show port";
01581       e->usage =
01582          "Usage: misdn show port <port>\n"
01583          "       Show detailed information for given port.\n";
01584       return NULL;
01585    case CLI_GENERATE:
01586       return NULL;
01587    }
01588 
01589    if (a->argc != 4)
01590       return CLI_SHOWUSAGE;
01591 
01592    port = atoi(a->argv[3]);
01593 
01594    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01595    get_show_stack_details(port, buf);
01596    ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01597 
01598    return CLI_SUCCESS;
01599 }

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

Definition at line 1545 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(), misdn_in_calls, misdn_out_calls, and ast_cli_entry::usage.

01546 {
01547    int port;
01548 
01549    switch (cmd) {
01550    case CLI_INIT:
01551       e->command = "misdn show ports stats";
01552       e->usage =
01553          "Usage: misdn show ports stats\n"
01554          "       Show mISDNs channel's call statistics per port.\n";
01555       return NULL;
01556    case CLI_GENERATE:
01557       return NULL;
01558    }
01559 
01560    if (a->argc != 4)
01561       return CLI_SHOWUSAGE;
01562 
01563    ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
01564    for (port = misdn_cfg_get_next_port(0); port > 0;
01565         port = misdn_cfg_get_next_port(port)) {
01566       ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
01567    }
01568    ast_cli(a->fd, "\n");
01569 
01570    return CLI_SUCCESS;
01571 }

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

Definition at line 1516 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(), misdn_debug, misdn_debug_only, and ast_cli_entry::usage.

01517 {
01518    int port;
01519 
01520    switch (cmd) {
01521    case CLI_INIT:
01522       e->command = "misdn show stacks";
01523       e->usage =
01524          "Usage: misdn show stacks\n"
01525          "       Show internal mISDN stack_list.\n";
01526       return NULL;
01527    case CLI_GENERATE:
01528       return NULL;
01529    }
01530 
01531    if (a->argc != 3)
01532       return CLI_SHOWUSAGE;
01533 
01534    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01535    for (port = misdn_cfg_get_next_port(0); port > 0;
01536         port = misdn_cfg_get_next_port(port)) {
01537       char buf[128];
01538       get_show_stack_details(port, buf);
01539       ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01540    }
01541 
01542    return CLI_SUCCESS;
01543 }

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

Definition at line 1769 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), chan_list::bc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, get_chan_by_ast_name(), manager_ec_disable(), manager_ec_enable(), chan_list::toggle_ec, update_ec_config(), and ast_cli_entry::usage.

01770 {
01771    char *channame;
01772    struct chan_list *tmp;
01773 
01774    switch (cmd) {
01775    case CLI_INIT:
01776       e->command = "misdn toggle echocancel";
01777       e->usage =
01778          "Usage: misdn toggle echocancel <channel>\n"
01779          "       Toggle EchoCancel on mISDN Channel.\n";
01780       return NULL;
01781    case CLI_GENERATE:
01782       return complete_ch(a);
01783    }
01784 
01785    if (a->argc != 4)
01786       return CLI_SHOWUSAGE;
01787 
01788    channame = a->argv[3];
01789   
01790    ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
01791   
01792    tmp = get_chan_by_ast_name(channame);
01793    if (!tmp) {
01794       ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
01795       return CLI_SUCCESS;
01796    }
01797 
01798    tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
01799 
01800    if (tmp->toggle_ec) {
01801 #ifdef MISDN_1_2
01802       update_pipeline_config(tmp->bc);
01803 #else
01804       update_ec_config(tmp->bc);
01805 #endif
01806       manager_ec_enable(tmp->bc);
01807    } else {
01808       manager_ec_disable(tmp->bc);
01809    }
01810 
01811    return CLI_SUCCESS;
01812 }

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

Definition at line 3850 of file chan_misdn.c.

References chan_list::ast, ast_hangup(), ast_queue_hangup_with_cause(), chan_list::bc, misdn_bchannel::cause, cb_log, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::port, and send_cause2ast().

Referenced by cb_events(), do_immediate_setup(), and start_pbx().

03851 {
03852    int port;
03853 
03854    if (!ch) {
03855       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03856       return;
03857    }
03858 
03859    port = bc->port;
03860    cb_log(5, port, "hangup_chan called\n");
03861 
03862    if (ch->need_hangup) {
03863       cb_log(2, port, " --> hangup\n");
03864       ch->need_hangup = 0;
03865       ch->need_queue_hangup = 0;
03866       if (ch->ast) {
03867          send_cause2ast(ch->ast, bc, ch);
03868          ast_hangup(ch->ast);
03869       }
03870       return;
03871    }
03872 
03873    if (!ch->need_queue_hangup) {
03874       cb_log(2, port, " --> No need to queue hangup\n");
03875    }
03876 
03877    ch->need_queue_hangup = 0;
03878    if (ch->ast) {
03879       send_cause2ast(ch->ast, bc, ch);
03880       ast_queue_hangup_with_cause(ch->ast, bc->cause);
03881       cb_log(2, port, " --> queue_hangup\n");
03882    } else {
03883       cb_log(1, port, "Cannot hangup chan, no ast\n");
03884    }
03885 }

static void hanguptone_indicate ( struct chan_list cl  )  [static]

Definition at line 3292 of file chan_misdn.c.

References chan_list::bc, misdn_lib_send_tone(), and TONE_HANGUP.

Referenced by cb_events(), do_immediate_setup(), misdn_hangup(), misdn_indication(), misdn_overlap_dial_task(), and start_pbx().

03293 {
03294    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03295 }

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

References ast_copy_string(), ast_log(), chan, chan_misdn_log(), cl_te, find_chan_by_pid(), misdn_bchannel::keypad, LOG_NOTICE, chan_list::other_ch, chan_list::other_pid, pbx_builtin_getvar_helper(), misdn_bchannel::port, misdn_bchannel::sending_complete, misdn_bchannel::uu, and misdn_bchannel::uulen.

Referenced by misdn_call().

04181 {
04182    const char *tmp;
04183 
04184    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04185    if (tmp) {
04186       ch->other_pid = atoi(tmp);
04187       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04188       if (ch->other_pid > 0) {
04189          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04190          if (ch->other_ch)
04191             ch->other_ch->other_ch = ch;
04192       }
04193    }
04194 
04195    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04196    if (tmp && (atoi(tmp) == 1)) {
04197       bc->sending_complete = 1;
04198    }
04199 
04200    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04201    if (tmp) {
04202       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04203       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04204       bc->uulen = strlen(bc->uu);
04205    }
04206 
04207    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04208    if (tmp) {
04209       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04210    }
04211 }

static struct chan_list* init_chan_list ( int  orig  )  [static]

Definition at line 3336 of file chan_misdn.c.

References ast_calloc, and chan_misdn_log().

Referenced by cb_events(), and misdn_request().

03337 {
03338    struct chan_list *cl;
03339 
03340    cl = ast_calloc(1, sizeof(*cl));
03341    if (!cl) {
03342       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03343       return NULL;
03344    }
03345    
03346    cl->originator = orig;
03347    cl->need_queue_hangup = 1;
03348    cl->need_hangup = 1;
03349    cl->need_busy = 1;
03350    cl->overlap_dial_task = -1;
03351 
03352    return cl;
03353 }

static int load_module ( void   )  [static]

Definition at line 5354 of file chan_misdn.c.

References ast_calloc, ast_channel_register(), ast_cli_register_multiple(), ast_free, ast_log(), ast_malloc, AST_MODULE_LOAD_DECLINE, ast_mutex_init(), ast_register_application, ast_strlen_zero(), BUFFERSIZE, misdn_lib_iface::cb_event, cb_events(), chan_misdn_clis, chan_misdn_jb_empty(), chan_misdn_log(), cl_te_lock, LOG_ERROR, max_ports, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), MISDN_CFG_L1_TIMEOUT, misdn_cfg_update_ptp(), misdn_check_l2l1(), misdn_debug, misdn_debug_only, misdn_facility_exec(), MISDN_GEN_DEBUG, MISDN_GEN_NTDEBUGFILE, MISDN_GEN_NTDEBUGFLAGS, MISDN_GEN_NTKEEPCALLS, MISDN_GEN_TRACEFILE, misdn_in_calls, misdn_l1_task(), misdn_lib_init(), misdn_lib_maxports_get(), misdn_lib_nt_debug_init(), misdn_lib_nt_keepcalls(), misdn_out_calls, misdn_set_opt_exec(), misdn_tasks_add(), misdn_tech, misdn_type, tracing, and unload_module().

05355 {
05356    int i, port;
05357    int ntflags = 0, ntkc = 0;
05358    char ports[256] = "";
05359    char tempbuf[BUFFERSIZE + 1];
05360    char ntfile[BUFFERSIZE + 1];
05361    struct misdn_lib_iface iface = {
05362       .cb_event = cb_events,
05363       .cb_log = chan_misdn_log,
05364       .cb_jb_empty = chan_misdn_jb_empty,
05365    };
05366 
05367    max_ports = misdn_lib_maxports_get();
05368    
05369    if (max_ports <= 0) {
05370       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05371       return AST_MODULE_LOAD_DECLINE;
05372    }
05373    
05374    if (misdn_cfg_init(max_ports, 0)) {
05375       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05376       return AST_MODULE_LOAD_DECLINE;
05377    }
05378    g_config_initialized = 1;
05379    
05380    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
05381    if (!misdn_debug) {
05382       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05383       return AST_MODULE_LOAD_DECLINE;
05384    }
05385    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
05386    if (!misdn_ports) {
05387       ast_free(misdn_debug);
05388       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05389       return AST_MODULE_LOAD_DECLINE;
05390    }
05391    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
05392    for (i = 1; i <= max_ports; i++) {
05393       misdn_debug[i] = misdn_debug[0];
05394       misdn_ports[i] = i;
05395    }
05396    *misdn_ports = 0;
05397    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
05398    if (!misdn_debug_only) {
05399       ast_free(misdn_ports);
05400       ast_free(misdn_debug);
05401       ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
05402       return AST_MODULE_LOAD_DECLINE;
05403    }
05404 
05405    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
05406    if (!ast_strlen_zero(tempbuf))
05407       tracing = 1;
05408 
05409    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05410    if (!misdn_in_calls) {
05411       ast_free(misdn_debug_only);
05412       ast_free(misdn_ports);
05413       ast_free(misdn_debug);
05414       ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
05415       return AST_MODULE_LOAD_DECLINE;
05416    }
05417    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05418    if (!misdn_out_calls) {
05419       ast_free(misdn_in_calls);
05420       ast_free(misdn_debug_only);
05421       ast_free(misdn_ports);
05422       ast_free(misdn_debug);
05423       ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
05424       return AST_MODULE_LOAD_DECLINE;
05425    }
05426 
05427    for (i = 1; i <= max_ports; i++) {
05428       misdn_in_calls[i] = 0;
05429       misdn_out_calls[i] = 0;
05430    }
05431 
05432    ast_mutex_init(&cl_te_lock);
05433    ast_mutex_init(&release_lock);
05434 
05435    misdn_cfg_update_ptp();
05436    misdn_cfg_get_ports_string(ports);
05437 
05438    if (!ast_strlen_zero(ports))
05439       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05440    if (misdn_lib_init(ports, &iface, NULL))
05441       chan_misdn_log(0, 0, "No te ports initialized\n");
05442 
05443    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
05444    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
05445    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
05446 
05447    misdn_lib_nt_keepcalls(ntkc);
05448    misdn_lib_nt_debug_init(ntflags, ntfile);
05449 
05450    if (ast_channel_register(&misdn_tech)) {
05451       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05452       unload_module();
05453       return AST_MODULE_LOAD_DECLINE;
05454    }
05455   
05456    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05457 
05458    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05459       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05460       "Sets mISDN opts. and optargs\n"
05461       "\n"
05462       "The available options are:\n"
05463       "    a - Have Asterisk detect DTMF tones on called channel\n"
05464       "    c - Make crypted outgoing call, optarg is keyindex\n"
05465       "    d - Send display text to called phone, text is the optarg\n"
05466       "    e - Perform echo cancelation on this channel,\n"
05467       "        takes taps as optarg (32,64,128,256)\n"
05468       "   e! - Disable echo cancelation on this channel\n"
05469       "    f - Enable fax detection\n"
05470       "    h - Make digital outgoing call\n"
05471       "   h1 - Make HDLC mode digital outgoing call\n"
05472       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05473       "        they will be transported inband.\n"
05474       "   jb - Set jitter buffer length, optarg is length\n"
05475       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05476       "   jn - Disable jitter buffer\n"
05477       "    n - Disable mISDN DSP on channel.\n"
05478       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05479       "    p - Caller ID presentation,\n"
05480       "        optarg is either 'allowed' or 'restricted'\n"
05481       "    s - Send Non-inband DTMF as inband\n"
05482       "   vr - Rx gain control, optarg is gain\n"
05483       "   vt - Tx gain control, optarg is gain\n"
05484       );
05485 
05486    
05487    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05488              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05489              "Sends the Facility Message FACILITY_TYPE with \n"
05490              "the given Arguments to the current ISDN Channel\n"
05491              "Supported Facilities are:\n"
05492              "\n"
05493              "type=calldeflect args=Nr where to deflect\n"
05494       );
05495 
05496 
05497    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05498              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05499              "Checks if the L2 and L1 are up on either the given <port> or\n"
05500              "on the ports in the group with <groupname>\n"
05501              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05502              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05503              "\n"
05504              "This application, ensures the L1/L2 state of the Ports in a group\n"
05505              "it is intended to make the pmp_l1_check option redundant and to\n"
05506              "fix a buggy switch config from your provider\n"
05507              "\n"
05508              "a sample dialplan would look like:\n\n"
05509              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05510              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05511              "\n"
05512       );
05513 
05514 
05515    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
05516 
05517    /* start the l1 watchers */
05518    
05519    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05520       int l1timeout;
05521       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05522       if (l1timeout) {
05523          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05524          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05525       }
05526    }
05527 
05528    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05529 
05530    return 0;
05531 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2483 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_PROTOCOL_ERROR, ast_copy_string(), ast_log(), ast_queue_hangup_with_cause(), ast_strlen_zero(), ast_true(), chan_list::bc, misdn_bchannel::cad, chan_misdn_log(), misdn_bchannel::crypt_key, misdn_bchannel::dad, EVENT_CONNECT, misdn_bchannel::hdlc, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_lib_send_event(), misdn_bchannel::nodsp, misdn_bchannel::nojitter, pbx_builtin_getvar_helper(), misdn_bchannel::port, start_bc_tones(), chan_list::state, and stop_indicate().

02484 {
02485    struct chan_list *p;
02486    const char *tmp;
02487 
02488    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02489    
02490    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
02491    
02492    if (!p) {
02493       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02494       ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
02495    }
02496 
02497    if (!p->bc) {
02498       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
02499 
02500       ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
02501    }
02502 
02503    tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
02504    if (!ast_strlen_zero(tmp)) {
02505       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02506       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
02507    } else {
02508       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02509    }
02510 
02511    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02512    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
02513       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02514       p->bc->nodsp = 1;
02515       p->bc->hdlc = 0;
02516       p->bc->nojitter = 1;
02517    }
02518 
02519    p->state = MISDN_CONNECTED;
02520    stop_indicate(p);
02521 
02522    if ( ast_strlen_zero(p->bc->cad) ) {
02523       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
02524       ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
02525    }
02526 
02527    misdn_lib_send_event( p->bc, EVENT_CONNECT);
02528    start_bc_tones(p);
02529 
02530    return 0;
02531 }

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

Definition at line 4026 of file chan_misdn.c.

References chan_list::ast, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_UNHOLD, ast_queue_control(), chan_misdn_log(), chan_list::hold, MISDN_ALERTING, MISDN_CONNECTED, MISDN_HOLD_TRANSFER, MISDN_PROCEEDING, MISDN_PROGRESS, ast_channel::name, hold_info::port, hold_info::state, and chan_list::state.

Referenced by cb_events().

04027 {
04028    int retval;
04029    struct ast_channel *bridged;
04030 
04031    switch (active_ch->state) {
04032    case MISDN_PROCEEDING:
04033    case MISDN_PROGRESS:
04034    case MISDN_ALERTING:
04035    case MISDN_CONNECTED:
04036       break;
04037    default:
04038       return -1;
04039    }
04040 
04041    bridged = ast_bridged_channel(held_ch->ast);
04042    if (bridged) {
04043       ast_queue_control(held_ch->ast, AST_CONTROL_UNHOLD);
04044       held_ch->hold.state = MISDN_HOLD_TRANSFER;
04045 
04046       chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
04047          held_ch->ast->name, active_ch->ast->name);
04048       retval = ast_channel_masquerade(active_ch->ast, bridged);
04049    } else {
04050       /*
04051        * Could not transfer.  Held channel is not bridged anymore.
04052        * Held party probably got tired of waiting and hung up.
04053        */
04054       retval = -1;
04055    }
04056 
04057    return retval;
04058 }

static enum ast_bridge_result misdn_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
) [static]

Definition at line 3156 of file chan_misdn.c.

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_read(), ast_verb, ast_waitfor_n(), ast_write(), chan_list::bc, chan_misdn_log(), ast_channel::exten, f, get_chan_by_ast(), chan_list::ignore_dtmf, LOG_NOTICE, MISDN_CFG_BRIDGING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_bridge(), misdn_lib_split_bridge(), ast_channel::name, misdn_bchannel::oad, misdn_bchannel::pid, and misdn_bchannel::port.

03162 {
03163    struct chan_list *ch1, *ch2;
03164    struct ast_channel *carr[2], *who;
03165    int to = -1;
03166    struct ast_frame *f;
03167    int p1_b, p2_b;
03168    int bridging;
03169   
03170    ch1 = get_chan_by_ast(c0);
03171    ch2 = get_chan_by_ast(c1);
03172 
03173    carr[0] = c0;
03174    carr[1] = c1;
03175   
03176    if (!(ch1 && ch2))
03177       return -1;
03178 
03179    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
03180    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
03181 
03182    if (! p1_b || ! p2_b) {
03183       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03184       return AST_BRIDGE_FAILED;
03185    }
03186 
03187    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03188    if (bridging) {
03189       /* trying to make a mISDN_dsp conference */
03190       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03191       misdn_lib_bridge(ch1->bc, ch2->bc);
03192    }
03193 
03194    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03195 
03196    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03197  
03198    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
03199       ch1->ignore_dtmf = 1;
03200 
03201    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
03202       ch2->ignore_dtmf = 1;
03203 
03204    for (;/*ever*/;) {
03205       to = -1;
03206       who = ast_waitfor_n(carr, 2, &to);
03207 
03208       if (!who) {
03209          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03210          break;
03211       }
03212       f = ast_read(who);
03213 
03214       if (!f || f->frametype == AST_FRAME_CONTROL) {
03215          /* got hangup .. */
03216 
03217          if (!f) 
03218             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03219          else
03220             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03221 
03222          *fo = f;
03223          *rc = who;
03224          break;
03225       }
03226       
03227       if ( f->frametype == AST_FRAME_DTMF ) {
03228          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03229 
03230          *fo = f;
03231          *rc = who;
03232          break;
03233       }
03234    
03235 #if 0
03236       if (f->frametype == AST_FRAME_VOICE) {
03237          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03238    
03239          continue;
03240       }
03241 #endif
03242 
03243       if (who == c0) {
03244          ast_write(c1, f);
03245       }
03246       else {
03247          ast_write(c0, f);
03248       }
03249    }
03250 
03251    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03252 
03253    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03254 
03255    return AST_BRIDGE_COMPLETE;
03256 }

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

Definition at line 2343 of file chan_misdn.c.

References ast_channel::_state, add_out_calls(), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), ast_transfercapability2str(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_callerid::cid_rdnis, ast_channel::context, misdn_bchannel::dad, misdn_bchannel::ec_enable, ENOCHAN, EVENT_SETUP, ext, ast_channel::exten, ast_channel::hangupcause, import_ch(), INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::l3_id, chan_list::l3id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_send_event(), misdn_set_opt_exec(), ast_channel::name, misdn_bchannel::nt, misdn_bchannel::oad, ORG_AST, chan_list::other_ch, pbx_builtin_setvar_helper(), misdn_bchannel::pid, misdn_bchannel::port, misdn_bchannel::rad, S_OR, chan_list::state, stop_bc_tones(), strsep(), ast_channel::transfercapability, and update_config().

02344 {
02345    int port = 0;
02346    int r;
02347    int exceed;
02348    int bridging;
02349    struct chan_list *ch;
02350    struct misdn_bchannel *newbc;
02351    char *opts, *ext;
02352    char *dest_cp;
02353 
02354    if (!ast) {
02355       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
02356       return -1;
02357    }
02358 
02359    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
02360       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02361       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02362       ast_setstate(ast, AST_STATE_DOWN);
02363       return -1;
02364    }
02365 
02366    ch = MISDN_ASTERISK_TECH_PVT(ast);
02367    if (!ch) {
02368       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02369       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02370       ast_setstate(ast, AST_STATE_DOWN);
02371       return -1;
02372    }
02373    
02374    newbc = ch->bc;
02375    if (!newbc) {
02376       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02377       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02378       ast_setstate(ast, AST_STATE_DOWN);
02379       return -1;
02380    }
02381    
02382    /*
02383     * dest is ---v
02384     * Dial(mISDN/g:group_name[/extension[/options]])
02385     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
02386     *
02387     * The dial extension could be empty if you are using MISDN_KEYPAD
02388     * to control ISDN provider features.
02389     */
02390    dest_cp = ast_strdupa(dest);
02391    strsep(&dest_cp, "/");/* Discard port/group token */
02392    ext = strsep(&dest_cp, "/");
02393    if (!ext) {
02394       ext = "";
02395    }
02396    opts = dest_cp;
02397    
02398    port = newbc->port;
02399 
02400    if ((exceed = add_out_calls(port))) {
02401       char tmp[16];
02402       snprintf(tmp, sizeof(tmp), "%d", exceed);
02403       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
02404       return -1;
02405    }
02406    
02407    chan_misdn_log(1, port, "* CALL: %s\n", dest);
02408    
02409    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
02410    
02411    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
02412    if (ast->exten) {
02413       ast_copy_string(ast->exten, ext, sizeof(ast->exten));
02414       ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
02415    }
02416 
02417    ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
02418 
02419    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
02420    if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
02421       ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
02422    }
02423 
02424    newbc->capability = ast->transfercapability;
02425    pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
02426    if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
02427       chan_misdn_log(2, port, " --> * Call with flag Digital\n");
02428    }
02429 
02430    /* update screening and presentation */ 
02431    update_config(ch, ORG_AST);
02432       
02433    /* fill in some ies from channel vary*/
02434    import_ch(ast, newbc, ch);
02435 
02436    /* Finally The Options Override Everything */
02437    if (opts)
02438       misdn_set_opt_exec(ast, opts);
02439    else
02440       chan_misdn_log(2, port, "NO OPTS GIVEN\n");
02441 
02442    /*check for bridging*/
02443    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
02444    if (bridging && ch->other_ch) {
02445 #ifdef MISDN_1_2
02446       chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
02447       *ch->bc->pipeline = 0;
02448       *ch->other_ch->bc->pipeline = 0;
02449 #else
02450       chan_misdn_log(1, port, "Disabling EC on both Sides\n");
02451       ch->bc->ec_enable = 0;
02452       ch->other_ch->bc->ec_enable = 0;
02453 #endif
02454    }
02455 
02456    r = misdn_lib_send_event( newbc, EVENT_SETUP );
02457 
02458    /** we should have l3id after sending setup **/
02459    ch->l3id = newbc->l3_id;
02460 
02461    if ( r == -ENOCHAN  ) {
02462       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
02463       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
02464       ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
02465       ast_setstate(ast, AST_STATE_DOWN);
02466       return -1;
02467    }
02468    
02469    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
02470 
02471    ast_setstate(ast, AST_STATE_DIALING);
02472    ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
02473    
02474    if (newbc->nt)
02475       stop_bc_tones(ch);
02476 
02477    ch->state = MISDN_CALLING;
02478    
02479    return 0; 
02480 }

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

Definition at line 5590 of file chan_misdn.c.

References 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, chan_misdn_log(), LOG_WARNING, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_CFG_GROUPNAME, misdn_lib_get_port_up(), misdn_lib_port_up(), and parse().

Referenced by load_module().

05591 {
05592    char *parse;
05593    char group[BUFFERSIZE + 1];
05594    char *port_str;
05595    int port = 0;
05596    int timeout;
05597    int dowait = 0;
05598    int port_up;
05599 
05600    AST_DECLARE_APP_ARGS(args,
05601          AST_APP_ARG(grouppar);
05602          AST_APP_ARG(timeout);
05603    );
05604 
05605    if (ast_strlen_zero((char *)data)) {
05606       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05607       return -1;
05608    }
05609 
05610    parse = ast_strdupa(data);
05611    AST_STANDARD_APP_ARGS(args, parse);
05612 
05613    if (args.argc != 2) {
05614       ast_log(LOG_WARNING, "Wrong argument count\n");
05615       return 0;
05616    }
05617 
05618    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05619    timeout = atoi(args.timeout);
05620    port_str = args.grouppar;
05621 
05622    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05623       /* We make a group call lets checkout which ports are in my group */
05624       port_str += 2;
05625       ast_copy_string(group, port_str, sizeof(group));
05626       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05627 
05628       for ( port = misdn_cfg_get_next_port(port); 
05629          port > 0;
05630          port = misdn_cfg_get_next_port(port)) {
05631          char cfg_group[BUFFERSIZE + 1];
05632 
05633          chan_misdn_log(2, 0, "trying port %d\n", port);
05634 
05635          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
05636 
05637          if (!strcasecmp(cfg_group, group)) {
05638             port_up = misdn_lib_port_up(port, 1);
05639 
05640             if (!port_up) {
05641                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05642                misdn_lib_get_port_up(port);
05643                dowait = 1;
05644             }
05645          }
05646       }
05647 
05648    } else {
05649       port = atoi(port_str);
05650       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05651       port_up = misdn_lib_port_up(port, 1);
05652       if (!port_up) {
05653          misdn_lib_get_port_up(port);
05654          dowait = 1;
05655       }
05656    }
05657 
05658    if (dowait) {
05659       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05660       ast_safe_sleep(chan, timeout * 1000);
05661    }
05662 
05663    return 0;
05664 }

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

Definition at line 2533 of file chan_misdn.c.

02534 {
02535    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02536    return 0;
02537 }

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

Definition at line 2539 of file chan_misdn.c.

References chan_list::ast, ast_copy_string(), ast_log(), chan_list::bc, buf, chan_misdn_log(), misdn_bchannel::dad, EVENT_INFORMATION, ast_channel::exten, misdn_bchannel::info_dad, misdn_bchannel::infos_pending, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, misdn_lib_send_event(), misdn_bchannel::port, send_digit_to_chan(), misdn_bchannel::send_dtmf, and chan_list::state.

02540 {
02541    struct chan_list *p;
02542    struct misdn_bchannel *bc;
02543    char buf[2] = { digit, 0 };
02544    
02545    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02546 
02547    bc = p->bc;
02548    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
02549    
02550    if (!bc) {
02551       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
02552       return -1;
02553    }
02554    
02555    switch (p->state ) {
02556    case MISDN_CALLING:
02557       if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1)
02558          strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
02559       break;
02560    case MISDN_CALLING_ACKNOWLEDGE:
02561       ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
02562       if (strlen(bc->dad) < sizeof(bc->dad) - 1)
02563          strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
02564       ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
02565       misdn_lib_send_event( bc, EVENT_INFORMATION);
02566       break;
02567    default: 
02568          if ( bc->send_dtmf ) 
02569             send_digit_to_chan(p,digit);
02570       break;
02571    }
02572 
02573    return 0;
02574 }

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

Definition at line 5544 of file chan_misdn.c.

References ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), chan_list::bc, chan, chan_misdn_log(), EVENT_FACILITY, misdn_bchannel::fac_out, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_lib_send_event(), parse(), misdn_bchannel::port, ast_channel::tech, and ast_channel_tech::type.

Referenced by load_module().

05545 {
05546    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05547    char *parse, *tok, *tokb;
05548 
05549    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05550    
05551    if (strcasecmp(chan->tech->type, "mISDN")) {
05552       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05553       return -1;
05554    }
05555    
05556    if (ast_strlen_zero((char *)data)) {
05557       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05558       return -1;
05559    }
05560 
05561    parse = ast_strdupa(data);
05562    tok = strtok_r(parse, "|", &tokb) ;
05563 
05564    if (!tok) {
05565       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05566       return -1;
05567    }
05568 
05569    if (!strcasecmp(tok, "calldeflect")) {
05570       tok = strtok_r(NULL, "|", &tokb) ;
05571       
05572       if (!tok) {
05573          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05574       }
05575 
05576       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05577          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05578          return 0; 
05579       }
05580       ch->bc->fac_out.Function = Fac_CD;
05581       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05582       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05583    } else {
05584       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05585    }
05586 
05587    return 0;
05588 }

static int misdn_fixup ( struct ast_channel oldast,
struct ast_channel ast 
) [static]

Definition at line 2577 of file chan_misdn.c.

References chan_list::ast, chan_list::bc, chan_misdn_log(), chan_list::l3id, MISDN_ASTERISK_TECH_PVT, misdn_get_ch_state(), and misdn_bchannel::port.

02578 {
02579    struct chan_list *p;
02580 
02581    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02582 
02583    chan_misdn_log(1, p->bc ? p->bc->port : 0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
02584 
02585    p->ast = ast;
02586 
02587    return 0;
02588 }

static const char* misdn_get_ch_state ( struct chan_list p  )  [static]

Definition at line 1279 of file chan_misdn.c.

References chan_list::state, state_array, and state_struct::txt.

Referenced by cb_events(), misdn_fixup(), misdn_hangup(), misdn_write(), and print_bc_info().

01280 {
01281    int i;
01282    static char state[8];
01283    
01284    if( !p) return NULL;
01285   
01286    for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
01287       if (state_array[i].state == p->state)
01288          return state_array[i].txt; 
01289    }
01290 
01291    snprintf(state, sizeof(state), "%d", p->state) ;
01292 
01293    return state;
01294 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2720 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_copy_string(), ast_debug, ast_log(), AST_STATE_RESERVED, chan_list::bc, misdn_bchannel::cause, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, ast_channel::exten, ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, INFO_PI_INBAND_AVAILABLE, chan_list::l3id, LOG_NOTICE, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_BUSY, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, misdn_get_ch_state(), MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, MISDN_INCOMING_SETUP, misdn_lib_find_held_bc(), misdn_lib_release(), misdn_lib_send_event(), MISDN_NOTHING, MISDN_PROCEEDING, MISDN_PROGRESS, ast_channel::name, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, misdn_bchannel::nt, ORG_AST, chan_list::originator, misdn_bchannel::out_cause, pbx_builtin_getvar_helper(), misdn_bchannel::pid, misdn_bchannel::port, hold_info::port, misdn_bchannel::progress_indicator, release_chan(), release_chan_early(), start_bc_tones(), chan_list::state, hold_info::state, stop_bc_tones(), misdn_bchannel::uu, misdn_bchannel::uulen, and var.

02721 {
02722    struct chan_list *p;
02723    struct misdn_bchannel *bc;
02724    const char *var;
02725 
02726    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
02727       return -1;
02728    }
02729    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02730 
02731    ast_debug(1, "misdn_hangup(%s)\n", ast->name);
02732 
02733    if (p->hold.state == MISDN_HOLD_IDLE) {
02734       bc = p->bc;
02735    } else {
02736       p->hold.state = MISDN_HOLD_DISCONNECT;
02737       bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
02738       if (!bc) {
02739          chan_misdn_log(4, p->hold.port,
02740             "misdn_hangup: Could not find held bc for (%s)\n", ast->name);
02741          release_chan_early(p);
02742          return 0;
02743       }
02744    }
02745 
02746    if (ast->_state == AST_STATE_RESERVED || p->state == MISDN_NOTHING) {
02747       /* between request and call */
02748       ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
02749       release_chan_early(p);
02750       if (bc) {
02751          misdn_lib_release(bc);
02752       }
02753       return 0;
02754    }
02755    if (!bc) {
02756       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
02757          misdn_get_ch_state(p), p->l3id);
02758       release_chan_early(p);
02759       return 0;
02760    }
02761 
02762    p->ast = NULL;
02763    p->need_hangup = 0;
02764    p->need_queue_hangup = 0;
02765    p->need_busy = 0;
02766 
02767    if (!bc->nt) {
02768       stop_bc_tones(p);
02769    }
02770 
02771    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02772 
02773    var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
02774    if (!var) {
02775       var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
02776    }
02777    if (var) {
02778       int tmpcause;
02779 
02780       tmpcause = atoi(var);
02781       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02782    }
02783 
02784    var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
02785    if (var) {
02786       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
02787       ast_copy_string(bc->uu, var, sizeof(bc->uu));
02788       bc->uulen = strlen(bc->uu);
02789    }
02790 
02791    chan_misdn_log(1, bc->port,
02792       "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",
02793       bc->pid,
02794       ast->context,
02795       ast->exten,
02796       ast->cid.cid_num,
02797       misdn_get_ch_state(p));
02798    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02799    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02800    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02801 
02802    switch (p->state) {
02803    case MISDN_INCOMING_SETUP:
02804       /*
02805        * This is the only place in misdn_hangup, where we
02806        * can call release_chan, else it might create a lot of trouble.
02807        */
02808       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02809       release_chan(p, bc);
02810       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
02811       return 0;
02812    case MISDN_DIALING:
02813       if (p->hold.state == MISDN_HOLD_IDLE) {
02814          start_bc_tones(p);
02815          hanguptone_indicate(p);
02816       }
02817 
02818       p->state = MISDN_CLEANING;
02819       if (bc->need_disconnect) {
02820          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02821       }
02822       break;
02823    case MISDN_CALLING_ACKNOWLEDGE:
02824       if (p->hold.state == MISDN_HOLD_IDLE) {
02825          start_bc_tones(p);
02826          hanguptone_indicate(p);
02827       }
02828 
02829       if (bc->need_disconnect) {
02830          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02831       }
02832       break;
02833 
02834    case MISDN_CALLING:
02835    case MISDN_ALERTING:
02836    case MISDN_PROGRESS:
02837    case MISDN_PROCEEDING:
02838       if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
02839          hanguptone_indicate(p);
02840       }
02841 
02842       if (bc->need_disconnect) {
02843          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02844       }
02845       break;
02846    case MISDN_CONNECTED:
02847       /*  Alerting or Disconnect */
02848       if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
02849          start_bc_tones(p);
02850          hanguptone_indicate(p);
02851          bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
02852       }
02853       if (bc->need_disconnect) {
02854          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02855       }
02856       break;
02857    case MISDN_DISCONNECTED:
02858       if (bc->need_release) {
02859          misdn_lib_send_event(bc, EVENT_RELEASE);
02860       }
02861       break;
02862 
02863    case MISDN_CLEANING:
02864       return 0;
02865 
02866    case MISDN_BUSY:
02867       break;
02868    default:
02869       if (bc->nt) {
02870          bc->out_cause = -1;
02871          if (bc->need_release) {
02872             misdn_lib_send_event(bc, EVENT_RELEASE);
02873          }
02874       } else {
02875          if (bc->need_disconnect) {
02876             misdn_lib_send_event(bc, EVENT_DISCONNECT);
02877          }
02878       }
02879       break;
02880    }
02881 
02882    p->state = MISDN_CLEANING;
02883    chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast->name,
02884       misdn_get_ch_state(p));
02885 
02886    return 0;
02887 }

static int misdn_indication ( struct ast_channel ast,
int  cond,
const void *  data,
size_t  datalen 
) [static]

Definition at line 2592 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_setstate(), AST_STATE_BUSY, AST_STATE_RING, chan_list::bc, chan_misdn_log(), EVENT_ALERTING, EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_PROGRESS, hanguptone_indicate(), chan_list::hold, chan_list::incoming_early_audio, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, MISDN_HOLD_IDLE, misdn_inband_avail(), misdn_lib_send_event(), ast_channel::name, misdn_bchannel::nt, ORG_MISDN, chan_list::originator, chan_list::other_ch, misdn_bchannel::out_cause, misdn_bchannel::pid, misdn_bchannel::port, start_bc_tones(), chan_list::state, hold_info::state, and stop_indicate().

02593 {
02594    struct chan_list *p;
02595 
02596    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02597       ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
02598       return -1;
02599    }
02600    
02601    if (!p->bc) {
02602       if (p->hold.state == MISDN_HOLD_IDLE) {
02603          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
02604             ast->name);
02605          ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02606       } else {
02607          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
02608             cond, ast->name);
02609       }
02610       return -1;
02611    }
02612    
02613    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n\n", cond, ast->name);
02614    
02615    switch (cond) {
02616    case AST_CONTROL_BUSY:
02617       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
02618       ast_setstate(ast, AST_STATE_BUSY);
02619 
02620       p->bc->out_cause = AST_CAUSE_USER_BUSY;
02621       if (p->state != MISDN_CONNECTED) {
02622          start_bc_tones(p);
02623          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02624       }
02625       return -1;
02626    case AST_CONTROL_RING:
02627       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02628       return -1;
02629    case AST_CONTROL_RINGING:
02630       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02631       switch (p->state) {
02632       case MISDN_ALERTING:
02633          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc ? p->bc->pid : -1);
02634          break;
02635       case MISDN_CONNECTED:
02636          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc ? p->bc->pid : -1);
02637          return -1;
02638       default:
02639          p->state = MISDN_ALERTING;
02640          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02641          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02642 
02643          if (p->other_ch && p->other_ch->bc) {
02644             if (misdn_inband_avail(p->other_ch->bc)) {
02645                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02646                break;
02647             }
02648 
02649             if (!p->other_ch->bc->nt) {
02650                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02651                break;
02652             }
02653          }
02654 
02655          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02656          ast_setstate(ast, AST_STATE_RING);
02657 
02658          if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio)
02659             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02660          else 
02661             return -1;
02662       }
02663       break;
02664    case AST_CONTROL_ANSWER:
02665       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02666       start_bc_tones(p);
02667       break;
02668    case AST_CONTROL_TAKEOFFHOOK:
02669       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02670       return -1;
02671    case AST_CONTROL_OFFHOOK:
02672       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02673       return -1;
02674    case AST_CONTROL_FLASH:
02675       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02676       break;
02677    case AST_CONTROL_PROGRESS:
02678       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02679       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02680       break;
02681    case AST_CONTROL_PROCEEDING:
02682       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02683       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02684       break;
02685    case AST_CONTROL_CONGESTION:
02686       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02687 
02688       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02689       start_bc_tones(p);
02690       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02691 
02692       if (p->bc->nt) {
02693          hanguptone_indicate(p);
02694       }
02695       break;
02696    case -1 :
02697       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02698 
02699       stop_indicate(p);
02700 
02701       if (p->state == MISDN_CONNECTED) 
02702          start_bc_tones(p);
02703       break;
02704    case AST_CONTROL_HOLD:
02705       ast_moh_start(ast, data, p->mohinterpret); 
02706       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02707       break;
02708    case AST_CONTROL_UNHOLD:
02709       ast_moh_stop(ast);
02710       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02711       break;
02712    default:
02713       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02714       return -1;
02715    }
02716   
02717    return 0;
02718 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

Definition at line 5929 of file chan_misdn.c.

References ast_free, ast_mutex_destroy(), misdn_jb::mutexjb, misdn_jb::ok, and misdn_jb::samples.

Referenced by config_jitterbuffer(), release_chan(), and release_chan_early().

05930 {
05931    ast_mutex_destroy(&jb->mutexjb);
05932    
05933    ast_free(jb->ok);
05934    ast_free(jb->samples);
05935    ast_free(jb);
05936 }

int misdn_jb_empty ( struct misdn_jb jb,
char *  data,
int  len 
)

gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data.

Definition at line 5999 of file chan_misdn.c.

References ast_mutex_lock(), ast_mutex_unlock(), chan_misdn_log(), misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::rp, misdn_jb::samples, misdn_jb::size, misdn_jb::state_buffer, misdn_jb::state_empty, and misdn_jb::wp.

Referenced by chan_misdn_jb_empty().

06000 {
06001    int i, wp, rp, read = 0;
06002 
06003    ast_mutex_lock(&jb->mutexjb);
06004 
06005    rp = jb->rp;
06006    wp = jb->wp;
06007 
06008    if (jb->state_empty) {  
06009       for (i = 0; i < len; i++) {
06010          if (wp == rp) {
06011             jb->rp = rp;
06012             jb->state_empty = 0;
06013 
06014             ast_mutex_unlock(&jb->mutexjb);
06015 
06016             return read;
06017          } else {
06018             if (jb->ok[rp] == 1) {
06019                data[i] = jb->samples[rp];
06020                jb->ok[rp] = 0;
06021                rp = (rp != jb->size - 1) ? rp + 1 : 0;
06022                read += 1;
06023             }
06024          }
06025       }
06026 
06027       if (wp >= rp)
06028          jb->state_buffer = wp - rp;
06029       else
06030          jb->state_buffer = jb->size - rp + wp;
06031       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
06032 
06033       jb->rp = rp;
06034    } else
06035       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
06036 
06037    ast_mutex_unlock(&jb->mutexjb);
06038 
06039    return read;
06040 }

int misdn_jb_fill ( struct misdn_jb jb,
const char *  data,
int  len 
)

fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).

Definition at line 5940 of file chan_misdn.c.

References ast_mutex_lock(), ast_mutex_unlock(), chan_misdn_log(), misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::rp, misdn_jb::samples, misdn_jb::size, misdn_jb::state_buffer, misdn_jb::state_empty, misdn_jb::state_full, misdn_jb::upper_threshold, and misdn_jb::wp.

05941 {
05942    int i, j, rp, wp;
05943 
05944    if (!jb || ! data)
05945       return 0;
05946 
05947    ast_mutex_lock(&jb->mutexjb);
05948    
05949    wp = jb->wp;
05950    rp = jb->rp;
05951    
05952    for (i = 0; i < len; i++) {
05953       jb->samples[wp] = data[i];
05954       jb->ok[wp] = 1;
05955       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05956 
05957       if (wp == jb->rp)
05958          jb->state_full = 1;
05959    }
05960 
05961    if (wp >= rp)
05962       jb->state_buffer = wp - rp;
05963    else
05964       jb->state_buffer = jb->size - rp + wp;
05965    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05966 
05967    if (jb->state_full) {
05968       jb->wp = wp;
05969 
05970       rp = wp;
05971       for (j = 0; j < jb->upper_threshold; j++)
05972          rp = (rp != 0) ? rp - 1 : jb->size - 1;
05973       jb->rp = rp;
05974       jb->state_full = 0;
05975       jb->state_empty = 1;
05976 
05977       ast_mutex_unlock(&jb->mutexjb);
05978 
05979       return -1;
05980    }
05981 
05982    if (!jb->state_empty) {
05983       jb->bytes_wrote += len;
05984       if (jb->bytes_wrote >= jb->upper_threshold) {
05985          jb->state_empty = 1;
05986          jb->bytes_wrote = 0;
05987       }
05988    }
05989    jb->wp = wp;
05990 
05991    ast_mutex_unlock(&jb->mutexjb);
05992    
05993    return 0;
05994 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

Definition at line 5888 of file chan_misdn.c.

References ast_free, ast_malloc, ast_mutex_init(), and chan_misdn_log().

Referenced by config_jitterbuffer().

05889 {
05890    int i;
05891    struct misdn_jb *jb;
05892 
05893    jb = ast_malloc(sizeof(*jb));
05894    if (!jb) {
05895        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05896        return NULL;
05897    }
05898    jb->size = size;
05899    jb->upper_threshold = upper_threshold;
05900    jb->wp = 0;
05901    jb->rp = 0;
05902    jb->state_full = 0;
05903    jb->state_empty = 0;
05904    jb->bytes_wrote = 0;
05905    jb->samples = ast_malloc(size * sizeof(char));
05906    if (!jb->samples) {
05907       ast_free(jb);
05908       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05909       return NULL;
05910    }
05911 
05912    jb->ok = ast_malloc(size * sizeof(char));
05913    if (!jb->ok) {
05914       ast_free(jb->samples);
05915       ast_free(jb);
05916       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05917       return NULL;
05918    }
05919 
05920    for (i = 0; i < size; i++)
05921       jb->ok[i] = 0;
05922 
05923    ast_mutex_init(&jb->mutexjb);
05924 
05925    return jb;
05926 }

static int misdn_l1_task ( const void *  data  )  [static]

Definition at line 830 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

00831 {
00832    misdn_lib_isdn_l1watcher(*(int *)data);
00833    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00834    return 1;
00835 }

static struct ast_channel * misdn_new ( struct chan_list cl,
int  state,
char *  exten,
char *  callerid,
int  format,
int  port,
int  c 
) [static]

Definition at line 3628 of file chan_misdn.c.

References ast_callerid_parse(), ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_jb_configure(), ast_log(), AST_STATE_RING, ast_strdup, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_ani, cid_name, cid_num, ast_channel::exten, LOG_ERROR, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_GEN_BRIDGING, misdn_get_global_jbconf(), misdn_lib_port_is_pri(), misdn_tech, misdn_tech_wo_bridge, misdn_type, ast_channel::nativeformats, chan_list::pipe, prefformat, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by cb_events(), and misdn_request().

03629 {
03630    struct ast_channel *tmp;
03631    char *cid_name = 0, *cid_num = 0;
03632    int chan_offset = 0;
03633    int tmp_port = misdn_cfg_get_next_port(0);
03634    int bridging;
03635 
03636    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03637       if (tmp_port == port)
03638          break;
03639       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03640    }
03641    if (c < 0)
03642       c = 0;
03643 
03644    if (callerid) {
03645       ast_callerid_parse(callerid, &cid_name, &cid_num);
03646    }
03647 
03648    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
03649    if (tmp) {
03650       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03651 
03652       tmp->nativeformats = prefformat;
03653 
03654       tmp->readformat = format;
03655       tmp->rawreadformat = format;
03656       tmp->writeformat = format;
03657       tmp->rawwriteformat = format;
03658     
03659       tmp->tech_pvt = chlist;
03660 
03661       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03662 
03663       if (bridging)
03664          tmp->tech = &misdn_tech;
03665       else
03666          tmp->tech = &misdn_tech_wo_bridge;
03667 
03668       tmp->writeformat = format;
03669       tmp->readformat = format;
03670       tmp->priority=1;
03671 
03672       if (exten) 
03673          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03674       else
03675          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03676 
03677       if (callerid)
03678          /* Don't use ast_set_callerid() here because it will
03679           * generate a needless NewCallerID event */
03680          tmp->cid.cid_ani = ast_strdup(cid_num);
03681 
03682       if (pipe(chlist->pipe) < 0)
03683          ast_log(LOG_ERROR, "Pipe failed\n");
03684       ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
03685 
03686       if (state == AST_STATE_RING)
03687          tmp->rings = 1;
03688       else
03689          tmp->rings = 0;
03690       
03691       ast_jb_configure(tmp, misdn_get_global_jbconf());
03692    } else {
03693       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03694    }
03695    
03696    return tmp;
03697 }

static int misdn_overlap_dial_task ( const void *  data  )  [static]

Definition at line 837 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_UNALLOCATED, ast_exists_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), chan_list::bc, chan_misdn_log(), chan_list::context, misdn_bchannel::dad, EVENT_DISCONNECT, ast_channel::exten, hanguptone_indicate(), MISDN_CLEANING, MISDN_DIALING, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::oad, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_start_chan(), misdn_bchannel::port, chan_list::state, and stop_indicate().

Referenced by cb_events().

00838 {
00839    struct timeval tv_end, tv_now;
00840    int diff;
00841    struct chan_list *ch = (struct chan_list *)data;
00842 
00843    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
00844 
00845    if (ch->state != MISDN_WAITING4DIGS) {
00846       ch->overlap_dial_task = -1;
00847       return 0;
00848    }
00849    
00850    ast_mutex_lock(&ch->overlap_tv_lock);
00851    tv_end = ch->overlap_tv;
00852    ast_mutex_unlock(&ch->overlap_tv_lock);
00853    
00854    tv_end.tv_sec += ch->overlap_dial;
00855    tv_now = ast_tvnow();
00856 
00857    diff = ast_tvdiff_ms(tv_end, tv_now);
00858 
00859    if (diff <= 100) {
00860       char *dad=ch->bc->dad, sexten[]="s";
00861       /* if we are 100ms near the timeout, we are satisfied.. */
00862       stop_indicate(ch);
00863       
00864       if (ast_strlen_zero(ch->bc->dad)) {
00865          dad=sexten;
00866          strcpy(ch->ast->exten, sexten);
00867       }
00868 
00869       if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
00870          ch->state=MISDN_DIALING;
00871          if (pbx_start_chan(ch) < 0) {
00872             chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
00873             goto misdn_overlap_dial_task_disconnect;
00874          }
00875       } else {
00876 misdn_overlap_dial_task_disconnect:
00877          hanguptone_indicate(ch);
00878          ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
00879          ch->state=MISDN_CLEANING;
00880          misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
00881       }
00882       ch->overlap_dial_task = -1;
00883       return 0;
00884    } else
00885       return diff;
00886 }

static struct ast_frame* misdn_read ( struct ast_channel ast  )  [static]

Definition at line 2960 of file chan_misdn.c.

References chan_list::ast_dsp, AST_FORMAT_ALAW, AST_FRAME_VOICE, chan_list::ast_rd_buf, ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), chan_list::bc, chan_misdn_log(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, chan_list::faxdetect, chan_list::faxdetect_timeout, chan_list::faxdetect_tv, chan_list::faxhandled, chan_list::frame, ast_frame::frametype, chan_list::hold, len(), ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, MISDN_HOLD_IDLE, ast_frame::offset, chan_list::pipe, misdn_bchannel::port, process_ast_dsp(), ast_frame::ptr, ast_frame::samples, ast_frame::src, hold_info::state, and ast_frame::subclass.

02961 {
02962    struct chan_list *tmp;
02963    fd_set rrfs;
02964    struct timeval tv;
02965    int len, t;
02966 
02967    if (!ast) {
02968       chan_misdn_log(1, 0, "misdn_read called without ast\n");
02969       return NULL;
02970    }
02971    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
02972       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
02973       return NULL;
02974    }
02975 
02976    if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
02977       chan_misdn_log(1, 0, "misdn_read called without bc\n");
02978       return NULL;
02979    }
02980 
02981    tv.tv_sec=0;
02982    tv.tv_usec=20000;
02983 
02984    FD_ZERO(&rrfs);
02985    FD_SET(tmp->pipe[0],&rrfs);
02986 
02987    t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
02988 
02989    if (!t) {
02990       chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
02991       len=160;
02992    }
02993 
02994    if (t<0) {
02995       chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
02996       return NULL;
02997    }
02998 
02999    if (FD_ISSET(tmp->pipe[0],&rrfs)) {
03000       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
03001 
03002       if (len<=0) {
03003          /* we hangup here, since our pipe is closed */
03004          chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
03005          return NULL;
03006       }
03007 
03008    } else {
03009       return NULL;
03010    }
03011 
03012    tmp->frame.frametype = AST_FRAME_VOICE;
03013    tmp->frame.subclass = AST_FORMAT_ALAW;
03014    tmp->frame.datalen = len;
03015    tmp->frame.samples = len;
03016    tmp->frame.mallocd = 0;
03017    tmp->frame.offset = 0;
03018    tmp->frame.delivery = ast_tv(0,0);
03019    tmp->frame.src = NULL;
03020    tmp->frame.data.ptr = tmp->ast_rd_buf;
03021 
03022    if (tmp->faxdetect && !tmp->faxhandled) {
03023       if (tmp->faxdetect_timeout) {
03024          if (ast_tvzero(tmp->faxdetect_tv)) {
03025             tmp->faxdetect_tv = ast_tvnow();
03026             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
03027             return process_ast_dsp(tmp, &tmp->frame);
03028          } else {
03029             struct timeval tv_now = ast_tvnow();
03030             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
03031             if (diff <= (tmp->faxdetect_timeout * 1000)) {
03032                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
03033                return process_ast_dsp(tmp, &tmp->frame);
03034             } else {
03035                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
03036                tmp->faxdetect = 0;
03037                return &tmp->frame;
03038             }
03039          }
03040       } else {
03041          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
03042          return process_ast_dsp(tmp, &tmp->frame);
03043       }
03044    } else {
03045       if (tmp->ast_dsp)
03046          return process_ast_dsp(tmp, &tmp->frame);
03047       else
03048          return &tmp->frame;
03049    }
03050 }

static struct ast_channel* misdn_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 3355 of file chan_misdn.c.

References chan_list::ast, ast_copy_string(), ast_free, ast_log(), AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, cl_queue_chan(), cl_te, misdn_bchannel::dec, ext, get_robin_position(), init_chan_list(), LOG_ERROR, LOG_WARNING, METHOD_ROUND_ROBIN, METHOD_STANDARD_DEC, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_next_port_spin(), MISDN_CFG_GROUPNAME, misdn_cfg_is_group_method(), MISDN_CFG_PMP_L1_CHECK, misdn_lib_get_free_bc(), misdn_lib_get_maxchans(), misdn_lib_port_up(), misdn_new(), misdn_type, chan_list::need_hangup, ORG_AST, misdn_bchannel::port, robin_list::port, read_config(), and strsep().

03356 {
03357    struct ast_channel *tmp = NULL;
03358    char group[BUFFERSIZE + 1] = "";
03359    char dial_str[128];
03360    char *buf2 = ast_strdupa(data);
03361    char *ext;
03362    char *port_str;
03363    char *p = NULL;
03364    int channel = 0;
03365    int port = 0;
03366    struct misdn_bchannel *newbc = NULL;
03367    int dec = 0;
03368    struct chan_list *cl;
03369 
03370    snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
03371 
03372    /*
03373     * data is ---v
03374     * Dial(mISDN/g:group_name[/extension[/options]])
03375     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
03376     *
03377     * The dial extension could be empty if you are using MISDN_KEYPAD
03378     * to control ISDN provider features.
03379     */
03380    port_str = strsep(&buf2, "/");
03381    if (!ast_strlen_zero(port_str)) {
03382       if (port_str[0] == 'g' && port_str[1] == ':' ) {
03383          /* We make a group call lets checkout which ports are in my group */
03384          port_str += 2;
03385          ast_copy_string(group, port_str, sizeof(group));
03386          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03387       } else if ((p = strchr(port_str, ':'))) {
03388          /* we have a preselected channel */
03389          *p = 0;
03390          channel = atoi(++p);
03391          port = atoi(port_str);
03392          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03393       } else {
03394          port = atoi(port_str);
03395       }
03396    } else {
03397       ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
03398       return NULL;
03399    }
03400 
03401    ext = strsep(&buf2, "/");
03402    if (!ext) {
03403       ext = "";
03404    }
03405 
03406    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03407       chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
03408       dec = 1;
03409    }
03410 
03411    if (!ast_strlen_zero(group)) {
03412       char cfg_group[BUFFERSIZE + 1];
03413       struct robin_list *rr = NULL;
03414 
03415       /* Group dial */
03416 
03417       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03418          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03419          rr = get_robin_position(group);
03420       }
03421 
03422       if (rr) {
03423          int robin_channel = rr->channel;
03424          int port_start;
03425          int next_chan = 1;
03426 
03427          do {
03428             port_start = 0;
03429             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
03430                 port = misdn_cfg_get_next_port_spin(port)) {
03431 
03432                if (!port_start)
03433                   port_start = port;
03434 
03435                if (port >= port_start)
03436                   next_chan = 1;
03437                
03438                if (port <= port_start && next_chan) {
03439                   int maxbchans=misdn_lib_get_maxchans(port);
03440                   if (++robin_channel >= maxbchans) {
03441                      robin_channel = 1;
03442                   }
03443                   next_chan = 0;
03444                }
03445 
03446                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03447 
03448                if (!strcasecmp(cfg_group, group)) {
03449                   int port_up;
03450                   int check;
03451                   misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03452                   port_up = misdn_lib_port_up(port, check);
03453 
03454                   if (check && !port_up) 
03455                      chan_misdn_log(1, port, "L1 is not Up on this Port\n");
03456                   
03457                   if (check && port_up < 0) {
03458                      ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
03459                   }
03460 
03461                   if (port_up > 0)  {
03462                      newbc = misdn_lib_get_free_bc(port, robin_channel, 0, 0);
03463                      if (newbc) {
03464                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03465                         if (port_up)
03466                            chan_misdn_log(4, port, "portup:%d\n",  port_up);
03467                         rr->port = newbc->port;
03468                         rr->channel = newbc->channel;
03469                         break;
03470                      }
03471                   }
03472                }
03473             }
03474          } while (!newbc && robin_channel != rr->channel);
03475          
03476       } else {    
03477          for (port = misdn_cfg_get_next_port(0); port > 0;
03478              port = misdn_cfg_get_next_port(port)) {
03479 
03480             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03481 
03482             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03483             if (!strcasecmp(cfg_group, group)) {
03484                int port_up;
03485                int check;
03486                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03487                port_up = misdn_lib_port_up(port, check);
03488 
03489                chan_misdn_log(4, port, "portup:%d\n", port_up);
03490 
03491                if (port_up > 0) {
03492                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03493                   if (newbc)
03494                      break;
03495                }
03496             }
03497          }
03498       }
03499       
03500       /* Group dial failed ?*/
03501       if (!newbc) {
03502          ast_log(LOG_WARNING, 
03503                "Could not Dial out on group '%s'.\n"
03504                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03505                "\tOr there was no free channel on none of the ports\n\n"
03506                , group);
03507          return NULL;
03508       }
03509    } else {
03510       /* 'Normal' Port dial * Port dial */
03511       if (channel)
03512          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03513       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03514 
03515       if (!newbc) {
03516          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03517          return NULL;
03518       }
03519    }
03520    
03521 
03522    /* create ast_channel and link all the objects together */
03523    cl = init_chan_list(ORG_AST);
03524    if (!cl) {
03525       ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
03526       return NULL;
03527    }
03528    cl->bc = newbc;
03529    
03530    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03531    if (!tmp) {
03532       ast_free(cl);
03533       ast_log(LOG_ERROR,"Could not create Asterisk object\n");
03534       return NULL;
03535    }
03536 
03537    cl->ast=tmp;
03538    
03539    /* register chan in local list */
03540    cl_queue_chan(&cl_te, cl) ;
03541    
03542    /* fill in the config into the objects */
03543    read_config(cl, ORG_AST);
03544 
03545    /* important */
03546    cl->need_hangup = 0;
03547    
03548    return tmp;
03549 }

static int misdn_send_text ( struct ast_channel chan,
const char *  text 
) [static]

Definition at line 3552 of file chan_misdn.c.

References ast_copy_string(), ast_log(), chan_list::bc, chan, misdn_bchannel::display, EVENT_INFORMATION, LOG_WARNING, misdn_lib_send_event(), and ast_channel::tech_pvt.

03553 {
03554    struct chan_list *tmp = chan->tech_pvt;
03555    
03556    if (tmp && tmp->bc) {
03557       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03558       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03559    } else {
03560       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03561       return -1;
03562    }
03563    
03564    return 0;
03565 }

static int misdn_set_opt_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 5666 of file chan_misdn.c.

References ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), ast_log(), ast_strdupa, ast_strlen_zero(), chan_list::bc, misdn_bchannel::capability, chan, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_GEN_CRYPT_KEYS, misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_bchannel::orig, chan_list::originator, parse(), misdn_bchannel::port, misdn_bchannel::pres, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, strsep(), ast_channel::tech, misdn_bchannel::txgain, and ast_channel_tech::type.

Referenced by load_module(), and misdn_call().

05667 {
05668    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05669    char *tok, *tokb, *parse;
05670    int  keyidx = 0;
05671    int rxgain = 0;
05672    int txgain = 0;
05673    int change_jitter = 0;
05674 
05675    if (strcasecmp(chan->tech->type, "mISDN")) {
05676       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05677       return -1;
05678    }
05679    
05680    if (ast_strlen_zero((char *)data)) {
05681       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05682       return -1;
05683    }
05684 
05685    parse = ast_strdupa(data);
05686    for (tok = strtok_r(parse, ":", &tokb);
05687         tok;
05688         tok = strtok_r(NULL, ":", &tokb) ) {
05689       int neglect = 0;
05690 
05691       if (tok[0] == '!' ) {
05692          neglect = 1;
05693          tok++;
05694       }
05695       
05696       switch(tok[0]) {
05697          
05698       case 'd' :
05699          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05700          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05701          break;
05702          
05703       case 'n':
05704          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05705          ch->bc->nodsp = 1;
05706          break;
05707 
05708       case 'j':
05709          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05710          tok++;
05711          change_jitter = 1;
05712 
05713          switch ( tok[0] ) {
05714          case 'b':
05715             ch->jb_len = atoi(++tok);
05716             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05717             break;
05718          case 't' :
05719             ch->jb_upper_threshold = atoi(++tok);
05720             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05721             break;
05722          case 'n':
05723             ch->bc->nojitter = 1;
05724             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05725             break;
05726          default:
05727             ch->jb_len = 4000;
05728             ch->jb_upper_threshold = 0;
05729             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05730             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05731          }
05732          break;
05733       case 'v':
05734          tok++;
05735 
05736          switch (tok[0]) {
05737          case 'r' :
05738             rxgain = atoi(++tok);
05739             if (rxgain < -8)
05740                rxgain = -8;
05741             if (rxgain > 8)
05742                rxgain = 8;
05743             ch->bc->rxgain = rxgain;
05744             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05745             break;
05746          case 't':
05747             txgain = atoi(++tok);
05748             if (txgain < -8)
05749                txgain = -8;
05750             if (txgain > 8)
05751                txgain = 8;
05752             ch->bc->txgain = txgain;
05753             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05754             break;
05755          }
05756          break;
05757       
05758       case 'c':
05759          keyidx = atoi(++tok);
05760          {
05761             char keys[4096];
05762             char *key = NULL, *tmp = keys;
05763             int i;
05764             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05765 
05766             for (i = 0; i < keyidx; i++) {
05767                key = strsep(&tmp, ",");
05768             }
05769 
05770             if (key) {
05771                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05772             }
05773 
05774             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05775             break;
05776          }
05777       case 'e':
05778          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05779          
05780          if (neglect) {
05781             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05782 #ifdef MISDN_1_2
05783             *ch->bc->pipeline = 0;
05784 #else
05785             ch->bc->ec_enable = 0;
05786 #endif
05787          } else {
05788 #ifdef MISDN_1_2
05789             update_pipeline_config(ch->bc);
05790 #else
05791             ch->bc->ec_enable = 1;
05792             ch->bc->orig = ch->originator;
05793             tok++;
05794             if (*tok) {
05795                ch->bc->ec_deftaps = atoi(tok);
05796             }
05797 #endif
05798          }
05799          
05800          break;
05801       case 'h':
05802          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05803          
05804          if (strlen(tok) > 1 && tok[1] == '1') {
05805             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05806             if (!ch->bc->hdlc) {
05807                ch->bc->hdlc = 1;
05808             }
05809          }
05810          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05811          break;
05812             
05813       case 's':
05814          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05815          ch->bc->send_dtmf = 1;
05816          break;
05817          
05818       case 'f':
05819          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05820          ch->faxdetect = 1;
05821          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05822          break;
05823 
05824       case 'a':
05825          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05826          ch->ast_dsp = 1;
05827          break;
05828 
05829       case 'p':
05830          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05831          /* CRICH: callingpres!!! */
05832          if (strstr(tok,"allowed")) {
05833             ch->bc->pres = 0;
05834          } else if (strstr(tok, "restricted")) {
05835             ch->bc->pres = 1;
05836          } else if (strstr(tok, "not_screened")) {
05837             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05838             ch->bc->pres = 1;
05839          }
05840          break;
05841       case 'i' :
05842          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05843          ch->ignore_dtmf=1;
05844          break;
05845       default:
05846          break;
05847       }
05848    }
05849 
05850    if (change_jitter)
05851       config_jitterbuffer(ch);
05852 
05853    if (ch->faxdetect || ch->ast_dsp) {
05854       if (!ch->dsp)
05855          ch->dsp = ast_dsp_new();
05856       if (ch->dsp)
05857          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
05858    }
05859 
05860    if (ch->ast_dsp) {
05861       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05862       ch->bc->nodsp = 1;
05863    }
05864    
05865    return 0;
05866 }

static int misdn_tasks_add ( int  timeout,
ast_sched_cb  callback,
const void *  data 
) [static]

Definition at line 815 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

00816 {
00817    return _misdn_tasks_add_variable(timeout, callback, data, 0);
00818 }

static int misdn_tasks_add_variable ( int  timeout,
ast_sched_cb  callback,
const void *  data 
) [static]

Definition at line 820 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

00821 {
00822    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00823 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 785 of file chan_misdn.c.

References cb_log, chan_misdn_log(), misdn_tasks, and sched_context_destroy().

Referenced by unload_module().

00786 {
00787    if (misdn_tasks) {
00788       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
00789       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
00790          cb_log(4, 0, "Joining misdn_tasks thread\n");
00791          pthread_join(misdn_tasks_thread, NULL);
00792       }
00793       sched_context_destroy(misdn_tasks);
00794    }
00795 }

static void misdn_tasks_init ( void   )  [static]

Definition at line 766 of file chan_misdn.c.

References chan_misdn_log(), misdn_tasks, misdn_tasks_thread_func(), pthread_create, and sched_context_create().

Referenced by _misdn_tasks_add_variable().

00767 {
00768    sem_t blocker;
00769    int i = 5;
00770 
00771    if (sem_init(&blocker, 0, 0)) {
00772       perror("chan_misdn: Failed to initialize semaphore!");
00773       exit(1);
00774    }
00775 
00776    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
00777    
00778    misdn_tasks = sched_context_create();
00779    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
00780 
00781    while (sem_wait(&blocker) && --i);
00782    sem_destroy(&blocker);
00783 }

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 825 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by release_chan(), and release_chan_early().

00826 {
00827    AST_SCHED_DEL(misdn_tasks, task_id);
00828 }

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

Definition at line 742 of file chan_misdn.c.

References ast_sched_runq(), ast_sched_wait(), chan_misdn_log(), misdn_tasks, and sighandler().

Referenced by misdn_tasks_init().

00743 {
00744    int wait;
00745    struct sigaction sa;
00746 
00747    sa.sa_handler = sighandler;
00748    sa.sa_flags = SA_NODEFER;
00749    sigemptyset(&sa.sa_mask);
00750    sigaddset(&sa.sa_mask, SIGUSR1);
00751    sigaction(SIGUSR1, &sa, NULL);
00752    
00753    sem_post((sem_t *)data);
00754 
00755    while (1) {
00756       wait = ast_sched_wait(misdn_tasks);
00757       if (wait < 0)
00758          wait = 8000;
00759       if (poll(NULL, 0, wait) < 0)
00760          chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
00761       ast_sched_runq(misdn_tasks);
00762    }
00763    return NULL;
00764 }

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 797 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

00798 {
00799    pthread_kill(misdn_tasks_thread, SIGUSR1);
00800 }

static int misdn_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 3053 of file chan_misdn.c.

References misdn_bchannel::addr, chan_list::ast, ast_debug, ast_log(), chan_list::bc, misdn_bchannel::bc_state, BCHAN_ACTIVATED, BCHAN_BRIDGED, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_frame::data, chan_list::dropped_frame_cnt, ast_channel::exten, chan_list::frame, chan_list::hold, misdn_bchannel::l3_id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_get_ch_state(), MISDN_HOLD_IDLE, misdn_lib_tone_generator_start(), chan_list::notxtone, misdn_bchannel::port, prefformat, ast_frame::ptr, ast_frame::samples, ast_frame::src, hold_info::state, ast_frame::subclass, and chan_list::ts.

03054 {
03055    struct chan_list *ch;
03056    int i  = 0;
03057    
03058    if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
03059 
03060    if (ch->hold.state != MISDN_HOLD_IDLE) {
03061       chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
03062       return 0;
03063    }
03064    
03065    if (!ch->bc ) {
03066       ast_log(LOG_WARNING, "private but no bc\n");
03067       return -1;
03068    }
03069    
03070    if (ch->notxtone) {
03071       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
03072       return 0;
03073    }
03074 
03075 
03076    if (!frame->subclass) {
03077       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
03078       return 0;
03079    }
03080    
03081    if (!(frame->subclass & prefformat)) {
03082       
03083       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
03084       return 0;
03085    }
03086    
03087 
03088    if (!frame->samples ) {
03089       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
03090       
03091       if (!strcmp(frame->src,"ast_prod")) {
03092          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
03093 
03094          if (ch->ts) {
03095             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
03096             misdn_lib_tone_generator_start(ch->bc);
03097          }
03098          return 0;
03099       }
03100 
03101       return -1;
03102    }
03103 
03104    if ( ! ch->bc->addr ) {
03105       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
03106       return 0;
03107    }
03108    
03109 #ifdef MISDN_DEBUG
03110    {
03111       int i, max = 5 > frame->samples ? frame->samples : 5;
03112 
03113       ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
03114 
03115       for (i = 0; i < max ; i++)
03116          ast_debug(1, "%2.2x ", ((char*) frame->data.ptr)[i]);
03117    }
03118 #endif
03119 
03120    switch (ch->bc->bc_state) {
03121    case BCHAN_ACTIVATED:
03122    case BCHAN_BRIDGED:
03123       break;
03124    default:
03125       if (!ch->dropped_frame_cnt)
03126          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n", frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
03127       
03128       ch->dropped_frame_cnt++;
03129       if (ch->dropped_frame_cnt > 100) {
03130          ch->dropped_frame_cnt = 0;
03131          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x  dropped > 100 frames!\n", frame->samples, ch->bc->addr);
03132       }
03133 
03134       return 0;
03135    }
03136 
03137    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
03138    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
03139       /* Buffered Transmit (triggered by read from isdn side)*/
03140       if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
03141          if (ch->bc->active)
03142             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
03143       }
03144       
03145    } else {
03146       /*transmit without jitterbuffer*/
03147       i = misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
03148    }
03149 
03150    return 0;
03151 }

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

Definition at line 3838 of file chan_misdn.c.

References chan_list::ast, ast_pbx_start(), and chan_list::need_hangup.

Referenced by cb_events(), do_immediate_setup(), misdn_overlap_dial_task(), and start_pbx().

03839 {
03840    int ret = ast_pbx_start(ch->ast);   
03841 
03842    if (ret >= 0) 
03843       ch->need_hangup = 0;
03844    else
03845       ch->need_hangup = 1;
03846 
03847    return ret;
03848 }

static void print_bc_info ( int  fd,
struct chan_list help,
struct misdn_bchannel bc 
) [static]

Definition at line 1341 of file chan_misdn.c.

References misdn_bchannel::active, misdn_bchannel::addr, chan_list::addr, chan_list::ast, ast_cli(), misdn_bchannel::bc_state, bc_state2str(), bearer2str(), misdn_bchannel::capability, misdn_bchannel::channel, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, misdn_bchannel::display, misdn_bchannel::ec_enable, ast_channel::exten, misdn_bchannel::holded, misdn_bchannel::l3_id, chan_list::l3id, misdn_debug, misdn_get_ch_state(), ast_channel::name, chan_list::norxtone, chan_list::notxtone, misdn_bchannel::nt, ORG_AST, chan_list::originator, misdn_bchannel::pid, misdn_bchannel::port, and misdn_bchannel::rad.

Referenced by handle_cli_misdn_show_channel(), and handle_cli_misdn_show_channels().

01342 {
01343    struct ast_channel *ast = help->ast;
01344    ast_cli(fd,
01345       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
01346 
01347       bc->pid, bc->port, bc->channel,
01348       bc->nt ? "NT" : "TE",
01349       help->originator == ORG_AST ? "*" : "I",
01350       ast ? ast->exten : NULL,
01351       ast ? ast->cid.cid_num : NULL,
01352       bc->rad,
01353       ast ? ast->context : NULL,
01354       misdn_get_ch_state(help)
01355       );
01356    if (misdn_debug[bc->port] > 0)
01357       ast_cli(fd,
01358          "  --> astname: %s\n"
01359          "  --> ch_l3id: %x\n"
01360          "  --> ch_addr: %x\n"
01361          "  --> bc_addr: %x\n"
01362          "  --> bc_l3id: %x\n"
01363          "  --> display: %s\n"
01364          "  --> activated: %d\n"
01365          "  --> state: %s\n"
01366          "  --> capability: %s\n"
01367 #ifdef MISDN_1_2
01368          "  --> pipeline: %s\n"
01369 #else
01370          "  --> echo_cancel: %d\n"
01371 #endif
01372          "  --> notone : rx %d tx:%d\n"
01373          "  --> bc_hold: %d\n",
01374          help->ast->name,
01375          help->l3id,
01376          help->addr,
01377          bc->addr,
01378          bc ? bc->l3_id : -1,
01379          bc->display,
01380          
01381          bc->active,
01382          bc_state2str(bc->bc_state),
01383          bearer2str(bc->capability),
01384 #ifdef MISDN_1_2
01385          bc->pipeline,
01386 #else
01387          bc->ec_enable,
01388 #endif
01389 
01390          help->norxtone, help->notxtone,
01391          bc->holded
01392          );
01393 
01394 }

static void print_bearer ( struct misdn_bchannel bc  )  [static]

Definition at line 665 of file chan_misdn.c.

References bearer2str(), misdn_bchannel::capability, chan_misdn_log(), INFO_CODEC_ALAW, INFO_CODEC_ULAW, misdn_bchannel::law, and misdn_bchannel::port.

Referenced by cb_events().

00666 {
00667    
00668    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00669    
00670    switch(bc->law) {
00671    case INFO_CODEC_ALAW:
00672       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00673       break;
00674    case INFO_CODEC_ULAW:
00675       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00676       break;
00677    }
00678 }

static void print_facility ( struct FacParm *  fac,
struct misdn_bchannel bc 
) [static]

Definition at line 614 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by cb_events().

00615 {
00616    switch (fac->Function) {
00617 #ifdef HAVE_MISDN_FAC_RESULT
00618    case Fac_RESULT:
00619       chan_misdn_log(0, bc->port," --> Received RESULT Operation\n");
00620       break;
00621 #endif
00622 #ifdef HAVE_MISDN_FAC_ERROR
00623    case Fac_ERROR:
00624       chan_misdn_log(0, bc->port," --> Received Error Operation\n");
00625       chan_misdn_log(0, bc->port," --> Value:%d Error:%s\n",fac->u.ERROR.errorValue, fac->u.ERROR.error);
00626       break;
00627 #endif
00628    case Fac_CD:
00629       chan_misdn_log(1,bc->port," --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
00630          fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
00631       break;
00632    case Fac_AOCDCurrency:
00633       if (fac->u.AOCDcur.chargeNotAvailable)
00634          chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
00635       else if (fac->u.AOCDcur.freeOfCharge)
00636          chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
00637       else if (fac->u.AOCDchu.billingId >= 0)
00638          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
00639             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00640             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
00641       else
00642          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
00643             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00644             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
00645       break;
00646    case Fac_AOCDChargingUnit:
00647       if (fac->u.AOCDchu.chargeNotAvailable)
00648          chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
00649       else if (fac->u.AOCDchu.freeOfCharge)
00650          chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
00651       else if (fac->u.AOCDchu.billingId >= 0)
00652          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
00653             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
00654       else
00655          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
00656             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
00657       break;
00658    case Fac_None:
00659    default:
00660       chan_misdn_log(1,bc->port," --> unknown facility\n");
00661       break;
00662    }
00663 }

static struct ast_frame * process_ast_dsp ( struct chan_list tmp,
struct ast_frame frame 
) [static]

Definition at line 2890 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), ast_debug, chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_log(), ast_strlen_zero(), ast_verb, chan_list::bc, BUFFERSIZE, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, chan_list::dsp, misdn_bchannel::ec_enable, ast_channel::exten, f, chan_list::faxdetect, chan_list::faxhandled, isdn_lib_stop_dtmf(), isdn_lib_update_ec(), isdn_lib_update_rxgain(), isdn_lib_update_txgain(), LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), ast_channel::name, pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, and misdn_bchannel::txgain.

Referenced by misdn_read().

02891 {
02892    struct ast_frame *f;
02893  
02894    if (tmp->dsp) {
02895       f = ast_dsp_process(tmp->ast, tmp->dsp, frame);
02896    } else {
02897       chan_misdn_log(0, tmp->bc->port, "No DSP-Path found\n");
02898       return NULL;
02899    }
02900 
02901    if (!f || (f->frametype != AST_FRAME_DTMF)) {
02902       return f;
02903    }
02904  
02905    ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
02906  
02907    if (tmp->faxdetect && (f->subclass == 'f')) {
02908       /* Fax tone -- Handle and return NULL */
02909       if (!tmp->faxhandled) {
02910          struct ast_channel *ast = tmp->ast;
02911          tmp->faxhandled++;
02912          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02913          tmp->bc->rxgain = 0;
02914          isdn_lib_update_rxgain(tmp->bc);
02915          tmp->bc->txgain = 0;
02916          isdn_lib_update_txgain(tmp->bc);
02917 #ifdef MISDN_1_2
02918          *tmp->bc->pipeline = 0;
02919 #else
02920          tmp->bc->ec_enable = 0;
02921 #endif
02922          isdn_lib_update_ec(tmp->bc);
02923          isdn_lib_stop_dtmf(tmp->bc);
02924          switch (tmp->faxdetect) {
02925          case 1:
02926             if (strcmp(ast->exten, "fax")) {
02927                char *context;
02928                char context_tmp[BUFFERSIZE];
02929                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02930                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02931                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02932                   ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02933                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02934                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02935                   if (ast_async_goto(ast, context, "fax", 1))
02936                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02937                } else
02938                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02939             } else {
02940                ast_debug(1, "Already in a fax extension, not redirecting\n");
02941             }
02942             break;
02943          case 2:
02944             ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02945             break;
02946          }
02947       } else {
02948          ast_debug(1, "Fax already handled\n");
02949       }
02950    }
02951    
02952    if (tmp->ast_dsp && (f->subclass != 'f')) {
02953       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02954    }
02955 
02956    return f;
02957 }

static int read_config ( struct chan_list ch,
int  orig 
) [static]

Definition at line 2127 of file chan_misdn.c.

References chan_list::allowed_bearers, misdn_bchannel::AOCDtype, chan_list::ast, ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), ast_free, ast_log(), ast_mutex_init(), ast_print_group(), ast_set_callerid(), ast_strdup, ast_string_field_set, ast_strlen_zero(), chan_list::bc, buf, BUFFERSIZE, ast_channel::callgroup, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_rdnis, config_jitterbuffer(), ast_channel::context, chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::dad, debug_numplan(), misdn_bchannel::dnumplan, chan_list::dsp, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::early_bconnect, ast_channel::exten, chan_list::far_alerting, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, chan_list::incoming_early_audio, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, misdn_bchannel::keypad, language, LOG_WARNING, MISDN_CFG_ALLOWED_BEARERS, MISDN_CFG_ASTDTMF, MISDN_CFG_CALLERID, MISDN_CFG_CALLGROUP, MISDN_CFG_CONTEXT, MISDN_CFG_CPNDIALPLAN, MISDN_CFG_DIALPLAN, MISDN_CFG_EARLY_BCONNECT, MISDN_CFG_FAR_ALERTING, MISDN_CFG_FAXDETECT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CFG_INTERNATPREFIX, MISDN_CFG_JITTERBUFFER, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CFG_LANGUAGE, MISDN_CFG_LOCALDIALPLAN, MISDN_CFG_MUSICCLASS, MISDN_CFG_NATPREFIX, MISDN_CFG_NEED_MORE_INFOS, MISDN_CFG_NOAUTORESPOND_ON_SETUP, MISDN_CFG_NTTIMEOUT, MISDN_CFG_OVERLAP_DIAL, MISDN_CFG_PICKUPGROUP, MISDN_CFG_RXGAIN, MISDN_CFG_SENDDTMF, MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CFG_TXGAIN, chan_list::mohinterpret, misdn_bchannel::need_more_infos, chan_list::noautorespond_on_setup, chan_list::nttimeout, NUMPLAN_INTERNATIONAL, NUMPLAN_NATIONAL, misdn_bchannel::oad, misdn_bchannel::onumplan, ORG_AST, misdn_bchannel::orig_dad, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, ast_channel::pickupgroup, misdn_bchannel::port, prefix, misdn_bchannel::rad, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, misdn_bchannel::te_choose_channel, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

02128 {
02129    struct ast_channel *ast;
02130    struct misdn_bchannel *bc;
02131    int port;
02132    int hdlc = 0;
02133    char lang[BUFFERSIZE + 1];
02134    char faxdetect[BUFFERSIZE + 1];
02135    char buf[256];
02136    char buf2[256];
02137    ast_group_t pg;
02138    ast_group_t cg;
02139 
02140    if (!ch) {
02141       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
02142       return -1;
02143    }
02144 
02145    ast = ch->ast;
02146    bc = ch->bc;
02147    if (! ast || ! bc) {
02148       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
02149       return -1;
02150    }
02151    
02152    port = bc->port;
02153    chan_misdn_log(1, port, "read_config: Getting Config\n");
02154 
02155    misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
02156    ast_string_field_set(ast, language, lang);
02157 
02158    misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
02159 
02160    misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
02161    misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
02162 
02163    misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
02164 
02165    misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
02166 
02167    misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
02168 
02169    if (ch->ast_dsp) {
02170       ch->ignore_dtmf = 1;
02171    }
02172 
02173    misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
02174    misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
02175 
02176    misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
02177 
02178    misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
02179 
02180    misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
02181 
02182    misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
02183 
02184    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
02185 
02186    if (hdlc) {
02187       switch (bc->capability) {
02188       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02189       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
02190          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
02191          bc->hdlc = 1;
02192          break;
02193       }
02194       
02195    }
02196    /*Initialize new Jitterbuffer*/
02197    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
02198    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
02199 
02200    config_jitterbuffer(ch);
02201 
02202    misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
02203 
02204    ast_copy_string(ast->context, ch->context, sizeof(ast->context));
02205 
02206 #ifdef MISDN_1_2
02207    update_pipeline_config(bc);
02208 #else
02209    update_ec_config(bc);
02210 #endif
02211 
02212    misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
02213 
02214    misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02215    misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02216 
02217    chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
02218    ast->pickupgroup = pg;
02219    ast->callgroup = cg;
02220    
02221    if (orig == ORG_AST) {
02222       char callerid[BUFFERSIZE + 1];
02223 
02224       /* ORIGINATOR Asterisk (outgoing call) */
02225 
02226       misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
02227 
02228       if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
02229          if (strstr(faxdetect, "nojump"))
02230             ch->faxdetect = 2;
02231          else
02232             ch->faxdetect = 1;
02233       }
02234 
02235       misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
02236       if ( ! ast_strlen_zero(callerid) ) {
02237          chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
02238          ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
02239       }
02240 
02241       misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
02242       misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
02243       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02244       debug_numplan(port, bc->dnumplan, "TON");
02245       debug_numplan(port, bc->onumplan, "LTON");
02246       debug_numplan(port, bc->cpnnumplan, "CTON");
02247 
02248       ch->overlap_dial = 0;
02249    } else {
02250       /* ORIGINATOR MISDN (incoming call) */
02251       char prefix[BUFFERSIZE + 1] = "";
02252 
02253       if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
02254          if (strstr(faxdetect, "nojump"))
02255             ch->faxdetect = 2;
02256          else
02257             ch->faxdetect = 1;
02258       }
02259 
02260       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02261       debug_numplan(port, bc->cpnnumplan, "CTON");
02262 
02263       switch (bc->onumplan) {
02264       case NUMPLAN_INTERNATIONAL:
02265          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02266          break;
02267 
02268       case NUMPLAN_NATIONAL:
02269          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02270          break;
02271       default:
02272          break;
02273       }
02274 
02275       ast_copy_string(buf, bc->oad, sizeof(buf));
02276       snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
02277 
02278       if (!ast_strlen_zero(bc->dad)) {
02279          ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
02280       }
02281 
02282       if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02283          ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
02284       }
02285 
02286       prefix[0] = 0;
02287 
02288       switch (bc->dnumplan) {
02289       case NUMPLAN_INTERNATIONAL:
02290          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02291          break;
02292       case NUMPLAN_NATIONAL:
02293          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02294          break;
02295       default:
02296          break;
02297       }
02298 
02299       ast_copy_string(buf, bc->dad, sizeof(buf));
02300       snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
02301 
02302       if (strcmp(bc->dad, ast->exten)) {
02303          ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
02304       }
02305 
02306       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
02307 
02308       if ( !ast_strlen_zero(bc->rad) ) {
02309          if (ast->cid.cid_rdnis)
02310             ast_free(ast->cid.cid_rdnis);
02311          ast->cid.cid_rdnis = ast_strdup(bc->rad);
02312       }
02313    
02314       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
02315       ast_mutex_init(&ch->overlap_tv_lock);
02316    } /* ORIG MISDN END */
02317 
02318    ch->overlap_dial_task = -1;
02319    
02320    if (ch->faxdetect  || ch->ast_dsp) {
02321       misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
02322       if (!ch->dsp)
02323          ch->dsp = ast_dsp_new();
02324       if (ch->dsp) {
02325          if (ch->faxdetect) 
02326             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
02327          else 
02328             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT );
02329       }
02330    }
02331 
02332    /* AOCD initialization */
02333    bc->AOCDtype = Fac_None;
02334 
02335    return 0;
02336 }

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

Definition at line 3898 of file chan_misdn.c.

References chan_list::ast, ast_free, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_misdn_log(), cl_dequeue_chan(), cl_te, chan_list::jb, misdn_bchannel::l3_id, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, misdn_in_calls, misdn_jb_destroy(), misdn_out_calls, misdn_tasks_remove(), misdn_bchannel::nojitter, ORG_AST, chan_list::originator, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, misdn_bchannel::pid, chan_list::pipe, misdn_bchannel::port, and chan_list::state.

Referenced by cb_events(), and misdn_hangup().

03899 {
03900    struct ast_channel *ast;
03901 
03902    ch->state = MISDN_CLEANING;
03903 
03904    ast_mutex_lock(&release_lock);
03905 
03906    cl_dequeue_chan(&cl_te, ch);
03907 
03908    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
03909 
03910    /* releasing jitterbuffer */
03911    if (ch->jb) {
03912       misdn_jb_destroy(ch->jb);
03913       ch->jb = NULL;
03914    } else {
03915       if (!bc->nojitter) {
03916          chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03917       }
03918    }
03919 
03920    if (ch->overlap_dial) {
03921       if (ch->overlap_dial_task != -1) {
03922          misdn_tasks_remove(ch->overlap_dial_task);
03923          ch->overlap_dial_task = -1;
03924       }
03925       ast_mutex_destroy(&ch->overlap_tv_lock);
03926    }
03927 
03928    if (ch->originator == ORG_AST) {
03929       --misdn_out_calls[bc->port];
03930    } else {
03931       --misdn_in_calls[bc->port];
03932    }
03933 
03934    close(ch->pipe[0]);
03935    close(ch->pipe[1]);
03936 
03937    ast = ch->ast;
03938    if (ast) {
03939       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03940       chan_misdn_log(1, bc->port,
03941          "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s\n",
03942          bc->pid,
03943          ast->context,
03944          ast->exten,
03945          ast->cid.cid_num);
03946 
03947       if (ast->_state != AST_STATE_RESERVED) {
03948          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03949          ast_setstate(ast, AST_STATE_DOWN);
03950       }
03951    }
03952 
03953    ast_free(ch);
03954 
03955    ast_mutex_unlock(&release_lock);
03956 }

static void release_chan_early ( struct chan_list ch  )  [static]

Definition at line 3968 of file chan_misdn.c.

References chan_list::ast, ast_free, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, cl_dequeue_chan(), cl_te, chan_list::hold, chan_list::jb, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, MISDN_HOLD_IDLE, misdn_in_calls, misdn_jb_destroy(), misdn_out_calls, misdn_tasks_remove(), ORG_AST, chan_list::originator, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, chan_list::pipe, hold_info::port, hold_info::state, and chan_list::state.

Referenced by misdn_hangup().

03969 {
03970    struct ast_channel *ast;
03971 
03972    ch->state = MISDN_CLEANING;
03973 
03974    ast_mutex_lock(&release_lock);
03975 
03976    cl_dequeue_chan(&cl_te, ch);
03977 
03978    /* releasing jitterbuffer */
03979    if (ch->jb) {
03980       misdn_jb_destroy(ch->jb);
03981       ch->jb = NULL;
03982    }
03983 
03984    if (ch->overlap_dial) {
03985       if (ch->overlap_dial_task != -1) {
03986          misdn_tasks_remove(ch->overlap_dial_task);
03987          ch->overlap_dial_task = -1;
03988       }
03989       ast_mutex_destroy(&ch->overlap_tv_lock);
03990    }
03991 
03992    if (ch->hold.state != MISDN_HOLD_IDLE) {
03993       if (ch->originator == ORG_AST) {
03994          --misdn_out_calls[ch->hold.port];
03995       } else {
03996          --misdn_in_calls[ch->hold.port];
03997       }
03998    }
03999 
04000    close(ch->pipe[0]);
04001    close(ch->pipe[1]);
04002 
04003    ast = ch->ast;
04004    if (ast) {
04005       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
04006       if (ast->_state != AST_STATE_RESERVED) {
04007          ast_setstate(ast, AST_STATE_DOWN);
04008       }
04009    }
04010 
04011    ast_free(ch);
04012 
04013    ast_mutex_unlock(&release_lock);
04014 }

static int reload ( void   )  [static]

Definition at line 5535 of file chan_misdn.c.

References reload_config().

05536 {
05537    reload_config();
05538 
05539    return 0;
05540 }

static void reload_config ( void   )  [static]

Definition at line 1298 of file chan_misdn.c.

References ast_log(), free_robin_list(), LOG_WARNING, max_ports, misdn_cfg_get(), misdn_cfg_reload(), misdn_cfg_update_ptp(), misdn_debug, misdn_debug_only, MISDN_GEN_DEBUG, and MISDN_GEN_TRACEFILE.

01299 {
01300    int i, cfg_debug;
01301 
01302    if (!g_config_initialized) {
01303       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
01304       return ;
01305    }
01306    
01307    free_robin_list();
01308    misdn_cfg_reload();
01309    misdn_cfg_update_ptp();
01310    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
01311    misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
01312 
01313    for (i = 0;  i <= max_ports; i++) {
01314       misdn_debug[i] = cfg_debug;
01315       misdn_debug_only[i] = 0;
01316    }
01317 }

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

Definition at line 4123 of file chan_misdn.c.

References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_ROUTE_TRANSIT_NET, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, ast_queue_control(), misdn_bchannel::cause, chan_misdn_log(), ast_channel::hangupcause, MISDN_BUSY, chan_list::need_busy, misdn_bchannel::pid, misdn_bchannel::port, and chan_list::state.

Referenced by hangup_chan().

04123                                                                                                      {
04124    if (!ast) {
04125       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
04126       return;
04127    }
04128    if (!bc) {
04129       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
04130       return;
04131    }
04132    if (!ch) {
04133       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
04134       return;
04135    }
04136 
04137    ast->hangupcause = bc->cause;
04138 
04139    switch (bc->cause) {
04140 
04141    case AST_CAUSE_UNALLOCATED:
04142    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
04143    case AST_CAUSE_NO_ROUTE_DESTINATION:
04144    case 4:  /* Send special information tone */
04145    case AST_CAUSE_NUMBER_CHANGED:
04146    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04147       /* Congestion Cases */
04148       /*
04149        * Not Queueing the Congestion anymore, since we want to hear
04150        * the inband message
04151        *
04152       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
04153       ch->state = MISDN_BUSY;
04154       
04155       ast_queue_control(ast, AST_CONTROL_CONGESTION);
04156       */
04157       break;
04158 
04159    case AST_CAUSE_CALL_REJECTED:
04160    case AST_CAUSE_USER_BUSY:
04161       ch->state = MISDN_BUSY;
04162 
04163       if (!ch->need_busy) {
04164          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
04165          break;
04166       }
04167 
04168       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04169       
04170       ast_queue_control(ast, AST_CONTROL_BUSY);
04171       
04172       ch->need_busy = 0;
04173       
04174       break;
04175    }
04176 }

static void send_digit_to_chan ( struct chan_list cl,
char  digit 
) [static]

Definition at line 888 of file chan_misdn.c.

References chan_list::ast, ast_debug, ast_playtones_start(), chan, and ast_channel::name.

Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().

00889 {
00890    static const char* dtmf_tones[] = {
00891       "!941+1336/100,!0/100", /* 0 */
00892       "!697+1209/100,!0/100", /* 1 */
00893       "!697+1336/100,!0/100", /* 2 */
00894       "!697+1477/100,!0/100", /* 3 */
00895       "!770+1209/100,!0/100", /* 4 */
00896       "!770+1336/100,!0/100", /* 5 */
00897       "!770+1477/100,!0/100", /* 6 */
00898       "!852+1209/100,!0/100", /* 7 */
00899       "!852+1336/100,!0/100", /* 8 */
00900       "!852+1477/100,!0/100", /* 9 */
00901       "!697+1633/100,!0/100", /* A */
00902       "!770+1633/100,!0/100", /* B */
00903       "!852+1633/100,!0/100", /* C */
00904       "!941+1633/100,!0/100", /* D */
00905       "!941+1209/100,!0/100", /* * */
00906       "!941+1477/100,!0/100" };  /* # */
00907    struct ast_channel *chan=cl->ast; 
00908   
00909    if (digit >= '0' && digit <='9')
00910       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00911    else if (digit >= 'A' && digit <= 'D')
00912       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00913    else if (digit == '*')
00914       ast_playtones_start(chan,0,dtmf_tones[14], 0);
00915    else if (digit == '#')
00916       ast_playtones_start(chan,0,dtmf_tones[15], 0);
00917    else {
00918       /* not handled */
00919       ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00920    }
00921 }

static void show_config_description ( int  fd,
enum misdn_cfg_elements  elem 
) [inline, static]

Definition at line 1147 of file chan_misdn.c.

References ast_cli(), BUFFERSIZE, COLOR_BRWHITE, COLOR_YELLOW, desc, misdn_cfg_get_desc(), misdn_cfg_get_name(), MISDN_CFG_LAST, name, and term_color().

Referenced by handle_cli_misdn_show_config().

01148 {
01149    char section[BUFFERSIZE];
01150    char name[BUFFERSIZE];
01151    char desc[BUFFERSIZE];
01152    char def[BUFFERSIZE];
01153    char tmp[BUFFERSIZE];
01154 
01155    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
01156    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
01157    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
01158 
01159    if (elem < MISDN_CFG_LAST)
01160       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
01161    else
01162       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
01163 
01164    if (*def)
01165       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
01166    else
01167       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
01168 }

static void sighandler ( int  sig  )  [static]

Definition at line 739 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00740 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3317 of file chan_misdn.c.

References chan_list::bc, misdn_lib_tone_generator_stop(), chan_list::norxtone, and chan_list::notxtone.

Referenced by cb_events(), misdn_answer(), misdn_hangup(), and misdn_indication().

03318 {
03319    misdn_lib_tone_generator_stop(cl->bc);
03320    cl->notxtone = 0;
03321    cl->norxtone = 0;
03322    return 0;
03323 }

static void start_pbx ( struct chan_list ch,
struct misdn_bchannel bc,
struct ast_channel chan 
) [static]

Definition at line 4269 of file chan_misdn.c.

References chan_misdn_log(), EVENT_RELEASE, EVENT_RELEASE_COMPLETE, hangup_chan(), hanguptone_indicate(), misdn_lib_send_event(), misdn_bchannel::nt, pbx_start_chan(), and misdn_bchannel::port.

Referenced by cb_events().

04269                                                                                                  {
04270    if (pbx_start_chan(ch) < 0) {
04271       hangup_chan(ch, bc);
04272       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04273       if (bc->nt) {
04274          hanguptone_indicate(ch);
04275          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04276       } else
04277          misdn_lib_send_event(bc, EVENT_RELEASE);
04278    }
04279 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3325 of file chan_misdn.c.

References chan_list::norxtone, and chan_list::notxtone.

Referenced by cb_events(), misdn_call(), and misdn_hangup().

03326 {
03327    if (!cl) return -1;
03328 
03329    cl->notxtone = 1;
03330    cl->norxtone = 1;
03331    
03332    return 0;
03333 }

static int stop_indicate ( struct chan_list cl  )  [static]

Definition at line 3297 of file chan_misdn.c.

References chan_list::ast, ast_playtones_stop(), chan_list::bc, chan_misdn_log(), misdn_lib_tone_generator_stop(), misdn_bchannel::port, and chan_list::ts.

Referenced by cb_events(), misdn_answer(), misdn_indication(), and misdn_overlap_dial_task().

03298 {
03299    struct ast_channel *ast = cl->ast;
03300 
03301    if (!ast) {
03302       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03303       return -1;
03304    }
03305 
03306    chan_misdn_log(3, cl->bc->port, " --> None\n");
03307    misdn_lib_tone_generator_stop(cl->bc);
03308    ast_playtones_stop(ast);
03309 
03310    cl->ts = NULL;
03311    /*ast_deactivate_generator(ast);*/
03312 
03313    return 0;
03314 }

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 5322 of file chan_misdn.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_free, ast_log(), ast_unregister_application(), chan_misdn_clis, free_robin_list(), LOG_VERBOSE, misdn_cfg_destroy(), misdn_debug, misdn_debug_only, misdn_in_calls, misdn_lib_destroy(), misdn_out_calls, misdn_tasks_destroy(), and misdn_tech.

05323 {
05324    /* First, take us out of the channel loop */
05325    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05326 
05327    misdn_tasks_destroy();
05328    
05329    if (!g_config_initialized)
05330       return 0;
05331    
05332    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05333    
05334    /* ast_unregister_application("misdn_crypt"); */
05335    ast_unregister_application("misdn_set_opt");
05336    ast_unregister_application("misdn_facility");
05337    ast_unregister_application("misdn_check_l2l1");
05338   
05339    ast_channel_unregister(&misdn_tech);
05340 
05341    free_robin_list();
05342    misdn_cfg_destroy();
05343    misdn_lib_destroy();
05344   
05345    ast_free(misdn_out_calls);
05346    ast_free(misdn_in_calls);
05347    ast_free(misdn_debug_only);
05348    ast_free(misdn_ports);
05349    ast_free(misdn_debug);
05350    
05351    return 0;
05352 }

static int update_config ( struct chan_list ch,
int  orig 
) [static]

Updates caller ID information from config.

Definition at line 1947 of file chan_misdn.c.

References chan_list::ast, ast_log(), AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_pres, misdn_bchannel::hdlc, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, LOG_WARNING, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_PRES, MISDN_CFG_SCREEN, misdn_bchannel::port, misdn_bchannel::pres, and misdn_bchannel::screen.

Referenced by misdn_call().

01948 {
01949    struct ast_channel *ast;
01950    struct misdn_bchannel *bc;
01951    int port, hdlc = 0;
01952    int pres, screen;
01953 
01954    if (!ch) {
01955       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01956       return -1;
01957    }
01958 
01959    ast = ch->ast;
01960    bc = ch->bc;
01961    if (! ast || ! bc) {
01962       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01963       return -1;
01964    }
01965 
01966    port = bc->port;
01967 
01968    chan_misdn_log(7, port, "update_config: Getting Config\n");
01969 
01970    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01971    
01972    if (hdlc) {
01973       switch (bc->capability) {
01974       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01975       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01976          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
01977          bc->hdlc = 1;
01978          break;
01979       }
01980    }
01981 
01982    misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
01983    misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
01984    chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
01985       
01986    if (pres < 0 || screen < 0) {
01987       chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
01988          
01989       switch (ast->cid.cid_pres & 0x60) {
01990       case AST_PRES_RESTRICTED:
01991          bc->pres = 1;
01992          chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
01993          break;
01994       case AST_PRES_UNAVAILABLE:
01995          bc->pres = 2;
01996          chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
01997          break;
01998       default:
01999          bc->pres = 0;
02000          chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
02001          break;
02002       }
02003 
02004       switch (ast->cid.cid_pres & 0x3) {
02005       default:
02006       case AST_PRES_USER_NUMBER_UNSCREENED:
02007          bc->screen = 0;
02008          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
02009          break;
02010       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02011          bc->screen = 1;
02012          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
02013          break;
02014       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02015          bc->screen = 2;
02016          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
02017          break;
02018       case AST_PRES_NETWORK_NUMBER:
02019          bc->screen = 3;
02020          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
02021          break;
02022       }
02023    } else {
02024       bc->screen = screen;
02025       bc->pres = pres;
02026    }
02027 
02028    return 0;
02029 }

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

Definition at line 2108 of file chan_misdn.c.

References misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, MISDN_CFG_ECHOCANCEL, misdn_cfg_get(), and misdn_bchannel::port.

Referenced by handle_cli_misdn_toggle_echocancel(), and read_config().

02109 {
02110    int ec;
02111    int port = bc->port;
02112 
02113    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
02114 
02115    if (ec == 1) {
02116       bc->ec_enable = 1;
02117    } else if (ec > 1) {
02118       bc->ec_enable = 1;
02119       bc->ec_deftaps = ec;
02120    }
02121 
02122    return 0;
02123 }

static void update_name ( struct ast_channel tmp,
int  port,
int  c 
) [static]

Definition at line 3607 of file chan_misdn.c.

References ast_change_name(), chan_misdn_log(), misdn_cfg_get_next_port(), misdn_lib_port_is_pri(), misdn_type, and ast_channel::name.

Referenced by cb_events().

03608 {
03609    int chan_offset = 0;
03610    int tmp_port = misdn_cfg_get_next_port(0);
03611    char newname[255];
03612    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03613       if (tmp_port == port)
03614          break;
03615       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03616    }
03617    if (c < 0)
03618       c = 0;
03619 
03620    snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
03621    if (strncmp(tmp->name, newname, strlen(newname))) {
03622       snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03623       ast_change_name(tmp, newname);
03624       chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03625    }
03626 }

static void wait_for_digits ( struct chan_list ch,
struct misdn_bchannel bc,
struct ast_channel chan 
) [static]

Definition at line 4281 of file chan_misdn.c.

References misdn_bchannel::dad, dialtone_indicate(), EVENT_SETUP_ACKNOWLEDGE, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::nt, and chan_list::state.

Referenced by cb_events().

04281                                                                                                        {
04282    ch->state=MISDN_WAITING4DIGS;
04283    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04284    if (bc->nt && !bc->dad[0])
04285       dialtone_indicate(ch);
04286 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 6116 of file chan_misdn.c.

struct allowed_bearers allowed_bearers_array[] [static]

Definition at line 589 of file chan_misdn.c.

Referenced by bearer2str(), and cb_events().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 6116 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1922 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

struct chan_list* cl_te = NULL

Global channel call record list head.

Definition at line 509 of file chan_misdn.c.

Referenced by cb_events(), chan_misdn_jb_empty(), get_chan_by_ast(), get_chan_by_ast_name(), handle_cli_misdn_show_channel(), handle_cli_misdn_show_channels(), import_ch(), misdn_request(), release_chan(), and release_chan_early().

ast_mutex_t cl_te_lock

Definition at line 510 of file chan_misdn.c.

Referenced by cl_dequeue_chan(), cl_queue_chan(), and load_module().

struct chan_list dummy_cl

Definition at line 504 of file chan_misdn.c.

int g_config_initialized = 0 [static]

Definition at line 77 of file chan_misdn.c.

int glob_channel = 0 [static]

Definition at line 3605 of file chan_misdn.c.

char global_tracefile[BUFFERSIZE+1]

Definition at line 75 of file chan_misdn.c.

ast_mutex_t lock

Definition at line 1493 of file chan_misdn.c.

int max_ports [static]

Definition at line 498 of file chan_misdn.c.

Referenced by _build_port_config(), chan_misdn_log(), load_module(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), misdn_cfg_is_group_method(), misdn_cfg_is_port_valid(), misdn_cfg_update_ptp(), and reload_config().

int MAXTICS = 8

Definition at line 1494 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 496 of file chan_misdn.c.

Referenced by chan_misdn_log(), handle_cli_misdn_show_channels(), handle_cli_misdn_show_port(), handle_cli_misdn_show_stacks(), load_module(), print_bc_info(), reload_config(), and unload_module().

int* misdn_debug_only [static]

Definition at line 497 of file chan_misdn.c.

Referenced by chan_misdn_log(), handle_cli_misdn_show_port(), handle_cli_misdn_show_stacks(), load_module(), reload_config(), and unload_module().

int* misdn_in_calls [static]

Definition at line 500 of file chan_misdn.c.

Referenced by add_in_calls(), handle_cli_misdn_show_ports_stats(), load_module(), release_chan(), release_chan_early(), and unload_module().

int* misdn_out_calls [static]

Definition at line 501 of file chan_misdn.c.

Referenced by add_out_calls(), handle_cli_misdn_show_ports_stats(), load_module(), release_chan(), release_chan_early(), and unload_module().

int* misdn_ports [static]

Definition at line 472 of file chan_misdn.c.

struct sched_context* misdn_tasks = NULL [static]

the main schedule context for stuff like l1 watcher, overlap dial, ...

Definition at line 469 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable(), misdn_tasks_destroy(), misdn_tasks_init(), misdn_tasks_remove(), and misdn_tasks_thread_func().

pthread_t misdn_tasks_thread [static]

Definition at line 470 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

Definition at line 3567 of file chan_misdn.c.

Referenced by load_module(), misdn_new(), and unload_module().

struct ast_channel_tech misdn_tech_wo_bridge [static]

Definition at line 3586 of file chan_misdn.c.

Referenced by misdn_new().

const char misdn_type[] = "mISDN" [static]

Definition at line 489 of file chan_misdn.c.

Referenced by load_module(), misdn_new(), misdn_request(), and update_name().

int prefformat = AST_FORMAT_ALAW [static]

Only alaw and mulaw is allowed for now.

Definition at line 494 of file chan_misdn.c.

Referenced by misdn_new(), and misdn_write().

ast_mutex_t release_lock

Definition at line 114 of file chan_misdn.c.

struct robin_list* robin = NULL [static]

Definition at line 420 of file chan_misdn.c.

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 1262 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 491 of file chan_misdn.c.

Referenced by load_module().


Generated on Wed Aug 18 22:34:11 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7