Fri Jul 24 00:41:26 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct allowed_bearers allowed_bearers_array []
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry chan_misdn_clis []
chan_listcl_te = NULL
 Global channel call record list head.
ast_mutex_t cl_te_lock
chan_list dummy_cl
static int g_config_initialized = 0
static int glob_channel = 0
char global_tracefile [BUFFERSIZE+1]
ast_mutex_t lock
static int max_ports
int MAXTICS = 8
static int * misdn_debug
static int * misdn_debug_only
static int * misdn_in_calls
static int * misdn_out_calls
static int * misdn_ports
static struct sched_contextmisdn_tasks = NULL
 the main schedule context for stuff like l1 watcher, overlap dial, ...
static pthread_t misdn_tasks_thread
static struct ast_channel_tech misdn_tech
static struct ast_channel_tech misdn_tech_wo_bridge
static const char misdn_type [] = "mISDN"
static int prefformat = AST_FORMAT_ALAW
 Only alaw and mulaw is allowed for now.
ast_mutex_t release_lock
static struct robin_listrobin = NULL
static struct state_struct state_array []
static int tracing = 0


Detailed Description

the chan_misdn channel driver for Asterisk

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

Definition in file chan_misdn.c.


Define Documentation

#define MISDN_ASTERISK_PVT ( ast   )     1

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

static void __unreg_module ( void   )  [static]

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

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

int add_out_calls ( int  port  ) 

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

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

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 4183 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, ast_frame::ptr, 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().

04184 {
04185    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04186    
04187    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
04188       int debuglevel = 1;
04189       if ( event == EVENT_CLEANUP && !user_data)
04190          debuglevel = 5;
04191 
04192       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");
04193       if (debuglevel == 1) {
04194          misdn_lib_log_ies(bc);
04195          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04196       }
04197    }
04198    
04199    if (!ch) {
04200       switch(event) {
04201       case EVENT_SETUP:
04202       case EVENT_DISCONNECT:
04203       case EVENT_PORT_ALARM:
04204       case EVENT_RETRIEVE:
04205       case EVENT_NEW_BC:
04206       case EVENT_FACILITY:
04207          break;
04208       case EVENT_RELEASE_COMPLETE:
04209          chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
04210          break;
04211       case EVENT_CLEANUP:
04212       case EVENT_TONE_GENERATE:
04213       case EVENT_BCHAN_DATA:
04214          return -1;
04215       default:
04216          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);
04217          return -1;
04218       }
04219    }
04220    
04221    if (ch) {
04222       switch (event) {
04223       case EVENT_TONE_GENERATE:
04224          break;
04225       case EVENT_DISCONNECT:
04226       case EVENT_RELEASE:
04227       case EVENT_RELEASE_COMPLETE:
04228       case EVENT_CLEANUP:
04229       case EVENT_TIMEOUT:
04230          if (!ch->ast)
04231             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));
04232          break;
04233       default:
04234          if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04235             if (event != EVENT_BCHAN_DATA)
04236                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04237             return -1;
04238          }
04239       }
04240    }
04241    
04242    
04243    switch (event) {
04244    case EVENT_PORT_ALARM:
04245       {
04246          int boa = 0;
04247          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
04248          if (boa) {
04249             cb_log(1, bc->port, " --> blocking\n");
04250             misdn_lib_port_block(bc->port); 
04251          }
04252       }
04253       break;
04254    case EVENT_BCHAN_ACTIVATED:
04255       break;
04256       
04257    case EVENT_NEW_CHANNEL:
04258       update_name(ch->ast,bc->port,bc->channel);
04259       break;
04260       
04261    case EVENT_NEW_L3ID:
04262       ch->l3id=bc->l3_id;
04263       ch->addr=bc->addr;
04264       break;
04265 
04266    case EVENT_NEW_BC:
04267       if (!ch) {
04268          ch = find_holded(cl_te,bc);
04269       }
04270       
04271       if (!ch) {
04272          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04273          break;
04274       }
04275 
04276       if (bc)
04277          ch->bc = (struct misdn_bchannel *)user_data;
04278       break;
04279       
04280    case EVENT_DTMF_TONE:
04281    {
04282       /*  sending INFOS as DTMF-Frames :) */
04283       struct ast_frame fr = { 0, };
04284       fr.frametype = AST_FRAME_DTMF;
04285       fr.subclass = bc->dtmf ;
04286       fr.src = NULL;
04287       fr.data.ptr = NULL;
04288       fr.datalen = 0;
04289       fr.samples = 0;
04290       fr.mallocd = 0;
04291       fr.offset = 0;
04292       fr.delivery = ast_tv(0,0);
04293       
04294       if (!ch->ignore_dtmf) {
04295          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04296          ast_queue_frame(ch->ast, &fr);
04297       } else {
04298          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04299       }
04300    }
04301       break;
04302    case EVENT_STATUS:
04303       break;
04304     
04305    case EVENT_INFORMATION:
04306    {
04307       if ( ch->state != MISDN_CONNECTED ) 
04308          stop_indicate(ch);
04309    
04310       if (!ch->ast)
04311          break;
04312 
04313       if (ch->state == MISDN_WAITING4DIGS ) {
04314          /*  Ok, incomplete Setup, waiting till extension exists */
04315          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04316             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04317             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04318          }
04319 
04320          strncat(bc->dad,bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04321          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04322 
04323          /* Check for Pickup Request first */
04324          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04325             if (ast_pickup_call(ch->ast)) {
04326                hangup_chan(ch);
04327             } else {
04328                struct ast_channel *chan = ch->ast;
04329                ch->state = MISDN_CALLING_ACKNOWLEDGE;
04330                ast_setstate(chan, AST_STATE_DOWN);
04331                hangup_chan(ch);
04332                ch->ast = NULL;
04333                break;
04334             }
04335          }
04336          
04337          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04338             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04339                ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
04340                strcpy(ch->ast->exten, "i");
04341 
04342                ch->state = MISDN_DIALING;
04343                start_pbx(ch, bc, ch->ast);
04344                break;
04345             }
04346 
04347             ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
04348                   "maybe you want to add an 'i' extension to catch this case.\n",
04349                   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.ptr = 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, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
04609             strcpy(ch->ast->exten, "i");
04610             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04611             ch->state = MISDN_DIALING;
04612             start_pbx(ch, bc, chan);
04613             break;
04614          }
04615 
04616          ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
04617                "maybe you want to add an 'i' extension to catch this case.\n",
04618                bc->port);
04619          if (bc->nt)
04620             hanguptone_indicate(ch);
04621 
04622          ch->state = MISDN_EXTCANTMATCH;
04623          bc->out_cause = AST_CAUSE_UNALLOCATED;
04624 
04625          if (bc->nt)
04626             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04627          else
04628             misdn_lib_send_event(bc, EVENT_RELEASE );
04629 
04630          break;
04631       }
04632 
04633       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
04634        * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
04635        * will be used by Asterisk automatically. */
04636       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04637          if (!ch->noautorespond_on_setup) {
04638             ch->state=MISDN_DIALING;
04639             misdn_lib_send_event(bc, EVENT_PROCEEDING );
04640          } else {
04641             ch->state = MISDN_INCOMING_SETUP;
04642          }
04643          start_pbx(ch, bc, chan);
04644          break;
04645       }
04646 
04647 
04648       /*
04649        * When we are NT and overlapdial is set and if 
04650        * the number is empty, we wait for the ISDN timeout
04651        * instead of our own timer.
04652        */
04653       if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04654          wait_for_digits(ch, bc, chan);
04655          break;
04656       }
04657 
04658       /* 
04659        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
04660        * Infos with a Interdigit Timeout.
04661        * */
04662       if (ch->overlap_dial) {
04663          ast_mutex_lock(&ch->overlap_tv_lock);
04664          ch->overlap_tv = ast_tvnow();
04665          ast_mutex_unlock(&ch->overlap_tv_lock);
04666 
04667          wait_for_digits(ch, bc, chan);
04668          if (ch->overlap_dial_task == -1) 
04669             ch->overlap_dial_task = 
04670                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04671 
04672          break;
04673       }
04674 
04675       /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
04676        * without interdigit timeout.
04677        * */
04678       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04679          wait_for_digits(ch, bc, chan);
04680          break;
04681       }
04682 
04683       /*
04684        * If the extension exists let's just jump into it.
04685        * */
04686       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04687          if (bc->need_more_infos)
04688             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04689          else
04690             misdn_lib_send_event(bc, EVENT_PROCEEDING);
04691 
04692          ch->state = MISDN_DIALING;
04693          start_pbx(ch, bc, chan);
04694          break;
04695       }
04696    }
04697    break;
04698 
04699    case EVENT_SETUP_ACKNOWLEDGE:
04700    {
04701       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04702 
04703       if (bc->channel) 
04704          update_name(ch->ast,bc->port,bc->channel);
04705       
04706       if (!ast_strlen_zero(bc->infos_pending)) {
04707          /* TX Pending Infos */
04708          strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04709 
04710          if (!ch->ast)
04711             break;
04712          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04713          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04714          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04715 
04716          misdn_lib_send_event(bc, EVENT_INFORMATION);
04717       }
04718    }
04719    break;
04720    case EVENT_PROCEEDING:
04721    {
04722       
04723       if (misdn_cap_is_speech(bc->capability) &&
04724            misdn_inband_avail(bc) ) {
04725          start_bc_tones(ch);
04726       }
04727 
04728       ch->state = MISDN_PROCEEDING;
04729       
04730       if (!ch->ast)
04731          break;
04732 
04733       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04734    }
04735    break;
04736    case EVENT_PROGRESS:
04737 
04738       if (bc->channel) 
04739          update_name(ch->ast, bc->port, bc->channel);
04740 
04741       if (!bc->nt ) {
04742          if ( misdn_cap_is_speech(bc->capability) &&
04743               misdn_inband_avail(bc)
04744             ) {
04745             start_bc_tones(ch);
04746          }
04747          
04748          ch->state = MISDN_PROGRESS;
04749 
04750          if (!ch->ast)
04751             break;
04752          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04753       }
04754       break;
04755       
04756       
04757    case EVENT_ALERTING:
04758    {
04759       ch->state = MISDN_ALERTING;
04760       
04761       if (!ch->ast)
04762          break;
04763 
04764       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04765       ast_setstate(ch->ast, AST_STATE_RINGING);
04766       
04767       cb_log(7, bc->port, " --> Set State Ringing\n");
04768       
04769       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04770          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04771          start_bc_tones(ch);
04772       } else {
04773          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04774          if (ch->far_alerting) {
04775             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04776             start_bc_tones(ch);
04777             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04778          }
04779       }
04780    }
04781    break;
04782    case EVENT_CONNECT:
04783    {
04784       struct ast_channel *bridged;
04785 
04786       /*we answer when we've got our very new L3 ID from the NT stack */
04787       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04788 
04789       if (!ch->ast)
04790          break;
04791 
04792       bridged = ast_bridged_channel(ch->ast);
04793       stop_indicate(ch);
04794 
04795       if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04796          struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04797 
04798          chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04799          if (bridged_ch) {
04800             bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04801             ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04802          }
04803       }
04804    }
04805    ch->l3id=bc->l3_id;
04806    ch->addr=bc->addr;
04807 
04808    start_bc_tones(ch);
04809    
04810    ch->state = MISDN_CONNECTED;
04811    
04812    ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04813    break;
04814    case EVENT_CONNECT_ACKNOWLEDGE:
04815    {
04816       ch->l3id = bc->l3_id;
04817       ch->addr = bc->addr;
04818 
04819       start_bc_tones(ch);
04820 
04821       ch->state = MISDN_CONNECTED;
04822    }
04823    break;
04824    case EVENT_DISCONNECT:
04825       /*we might not have an ch->ast ptr here anymore*/
04826       if (ch) {
04827          struct chan_list *holded_ch = find_holded(cl_te, bc);
04828 
04829          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);
04830          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04831             /* If there's inband information available (e.g. a
04832                recorded message saying what was wrong with the
04833                dialled number, or perhaps even giving an
04834                alternative number, then play it instead of
04835                immediately releasing the call */
04836             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04837       
04838             ch->state = MISDN_DISCONNECTED;
04839             start_bc_tones(ch);
04840 
04841             if (ch->ast) {
04842                ch->ast->hangupcause = bc->cause;
04843                if (bc->cause == AST_CAUSE_USER_BUSY)
04844                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04845             }
04846             ch->need_busy = 0;
04847             break;
04848          }
04849 
04850          /*Check for holded channel, to implement transfer*/
04851          if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
04852             cb_log(1, bc->port, " --> found holded ch\n");
04853             misdn_transfer_bc(ch, holded_ch) ;
04854          }
04855 
04856          bc->need_disconnect = 0;
04857 
04858          stop_bc_tones(ch);
04859          hangup_chan(ch);
04860 #if 0
04861       } else {
04862          ch = find_holded_l3(cl_te, bc->l3_id,1);
04863          if (ch) {
04864             hangup_chan(ch);
04865          }
04866 #endif
04867       }
04868       bc->out_cause = -1;
04869       if (bc->need_release)
04870          misdn_lib_send_event(bc, EVENT_RELEASE);
04871       break;
04872    
04873    case EVENT_RELEASE:
04874       {
04875          bc->need_disconnect = 0;
04876          bc->need_release = 0;
04877 
04878          hangup_chan(ch);
04879          release_chan(bc);
04880       }
04881       break;
04882    case EVENT_RELEASE_COMPLETE:
04883    {
04884       bc->need_disconnect = 0;
04885       bc->need_release = 0;
04886       bc->need_release_complete = 0;
04887 
04888       stop_bc_tones(ch);
04889       hangup_chan(ch);
04890 
04891       if (ch)
04892          ch->state = MISDN_CLEANING;
04893 
04894       release_chan(bc);
04895    }
04896    break;
04897    case EVENT_BCHAN_ERROR:
04898    case EVENT_CLEANUP:
04899    {
04900       stop_bc_tones(ch);
04901       
04902       switch (ch->state) {
04903       case MISDN_CALLING:
04904          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04905          break;
04906       default:
04907          break;
04908       }
04909       
04910       hangup_chan(ch);
04911       release_chan(bc);
04912    }
04913    break;
04914 
04915    case EVENT_TONE_GENERATE:
04916    {
04917       int tone_len = bc->tone_cnt;
04918       struct ast_channel *ast = ch->ast;
04919       void *tmp;
04920       int res;
04921       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04922 
04923       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
04924 
04925       if (!ast)
04926          break;
04927 
04928       if (!ast->generator)
04929          break;
04930 
04931       tmp = ast->generatordata;
04932       ast->generatordata = NULL;
04933       generate = ast->generator->generate;
04934 
04935       if (tone_len < 0 || tone_len > 512 ) {
04936          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
04937          tone_len = 128;
04938       }
04939 
04940       res = generate(ast, tmp, tone_len, tone_len);
04941       ast->generatordata = tmp;
04942       
04943       if (res) {
04944          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04945          ast_deactivate_generator(ast);
04946       } else {
04947          bc->tone_cnt = 0;
04948       }
04949    }
04950    break;
04951 
04952    case EVENT_BCHAN_DATA:
04953    {
04954       if (ch->bc->AOCD_need_export)
04955          export_aoc_vars(ch->originator, ch->ast, ch->bc);
04956       if (!misdn_cap_is_speech(ch->bc->capability) ) {
04957          struct ast_frame frame;
04958          /*In Data Modes we queue frames*/
04959          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
04960          frame.subclass = AST_FORMAT_ALAW;
04961          frame.datalen = bc->bframe_len;
04962          frame.samples = bc->bframe_len;
04963          frame.mallocd = 0;
04964          frame.offset = 0;
04965          frame.delivery = ast_tv(0,0);
04966          frame.src = NULL;
04967          frame.data.ptr = bc->bframe;
04968 
04969          if (ch->ast) 
04970             ast_queue_frame(ch->ast, &frame);
04971       } else {
04972          fd_set wrfs;
04973          struct timeval tv = { 0, 0 };
04974          int t;
04975 
04976          FD_ZERO(&wrfs);
04977          FD_SET(ch->pipe[1], &wrfs);
04978 
04979          t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
04980 
04981          if (!t) {
04982             chan_misdn_log(9, bc->port, "Select Timed out\n");
04983             break;
04984          }
04985          
04986          if (t < 0) {
04987             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
04988             break;
04989          }
04990          
04991          if (FD_ISSET(ch->pipe[1], &wrfs)) {
04992             chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n", bc->bframe_len);
04993             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
04994                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
04995 
04996                stop_bc_tones(ch);
04997                hangup_chan(ch);
04998                release_chan(bc);
04999             }
05000          } else {
05001             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
05002          }
05003       }
05004    }
05005    break;
05006    case EVENT_TIMEOUT:
05007       {
05008       if (ch && bc)
05009          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
05010 
05011       switch (ch->state) {
05012       case MISDN_DIALING:
05013       case MISDN_PROGRESS:
05014          if (bc->nt && !ch->nttimeout)
05015             break;
05016          
05017       case MISDN_CALLING:
05018       case MISDN_ALERTING:
05019       case MISDN_PROCEEDING:
05020       case MISDN_CALLING_ACKNOWLEDGE:
05021          if (bc->nt) {
05022             bc->progress_indicator = 8;
05023             hanguptone_indicate(ch);
05024          }
05025             
05026          bc->out_cause = AST_CAUSE_UNALLOCATED;
05027          misdn_lib_send_event(bc, EVENT_DISCONNECT);
05028          break;
05029 
05030       case MISDN_WAITING4DIGS:
05031          if (bc->nt) {
05032             bc->progress_indicator = 8;
05033             bc->out_cause = AST_CAUSE_UNALLOCATED;
05034             hanguptone_indicate(ch);
05035             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05036          } else {
05037             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
05038             misdn_lib_send_event(bc, EVENT_RELEASE);
05039          }
05040             
05041          break;
05042 
05043       case MISDN_CLEANING: 
05044          chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
05045          break;
05046 
05047       default:
05048          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
05049       }
05050    }
05051    break;
05052 
05053     
05054    /****************************/
05055    /** Supplementary Services **/
05056    /****************************/
05057    case EVENT_RETRIEVE:
05058    {
05059       struct ast_channel *hold_ast;
05060 
05061       if (!ch) {
05062          chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
05063          ch = find_holded_l3(cl_te, bc->l3_id, 1);
05064       }
05065 
05066       if (!ch) {
05067          ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
05068          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05069          break;
05070       }
05071 
05072       /*remember the channel again*/
05073       ch->bc = bc;
05074       ch->state = MISDN_CONNECTED;
05075 
05076       ch->hold_info.port = 0;
05077       ch->hold_info.channel = 0;
05078 
05079       hold_ast = ast_bridged_channel(ch->ast);
05080 
05081       if (hold_ast) {
05082          ast_moh_stop(hold_ast);
05083       }
05084    
05085       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
05086          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
05087          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05088       }
05089    }
05090    break;
05091     
05092    case EVENT_HOLD:
05093    {
05094       int hold_allowed;
05095       struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05096 
05097       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
05098 
05099       if (!hold_allowed) {
05100 
05101          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
05102          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05103          break;
05104       }
05105 
05106       if (bridged) {
05107          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
05108          ch->state = MISDN_HOLDED;
05109          ch->l3id = bc->l3_id;
05110          
05111          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
05112 
05113          /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
05114           * instead of starting moh on the bridged channel directly */
05115          ast_moh_start(bridged, NULL, NULL);
05116 
05117          /*forget the channel now*/
05118          ch->bc = NULL;
05119          ch->hold_info.port = bc->port;
05120          ch->hold_info.channel = bc->channel;
05121 
05122       } else {
05123          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05124          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
05125       }
05126    } 
05127    break;
05128    
05129    case EVENT_FACILITY:
05130       print_facility(&(bc->fac_in), bc);
05131       
05132       switch (bc->fac_in.Function) {
05133 #ifdef HAVE_MISDN_FAC_RESULT
05134       case Fac_RESULT:
05135       break;
05136 #endif
05137       case Fac_CD:
05138          if (ch) {
05139             struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05140             struct chan_list *ch_br;
05141             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
05142                ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
05143                /*ch->state = MISDN_FACILITY_DEFLECTED;*/
05144                if (ch_br->bc) {
05145                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
05146                      ch_br->state = MISDN_DIALING;
05147                      if (pbx_start_chan(ch_br) < 0) {
05148                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
05149                      }
05150                   }
05151                }
05152             }
05153             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05154          } 
05155          break;
05156       case Fac_AOCDCurrency:
05157          if (ch) {
05158             bc->AOCDtype = Fac_AOCDCurrency;
05159             memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
05160             bc->AOCD_need_export = 1;
05161             export_aoc_vars(ch->originator, ch->ast, bc);
05162          }
05163          break;
05164       case Fac_AOCDChargingUnit:
05165          if (ch) {
05166             bc->AOCDtype = Fac_AOCDChargingUnit;
05167             memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
05168             bc->AOCD_need_export = 1;
05169             export_aoc_vars(ch->originator, ch->ast, bc);
05170          }
05171          break;
05172       case Fac_None:
05173 #ifdef HAVE_MISDN_FAC_ERROR
05174       case Fac_ERROR:
05175 #endif
05176       break;
05177       default:
05178          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
05179       }
05180       
05181       break;
05182 
05183    case EVENT_RESTART:
05184 
05185       if (!bc->dummy) {
05186          stop_bc_tones(ch);
05187          release_chan(bc);
05188       }
05189       break;
05190 
05191    default:
05192       chan_misdn_log(1, 0, "Got Unknown Event\n");
05193       break;
05194    }
05195    
05196    return RESPONSE_OK;
05197 }

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

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

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

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

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

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

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

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

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

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

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

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

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

References chan_list::ast, 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, ast_frame::offset, pbx_start_chan(), misdn_bchannel::port, ast_frame::ptr, ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

Referenced by cb_events().

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

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

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

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

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

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

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

Definition at line 3727 of file chan_misdn.c.

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

Referenced by import_ch().

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

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

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

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

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

Definition at line 3758 of file chan_misdn.c.

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

Referenced by cb_events().

03759 {
03760    struct chan_list *help = list;
03761 
03762    for (; help; help = help->next) {
03763       if ( (help->state == MISDN_HOLDED) &&
03764           (help->l3id == l3_id)   
03765          ) 
03766          return help;
03767    }
03768 
03769    return NULL;
03770 }

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

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

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

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

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

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

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

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

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2507 of file chan_misdn.c.

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

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_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
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_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
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 5456 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().

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

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

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

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    case MISDN_CALLING:
02828       p->state = MISDN_CLEANING;
02829       /* This is the only place in misdn_hangup, where we 
02830        * can call release_chan, else it might create lot's of trouble
02831        * */
02832       ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
02833       release_chan(bc);
02834       misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02835       break;
02836    case MISDN_HOLDED:
02837    case MISDN_DIALING:
02838       start_bc_tones(p);
02839       hanguptone_indicate(p);
02840       
02841       p->state=MISDN_CLEANING;
02842       if (bc->need_disconnect)
02843          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02844       break;
02845    case MISDN_CALLING_ACKNOWLEDGE:
02846       start_bc_tones(p);
02847       hanguptone_indicate(p);
02848       
02849       if (bc->need_disconnect)
02850          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02851       break;
02852       
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 5796 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().

05797 {
05798    ast_mutex_destroy(&jb->mutexjb);
05799    
05800    ast_free(jb->ok);
05801    ast_free(jb->samples);
05802    ast_free(jb);
05803 }

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

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

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

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

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

Definition at line 5753 of file chan_misdn.c.

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

Referenced by config_jitterbuffer().

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

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

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

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::ptr, 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.ptr = 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 5532 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_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_GEN_CRYPT_KEYS, misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_bchannel::orig, chan_list::originator, parse(), misdn_bchannel::port, misdn_bchannel::pres, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, strsep(), ast_channel::tech, misdn_bchannel::txgain, and ast_channel_tech::type.

Referenced by load_module(), and misdn_call().

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

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

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

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::ptr, 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.ptr)[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.ptr, 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.ptr, frame->samples);
03178    }
03179 
03180    return 0;
03181 }

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

03824 {
03825    int ret = ast_pbx_start(ch->ast);   
03826 
03827    if (ret >= 0) 
03828       ch->need_hangup = 0;
03829    else
03830       ch->need_hangup = 1;
03831 
03832    return ret;
03833 }

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_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::early_bconnect, ast_channel::exten, chan_list::far_alerting, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, chan_list::incoming_early_audio, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, misdn_bchannel::keypad, language, LOG_WARNING, MISDN_CFG_ALLOWED_BEARERS, MISDN_CFG_ASTDTMF, MISDN_CFG_CALLERID, MISDN_CFG_CALLGROUP, MISDN_CFG_CONTEXT, MISDN_CFG_CPNDIALPLAN, MISDN_CFG_DIALPLAN, MISDN_CFG_EARLY_BCONNECT, MISDN_CFG_FAR_ALERTING, MISDN_CFG_FAXDETECT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CFG_INTERNATPREFIX, MISDN_CFG_JITTERBUFFER, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CFG_LANGUAGE, MISDN_CFG_LOCALDIALPLAN, MISDN_CFG_MUSICCLASS, MISDN_CFG_NATPREFIX, MISDN_CFG_NEED_MORE_INFOS, MISDN_CFG_NOAUTORESPOND_ON_SETUP, MISDN_CFG_NTTIMEOUT, MISDN_CFG_OVERLAP_DIAL, MISDN_CFG_PICKUPGROUP, MISDN_CFG_RXGAIN, MISDN_CFG_SENDDTMF, MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CFG_TXGAIN, chan_list::mohinterpret, misdn_bchannel::need_more_infos, chan_list::noautorespond_on_setup, chan_list::nttimeout, NUMPLAN_INTERNATIONAL, NUMPLAN_NATIONAL, misdn_bchannel::oad, misdn_bchannel::onumplan, ORG_AST, misdn_bchannel::orig_dad, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, ast_channel::pickupgroup, misdn_bchannel::port, prefix, misdn_bchannel::rad, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, misdn_bchannel::te_choose_channel, 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_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
02353          else 
02354             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_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 3872 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().

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

static int reload ( void   )  [static]

Definition at line 5401 of file chan_misdn.c.

References reload_config().

05402 {
05403    reload_config();
05404 
05405    return 0;
05406 }

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

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

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

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

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

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

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_change_name(), chan_misdn_log(), misdn_cfg_get_next_port(), misdn_lib_port_is_pri(), misdn_type, and ast_channel::name.

Referenced by cb_events().

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

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

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

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Channel driver for mISDN Support (BRI/PRI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

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

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 5983 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 Fri Jul 24 00:41:27 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7