Thu Jul 9 13:41:01 2009

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

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_PRECONNECTED, MISDN_DISCONNECTED, MISDN_RELEASED, MISDN_BRIDGED,
  MISDN_CLEANING, MISDN_HUNGUP_FROM_MISDN, MISDN_HUNGUP_FROM_AST, MISDN_HOLDED,
  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 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_holded (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_holded_l3 (struct chan_list *list, unsigned long l3_id, int w)
static void free_robin_list (void)
static void free_robin_list_r (struct robin_list *r)
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)
static int 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 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 void misdn_transfer_bc (struct chan_list *tmp_ch, struct chan_list *holded_chan)
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 misdn_bchannel *bc)
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct allowed_bearers allowed_bearers_array []
static const 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 486 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 485 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(), and release_chan().

#define ORG_AST   1

Definition at line 141 of file chan_misdn.c.

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

#define ORG_MISDN   2

Definition at line 142 of file chan_misdn.c.

Referenced by cb_events(), and misdn_indication().


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_PRECONNECTED  when connected
MISDN_DISCONNECTED  when connected
MISDN_RELEASED  when connected
MISDN_BRIDGED  when bridged
MISDN_CLEANING  when hangup from * but we were connected before
MISDN_HUNGUP_FROM_MISDN  when DISCONNECT/RELEASE/REL_COMP came from misdn
MISDN_HUNGUP_FROM_AST  when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup
MISDN_HOLDED  if this chan is holded
MISDN_HOLD_DISCONNECT  if this chan is holded

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_PRECONNECTED, /*!<  when connected */
00130    MISDN_DISCONNECTED, /*!<  when connected */
00131    MISDN_RELEASED, /*!<  when connected */
00132    MISDN_BRIDGED, /*!<  when bridged */
00133    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00134    MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  came from misdn */
00135    MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
00136    MISDN_HOLDED, /*!< if this chan is holded */
00137    MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
00138   
00139 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 5986 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

00821 {
00822    int task_id;
00823 
00824    if (!misdn_tasks) {
00825       misdn_tasks_init();
00826    }
00827    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00828    misdn_tasks_wakeup();
00829 
00830    return task_id;
00831 }

int add_in_calls ( int  port  ) 

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

04126 {
04127    int max_in_calls;
04128    
04129    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04130    misdn_in_calls[port]++;
04131 
04132    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04133       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04134       return misdn_in_calls[port] - max_in_calls;
04135    }
04136    
04137    return 0;
04138 }

int add_out_calls ( int  port  ) 

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

04141 {
04142    int max_out_calls;
04143    
04144    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04145 
04146    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04147       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04148       return (misdn_out_calls[port] + 1) - max_out_calls;
04149    }
04150 
04151    misdn_out_calls[port]++;
04152    
04153    return 0;
04154 }

static char* bearer2str ( int  cap  )  [static]

Definition at line 599 of file chan_misdn.c.

References INFO_CAPABILITY_AUDIO_3_1K, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, INFO_CAPABILITY_SPEECH, and INFO_CAPABILITY_VIDEO.

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

00599                                  {
00600    static char *bearers[]={
00601       "Speech",
00602       "Audio 3.1k",
00603       "Unres Digital",
00604       "Res Digital",
00605       "Video",
00606       "Unknown Bearer"
00607    };
00608    
00609    switch (cap) {
00610    case INFO_CAPABILITY_SPEECH:
00611       return bearers[0];
00612       break;
00613    case INFO_CAPABILITY_AUDIO_3_1K:
00614       return bearers[1];
00615       break;
00616    case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00617       return bearers[2];
00618       break;
00619    case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00620       return bearers[3];
00621       break;
00622    case INFO_CAPABILITY_VIDEO:
00623       return bearers[4];
00624       break;
00625    default:
00626       return bearers[5];
00627       break;
00628    }
00629 }

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

Definition at line 4180 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_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_copy_string(), ast_deactivate_generator(), ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_moh_start(), ast_moh_stop(), 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, ast_frame::data, ast_frame::datalen, ast_frame::delivery, 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_holded(), find_holded_l3(), ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, hangup_chan(), ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold_info, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::info_dad, misdn_bchannel::infos_pending, init_chan_list(), misdn_bchannel::keypad, misdn_bchannel::l3_id, chan_list::l3id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_isdn_get_info(), MISDN_ALERTING, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, 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_HOLDED, 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_transfer_bc(), 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, ast_frame::offset, ORG_AST, ORG_MISDN, chan_list::originator, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_builtin_setvar_helper(), 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, ast_frame::samples, misdn_bchannel::screen, misdn_bchannel::sending_complete, ast_frame::src, start_bc_tones(), start_pbx(), chan_list::state, stop_bc_tones(), stop_indicate(), ast_frame::subclass, ast_channel::tech, misdn_bchannel::tone_cnt, ast_channel::transfercapability, ast_channel_tech::type, update_name(), and wait_for_digits().

Referenced by load_module().

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

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

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

05738 {
05739    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05740    
05741    if (ch && ch->jb) {
05742       return misdn_jb_empty(ch->jb, buf, len);
05743    }
05744    
05745    return -1;
05746 }

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

Definition at line 5922 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_holded(), import_ch(), init_chan_list(), load_module(), misdn_answer(), 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_transfer_bc(), misdn_write(), print_bearer(), print_facility(), process_ast_dsp(), read_config(), release_chan(), send_cause2ast(), start_pbx(), stop_indicate(), update_config(), and update_name().

05923 {
05924    va_list ap;
05925    char buf[1024];
05926    char port_buf[8];
05927 
05928    if (! ((0 <= port) && (port <= max_ports))) {
05929       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05930       port = 0;
05931       level = -1;
05932    }
05933 
05934    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05935 
05936    va_start(ap, tmpl);
05937    vsnprintf(buf, sizeof(buf), tmpl, ap);
05938    va_end(ap);
05939 
05940    if (level == -1)
05941       ast_log(LOG_WARNING, "%s", buf);
05942 
05943    else if (misdn_debug_only[port] ? 
05944          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
05945        : level <= misdn_debug[port]) {
05946       
05947       ast_console_puts(port_buf);
05948       ast_console_puts(buf);
05949    }
05950    
05951    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05952       char ctimebuf[30];
05953       time_t tm = time(NULL);
05954       char *tmp = ctime_r(&tm, ctimebuf), *p;
05955 
05956       FILE *fp = fopen(global_tracefile, "a+");
05957 
05958       p = strchr(tmp, '\n');
05959       if (p)
05960          *p = ':';
05961       
05962       if (!fp) {
05963          ast_console_puts("Error opening Tracefile: [ ");
05964          ast_console_puts(global_tracefile);
05965          ast_console_puts(" ] ");
05966          
05967          ast_console_puts(strerror(errno));
05968          ast_console_puts("\n");
05969          return ;
05970       }
05971       
05972       fputs(tmp, fp);
05973       fputs(" ", fp);
05974       fputs(port_buf, fp);
05975       fputs(" ", fp);
05976       fputs(buf, fp);
05977 
05978       fclose(fp);
05979    }
05980 }

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

Definition at line 3784 of file chan_misdn.c.

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

Referenced by misdn_hangup(), and release_chan().

03785 {
03786    struct chan_list *help;
03787 
03788    if (chan->dsp) 
03789       ast_dsp_free(chan->dsp);
03790    if (chan->trans)
03791       ast_translator_free_path(chan->trans);
03792 
03793    ast_mutex_lock(&cl_te_lock);
03794    if (!*list) {
03795       ast_mutex_unlock(&cl_te_lock);
03796       return;
03797    }
03798   
03799    if (*list == chan) {
03800       *list = (*list)->next;
03801       ast_mutex_unlock(&cl_te_lock);
03802       return;
03803    }
03804   
03805    for (help = *list; help->next; help = help->next) {
03806       if (help->next == chan) {
03807          help->next = help->next->next;
03808          ast_mutex_unlock(&cl_te_lock);
03809          return;
03810       }
03811    }
03812    
03813    ast_mutex_unlock(&cl_te_lock);
03814 }

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

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

03769 {
03770    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03771   
03772    ast_mutex_lock(&cl_te_lock);
03773    if (!*list) {
03774       *list = chan;
03775    } else {
03776       struct chan_list *help = *list;
03777       for (; help->next; help = help->next); 
03778       help->next = chan;
03779    }
03780    chan->next = NULL;
03781    ast_mutex_unlock(&cl_te_lock);
03782 }

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

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

01874 {
01875    return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
01876 }

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

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

01879 {
01880    if (a->n)
01881       return NULL;
01882 
01883    switch (a->pos) {
01884    case 4:
01885       if (a->word[0] == 'p')
01886          return ast_strdup("port");
01887       else if (a->word[0] == 'o')
01888          return ast_strdup("only");
01889       break;
01890    case 6:
01891       if (a->word[0] == 'o')
01892          return ast_strdup("only");
01893       break;
01894    }
01895    return NULL;
01896 }

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

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

01899 {
01900    char buffer[BUFFERSIZE];
01901    enum misdn_cfg_elements elem;
01902    int wordlen = strlen(a->word);
01903    int which = 0;
01904    int port = 0;
01905 
01906    switch (a->pos) {
01907    case 3:
01908       if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n))
01909          return ast_strdup("description");
01910       if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n))
01911          return ast_strdup("descriptions");
01912       if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n))
01913          return ast_strdup("0");
01914       while ((port = misdn_cfg_get_next_port(port)) != -1) {
01915          snprintf(buffer, sizeof(buffer), "%d", port);
01916          if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
01917             return ast_strdup(buffer);
01918          }
01919       }
01920       break;
01921    case 4:
01922       if (strstr(a->line, "description ")) {
01923          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01924             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
01925                continue;
01926             misdn_cfg_get_name(elem, buffer, sizeof(buffer));
01927             if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
01928                if (++which > a->n)
01929                   return ast_strdup(buffer);
01930             }
01931          }
01932       } else if (strstr(a->line, "descriptions ")) {
01933          if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n))
01934             return ast_strdup("general");
01935          if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n))
01936             return ast_strdup("ports");
01937       }
01938       break;
01939    }
01940    return NULL;
01941 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

02059 {
02060    struct misdn_bchannel *bc = ch->bc;
02061    int len = ch->jb_len, threshold = ch->jb_upper_threshold;
02062    
02063    chan_misdn_log(5, bc->port, "config_jb: Called\n");
02064    
02065    if (! len) {
02066       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
02067       bc->nojitter=1;
02068    } else {
02069       if (len <= 100 || len > 8000) {
02070          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
02071          len = 1000;
02072       }
02073 
02074       if ( threshold > len ) {
02075          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
02076       }
02077 
02078       if ( ch->jb) {
02079          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
02080          misdn_jb_destroy(ch->jb);
02081          ch->jb = NULL;
02082       }
02083 
02084       ch->jb=misdn_jb_init(len, threshold);
02085 
02086       if (!ch->jb ) 
02087          bc->nojitter = 1;
02088    }
02089 }

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

Definition at line 2092 of file chan_misdn.c.

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

Referenced by read_config().

02093 {
02094    switch (numplan) {
02095    case NUMPLAN_INTERNATIONAL:
02096       chan_misdn_log(2, port, " --> %s: International\n", type);
02097       break;
02098    case NUMPLAN_NATIONAL:
02099       chan_misdn_log(2, port, " --> %s: National\n", type);
02100       break;
02101    case NUMPLAN_SUBSCRIBER:
02102       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
02103       break;
02104    case NUMPLAN_UNKNOWN:
02105       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
02106       break;
02107       /* Maybe we should cut off the prefix if present ? */
02108    default:
02109       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
02110       break;
02111    }
02112 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

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

03291 {
03292    const struct tone_zone_sound *ts = NULL;
03293    struct ast_channel *ast = cl->ast;
03294    int nd = 0;
03295 
03296    if (!ast) {
03297       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03298       return -1;
03299    }
03300 
03301    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03302 
03303    if (nd) {
03304       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03305       return 0;
03306    }
03307    
03308    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03309    ts = ast_get_indication_tone(ast->zone, "dial");
03310    cl->ts = ts;   
03311    
03312    if (ts) {
03313       cl->notxtone = 0;
03314       cl->norxtone = 0;
03315       /* This prods us in misdn_write */
03316       ast_playtones_start(ast, 0, ts->data, 0);
03317    }
03318 
03319    return 0;
03320 }

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

Definition at line 3951 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::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

Referenced by cb_events().

03952 {
03953    char *predial;
03954    struct ast_frame fr;
03955 
03956    predial = ast_strdupa(ast->exten);
03957 
03958    ch->state = MISDN_DIALING;
03959 
03960    if (!ch->noautorespond_on_setup) {
03961       if (bc->nt) {
03962          int ret; 
03963          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03964       } else {
03965          int ret;
03966          if ( misdn_lib_is_ptp(bc->port)) {
03967             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03968          } else {
03969             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03970          }
03971       }
03972    } else {
03973       ch->state = MISDN_INCOMING_SETUP;
03974    }
03975 
03976    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);
03977   
03978    strncpy(ast->exten, "s", 2);
03979   
03980    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03981       ast = NULL;
03982       bc->out_cause = AST_CAUSE_UNALLOCATED;
03983       hangup_chan(ch);
03984       hanguptone_indicate(ch);
03985 
03986       if (bc->nt)
03987          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03988       else
03989          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03990    }
03991   
03992   
03993    while (!ast_strlen_zero(predial) ) {
03994       fr.frametype = AST_FRAME_DTMF;
03995       fr.subclass = *predial;
03996       fr.src = NULL;
03997       fr.data = NULL;
03998       fr.datalen = 0;
03999       fr.samples = 0;
04000       fr.mallocd = 0;
04001       fr.offset = 0;
04002       fr.delivery = ast_tv(0,0);
04003 
04004       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04005          ast_queue_frame(ch->ast, &fr);
04006       }
04007       predial++;
04008    }
04009 }

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

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

00699 {
00700    char buf[128];
00701 
00702    if (!bc->AOCD_need_export || !ast)
00703       return;
00704 
00705    if (originator == ORG_AST) {
00706       ast = ast_bridged_channel(ast);
00707       if (!ast)
00708          return;
00709    }
00710 
00711    switch (bc->AOCDtype) {
00712    case Fac_AOCDCurrency:
00713       pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
00714       if (bc->AOCD.currency.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.currency.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 %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
00723                pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
00724                if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
00725                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00726             }
00727          }
00728       }
00729       break;
00730    case Fac_AOCDChargingUnit:
00731       pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
00732       if (bc->AOCD.chargingUnit.chargeNotAvailable)
00733          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00734       else {
00735          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00736          if (bc->AOCD.chargingUnit.freeOfCharge)
00737             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00738          else {
00739             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00740             if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
00741                pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
00742                if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
00743                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00744             }
00745          }
00746       }
00747       break;
00748    default:
00749       break;
00750    }
00751    
00752    bc->AOCD_need_export = 0;
00753 }

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

04102 {
04103    char tmp[32];
04104    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04105    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04106    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04107 
04108    if (bc->sending_complete) {
04109       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04110       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04111    }
04112 
04113    if (bc->urate) {
04114       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04115       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04116    }
04117 
04118    if (bc->uulen)
04119       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04120 
04121    if (!ast_strlen_zero(bc->keypad)) 
04122       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04123 }

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

Definition at line 3711 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(), chan_misdn_jb_empty(), and release_chan().

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

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

Definition at line 3723 of file chan_misdn.c.

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

Referenced by import_ch().

03724 {
03725    struct chan_list *help = list;
03726    for (; help; help = help->next) {
03727       if ( help->bc && (help->bc->pid == pid) ) return help;
03728    }
03729 
03730    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03731 
03732    return NULL;
03733 }

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

Definition at line 3735 of file chan_misdn.c.

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

Referenced by cb_events().

03736 {
03737    struct chan_list *help = list;
03738 
03739    if (bc->pri) return NULL;
03740 
03741    chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03742    for (;help; help = help->next) {
03743       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state==MISDN_HOLDED, help->hold_info.channel);
03744       if (  (help->state == MISDN_HOLDED) && 
03745          (help->hold_info.port == bc->port) ) 
03746          return help;
03747    }
03748    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03749 
03750    return NULL;
03751 }

static struct chan_list* find_holded_l3 ( struct chan_list list,
unsigned long  l3_id,
int  w 
) [static]

Definition at line 3754 of file chan_misdn.c.

References chan_list::l3id, MISDN_HOLDED, chan_list::next, and chan_list::state.

Referenced by cb_events().

03755 {
03756    struct chan_list *help = list;
03757 
03758    for (; help; help = help->next) {
03759       if ( (help->state == MISDN_HOLDED) &&
03760           (help->l3id == l3_id)   
03761          ) 
03762          return help;
03763    }
03764 
03765    return NULL;
03766 }

static void free_robin_list ( void   )  [static]

Definition at line 444 of file chan_misdn.c.

References free_robin_list_r(), and robin.

Referenced by reload_config(), and unload_module().

00445 {
00446    free_robin_list_r(robin);
00447    robin = NULL;
00448 }

static void free_robin_list_r ( struct robin_list r  )  [inline, static]

Definition at line 433 of file chan_misdn.c.

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

Referenced by free_robin_list().

00434 {
00435    if (r) {
00436       if (r->next)
00437          free_robin_list_r(r->next);
00438       if (r->group)
00439          ast_free(r->group);
00440       ast_free(r);
00441    }
00442 }

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

Definition at line 559 of file chan_misdn.c.

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

Referenced by misdn_bridge().

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

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

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

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

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

Definition at line 450 of file chan_misdn.c.

References ast_calloc, robin_list::group, robin_list::next, robin_list::prev, robin, and strndup.

Referenced by misdn_request().

00451 {
00452    struct robin_list *new;
00453    struct robin_list *iter = robin;
00454    for (; iter; iter = iter->next) {
00455       if (!strcasecmp(iter->group, group))
00456          return iter;
00457    }
00458    new = ast_calloc(1, sizeof(*new));
00459    new->group = strndup(group, strlen(group));
00460    new->channel = 1;
00461    if (robin) {
00462       new->next = robin;
00463       robin->prev = new;
00464    }
00465    robin = new;
00466    return robin;
00467 }

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

Definition at line 1038 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.

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

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

Definition at line 1143 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.

01144 {
01145    switch (cmd) {
01146    case CLI_INIT:
01147       e->command = "misdn port down";
01148       e->usage =
01149          "Usage: misdn port down <port>\n"
01150          "       Try to deactivate the L1 on the given port.\n";
01151       return NULL;
01152    case CLI_GENERATE:
01153       return NULL;
01154    }
01155 
01156    if (a->argc != 4)
01157       return CLI_SHOWUSAGE;
01158 
01159    misdn_lib_get_port_down(atoi(a->argv[3]));
01160 
01161    return CLI_SUCCESS;
01162 }

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

Definition at line 1059 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.

01060 {
01061    switch (cmd) {
01062    case CLI_INIT:
01063       e->command = "misdn port unblock";
01064       e->usage =
01065          "Usage: misdn port unblock <port>\n"
01066          "       Unblock the port specified by <port>.\n";
01067       return NULL;
01068    case CLI_GENERATE:
01069       return NULL;
01070    }
01071 
01072    if (a->argc != 4)
01073       return CLI_SHOWUSAGE;
01074 
01075    misdn_lib_port_unblock(atoi(a->argv[3]));
01076 
01077    return CLI_SUCCESS;
01078 }

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

Definition at line 1122 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.

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

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

Definition at line 1345 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.

01346 {
01347    switch (cmd) {
01348    case CLI_INIT:
01349       e->command = "misdn reload";
01350       e->usage =
01351          "Usage: misdn reload\n"
01352          "       Reload internal mISDN config, read from the config\n"
01353          "       file.\n";
01354       return NULL;
01355    case CLI_GENERATE:
01356       return NULL;
01357    }
01358 
01359    if (a->argc != 2)
01360       return CLI_SHOWUSAGE;
01361 
01362    ast_cli(a->fd, "Reloading mISDN configuration\n");
01363    reload_config();
01364    return CLI_SUCCESS;
01365 }

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

Definition at line 1101 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.

01102 {
01103    switch (cmd) {
01104    case CLI_INIT:
01105       e->command = "misdn restart pid";
01106       e->usage =
01107          "Usage: misdn restart pid <pid>\n"
01108          "       Restart the given pid\n";
01109       return NULL;
01110    case CLI_GENERATE:
01111       return NULL;
01112    }
01113 
01114    if (a->argc != 4)
01115       return CLI_SHOWUSAGE;
01116 
01117    misdn_lib_pid_restart(atoi(a->argv[3]));
01118 
01119    return CLI_SUCCESS;
01120 }

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

Definition at line 1080 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.

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

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

Definition at line 1742 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.

01743 {
01744    char *channame; 
01745    char *msg; 
01746    struct chan_list *tmp;
01747    int i, msglen;
01748 
01749    switch (cmd) {
01750    case CLI_INIT:
01751       e->command = "misdn send digit";
01752       e->usage =
01753          "Usage: misdn send digit <channel> \"<msg>\" \n"
01754          "       Send <digit> to <channel> as DTMF Tone\n"
01755          "       when channel is a mISDN channel\n";
01756       return NULL;
01757    case CLI_GENERATE:
01758       return complete_ch(a);
01759    }
01760 
01761    if (a->argc != 5)
01762       return CLI_SHOWUSAGE;
01763 
01764    channame = a->argv[3];
01765    msg = a->argv[4];
01766    msglen = strlen(msg);
01767 
01768    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01769 
01770    tmp = get_chan_by_ast_name(channame);
01771    if (!tmp) {
01772       ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
01773       return CLI_SUCCESS; 
01774    }
01775 #if 1
01776    for (i = 0; i < msglen; i++) {
01777       ast_cli(a->fd, "Sending: %c\n", msg[i]);
01778       send_digit_to_chan(tmp, msg[i]);
01779       /* res = ast_safe_sleep(tmp->ast, 250); */
01780       usleep(250000);
01781       /* res = ast_waitfor(tmp->ast,100); */
01782    }
01783 #else
01784    ast_dtmf_stream(tmp->ast, NULL, msg, 250);
01785 #endif
01786 
01787    return CLI_SUCCESS;
01788 }

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

Definition at line 1835 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.

01836 {
01837    char *channame;
01838    char *msg;
01839    struct chan_list *tmp;
01840 
01841    switch (cmd) {
01842    case CLI_INIT:
01843       e->command = "misdn send display";
01844       e->usage =
01845          "Usage: misdn send display <channel> \"<msg>\" \n"
01846          "       Send <msg> to <channel> as Display Message\n"
01847          "       when channel is a mISDN channel\n";
01848       return NULL;
01849    case CLI_GENERATE:
01850       return complete_ch(a);
01851    }
01852 
01853    if (a->argc != 5)
01854       return CLI_SHOWUSAGE;
01855 
01856    channame = a->argv[3];
01857    msg = a->argv[4];
01858 
01859    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01860    tmp = get_chan_by_ast_name(channame);
01861     
01862    if (tmp && tmp->bc) {
01863       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01864       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01865    } else {
01866       ast_cli(a->fd, "No such channel %s\n", channame);
01867       return CLI_SUCCESS;
01868    }
01869 
01870    return CLI_SUCCESS;
01871 }

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

Definition at line 1627 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.

01628 {
01629    char *channame; 
01630    char *nr;
01631    struct chan_list *tmp;
01632    int port; 
01633    char *served_nr;
01634    struct misdn_bchannel dummy, *bc=&dummy;
01635  
01636    switch (cmd) {
01637    case CLI_INIT:
01638       e->command = "misdn send facility";
01639       e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
01640       "\t type is one of:\n"
01641       "\t - calldeflect\n"
01642       "\t - CFActivate\n"
01643       "\t - CFDeactivate\n";
01644 
01645       return NULL;
01646    case CLI_GENERATE:
01647       return complete_ch(a);
01648    }
01649 
01650    if (a->argc < 5)
01651       return CLI_SHOWUSAGE;
01652  
01653    if (strstr(a->argv[3], "calldeflect")) {
01654       if (a->argc < 6) {
01655          ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
01656          return 0;
01657       }
01658       channame = a->argv[4];
01659       nr = a->argv[5];
01660 
01661       ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
01662       tmp = get_chan_by_ast_name(channame);
01663       if (!tmp) {
01664          ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
01665          return 0; 
01666       }
01667 
01668       if (strlen(nr) >= 15) {
01669          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
01670          return 0; 
01671       }
01672       tmp->bc->fac_out.Function = Fac_CD;
01673       ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
01674       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
01675    } else if (strstr(a->argv[3],"CFActivate")) {
01676       if (a->argc < 7) {
01677          ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
01678          return 0;
01679       }
01680       port = atoi(a->argv[4]);
01681       served_nr = a->argv[5];
01682       nr = a->argv[6];
01683 
01684       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01685 
01686       ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
01687 
01688       bc->fac_out.Function = Fac_CFActivate;
01689       bc->fac_out.u.CFActivate.BasicService = 0; //All Services
01690       bc->fac_out.u.CFActivate.Procedure = 0; //Unconditional
01691       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01692       ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
01693 
01694       misdn_lib_send_event(bc, EVENT_FACILITY);
01695    } else if (strstr(a->argv[3],"CFDeactivate")) {
01696 
01697       if (a->argc < 6) {
01698          ast_verbose("CFActivate requires 1 arg: FromNumber\n\n");
01699          return 0;
01700       }
01701       port = atoi(a->argv[4]);
01702       served_nr = a->argv[5];
01703       
01704       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01705       ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
01706 
01707       bc->fac_out.Function = Fac_CFDeactivate;
01708       bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
01709       bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
01710       
01711       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01712       misdn_lib_send_event(bc, EVENT_FACILITY);
01713    }
01714 
01715    return CLI_SUCCESS;
01716 }

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

Definition at line 1718 of file chan_misdn.c.

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

01719 {
01720    switch (cmd) {
01721    case CLI_INIT:
01722       e->command = "misdn send restart";
01723       e->usage =
01724          "Usage: misdn send restart [port [channel]]\n"
01725          "       Send a restart for every bchannel on the given port.\n";
01726       return NULL;
01727    case CLI_GENERATE:
01728       return NULL;
01729    }
01730 
01731    if (a->argc < 4 || a->argc > 5)
01732       return CLI_SHOWUSAGE;
01733 
01734    if (a->argc == 5)
01735       misdn_lib_send_restart(atoi(a->argv[3]), atoi(a->argv[4]));
01736    else
01737       misdn_lib_send_restart(atoi(a->argv[3]), -1);
01738 
01739    return CLI_SUCCESS;
01740 }

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

Definition at line 1016 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.

01017 {
01018    switch (cmd) {
01019    case CLI_INIT:
01020       e->command = "misdn set crypt debug";
01021       e->usage =
01022          "Usage: misdn set crypt debug <level>\n"
01023          "       Set the crypt debug level of the mISDN channel. Level\n"
01024          "       must be 1 or 2.\n";
01025       return NULL;
01026    case CLI_GENERATE:
01027       return NULL;
01028    }
01029 
01030    if (a->argc != 5)
01031       return CLI_SHOWUSAGE;
01032 
01033    /* Is this supposed to not do anything? */
01034 
01035    return CLI_SUCCESS;
01036 }

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

Definition at line 942 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.

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

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

Definition at line 1522 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.

01523 {
01524    switch (cmd) {
01525    case CLI_INIT:
01526       e->command = "misdn set tics";
01527       e->usage =
01528          "Usage: misdn set tics <value>\n";
01529       return NULL;
01530    case CLI_GENERATE:
01531       return NULL;
01532    }
01533 
01534    if (a->argc != 4)
01535       return CLI_SHOWUSAGE;
01536 
01537    MAXTICS = atoi(a->argv[3]);
01538 
01539    return CLI_SUCCESS;
01540 }

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

Definition at line 1484 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.

01485 {
01486    struct chan_list *help = NULL;
01487 
01488    switch (cmd) {
01489    case CLI_INIT:
01490       e->command = "misdn show channel";
01491       e->usage =
01492          "Usage: misdn show channel <channel>\n"
01493          "       Show an internal mISDN channel\n.";
01494       return NULL;
01495    case CLI_GENERATE:
01496       return complete_ch(a);
01497    }
01498 
01499    if (a->argc != 4)
01500       return CLI_SHOWUSAGE;
01501 
01502    help = cl_te;
01503 
01504    for (; help; help = help->next) {
01505       struct misdn_bchannel *bc = help->bc;   
01506       struct ast_channel *ast = help->ast;
01507     
01508       if (bc && ast) {
01509          if (!strcasecmp(ast->name, a->argv[3])) {
01510             print_bc_info(a->fd, help, bc);
01511             break; 
01512          }
01513       } 
01514    }
01515 
01516    return CLI_SUCCESS;
01517 }

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

Definition at line 1422 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_info, chan_list::l3id, misdn_debug, misdn_dump_chanlist(), MISDN_HOLDED, chan_list::next, misdn_bchannel::pid, hold_info::port, print_bc_info(), chan_list::state, and ast_cli_entry::usage.

01423 {
01424    struct chan_list *help = NULL;
01425 
01426    switch (cmd) {
01427    case CLI_INIT:
01428       e->command = "misdn show channels";
01429       e->usage =
01430          "Usage: misdn show channels\n"
01431          "       Show the internal mISDN channel list\n";
01432       return NULL;
01433    case CLI_GENERATE:
01434       return NULL;
01435    }
01436 
01437    if (a->argc != 3)
01438       return CLI_SHOWUSAGE;
01439 
01440    help = cl_te;
01441   
01442    ast_cli(a->fd, "Channel List: %p\n", cl_te); 
01443 
01444    for (; help; help = help->next) {
01445       struct misdn_bchannel *bc = help->bc;   
01446       struct ast_channel *ast = help->ast;
01447       if (!ast) {
01448          if (!bc) {
01449             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
01450             continue;
01451          }
01452          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
01453          continue;
01454       }
01455 
01456       if (misdn_debug[0] > 2)
01457          ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
01458       if (bc) {
01459          print_bc_info(a->fd, help, bc);
01460       } else {
01461          if (help->state == MISDN_HOLDED) {
01462             ast_cli(a->fd, "ITS A HOLDED BC:\n");
01463             ast_cli(a->fd, " --> l3_id: %x\n"
01464                   " --> dad:%s oad:%s\n"
01465                   " --> hold_port: %d\n"
01466                   " --> hold_channel: %d\n",
01467                   help->l3id,
01468                   ast->exten,
01469                   ast->cid.cid_num,
01470                   help->hold_info.port,
01471                   help->hold_info.channel
01472                   );
01473          } else {
01474             ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
01475          }
01476       }
01477    }
01478 
01479    misdn_dump_chanlist();
01480 
01481    return CLI_SUCCESS;
01482 }

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

Definition at line 1189 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.

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

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

Definition at line 1599 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.

01600 {
01601    int port;
01602    char buf[128];
01603 
01604    switch (cmd) {
01605    case CLI_INIT:
01606       e->command = "misdn show port";
01607       e->usage =
01608          "Usage: misdn show port <port>\n"
01609          "       Show detailed information for given port.\n";
01610       return NULL;
01611    case CLI_GENERATE:
01612       return NULL;
01613    }
01614 
01615    if (a->argc != 4)
01616       return CLI_SHOWUSAGE;
01617 
01618    port = atoi(a->argv[3]);
01619   
01620    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01621    get_show_stack_details(port, buf);
01622    ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01623 
01624    return CLI_SUCCESS;
01625 }

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

Definition at line 1571 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.

01572 {
01573    int port;
01574 
01575    switch (cmd) {
01576    case CLI_INIT:
01577       e->command = "misdn show ports stats";
01578       e->usage =
01579          "Usage: misdn show ports stats\n"
01580          "       Show mISDNs channel's call statistics per port.\n";
01581       return NULL;
01582    case CLI_GENERATE:
01583       return NULL;
01584    }
01585 
01586    if (a->argc != 4)
01587       return CLI_SHOWUSAGE;
01588 
01589    ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
01590    for (port = misdn_cfg_get_next_port(0); port > 0;
01591         port = misdn_cfg_get_next_port(port)) {
01592       ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
01593    }
01594    ast_cli(a->fd, "\n");
01595 
01596    return CLI_SUCCESS;
01597 }

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

Definition at line 1542 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.

01543 {
01544    int port;
01545 
01546    switch (cmd) {
01547    case CLI_INIT:
01548       e->command = "misdn show stacks";
01549       e->usage =
01550          "Usage: misdn show stacks\n"
01551          "       Show internal mISDN stack_list.\n";
01552       return NULL;
01553    case CLI_GENERATE:
01554       return NULL;
01555    }
01556 
01557    if (a->argc != 3)
01558       return CLI_SHOWUSAGE;
01559 
01560    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01561    for (port = misdn_cfg_get_next_port(0); port > 0;
01562         port = misdn_cfg_get_next_port(port)) {
01563       char buf[128];
01564       get_show_stack_details(port, buf);
01565       ast_cli(a->fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01566    }
01567 
01568    return CLI_SUCCESS;
01569 }

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

Definition at line 1790 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.

01791 {
01792    char *channame;
01793    struct chan_list *tmp;
01794 
01795    switch (cmd) {
01796    case CLI_INIT:
01797       e->command = "misdn toggle echocancel";
01798       e->usage =
01799          "Usage: misdn toggle echocancel <channel>\n"
01800          "       Toggle EchoCancel on mISDN Channel.\n";
01801       return NULL;
01802    case CLI_GENERATE:
01803       return complete_ch(a);
01804    }
01805 
01806    if (a->argc != 4)
01807       return CLI_SHOWUSAGE;
01808 
01809    channame = a->argv[3];
01810   
01811    ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
01812   
01813    tmp = get_chan_by_ast_name(channame);
01814    if (!tmp) {
01815       ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
01816       return CLI_SUCCESS;
01817    }
01818 
01819    tmp->toggle_ec = tmp->toggle_ec?0:1;
01820 
01821    if (tmp->toggle_ec) {
01822 #ifdef MISDN_1_2
01823       update_pipeline_config(tmp->bc);
01824 #else
01825       update_ec_config(tmp->bc);
01826 #endif
01827       manager_ec_enable(tmp->bc);
01828    } else {
01829       manager_ec_disable(tmp->bc);
01830    }
01831 
01832    return CLI_SUCCESS;
01833 }

static void hangup_chan ( struct chan_list ch  )  [static]

Definition at line 3831 of file chan_misdn.c.

References chan_list::ast, ast_hangup(), ast_queue_hangup(), chan_list::bc, 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().

03832 {
03833    int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
03834    if (!ch) {
03835       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03836       return;
03837    }
03838 
03839    cb_log(5, port, "hangup_chan called\n");
03840 
03841    if (ch->need_hangup) {
03842       cb_log(2, port, " --> hangup\n");
03843       send_cause2ast(ch->ast, ch->bc, ch);
03844       ch->need_hangup = 0;
03845       ch->need_queue_hangup = 0;
03846       if (ch->ast)
03847          ast_hangup(ch->ast);
03848       return;
03849    }
03850 
03851    if (!ch->need_queue_hangup) {
03852       cb_log(2, port, " --> No need to queue hangup\n");
03853    }
03854 
03855    ch->need_queue_hangup = 0;
03856    if (ch->ast) {
03857       send_cause2ast(ch->ast, ch->bc, ch);
03858 
03859       if (ch->ast)
03860          ast_queue_hangup(ch->ast);
03861       cb_log(2, port, " --> queue_hangup\n");
03862    } else {
03863       cb_log(1, port, "Cannot hangup chan, no ast\n");
03864    }
03865 }

static int hanguptone_indicate ( struct chan_list cl  )  [static]

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

03323 {
03324    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03325    return 0;
03326 }

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

04071 {
04072    const char *tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04073    if (tmp) {
04074       ch->other_pid = atoi(tmp);
04075       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04076       if (ch->other_pid > 0) {
04077          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04078          if (ch->other_ch)
04079             ch->other_ch->other_ch = ch;
04080       }
04081    }
04082 
04083    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04084    if (tmp && (atoi(tmp) == 1)) {
04085       bc->sending_complete = 1;
04086    }
04087 
04088    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04089    if (tmp) {
04090       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04091       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04092       bc->uulen = strlen(bc->uu);
04093    }
04094 
04095    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04096    if (tmp)
04097       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04098 }

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

Definition at line 3367 of file chan_misdn.c.

References ast_calloc, and chan_misdn_log().

Referenced by cb_events(), and misdn_request().

03368 {
03369    struct chan_list *cl;
03370 
03371    cl = ast_calloc(1, sizeof(*cl));
03372 
03373    if (!cl) {
03374       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03375       return NULL;
03376    }
03377    
03378    cl->originator = orig;
03379    cl->need_queue_hangup = 1;
03380    cl->need_hangup = 1;
03381    cl->need_busy = 1;
03382    cl->overlap_dial_task = -1;
03383 
03384    return cl;
03385 }

static int load_module ( void   )  [static]

Definition at line 5245 of file chan_misdn.c.

References ast_calloc, ast_channel_register(), ast_cli_register_multiple(), 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().

05246 {
05247    int i, port;
05248    int ntflags = 0, ntkc = 0;
05249    char ports[256] = "";
05250    char tempbuf[BUFFERSIZE + 1];
05251    char ntfile[BUFFERSIZE + 1];
05252    struct misdn_lib_iface iface = {
05253       .cb_event = cb_events,
05254       .cb_log = chan_misdn_log,
05255       .cb_jb_empty = chan_misdn_jb_empty,
05256    };
05257 
05258    max_ports = misdn_lib_maxports_get();
05259    
05260    if (max_ports <= 0) {
05261       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05262       return AST_MODULE_LOAD_DECLINE;
05263    }
05264    
05265    if (misdn_cfg_init(max_ports, 0)) {
05266       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05267       return AST_MODULE_LOAD_DECLINE;
05268    }
05269    g_config_initialized = 1;
05270    
05271    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
05272    if (!misdn_debug) {
05273       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05274       return AST_MODULE_LOAD_DECLINE;
05275    }
05276    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
05277    if (!misdn_ports) {
05278       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05279       return AST_MODULE_LOAD_DECLINE;
05280    }
05281    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
05282    for (i = 1; i <= max_ports; i++) {
05283       misdn_debug[i] = misdn_debug[0];
05284       misdn_ports[i] = i;
05285    }
05286    *misdn_ports = 0;
05287    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
05288 
05289    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
05290    if (!ast_strlen_zero(tempbuf))
05291       tracing = 1;
05292 
05293    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05294    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05295 
05296    for (i = 1; i <= max_ports; i++) {
05297       misdn_in_calls[i] = 0;
05298       misdn_out_calls[i] = 0;
05299    }
05300 
05301    ast_mutex_init(&cl_te_lock);
05302    ast_mutex_init(&release_lock);
05303 
05304    misdn_cfg_update_ptp();
05305    misdn_cfg_get_ports_string(ports);
05306 
05307    if (!ast_strlen_zero(ports))
05308       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05309    if (misdn_lib_init(ports, &iface, NULL))
05310       chan_misdn_log(0, 0, "No te ports initialized\n");
05311 
05312    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
05313    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
05314    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
05315 
05316    misdn_lib_nt_keepcalls(ntkc);
05317    misdn_lib_nt_debug_init(ntflags, ntfile);
05318 
05319    if (ast_channel_register(&misdn_tech)) {
05320       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05321       unload_module();
05322       return AST_MODULE_LOAD_DECLINE;
05323    }
05324   
05325    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05326 
05327    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05328       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05329       "Sets mISDN opts. and optargs\n"
05330       "\n"
05331       "The available options are:\n"
05332       "    a - Have Asterisk detect DTMF tones on called channel\n"
05333       "    c - Make crypted outgoing call, optarg is keyindex\n"
05334       "    d - Send display text to called phone, text is the optarg\n"
05335       "    e - Perform echo cancelation on this channel,\n"
05336       "        takes taps as optarg (32,64,128,256)\n"
05337       "   e! - Disable echo cancelation on this channel\n"
05338       "    f - Enable fax detection\n"
05339       "    h - Make digital outgoing call\n"
05340       "   h1 - Make HDLC mode digital outgoing call\n"
05341       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05342       "        they will be transported inband.\n"
05343       "   jb - Set jitter buffer length, optarg is length\n"
05344       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05345       "   jn - Disable jitter buffer\n"
05346       "    n - Disable mISDN DSP on channel.\n"
05347       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05348       "    p - Caller ID presentation,\n"
05349       "        optarg is either 'allowed' or 'restricted'\n"
05350       "    s - Send Non-inband DTMF as inband\n"
05351       "   vr - Rx gain control, optarg is gain\n"
05352       "   vt - Tx gain control, optarg is gain\n"
05353       );
05354 
05355    
05356    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05357              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05358              "Sends the Facility Message FACILITY_TYPE with \n"
05359              "the given Arguments to the current ISDN Channel\n"
05360              "Supported Facilities are:\n"
05361              "\n"
05362              "type=calldeflect args=Nr where to deflect\n"
05363       );
05364 
05365 
05366    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05367              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05368              "Checks if the L2 and L1 are up on either the given <port> or\n"
05369              "on the ports in the group with <groupname>\n"
05370              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05371              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05372              "\n"
05373              "This application, ensures the L1/L2 state of the Ports in a group\n"
05374              "it is intended to make the pmp_l1_check option redundant and to\n"
05375              "fix a buggy switch config from your provider\n"
05376              "\n"
05377              "a sample dialplan would look like:\n\n"
05378              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05379              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05380              "\n"
05381       );
05382 
05383 
05384    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
05385 
05386    /* start the l1 watchers */
05387    
05388    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05389       int l1timeout;
05390       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05391       if (l1timeout) {
05392          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05393          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05394       }
05395    }
05396 
05397    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05398 
05399    return 0;
05400 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2507 of file chan_misdn.c.

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

02508 {
02509    struct chan_list *p;
02510    const char *tmp;
02511 
02512    if (!ast || ! (p = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02513    
02514    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
02515    
02516    if (!p) {
02517       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02518       ast_queue_hangup(ast);
02519    }
02520 
02521    if (!p->bc) {
02522       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
02523 
02524       ast_queue_hangup(ast);
02525    }
02526 
02527    tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
02528 
02529    if (!ast_strlen_zero(tmp)) {
02530       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02531       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
02532    } else {
02533       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02534    }
02535 
02536    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02537    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
02538       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02539       p->bc->nodsp = 1;
02540       p->bc->hdlc = 0;
02541       p->bc->nojitter = 1;
02542    }
02543 
02544    p->state = MISDN_CONNECTED;
02545    stop_indicate(p);
02546 
02547    if ( ast_strlen_zero(p->bc->cad) ) {
02548       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
02549       ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
02550    }
02551 
02552    misdn_lib_send_event( p->bc, EVENT_CONNECT);
02553    start_bc_tones(p);
02554 
02555    return 0;
02556 }

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 3186 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.

03192 {
03193    struct chan_list *ch1, *ch2;
03194    struct ast_channel *carr[2], *who;
03195    int to = -1;
03196    struct ast_frame *f;
03197    int p1_b, p2_b;
03198    int bridging;
03199   
03200    ch1 = get_chan_by_ast(c0);
03201    ch2 = get_chan_by_ast(c1);
03202 
03203    carr[0] = c0;
03204    carr[1] = c1;
03205   
03206    if (!(ch1 && ch2))
03207       return -1;
03208 
03209    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
03210    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
03211 
03212    if (! p1_b || ! p2_b) {
03213       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03214       return AST_BRIDGE_FAILED;
03215    }
03216 
03217    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03218    if (bridging) {
03219       /* trying to make a mISDN_dsp conference */
03220       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03221       misdn_lib_bridge(ch1->bc, ch2->bc);
03222    }
03223 
03224    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03225 
03226    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03227  
03228    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
03229       ch1->ignore_dtmf = 1;
03230 
03231    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
03232       ch2->ignore_dtmf = 1;
03233 
03234    for (;/*ever*/;) {
03235       to = -1;
03236       who = ast_waitfor_n(carr, 2, &to);
03237 
03238       if (!who) {
03239          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03240          break;
03241       }
03242       f = ast_read(who);
03243 
03244       if (!f || f->frametype == AST_FRAME_CONTROL) {
03245          /* got hangup .. */
03246 
03247          if (!f) 
03248             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03249          else
03250             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03251 
03252          *fo = f;
03253          *rc = who;
03254          break;
03255       }
03256       
03257       if ( f->frametype == AST_FRAME_DTMF ) {
03258          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03259 
03260          *fo = f;
03261          *rc = who;
03262          break;
03263       }
03264    
03265 #if 0
03266       if (f->frametype == AST_FRAME_VOICE) {
03267          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03268    
03269          continue;
03270       }
03271 #endif
03272 
03273       if (who == c0) {
03274          ast_write(c1, f);
03275       }
03276       else {
03277          ast_write(c0, f);
03278       }
03279    }
03280 
03281    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03282 
03283    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03284 
03285    return AST_BRIDGE_COMPLETE;
03286 }

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

Definition at line 2371 of file chan_misdn.c.

References ast_channel::_state, add_out_calls(), chan_list::ast, 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(), ast_channel::transfercapability, and update_config().

02372 {
02373    int port = 0;
02374    int r;
02375    int exceed;
02376    int bridging;
02377    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(ast);
02378    struct misdn_bchannel *newbc;
02379    char *opts = NULL, *ext, *tokb;
02380    char *dest_cp = ast_strdupa(dest);
02381 
02382    ext = strtok_r(dest_cp, "/", &tokb);
02383 
02384    if (ext) {
02385       ext = strtok_r(NULL, "/", &tokb);
02386       if (ext) {
02387          opts = strtok_r(NULL, "/", &tokb);
02388       } else {
02389          chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
02390          return -1;
02391       }
02392    }
02393 
02394    if (!ast) {
02395       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
02396       return -1;
02397    }
02398 
02399    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
02400       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02401       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02402       ast_setstate(ast, AST_STATE_DOWN);
02403       return -1;
02404    }
02405 
02406    if (!ch) {
02407       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02408       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02409       ast_setstate(ast, AST_STATE_DOWN);
02410       return -1;
02411    }
02412    
02413    newbc = ch->bc;
02414    
02415    if (!newbc) {
02416       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02417       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02418       ast_setstate(ast, AST_STATE_DOWN);
02419       return -1;
02420    }
02421    
02422    port = newbc->port;
02423 
02424    if ((exceed = add_out_calls(port))) {
02425       char tmp[16];
02426       snprintf(tmp, sizeof(tmp), "%d", exceed);
02427       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
02428       return -1;
02429    }
02430    
02431    chan_misdn_log(1, port, "* CALL: %s\n", dest);
02432    
02433    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
02434    
02435    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
02436    if (ast->exten) {
02437       ast_copy_string(ast->exten, ext, sizeof(ast->exten));
02438       ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
02439    }
02440 
02441    ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
02442 
02443    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
02444    if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
02445       ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
02446    }
02447 
02448    newbc->capability = ast->transfercapability;
02449    pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
02450    if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
02451       chan_misdn_log(2, port, " --> * Call with flag Digital\n");
02452    }
02453 
02454    /* update screening and presentation */ 
02455    update_config(ch, ORG_AST);
02456       
02457    /* fill in some ies from channel vary*/
02458    import_ch(ast, newbc, ch);
02459 
02460    /* Finally The Options Override Everything */
02461    if (opts)
02462       misdn_set_opt_exec(ast, opts);
02463    else
02464       chan_misdn_log(2, port, "NO OPTS GIVEN\n");
02465 
02466    /*check for bridging*/
02467    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
02468    if (bridging && ch->other_ch) {
02469 #ifdef MISDN_1_2
02470       chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
02471       *ch->bc->pipeline = 0;
02472       *ch->other_ch->bc->pipeline = 0;
02473 #else
02474       chan_misdn_log(1, port, "Disabling EC on both Sides\n");
02475       ch->bc->ec_enable = 0;
02476       ch->other_ch->bc->ec_enable = 0;
02477 #endif
02478    }
02479 
02480    r = misdn_lib_send_event( newbc, EVENT_SETUP );
02481 
02482    /** we should have l3id after sending setup **/
02483    ch->l3id = newbc->l3_id;
02484 
02485    if ( r == -ENOCHAN  ) {
02486       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
02487       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
02488       ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
02489       ast_setstate(ast, AST_STATE_DOWN);
02490       return -1;
02491    }
02492    
02493    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
02494 
02495    ast_setstate(ast, AST_STATE_DIALING);
02496    ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
02497    
02498    if (newbc->nt)
02499       stop_bc_tones(ch);
02500 
02501    ch->state = MISDN_CALLING;
02502    
02503    return 0; 
02504 }

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

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

05460 {
05461    char *parse;
05462    char group[BUFFERSIZE + 1];
05463    char *port_str;
05464    int port = 0;
05465    int timeout;
05466    int dowait = 0;
05467    int port_up;
05468 
05469    AST_DECLARE_APP_ARGS(args,
05470          AST_APP_ARG(grouppar);
05471          AST_APP_ARG(timeout);
05472    );
05473 
05474    if (ast_strlen_zero((char *)data)) {
05475       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05476       return -1;
05477    }
05478 
05479    parse = ast_strdupa(data);
05480    AST_STANDARD_APP_ARGS(args, parse);
05481 
05482    if (args.argc != 2) {
05483       ast_log(LOG_WARNING, "Wrong argument count\n");
05484       return 0;
05485    }
05486 
05487    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05488    timeout = atoi(args.timeout);
05489    port_str = args.grouppar;
05490 
05491    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05492       /* We make a group call lets checkout which ports are in my group */
05493       port_str += 2;
05494       ast_copy_string(group, port_str, sizeof(group));
05495       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05496 
05497       for ( port = misdn_cfg_get_next_port(port); 
05498          port > 0;
05499          port = misdn_cfg_get_next_port(port)) {
05500          char cfg_group[BUFFERSIZE + 1];
05501 
05502          chan_misdn_log(2, 0, "trying port %d\n", port);
05503 
05504          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
05505 
05506          if (!strcasecmp(cfg_group, group)) {
05507             port_up = misdn_lib_port_up(port, 1);
05508 
05509             if (!port_up) {
05510                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05511                misdn_lib_get_port_up(port);
05512                dowait = 1;
05513             }
05514          }
05515       }
05516 
05517    } else {
05518       port = atoi(port_str);
05519       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05520       port_up = misdn_lib_port_up(port, 1);
05521       if (!port_up) {
05522          misdn_lib_get_port_up(port);
05523          dowait = 1;
05524       }
05525    }
05526 
05527    if (dowait) {
05528       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05529       ast_safe_sleep(chan, timeout * 1000);
05530    }
05531 
05532    return 0;
05533 }

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

Definition at line 2558 of file chan_misdn.c.

02559 {
02560    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02561    return 0;
02562 }

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

Definition at line 2564 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(), chan_list::other_ch, misdn_bchannel::port, send_digit_to_chan(), misdn_bchannel::send_dtmf, and chan_list::state.

02565 {
02566    struct chan_list *p;
02567    struct misdn_bchannel *bc;
02568    char buf[2] = { digit, 0 };
02569    
02570    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02571 
02572    bc = p->bc;
02573    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
02574    
02575    if (!bc) {
02576       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
02577       return -1;
02578    }
02579    
02580    switch (p->state ) {
02581    case MISDN_CALLING:
02582       if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1)
02583          strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
02584       break;
02585    case MISDN_CALLING_ACKNOWLEDGE:
02586       ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
02587       if (strlen(bc->dad) < sizeof(bc->dad) - 1)
02588          strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
02589       ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
02590       misdn_lib_send_event( bc, EVENT_INFORMATION);
02591       break;
02592    default: 
02593          /* Do not send Digits in CONNECTED State, when
02594           * the other side is too mISDN. */
02595          if (p->other_ch ) 
02596             return 0;
02597 
02598          if ( bc->send_dtmf ) 
02599             send_digit_to_chan(p,digit);
02600       break;
02601 }
02602 
02603    return 0;
02604 }

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

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

05414 {
05415    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05416    char *parse, *tok, *tokb;
05417 
05418    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05419    
05420    if (strcasecmp(chan->tech->type, "mISDN")) {
05421       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05422       return -1;
05423    }
05424    
05425    if (ast_strlen_zero((char *)data)) {
05426       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05427       return -1;
05428    }
05429 
05430    parse = ast_strdupa(data);
05431    tok = strtok_r(parse, "|", &tokb) ;
05432 
05433    if (!tok) {
05434       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05435       return -1;
05436    }
05437 
05438    if (!strcasecmp(tok, "calldeflect")) {
05439       tok = strtok_r(NULL, "|", &tokb) ;
05440       
05441       if (!tok) {
05442          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05443       }
05444 
05445       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05446          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05447          return 0; 
05448       }
05449       ch->bc->fac_out.Function = Fac_CD;
05450       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05451       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05452    } else {
05453       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05454    }
05455 
05456    return 0;
05457 }

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

Definition at line 2607 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.

02608 {
02609    struct chan_list *p;
02610 
02611    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02612 
02613    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);
02614 
02615    p->ast = ast;
02616 
02617    return 0;
02618 }

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

Definition at line 1305 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(), print_bc_info(), and release_chan().

01306 {
01307    int i;
01308    static char state[8];
01309    
01310    if( !p) return NULL;
01311   
01312    for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
01313       if (state_array[i].state == p->state)
01314          return state_array[i].txt; 
01315    }
01316 
01317    snprintf(state, sizeof(state), "%d", p->state) ;
01318 
01319    return state;
01320 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2745 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, chan_list::bc, misdn_bchannel::cause, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, cl_dequeue_chan(), cl_te, ast_channel::context, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, ast_channel::exten, ast_channel::hangupcause, hanguptone_indicate(), 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_HOLDED, MISDN_INCOMING_SETUP, misdn_lib_release(), misdn_lib_send_event(), MISDN_NOTHING, MISDN_PRECONNECTED, MISDN_PROCEEDING, MISDN_PROGRESS, MISDN_RELEASED, 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, chan_list::pipe, misdn_bchannel::port, release_chan(), start_bc_tones(), chan_list::state, stop_bc_tones(), misdn_bchannel::uu, and misdn_bchannel::uulen.

02746 {
02747    struct chan_list *p;
02748    struct misdn_bchannel *bc = NULL;
02749    const char *varcause = NULL;
02750 
02751    ast_debug(1, "misdn_hangup(%s)\n", ast->name);
02752 
02753    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
02754 
02755    if (!p) {
02756       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
02757       return 0 ;
02758    }
02759 
02760    bc = p->bc;
02761 
02762    if (bc) {
02763       const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
02764       if (tmp) {
02765          ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
02766          strcpy(bc->uu, tmp);
02767          bc->uulen=strlen(bc->uu);
02768       }
02769    }
02770 
02771    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02772    p->ast = NULL;
02773 
02774    if (ast->_state == AST_STATE_RESERVED || 
02775       p->state == MISDN_NOTHING || 
02776       p->state == MISDN_HOLDED || 
02777       p->state == MISDN_HOLD_DISCONNECT ) {
02778 
02779       CLEAN_CH:
02780       /* between request and call */
02781       ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
02782       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02783    
02784       ast_mutex_lock(&release_lock);
02785       cl_dequeue_chan(&cl_te, p);
02786       close(p->pipe[0]);
02787       close(p->pipe[1]);
02788       ast_free(p);
02789       ast_mutex_unlock(&release_lock);
02790       
02791       if (bc)
02792          misdn_lib_release(bc);
02793       
02794       return 0;
02795    }
02796 
02797    if (!bc) {
02798       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02799       goto CLEAN_CH;
02800    }
02801 
02802 
02803    p->need_hangup = 0;
02804    p->need_queue_hangup = 0;
02805    p->need_busy = 0;
02806 
02807 
02808    if (!p->bc->nt) 
02809       stop_bc_tones(p);
02810 
02811    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02812       
02813    if ( (varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02814         (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02815       int tmpcause = atoi(varcause);
02816       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02817    }
02818     
02819    chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n", p->bc ? p->bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
02820    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02821    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02822    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02823    chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02824 
02825    switch (p->state) {
02826    case MISDN_INCOMING_SETUP:
02827       p->state = MISDN_CLEANING;
02828       /* This is the only place in misdn_hangup, where we 
02829        * can call release_chan, else it might create lot's of trouble
02830        * */
02831       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02832       release_chan(bc);
02833       misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02834       break;
02835    case MISDN_HOLDED:
02836    case MISDN_DIALING:
02837       start_bc_tones(p);
02838       hanguptone_indicate(p);
02839       
02840       p->state=MISDN_CLEANING;
02841       if (bc->need_disconnect)
02842          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02843       break;
02844    case MISDN_CALLING_ACKNOWLEDGE:
02845       start_bc_tones(p);
02846       hanguptone_indicate(p);
02847       
02848       if (bc->need_disconnect)
02849          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02850       break;
02851       
02852    case MISDN_CALLING:
02853    case MISDN_ALERTING:
02854    case MISDN_PROGRESS:
02855    case MISDN_PROCEEDING:
02856       if (p->originator != ORG_AST) 
02857          hanguptone_indicate(p);
02858       
02859       /*p->state=MISDN_CLEANING;*/
02860       if (bc->need_disconnect)
02861          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02862       break;
02863    case MISDN_CONNECTED:
02864    case MISDN_PRECONNECTED:
02865       /*  Alerting or Disconnect */
02866       if (p->bc->nt) {
02867          start_bc_tones(p);
02868          hanguptone_indicate(p);
02869          p->bc->progress_indicator = 8;
02870       }
02871       if (bc->need_disconnect)
02872          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02873 
02874       /*p->state=MISDN_CLEANING;*/
02875       break;
02876    case MISDN_DISCONNECTED:
02877       if (bc->need_release)
02878          misdn_lib_send_event( bc, EVENT_RELEASE);
02879       p->state = MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
02880       break;
02881 
02882    case MISDN_RELEASED:
02883    case MISDN_CLEANING:
02884       p->state = MISDN_CLEANING;
02885       break;
02886 
02887    case MISDN_BUSY:
02888       break;
02889       
02890    case MISDN_HOLD_DISCONNECT:
02891       /* need to send release here */
02892       chan_misdn_log(1, bc->port, " --> cause %d\n", bc->cause);
02893       chan_misdn_log(1, bc->port, " --> out_cause %d\n", bc->out_cause);
02894 
02895       bc->out_cause = -1;
02896       if (bc->need_release)
02897          misdn_lib_send_event(bc, EVENT_RELEASE);
02898       p->state = MISDN_CLEANING;
02899       break;
02900    default:
02901       if (bc->nt) {
02902          bc->out_cause = -1;
02903          if (bc->need_release)
02904             misdn_lib_send_event(bc, EVENT_RELEASE);
02905          p->state = MISDN_CLEANING; 
02906       } else {
02907          if (bc->need_disconnect)
02908             misdn_lib_send_event(bc, EVENT_DISCONNECT);
02909       }
02910    }
02911 
02912    p->state = MISDN_CLEANING;
02913     
02914    chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
02915 
02916    return 0;
02917 }

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

Definition at line 2622 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, ast_channel::exten, hanguptone_indicate(), chan_list::incoming_early_audio, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, 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, and stop_indicate().

02623 {
02624    struct chan_list *p;
02625 
02626    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02627       ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
02628       return -1;
02629    }
02630    
02631    if (!p->bc ) {
02632       chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast->exten);
02633       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02634       return -1;
02635    }
02636    
02637    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n", cond, ast->exten);
02638    
02639    switch (cond) {
02640    case AST_CONTROL_BUSY:
02641       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
02642       ast_setstate(ast, AST_STATE_BUSY);
02643 
02644       p->bc->out_cause = AST_CAUSE_USER_BUSY;
02645       if (p->state != MISDN_CONNECTED) {
02646          start_bc_tones(p);
02647          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02648       } else {
02649          chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
02650       }
02651       return -1;
02652    case AST_CONTROL_RING:
02653       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02654       return -1;
02655    case AST_CONTROL_RINGING:
02656       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02657       switch (p->state) {
02658       case MISDN_ALERTING:
02659          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);
02660          break;
02661       case MISDN_CONNECTED:
02662          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);
02663          return -1;
02664       default:
02665          p->state = MISDN_ALERTING;
02666          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02667          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02668          
02669          if (p->other_ch && p->other_ch->bc) {
02670             if (misdn_inband_avail(p->other_ch->bc)) {
02671                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02672                break;
02673             }
02674 
02675             if (!p->other_ch->bc->nt) {
02676                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02677                break;
02678             }
02679          }
02680 
02681          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02682          ast_setstate(ast, AST_STATE_RING);
02683          
02684          if ( !p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio ) 
02685             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02686          else 
02687             return -1;
02688       }
02689       break;
02690    case AST_CONTROL_ANSWER:
02691       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02692       start_bc_tones(p);
02693       break;
02694    case AST_CONTROL_TAKEOFFHOOK:
02695       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02696       return -1;
02697    case AST_CONTROL_OFFHOOK:
02698       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02699       return -1;
02700    case AST_CONTROL_FLASH:
02701       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02702       break;
02703    case AST_CONTROL_PROGRESS:
02704       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02705       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02706       break;
02707    case AST_CONTROL_PROCEEDING:
02708       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02709       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02710       break;
02711    case AST_CONTROL_CONGESTION:
02712       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02713 
02714       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02715       start_bc_tones(p);
02716       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02717 
02718       if (p->bc->nt) {
02719          hanguptone_indicate(p);
02720       }
02721       break;
02722    case -1 :
02723       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02724 
02725       stop_indicate(p);
02726 
02727       if (p->state == MISDN_CONNECTED) 
02728          start_bc_tones(p);
02729       break;
02730    case AST_CONTROL_HOLD:
02731       ast_moh_start(ast, data, p->mohinterpret); 
02732       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02733       break;
02734    case AST_CONTROL_UNHOLD:
02735       ast_moh_stop(ast);
02736       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02737       break;
02738    default:
02739       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02740    }
02741   
02742    return 0;
02743 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

Definition at line 5799 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(), and release_chan().

05800 {
05801    ast_mutex_destroy(&jb->mutexjb);
05802    
05803    ast_free(jb->ok);
05804    ast_free(jb->samples);
05805    ast_free(jb);
05806 }

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

05870 {
05871    int i, wp, rp, read = 0;
05872 
05873    ast_mutex_lock(&jb->mutexjb);
05874 
05875    rp = jb->rp;
05876    wp = jb->wp;
05877 
05878    if (jb->state_empty) {  
05879       for (i = 0; i < len; i++) {
05880          if (wp == rp) {
05881             jb->rp = rp;
05882             jb->state_empty = 0;
05883 
05884             ast_mutex_unlock(&jb->mutexjb);
05885 
05886             return read;
05887          } else {
05888             if (jb->ok[rp] == 1) {
05889                data[i] = jb->samples[rp];
05890                jb->ok[rp] = 0;
05891                rp = (rp != jb->size - 1) ? rp + 1 : 0;
05892                read += 1;
05893             }
05894          }
05895       }
05896 
05897       if (wp >= rp)
05898          jb->state_buffer = wp - rp;
05899       else
05900          jb->state_buffer = jb->size - rp + wp;
05901       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05902 
05903       jb->rp = rp;
05904    } else
05905       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05906 
05907    ast_mutex_unlock(&jb->mutexjb);
05908 
05909    return read;
05910 }

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 5810 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.

05811 {
05812    int i, j, rp, wp;
05813 
05814    if (!jb || ! data)
05815       return 0;
05816 
05817    ast_mutex_lock(&jb->mutexjb);
05818    
05819    wp = jb->wp;
05820    rp = jb->rp;
05821    
05822    for (i = 0; i < len; i++) {
05823       jb->samples[wp] = data[i];
05824       jb->ok[wp] = 1;
05825       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05826 
05827       if (wp == jb->rp)
05828          jb->state_full = 1;
05829    }
05830 
05831    if (wp >= rp)
05832       jb->state_buffer = wp - rp;
05833    else
05834       jb->state_buffer = jb->size - rp + wp;
05835    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05836 
05837    if (jb->state_full) {
05838       jb->wp = wp;
05839 
05840       rp = wp;
05841       for (j = 0; j < jb->upper_threshold; j++)
05842          rp = rp != 0 ? rp - 1 : jb->size - 1;
05843       jb->rp = rp;
05844       jb->state_full = 0;
05845       jb->state_empty = 1;
05846 
05847       ast_mutex_unlock(&jb->mutexjb);
05848 
05849       return -1;
05850    }
05851 
05852    if (!jb->state_empty) {
05853       jb->bytes_wrote += len;
05854       if (jb->bytes_wrote >= jb->upper_threshold) {
05855          jb->state_empty = 1;
05856          jb->bytes_wrote = 0;
05857       }
05858    }
05859    jb->wp = wp;
05860 
05861    ast_mutex_unlock(&jb->mutexjb);
05862    
05863    return 0;
05864 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

Definition at line 5756 of file chan_misdn.c.

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

Referenced by config_jitterbuffer().

05757 {
05758    int i;
05759    struct misdn_jb *jb;
05760 
05761    jb = ast_malloc(sizeof(*jb));
05762    if (!jb) {
05763        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05764        return NULL;
05765    }
05766    jb->size = size;
05767    jb->upper_threshold = upper_threshold;
05768    jb->wp = 0;
05769    jb->rp = 0;
05770    jb->state_full = 0;
05771    jb->state_empty = 0;
05772    jb->bytes_wrote = 0;
05773    jb->samples = ast_malloc(size * sizeof(char));
05774 
05775    if (!jb->samples) {
05776       ast_free(jb);
05777       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05778       return NULL;
05779    }
05780    
05781    jb->ok = ast_malloc(size * sizeof(char));
05782 
05783    if (!jb->ok) {
05784       ast_free(jb->samples);
05785       ast_free(jb);
05786       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05787       return NULL;
05788    }
05789 
05790    for (i = 0; i < size; i++)
05791       jb->ok[i] = 0;
05792 
05793    ast_mutex_init(&jb->mutexjb);
05794 
05795    return jb;
05796 }

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

Definition at line 848 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

00849 {
00850    misdn_lib_isdn_l1watcher(*(int *)data);
00851    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00852    return 1;
00853 }

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

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

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

Definition at line 855 of file chan_misdn.c.

References chan_list::ast, 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().

00856 {
00857    struct timeval tv_end, tv_now;
00858    int diff;
00859    struct chan_list *ch = (struct chan_list *)data;
00860 
00861    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
00862 
00863    if (ch->state != MISDN_WAITING4DIGS) {
00864       ch->overlap_dial_task = -1;
00865       return 0;
00866    }
00867    
00868    ast_mutex_lock(&ch->overlap_tv_lock);
00869    tv_end = ch->overlap_tv;
00870    ast_mutex_unlock(&ch->overlap_tv_lock);
00871    
00872    tv_end.tv_sec += ch->overlap_dial;
00873    tv_now = ast_tvnow();
00874 
00875    diff = ast_tvdiff_ms(tv_end, tv_now);
00876 
00877    if (diff <= 100) {
00878       char *dad=ch->bc->dad, sexten[]="s";
00879       /* if we are 100ms near the timeout, we are satisfied.. */
00880       stop_indicate(ch);
00881       
00882       if (ast_strlen_zero(ch->bc->dad)) {
00883          dad=sexten;
00884          strcpy(ch->ast->exten, sexten);
00885       }
00886 
00887       if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
00888          ch->state=MISDN_DIALING;
00889          if (pbx_start_chan(ch) < 0) {
00890             chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
00891             goto misdn_overlap_dial_task_disconnect;
00892          }
00893       } else {
00894 misdn_overlap_dial_task_disconnect:
00895          hanguptone_indicate(ch);
00896          ch->bc->out_cause=1;
00897          ch->state=MISDN_CLEANING;
00898          misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
00899       }
00900       ch->overlap_dial_task = -1;
00901       return 0;
00902    } else
00903       return diff;
00904 }

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

Definition at line 2990 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, len(), ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, MISDN_HOLDED, ast_frame::offset, chan_list::pipe, misdn_bchannel::port, process_ast_dsp(), ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

02991 {
02992    struct chan_list *tmp;
02993    fd_set rrfs;
02994    struct timeval tv;
02995    int len, t;
02996 
02997    if (!ast) {
02998       chan_misdn_log(1, 0, "misdn_read called without ast\n");
02999       return NULL;
03000    }
03001    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
03002       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
03003       return NULL;
03004    }
03005 
03006    if (!tmp->bc && !(tmp->state == MISDN_HOLDED)) {
03007       chan_misdn_log(1, 0, "misdn_read called without bc\n");
03008       return NULL;
03009    }
03010 
03011    tv.tv_sec=0;
03012    tv.tv_usec=20000;
03013 
03014    FD_ZERO(&rrfs);
03015    FD_SET(tmp->pipe[0],&rrfs);
03016 
03017    t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
03018 
03019    if (!t) {
03020       chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
03021       len=160;
03022    }
03023 
03024    if (t<0) {
03025       chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
03026       return NULL;
03027    }
03028 
03029    if (FD_ISSET(tmp->pipe[0],&rrfs)) {
03030       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
03031 
03032       if (len<=0) {
03033          /* we hangup here, since our pipe is closed */
03034          chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
03035          return NULL;
03036       }
03037 
03038    } else {
03039       return NULL;
03040    }
03041 
03042    tmp->frame.frametype = AST_FRAME_VOICE;
03043    tmp->frame.subclass = AST_FORMAT_ALAW;
03044    tmp->frame.datalen = len;
03045    tmp->frame.samples = len;
03046    tmp->frame.mallocd = 0;
03047    tmp->frame.offset = 0;
03048    tmp->frame.delivery = ast_tv(0,0);
03049    tmp->frame.src = NULL;
03050    tmp->frame.data = tmp->ast_rd_buf;
03051 
03052    if (tmp->faxdetect && !tmp->faxhandled) {
03053       if (tmp->faxdetect_timeout) {
03054          if (ast_tvzero(tmp->faxdetect_tv)) {
03055             tmp->faxdetect_tv = ast_tvnow();
03056             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
03057             return process_ast_dsp(tmp, &tmp->frame);
03058          } else {
03059             struct timeval tv_now = ast_tvnow();
03060             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
03061             if (diff <= (tmp->faxdetect_timeout * 1000)) {
03062                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
03063                return process_ast_dsp(tmp, &tmp->frame);
03064             } else {
03065                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
03066                tmp->faxdetect = 0;
03067                return &tmp->frame;
03068             }
03069          }
03070       } else {
03071          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
03072          return process_ast_dsp(tmp, &tmp->frame);
03073       }
03074    } else {
03075       if (tmp->ast_dsp)
03076          return process_ast_dsp(tmp, &tmp->frame);
03077       else
03078          return &tmp->frame;
03079    }
03080 }

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

Definition at line 3387 of file chan_misdn.c.

References chan_list::ast, ast_copy_string(), ast_log(), AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), chan_list::bc, buf, 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, and read_config().

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

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

Definition at line 3566 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.

03567 {
03568    struct chan_list *tmp = chan->tech_pvt;
03569    
03570    if (tmp && tmp->bc) {
03571       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03572       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03573    } else {
03574       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03575       return -1;
03576    }
03577    
03578    return 0;
03579 }

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

Definition at line 5535 of file chan_misdn.c.

References ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_strdupa, ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, misdn_bchannel::capability, chan, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, DSP_FEATURE_DTMF_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().

05536 {
05537    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05538    char *tok, *tokb, *parse;
05539    int  keyidx = 0;
05540    int rxgain = 0;
05541    int txgain = 0;
05542    int change_jitter = 0;
05543 
05544    if (strcasecmp(chan->tech->type, "mISDN")) {
05545       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05546       return -1;
05547    }
05548    
05549    if (ast_strlen_zero((char *)data)) {
05550       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05551       return -1;
05552    }
05553 
05554    parse = ast_strdupa(data);
05555    for (tok = strtok_r(parse, ":", &tokb);
05556         tok;
05557         tok = strtok_r(NULL, ":", &tokb) ) {
05558       int neglect = 0;
05559 
05560       if (tok[0] == '!' ) {
05561          neglect = 1;
05562          tok++;
05563       }
05564       
05565       switch(tok[0]) {
05566          
05567       case 'd' :
05568          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05569          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05570          break;
05571          
05572       case 'n':
05573          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05574          ch->bc->nodsp = 1;
05575          break;
05576 
05577       case 'j':
05578          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05579          tok++;
05580          change_jitter = 1;
05581 
05582          switch ( tok[0] ) {
05583          case 'b':
05584             ch->jb_len = atoi(++tok);
05585             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05586             break;
05587          case 't' :
05588             ch->jb_upper_threshold = atoi(++tok);
05589             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05590             break;
05591          case 'n':
05592             ch->bc->nojitter = 1;
05593             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05594             break;
05595          default:
05596             ch->jb_len = 4000;
05597             ch->jb_upper_threshold = 0;
05598             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05599             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05600          }
05601          break;
05602       case 'v':
05603          tok++;
05604 
05605          switch (tok[0]) {
05606          case 'r' :
05607             rxgain = atoi(++tok);
05608             if (rxgain < -8)
05609                rxgain = -8;
05610             if (rxgain > 8)
05611                rxgain = 8;
05612             ch->bc->rxgain = rxgain;
05613             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05614             break;
05615          case 't':
05616             txgain = atoi(++tok);
05617             if (txgain < -8)
05618                txgain = -8;
05619             if (txgain > 8)
05620                txgain = 8;
05621             ch->bc->txgain = txgain;
05622             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05623             break;
05624          }
05625          break;
05626       
05627       case 'c':
05628          keyidx = atoi(++tok);
05629          {
05630             char keys[4096];
05631             char *key = NULL, *tmp = keys;
05632             int i;
05633             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05634 
05635             for (i = 0; i < keyidx; i++) {
05636                key = strsep(&tmp, ",");
05637             }
05638 
05639             if (key) {
05640                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05641             }
05642 
05643             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05644             break;
05645          }
05646       case 'e':
05647          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05648          
05649          if (neglect) {
05650             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05651 #ifdef MISDN_1_2
05652             *ch->bc->pipeline = 0;
05653 #else
05654             ch->bc->ec_enable = 0;
05655 #endif
05656          } else {
05657 #ifdef MISDN_1_2
05658             update_pipeline_config(ch->bc);
05659 #else
05660             ch->bc->ec_enable = 1;
05661             ch->bc->orig = ch->originator;
05662             tok++;
05663             if (*tok) {
05664                ch->bc->ec_deftaps = atoi(tok);
05665             }
05666 #endif
05667          }
05668          
05669          break;
05670       case 'h':
05671          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05672          
05673          if (strlen(tok) > 1 && tok[1] == '1') {
05674             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05675             if (!ch->bc->hdlc) {
05676                ch->bc->hdlc = 1;
05677             }
05678          }
05679          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05680          break;
05681             
05682       case 's':
05683          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05684          ch->bc->send_dtmf = 1;
05685          break;
05686          
05687       case 'f':
05688          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05689          ch->faxdetect = 1;
05690          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05691          break;
05692 
05693       case 'a':
05694          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05695          ch->ast_dsp = 1;
05696          break;
05697 
05698       case 'p':
05699          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05700          /* CRICH: callingpres!!! */
05701          if (strstr(tok,"allowed")) {
05702             ch->bc->pres = 0;
05703          } else if (strstr(tok, "not_screened")) {
05704             ch->bc->pres = 1;
05705          }
05706          break;
05707       case 'i' :
05708          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05709          ch->ignore_dtmf=1;
05710          break;
05711       default:
05712          break;
05713       }
05714    }
05715 
05716    if (change_jitter)
05717       config_jitterbuffer(ch);
05718 
05719    if (ch->faxdetect || ch->ast_dsp) {
05720       if (!ch->dsp)
05721          ch->dsp = ast_dsp_new();
05722       if (ch->dsp)
05723          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
05724       if (!ch->trans)
05725          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05726    }
05727 
05728    if (ch->ast_dsp) {
05729       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05730       ch->bc->nodsp = 1;
05731    }
05732    
05733    return 0;
05734 }

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

Definition at line 833 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

00834 {
00835    return _misdn_tasks_add_variable(timeout, callback, data, 0);
00836 }

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

Definition at line 838 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

00839 {
00840    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00841 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 803 of file chan_misdn.c.

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

Referenced by unload_module().

00804 {
00805    if (misdn_tasks) {
00806       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
00807       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
00808          cb_log(4, 0, "Joining misdn_tasks thread\n");
00809          pthread_join(misdn_tasks_thread, NULL);
00810       }
00811       sched_context_destroy(misdn_tasks);
00812    }
00813 }

static void misdn_tasks_init ( void   )  [static]

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

00785 {
00786    sem_t blocker;
00787    int i = 5;
00788 
00789    if (sem_init(&blocker, 0, 0)) {
00790       perror("chan_misdn: Failed to initialize semaphore!");
00791       exit(1);
00792    }
00793 
00794    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
00795    
00796    misdn_tasks = sched_context_create();
00797    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
00798 
00799    while (sem_wait(&blocker) && --i);
00800    sem_destroy(&blocker);
00801 }

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 843 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by release_chan().

00844 {
00845    AST_SCHED_DEL(misdn_tasks, task_id);
00846 }

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

Definition at line 760 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

00761 {
00762    int wait;
00763    struct sigaction sa;
00764 
00765    sa.sa_handler = sighandler;
00766    sa.sa_flags = SA_NODEFER;
00767    sigemptyset(&sa.sa_mask);
00768    sigaddset(&sa.sa_mask, SIGUSR1);
00769    sigaction(SIGUSR1, &sa, NULL);
00770    
00771    sem_post((sem_t *)data);
00772 
00773    while (1) {
00774       wait = ast_sched_wait(misdn_tasks);
00775       if (wait < 0)
00776          wait = 8000;
00777       if (poll(NULL, 0, wait) < 0)
00778          chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
00779       ast_sched_runq(misdn_tasks);
00780    }
00781    return NULL;
00782 }

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 815 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

00816 {
00817    pthread_kill(misdn_tasks_thread, SIGUSR1);
00818 }

static void misdn_transfer_bc ( struct chan_list tmp_ch,
struct chan_list holded_chan 
) [static]

Definition at line 3937 of file chan_misdn.c.

References chan_list::ast, ast_bridged_channel(), ast_channel_masquerade(), ast_moh_stop(), chan_misdn_log(), MISDN_CONNECTED, MISDN_HOLD_DISCONNECT, ast_channel::name, and chan_list::state.

Referenced by cb_events().

03938 {
03939    chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
03940 
03941    tmp_ch->state = MISDN_HOLD_DISCONNECT;
03942 
03943    ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03944 
03945    holded_chan->state=MISDN_CONNECTED;
03946    /* misdn_lib_transfer(holded_chan->bc); */
03947    ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03948 }

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

Definition at line 3083 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, misdn_bchannel::l3_id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_get_ch_state(), MISDN_HOLDED, misdn_lib_tone_generator_start(), chan_list::notxtone, misdn_bchannel::port, prefformat, ast_frame::samples, ast_frame::src, chan_list::state, ast_frame::subclass, and chan_list::ts.

03084 {
03085    struct chan_list *ch;
03086    int i  = 0;
03087    
03088    if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
03089 
03090    if (ch->state == MISDN_HOLDED) {
03091       chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
03092       return 0;
03093    }
03094    
03095    if (!ch->bc ) {
03096       ast_log(LOG_WARNING, "private but no bc\n");
03097       return -1;
03098    }
03099    
03100    if (ch->notxtone) {
03101       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
03102       return 0;
03103    }
03104 
03105 
03106    if (!frame->subclass) {
03107       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
03108       return 0;
03109    }
03110    
03111    if (!(frame->subclass & prefformat)) {
03112       
03113       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
03114       return 0;
03115    }
03116    
03117 
03118    if (!frame->samples ) {
03119       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
03120       
03121       if (!strcmp(frame->src,"ast_prod")) {
03122          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
03123 
03124          if (ch->ts) {
03125             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
03126             misdn_lib_tone_generator_start(ch->bc);
03127          }
03128          return 0;
03129       }
03130 
03131       return -1;
03132    }
03133 
03134    if ( ! ch->bc->addr ) {
03135       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
03136       return 0;
03137    }
03138    
03139 #ifdef MISDN_DEBUG
03140    {
03141       int i, max = 5 > frame->samples ? frame->samples : 5;
03142 
03143       ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
03144 
03145       for (i = 0; i < max ; i++)
03146          ast_debug(1, "%2.2x ", ((char*) frame->data)[i]);
03147    }
03148 #endif
03149 
03150    switch (ch->bc->bc_state) {
03151    case BCHAN_ACTIVATED:
03152    case BCHAN_BRIDGED:
03153       break;
03154    default:
03155       if (!ch->dropped_frame_cnt)
03156          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);
03157       
03158       ch->dropped_frame_cnt++;
03159       if (ch->dropped_frame_cnt > 100) {
03160          ch->dropped_frame_cnt = 0;
03161          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);
03162       }
03163 
03164       return 0;
03165    }
03166 
03167    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n", frame->samples);
03168    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
03169       /* Buffered Transmit (triggered by read from isdn side)*/
03170       if (misdn_jb_fill(ch->jb, frame->data, frame->samples) < 0) {
03171          if (ch->bc->active)
03172             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
03173       }
03174       
03175    } else {
03176       /*transmit without jitterbuffer*/
03177       i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
03178    }
03179 
03180    return 0;
03181 }

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

03820 {
03821    int ret = ast_pbx_start(ch->ast);   
03822 
03823    if (ret >= 0) 
03824       ch->need_hangup = 0;
03825    else
03826       ch->need_hangup = 1;
03827 
03828    return ret;
03829 }

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

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

01368 {
01369    struct ast_channel *ast = help->ast;
01370    ast_cli(fd,
01371       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
01372 
01373       bc->pid, bc->port, bc->channel,
01374       bc->nt ? "NT" : "TE",
01375       help->originator == ORG_AST ? "*" : "I",
01376       ast ? ast->exten : NULL,
01377       ast ? ast->cid.cid_num : NULL,
01378       bc->rad,
01379       ast ? ast->context : NULL,
01380       misdn_get_ch_state(help)
01381       );
01382    if (misdn_debug[bc->port] > 0)
01383       ast_cli(fd,
01384          "  --> astname: %s\n"
01385          "  --> ch_l3id: %x\n"
01386          "  --> ch_addr: %x\n"
01387          "  --> bc_addr: %x\n"
01388          "  --> bc_l3id: %x\n"
01389          "  --> display: %s\n"
01390          "  --> activated: %d\n"
01391          "  --> state: %s\n"
01392          "  --> capability: %s\n"
01393 #ifdef MISDN_1_2
01394          "  --> pipeline: %s\n"
01395 #else
01396          "  --> echo_cancel: %d\n"
01397 #endif
01398          "  --> notone : rx %d tx:%d\n"
01399          "  --> bc_hold: %d\n",
01400          help->ast->name,
01401          help->l3id,
01402          help->addr,
01403          bc->addr,
01404          bc ? bc->l3_id : -1,
01405          bc->display,
01406          
01407          bc->active,
01408          bc_state2str(bc->bc_state),
01409          bearer2str(bc->capability),
01410 #ifdef MISDN_1_2
01411          bc->pipeline,
01412 #else
01413          bc->ec_enable,
01414 #endif
01415 
01416          help->norxtone, help->notxtone,
01417          bc->holded
01418          );
01419 
01420 }

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

00684 {
00685    
00686    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00687    
00688    switch(bc->law) {
00689    case INFO_CODEC_ALAW:
00690       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00691       break;
00692    case INFO_CODEC_ULAW:
00693       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00694       break;
00695    }
00696 }

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

Definition at line 632 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by cb_events().

00633 {
00634    switch (fac->Function) {
00635 #ifdef HAVE_MISDN_FAC_RESULT
00636    case Fac_RESULT:
00637       chan_misdn_log(0, bc->port," --> Received RESULT Operation\n");
00638       break;
00639 #endif
00640 #ifdef HAVE_MISDN_FAC_ERROR
00641    case Fac_ERROR:
00642       chan_misdn_log(0, bc->port," --> Received Error Operation\n");
00643       chan_misdn_log(0, bc->port," --> Value:%d Error:%s\n",fac->u.ERROR.errorValue, fac->u.ERROR.error);
00644       break;
00645 #endif
00646    case Fac_CD:
00647       chan_misdn_log(1,bc->port," --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
00648          fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
00649       break;
00650    case Fac_AOCDCurrency:
00651       if (fac->u.AOCDcur.chargeNotAvailable)
00652          chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
00653       else if (fac->u.AOCDcur.freeOfCharge)
00654          chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
00655       else if (fac->u.AOCDchu.billingId >= 0)
00656          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
00657             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00658             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
00659       else
00660          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
00661             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00662             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
00663       break;
00664    case Fac_AOCDChargingUnit:
00665       if (fac->u.AOCDchu.chargeNotAvailable)
00666          chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
00667       else if (fac->u.AOCDchu.freeOfCharge)
00668          chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
00669       else if (fac->u.AOCDchu.billingId >= 0)
00670          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
00671             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
00672       else
00673          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
00674             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
00675       break;
00676    case Fac_None:
00677    default:
00678       chan_misdn_log(1,bc->port," --> unknown facility\n");
00679       break;
00680    }
00681 }

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

Definition at line 2920 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_translate(), 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, chan_list::trans, and misdn_bchannel::txgain.

Referenced by misdn_read().

02921 {
02922    struct ast_frame *f,*f2;
02923  
02924    if (tmp->trans) {
02925       f2 = ast_translate(tmp->trans, frame, 0);
02926       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02927    } else {
02928       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02929       return NULL;
02930    }
02931 
02932    if (!f || (f->frametype != AST_FRAME_DTMF))
02933       return frame;
02934  
02935    ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
02936  
02937    if (tmp->faxdetect && (f->subclass == 'f')) {
02938       /* Fax tone -- Handle and return NULL */
02939       if (!tmp->faxhandled) {
02940          struct ast_channel *ast = tmp->ast;
02941          tmp->faxhandled++;
02942          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02943          tmp->bc->rxgain = 0;
02944          isdn_lib_update_rxgain(tmp->bc);
02945          tmp->bc->txgain = 0;
02946          isdn_lib_update_txgain(tmp->bc);
02947 #ifdef MISDN_1_2
02948          *tmp->bc->pipeline = 0;
02949 #else
02950          tmp->bc->ec_enable = 0;
02951 #endif
02952          isdn_lib_update_ec(tmp->bc);
02953          isdn_lib_stop_dtmf(tmp->bc);
02954          switch (tmp->faxdetect) {
02955          case 1:
02956             if (strcmp(ast->exten, "fax")) {
02957                char *context;
02958                char context_tmp[BUFFERSIZE];
02959                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02960                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02961                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02962                   ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02963                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02964                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02965                   if (ast_async_goto(ast, context, "fax", 1))
02966                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02967                } else
02968                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02969             } else {
02970                ast_debug(1, "Already in a fax extension, not redirecting\n");
02971             }
02972             break;
02973          case 2:
02974             ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02975             break;
02976          }
02977       } else {
02978          ast_debug(1, "Fax already handled\n");
02979       }
02980    }
02981    
02982    if (tmp->ast_dsp && (f->subclass != 'f')) {
02983       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02984    }
02985 
02986    return f;
02987 }

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

Definition at line 2153 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_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_mutex_init(), ast_print_group(), ast_set_callerid(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_translator_build_path(), 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_DTMF_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, chan_list::trans, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

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

static void release_chan ( struct misdn_bchannel bc  )  [static]

Isdn asks us to release channel, pendant to misdn_hangup

Definition at line 3868 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, ast_free, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_list::bc, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, cl_dequeue_chan(), cl_te, ast_channel::context, ast_channel::exten, find_chan_by_bc(), chan_list::jb, misdn_bchannel::l3_id, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, misdn_get_ch_state(), 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().

03868                                                     {
03869    struct ast_channel *ast=NULL;
03870 
03871    ast_mutex_lock(&release_lock);
03872    {
03873       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03874       if (!ch)  {
03875          chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03876          ast_mutex_unlock(&release_lock);
03877          return;
03878       }
03879 
03880       if (ch->ast) {
03881          ast = ch->ast;
03882       } 
03883 
03884       chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
03885 
03886       /*releasing jitterbuffer*/
03887       if (ch->jb ) {
03888          misdn_jb_destroy(ch->jb);
03889          ch->jb = NULL;
03890       } else {
03891          if (!bc->nojitter)
03892             chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03893       }
03894 
03895       if (ch->overlap_dial) {
03896          if (ch->overlap_dial_task != -1) {
03897             misdn_tasks_remove(ch->overlap_dial_task);
03898             ch->overlap_dial_task = -1;
03899          }
03900          ast_mutex_destroy(&ch->overlap_tv_lock);
03901       }
03902 
03903       if (ch->originator == ORG_AST) {
03904          misdn_out_calls[bc->port]--;
03905       } else {
03906          misdn_in_calls[bc->port]--;
03907       }
03908 
03909       if (ch) {
03910          close(ch->pipe[0]);
03911          close(ch->pipe[1]);
03912 
03913          if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03914             chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n", bc ? bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch));
03915             chan_misdn_log(3, bc->port, " --> * State Down\n");
03916             MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03917 
03918             if (ast->_state != AST_STATE_RESERVED) {
03919                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03920                ast_setstate(ast, AST_STATE_DOWN);
03921             }
03922          }
03923 
03924          ch->state = MISDN_CLEANING;
03925          cl_dequeue_chan(&cl_te, ch);
03926 
03927          ast_free(ch);
03928       } else {
03929          /* chan is already cleaned, so exiting  */
03930       }
03931 
03932       ast_mutex_unlock(&release_lock);
03933    }
03934 /*** release end **/
03935 }

static int reload ( void   )  [static]

Definition at line 5404 of file chan_misdn.c.

References reload_config().

05405 {
05406    reload_config();
05407 
05408    return 0;
05409 }

static void reload_config ( void   )  [static]

Definition at line 1324 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.

01325 {
01326    int i, cfg_debug;
01327 
01328    if (!g_config_initialized) {
01329       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
01330       return ;
01331    }
01332    
01333    free_robin_list();
01334    misdn_cfg_reload();
01335    misdn_cfg_update_ptp();
01336    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
01337    misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
01338 
01339    for (i = 0;  i <= max_ports; i++) {
01340       misdn_debug[i] = cfg_debug;
01341       misdn_debug_only[i] = 0;
01342    }
01343 }

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

Definition at line 4013 of file chan_misdn.c.

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

04013                                                                                                      {
04014    if (!ast) {
04015       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
04016       return;
04017    }
04018    if (!bc) {
04019       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
04020       return;
04021    }
04022    if (!ch) {
04023       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
04024       return;
04025    }
04026 
04027    ast->hangupcause = bc->cause;
04028 
04029    switch (bc->cause) {
04030 
04031    case 1: /** Congestion Cases **/
04032    case 2:
04033    case 3:
04034    case 4:
04035    case 22:
04036    case 27:
04037       /*
04038        * Not Queueing the Congestion anymore, since we want to hear
04039        * the inband message
04040        *
04041       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
04042       ch->state = MISDN_BUSY;
04043       
04044       ast_queue_control(ast, AST_CONTROL_CONGESTION);
04045       */
04046       break;
04047 
04048    case 21:
04049    case 17: /* user busy */
04050 
04051       ch->state = MISDN_BUSY;
04052 
04053       if (!ch->need_busy) {
04054          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
04055          break;
04056       }
04057 
04058       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04059       
04060       ast_queue_control(ast, AST_CONTROL_BUSY);
04061       
04062       ch->need_busy = 0;
04063       
04064       break;
04065    }
04066 }

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

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

00907 {
00908    static const char* dtmf_tones[] = {
00909       "!941+1336/100,!0/100", /* 0 */
00910       "!697+1209/100,!0/100", /* 1 */
00911       "!697+1336/100,!0/100", /* 2 */
00912       "!697+1477/100,!0/100", /* 3 */
00913       "!770+1209/100,!0/100", /* 4 */
00914       "!770+1336/100,!0/100", /* 5 */
00915       "!770+1477/100,!0/100", /* 6 */
00916       "!852+1209/100,!0/100", /* 7 */
00917       "!852+1336/100,!0/100", /* 8 */
00918       "!852+1477/100,!0/100", /* 9 */
00919       "!697+1633/100,!0/100", /* A */
00920       "!770+1633/100,!0/100", /* B */
00921       "!852+1633/100,!0/100", /* C */
00922       "!941+1633/100,!0/100", /* D */
00923       "!941+1209/100,!0/100", /* * */
00924       "!941+1477/100,!0/100" };  /* # */
00925    struct ast_channel *chan=cl->ast; 
00926   
00927    if (digit >= '0' && digit <='9')
00928       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00929    else if (digit >= 'A' && digit <= 'D')
00930       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00931    else if (digit == '*')
00932       ast_playtones_start(chan,0,dtmf_tones[14], 0);
00933    else if (digit == '#')
00934       ast_playtones_start(chan,0,dtmf_tones[15], 0);
00935    else {
00936       /* not handled */
00937       ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00938    }
00939 }

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

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

01165 {
01166    char section[BUFFERSIZE];
01167    char name[BUFFERSIZE];
01168    char desc[BUFFERSIZE];
01169    char def[BUFFERSIZE];
01170    char tmp[BUFFERSIZE];
01171 
01172    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
01173    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
01174    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
01175 
01176    if (elem < MISDN_CFG_LAST)
01177       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
01178    else
01179       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
01180 
01181    if (*def)
01182       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
01183    else
01184       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
01185 
01186    return;
01187 }

static void sighandler ( int  sig  )  [static]

Definition at line 757 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00758 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

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

03349 {
03350    misdn_lib_tone_generator_stop(cl->bc);
03351    cl->notxtone = 0;
03352    cl->norxtone = 0;
03353    return 0;
03354 }

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

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

04156                                                                                                  {
04157    if (pbx_start_chan(ch) < 0) {
04158       hangup_chan(ch);
04159       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04160       if (bc->nt) {
04161          hanguptone_indicate(ch);
04162          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04163       } else
04164          misdn_lib_send_event(bc, EVENT_RELEASE);
04165    }
04166 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3356 of file chan_misdn.c.

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

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

03357 {
03358    if (!cl) return -1;
03359 
03360    cl->notxtone = 1;
03361    cl->norxtone = 1;
03362    
03363    return 0;
03364 }

static int stop_indicate ( struct chan_list cl  )  [static]

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

03329 {
03330    struct ast_channel *ast = cl->ast;
03331 
03332    if (!ast) {
03333       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03334       return -1;
03335    }
03336 
03337    chan_misdn_log(3, cl->bc->port, " --> None\n");
03338    misdn_lib_tone_generator_stop(cl->bc);
03339    ast_playtones_stop(ast);
03340 
03341    cl->ts = NULL;
03342    /*ast_deactivate_generator(ast);*/
03343 
03344    return 0;
03345 }

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 5213 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_lib_destroy(), misdn_tasks_destroy(), and misdn_tech.

05214 {
05215    /* First, take us out of the channel loop */
05216    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05217 
05218    misdn_tasks_destroy();
05219    
05220    if (!g_config_initialized)
05221       return 0;
05222    
05223    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05224    
05225    /* ast_unregister_application("misdn_crypt"); */
05226    ast_unregister_application("misdn_set_opt");
05227    ast_unregister_application("misdn_facility");
05228    ast_unregister_application("misdn_check_l2l1");
05229   
05230    ast_channel_unregister(&misdn_tech);
05231 
05232    free_robin_list();
05233    misdn_cfg_destroy();
05234    misdn_lib_destroy();
05235   
05236    if (misdn_debug)
05237       ast_free(misdn_debug);
05238    if (misdn_debug_only)
05239       ast_free(misdn_debug_only);
05240    ast_free(misdn_ports);
05241    
05242    return 0;
05243 }

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

Updates caller ID information from config.

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

01969 {
01970    struct ast_channel *ast;
01971    struct misdn_bchannel *bc;
01972    int port, hdlc = 0;
01973    int pres, screen;
01974 
01975    if (!ch) {
01976       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01977       return -1;
01978    }
01979 
01980    ast = ch->ast;
01981    bc = ch->bc;
01982    if (! ast || ! bc) {
01983       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01984       return -1;
01985    }
01986 
01987    port = bc->port;
01988 
01989    chan_misdn_log(7, port, "update_config: Getting Config\n");
01990 
01991    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01992    
01993    if (hdlc) {
01994       switch (bc->capability) {
01995       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01996       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01997          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
01998          bc->hdlc = 1;
01999          break;
02000       }
02001    }
02002 
02003 
02004    misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
02005    misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
02006    chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
02007       
02008    if ( (pres + screen) < 0 ) {
02009 
02010       chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
02011          
02012       switch (ast->cid.cid_pres & 0x60) {
02013             
02014       case AST_PRES_RESTRICTED:
02015          bc->pres = 1;
02016          chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
02017          break;
02018       case AST_PRES_UNAVAILABLE:
02019          bc->pres = 2;
02020          chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
02021          break;
02022       default:
02023          bc->pres = 0;
02024          chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
02025       }
02026          
02027       switch (ast->cid.cid_pres & 0x3) {
02028 
02029       case AST_PRES_USER_NUMBER_UNSCREENED:
02030          bc->screen = 0;
02031          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
02032          break;
02033       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02034          bc->screen = 1;
02035          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
02036          break;
02037       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02038          bc->screen = 2;
02039          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
02040          break;
02041       case AST_PRES_NETWORK_NUMBER:
02042          bc->screen = 3;
02043          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
02044          break;
02045       default:
02046          bc->screen = 0;
02047          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
02048       }
02049    } else {
02050       bc->screen = screen;
02051       bc->pres = pres;
02052    }
02053 
02054    return 0;
02055 }

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

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

02135 {
02136    int ec;
02137    int port = bc->port;
02138 
02139    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
02140 
02141    if (ec == 1) {
02142       bc->ec_enable = 1;
02143    } else if (ec > 1) {
02144       bc->ec_enable = 1;
02145       bc->ec_deftaps = ec;
02146    }
02147 
02148    return 0;
02149 }

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

Definition at line 3621 of file chan_misdn.c.

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

Referenced by cb_events().

03622 {
03623    int chan_offset = 0;
03624    int tmp_port = misdn_cfg_get_next_port(0);
03625    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03626       if (tmp_port == port)
03627          break;
03628       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03629    }
03630    if (c < 0)
03631       c = 0;
03632 
03633    ast_string_field_build(tmp, name, "%s/%d-u%d",
03634              misdn_type, chan_offset+c, glob_channel++);
03635 
03636    chan_misdn_log(3 , port, " --> updating channel name to [%s]\n", tmp->name);
03637 }

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

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

04168                                                                                                        {
04169    ch->state=MISDN_WAITING4DIGS;
04170    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04171    if (bc->nt && !bc->dad[0])
04172       dialtone_indicate(ch);
04173 }


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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 5986 of file chan_misdn.c.

struct allowed_bearers allowed_bearers_array[] [static]

Definition at line 590 of file chan_misdn.c.

Referenced by cb_events().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 5986 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1943 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 512 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_hangup(), misdn_request(), and release_chan().

ast_mutex_t cl_te_lock

Definition at line 513 of file chan_misdn.c.

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

struct chan_list dummy_cl

Definition at line 507 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 3619 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 1519 of file chan_misdn.c.

int max_ports [static]

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

int* misdn_debug [static]

Definition at line 499 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 500 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 503 of file chan_misdn.c.

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

int* misdn_out_calls [static]

Definition at line 504 of file chan_misdn.c.

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

int* misdn_ports [static]

Definition at line 474 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 471 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 472 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

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

Referenced by misdn_new().

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

Definition at line 492 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 497 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 425 of file chan_misdn.c.

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 1281 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 494 of file chan_misdn.c.

Referenced by load_module().


Generated on Thu Jul 9 13:41:02 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7