Mon May 14 04:45:36 2007

Asterisk developer's documentation


chan_misdn.c File Reference

the chan_misdn channel driver for Asterisk More...

#include "asterisk.h"
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.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/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.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 "chan_misdn_config.h"
#include "isdn_lib.h"
#include <asterisk/strings.h>

Include dependency graph for chan_misdn.c:

Go to the source code of this file.

Data Structures

struct  allowed_bearers
struct  chan_list
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 int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data, int variable)
int add_in_calls (int port)
int add_out_calls (int port)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Channel driver for mISDN Support (BRI/PRI)",.load=load_module,.unload=unload_module,.reload=reload,)
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 (const char *line, const char *word, int pos, int state)
static char * complete_ch_helper (const char *line, const char *word, int pos, int state, int rpos)
static char * complete_debug_port (const char *line, const char *word, int pos, int state)
static char * complete_show_config (const char *line, const char *word, int pos, int state)
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)
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 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)
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 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)
int misdn_jb_empty (struct misdn_jb *jb, char *data, int len)
int misdn_jb_fill (struct misdn_jb *jb, const char *data, int len)
misdn_jbmisdn_jb_init (int size, int upper_threshold)
static int misdn_l1_task (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 (void *data)
static int misdn_port_block (int fd, int argc, char *argv[])
static int misdn_port_down (int fd, int argc, char *argv[])
static int misdn_port_unblock (int fd, int argc, char *argv[])
static int misdn_port_up (int fd, int argc, char *argv[])
static struct ast_framemisdn_read (struct ast_channel *ast)
static int misdn_reload (int fd, int argc, char *argv[])
static struct ast_channelmisdn_request (const char *type, int format, void *data, int *cause)
static int misdn_restart_pid (int fd, int argc, char *argv[])
static int misdn_restart_port (int fd, int argc, char *argv[])
static int misdn_send_cd (int fd, int argc, char *argv[])
static int misdn_send_digit (int fd, int argc, char *argv[])
static int misdn_send_display (int fd, int argc, char *argv[])
static int misdn_send_restart (int fd, int argc, char *argv[])
static int misdn_send_text (struct ast_channel *chan, const char *text)
static int misdn_set_crypt_debug (int fd, int argc, char *argv[])
static int misdn_set_debug (int fd, int argc, char *argv[])
static int misdn_set_opt_exec (struct ast_channel *chan, void *data)
static int misdn_set_tics (int fd, int argc, char *argv[])
static int misdn_show_cl (int fd, int argc, char *argv[])
static int misdn_show_cls (int fd, int argc, char *argv[])
static int misdn_show_config (int fd, int argc, char *argv[])
static int misdn_show_port (int fd, int argc, char *argv[])
static int misdn_show_ports_stats (int fd, int argc, char *argv[])
static int misdn_show_stacks (int fd, int argc, char *argv[])
static int misdn_tasks_add (int timeout, ast_sched_cb callback, void *data)
static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data)
static void misdn_tasks_destroy (void)
static void misdn_tasks_init (void)
static void misdn_tasks_remove (int task_id)
static void * misdn_tasks_thread_func (void *data)
static void misdn_tasks_wakeup (void)
static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
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 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)
static int update_ec_config (struct misdn_bchannel *bc)
static void update_name (struct ast_channel *tmp, int port, int c)

Variables

allowed_bearers allowed_bearers_array []
static struct ast_cli_entry chan_misdn_clis []
chan_listcl_te = NULL
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
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
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>

Definition in file chan_misdn.c.


Define Documentation

#define MISDN_ASTERISK_PVT ( ast   )     1

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

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

#define ORG_MISDN   2

Definition at line 140 of file chan_misdn.c.

Referenced by cb_events(), do_immediate_setup(), 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 couldnt 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 cam from misdn
MISDN_HUNGUP_FROM_AST  when DISCONNECT/RELEASE/REL_COMP came out of
MISDN_HOLDED  if this chan is holded
MISDN_HOLD_DISCONNECT  if this chan is holded

Definition at line 113 of file chan_misdn.c.

00113                       {
00114    MISDN_NOTHING=0,  /*!< at beginning */
00115    MISDN_WAITING4DIGS, /*!<  when waiting for infos */
00116    MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
00117    MISDN_INCOMING_SETUP, /*!<  for incoming setups*/
00118    MISDN_DIALING, /*!<  when pbx_start */
00119    MISDN_PROGRESS, /*!<  we got a progress */
00120    MISDN_PROCEEDING, /*!<  we got a progress */
00121    MISDN_CALLING, /*!<  when misdn_call is called */
00122    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
00123    MISDN_ALERTING, /*!<  when Alerting */
00124    MISDN_BUSY, /*!<  when BUSY */
00125    MISDN_CONNECTED, /*!<  when connected */
00126    MISDN_PRECONNECTED, /*!<  when connected */
00127    MISDN_DISCONNECTED, /*!<  when connected */
00128    MISDN_RELEASED, /*!<  when connected */
00129    MISDN_BRIDGED, /*!<  when bridged */
00130    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00131    MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
00132    MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
00133    /* misdn_hangup */
00134    MISDN_HOLDED, /*!< if this chan is holded */
00135    MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
00136   
00137 };


Function Documentation

static int _misdn_tasks_add_variable ( int  timeout,
ast_sched_cb  callback,
void *  data,
int  variable 
) [inline, static]

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

00612 {
00613    int task_id;
00614 
00615    if (!misdn_tasks) {
00616       misdn_tasks_init();
00617    }
00618    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00619    misdn_tasks_wakeup();
00620 
00621    return task_id;
00622 }

int add_in_calls ( int  port  ) 

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

03744 {
03745    int max_in_calls;
03746    
03747    misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
03748 
03749    misdn_in_calls[port]++;
03750 
03751    if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) {
03752       ast_log(LOG_NOTICE,"Marking Incoming Call on port[%d]\n",port);
03753       return misdn_in_calls[port]-max_in_calls;
03754    }
03755    
03756    return 0;
03757 }

int add_out_calls ( int  port  ) 

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

03760 {
03761    int max_out_calls;
03762    
03763    misdn_cfg_get( port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
03764    
03765 
03766    if (max_out_calls >=0 && max_out_calls<=misdn_out_calls[port]) {
03767       ast_log(LOG_NOTICE,"Rejecting Outgoing Call on port[%d]\n",port);
03768       return (misdn_out_calls[port]+1)-max_out_calls;
03769    }
03770 
03771    misdn_out_calls[port]++;
03772    
03773    return 0;
03774 }

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
"Channel driver for mISDN Support (BRI/PRI)"  ,
load = load_module,
unload = unload_module,
reload = reload 
)

static char* bearer2str ( int  cap  )  [static]

Definition at line 405 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 misdn_lib_log_ies(), print_bc_info(), and print_bearer().

00405                                  {
00406    static char *bearers[]={
00407       "Speech",
00408       "Audio 3.1k",
00409       "Unres Digital",
00410       "Res Digital",
00411       "Video",
00412       "Unknown Bearer"
00413    };
00414    
00415    switch (cap) {
00416    case INFO_CAPABILITY_SPEECH:
00417       return bearers[0];
00418       break;
00419    case INFO_CAPABILITY_AUDIO_3_1K:
00420       return bearers[1];
00421       break;
00422    case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00423       return bearers[2];
00424       break;
00425    case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00426       return bearers[3];
00427       break;
00428    case INFO_CAPABILITY_VIDEO:
00429       return bearers[4];
00430       break;
00431    default:
00432       return bearers[5];
00433       break;
00434    }
00435 }

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

Definition at line 3782 of file chan_misdn.c.

References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, allowed_bearers_array, chan_list::ast, ast_canmatch_extension(), ast_cdr_update(), ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pickup_call(), ast_pickup_ext(), AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_frame(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_transfercapability2str(), chan_list::bc, misdn_bchannel::bc_state, bc_state2str(), misdn_bchannel::capability, cb_log, chan_misdn_log(), misdn_bchannel::channel, ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), cl_te, chan_list::context, misdn_bchannel::cw, misdn_bchannel::dad, ast_frame::data, ast_frame::datalen, ast_frame::delivery, misdn_bchannel::dtmf, EVENT_BCHAN_ACTIVATED, EVENT_BCHAN_DATA, EVENT_CLEANUP, EVENT_DISCONNECT, EVENT_DTMF_TONE, EVENT_FACILITY, EVENT_INFORMATION, EVENT_NEW_BC, EVENT_NEW_CHANNEL, EVENT_NEW_L3ID, EVENT_PORT_ALARM, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, EVENT_RETRIEVE, EVENT_SETUP, EVENT_SETUP_ACKNOWLEDGE, EVENT_STATUS, EVENT_TIMEOUT, EVENT_TONE_GENERATE, export_ch(), ast_channel::exten, find_chan_by_bc(), find_holded(), ast_frame::frametype, hangup_chan(), hanguptone_indicate(), chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::info_dad, init_chan_list(), misdn_bchannel::keypad, misdn_bchannel::l3_id, chan_list::l3id, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_isdn_get_info(), MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING_ACKNOWLEDGE, MISDN_CFG_ALARM_BLOCK, misdn_cfg_get(), misdn_cfg_is_msn_valid(), MISDN_CFG_REJECT_CAUSE, MISDN_CONNECTED, MISDN_DIALING, MISDN_EXTCANTMATCH, MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_GEN_STOP_TONE, misdn_get_ch_state(), MISDN_INCOMING_SETUP, misdn_lib_log_ies(), misdn_lib_port_block(), misdn_lib_send_event(), misdn_new(), MISDN_NOTHING, misdn_overlap_dial_task(), misdn_tasks_add_variable(), MISDN_WAITING4DIGS, allowed_bearers::name, chan_list::noautorespond_on_setup, misdn_bchannel::nt, misdn_bchannel::oad, ast_frame::offset, 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, misdn_bchannel::port, misdn_bchannel::pres, print_bearer(), read_config(), RESPONSE_IGNORE_SETUP, RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE, RESPONSE_OK, RESPONSE_RELEASE_SETUP, ast_channel::rings, ast_frame::samples, misdn_bchannel::screen, ast_frame::src, chan_list::state, stop_indicate(), ast_frame::subclass, ast_channel::transfercapability, and update_name().

Referenced by load_module().

03783 {
03784    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03785    
03786    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
03787       int debuglevel=1;
03788       if ( event==EVENT_CLEANUP && !user_data)
03789          debuglevel=5;
03790 
03791       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");
03792       if (debuglevel==1) {
03793          misdn_lib_log_ies(bc);
03794          chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
03795       }
03796    }
03797    
03798    if (!ch) {
03799       switch(event) {
03800          case EVENT_SETUP:
03801          case EVENT_DISCONNECT:
03802          case EVENT_PORT_ALARM:
03803          case EVENT_RETRIEVE:
03804          case EVENT_NEW_BC:
03805          case EVENT_FACILITY:
03806             break;
03807          case EVENT_RELEASE_COMPLETE:
03808             chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
03809             break;
03810          case EVENT_CLEANUP:
03811          case EVENT_TONE_GENERATE:
03812          case EVENT_BCHAN_DATA:
03813             return -1;
03814 
03815          default:
03816             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);
03817             return -1;
03818       }
03819    }
03820    
03821    if (ch ) {
03822       switch (event) {
03823       case EVENT_TONE_GENERATE:
03824       break;
03825       case EVENT_DISCONNECT:
03826       case EVENT_RELEASE:
03827       case EVENT_RELEASE_COMPLETE:
03828       case EVENT_CLEANUP:
03829       case EVENT_TIMEOUT:
03830          if (!ch->ast)
03831             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));
03832          break;
03833       default:
03834          if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03835             if (event!=EVENT_BCHAN_DATA)
03836                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
03837             return -1;
03838          }
03839       }
03840    }
03841    
03842    
03843    switch (event) {
03844    case EVENT_PORT_ALARM:
03845       {
03846          int boa=0;
03847          misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
03848          if (boa) {
03849             cb_log(1,bc->port," --> blocking\n");
03850             misdn_lib_port_block(bc->port); 
03851          }
03852       }
03853    break;
03854    case EVENT_BCHAN_ACTIVATED:
03855       break;
03856       
03857    case EVENT_NEW_CHANNEL:
03858       update_name(ch->ast,bc->port,bc->channel);
03859       break;
03860       
03861    case EVENT_NEW_L3ID:
03862       ch->l3id=bc->l3_id;
03863       ch->addr=bc->addr;
03864       break;
03865 
03866    case EVENT_NEW_BC:
03867       if (!ch) {
03868          ch=find_holded(cl_te,bc);
03869       }
03870       
03871       if (!ch) {
03872          ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
03873          break;
03874       }
03875 
03876       if (bc)
03877          ch->bc=(struct misdn_bchannel*)user_data;
03878       break;
03879       
03880    case EVENT_DTMF_TONE:
03881    {
03882       /*  sending INFOS as DTMF-Frames :) */
03883       struct ast_frame fr;
03884       memset(&fr, 0 , sizeof(fr));
03885       fr.frametype = AST_FRAME_DTMF;
03886       fr.subclass = bc->dtmf ;
03887       fr.src=NULL;
03888       fr.data = NULL ;
03889       fr.datalen = 0;
03890       fr.samples = 0 ;
03891       fr.mallocd =0 ;
03892       fr.offset= 0 ;
03893       fr.delivery= ast_tv(0,0) ;
03894       
03895       if (!ch->ignore_dtmf) {
03896          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
03897          ast_queue_frame(ch->ast, &fr);
03898       } else {
03899          chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
03900       }
03901    }
03902    break;
03903    case EVENT_STATUS:
03904       break;
03905     
03906    case EVENT_INFORMATION:
03907    {
03908       int stop_tone;
03909       misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03910       if ( stop_tone ) {
03911          stop_indicate(ch);
03912       }
03913    
03914       if (!ch->ast) break;
03915 
03916       if (ch->state == MISDN_WAITING4DIGS ) {
03917          /*  Ok, incomplete Setup, waiting till extension exists */
03918 
03919          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
03920             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
03921             strcpy(bc->info_dad,bc->keypad);
03922          }
03923 
03924          {
03925             int l = sizeof(bc->dad);
03926             strncat(bc->dad,bc->info_dad, l);
03927             bc->dad[l-1] = 0;
03928          }
03929          
03930          
03931          {
03932             int l = sizeof(ch->ast->exten);
03933             strncpy(ch->ast->exten, bc->dad, l);
03934             ch->ast->exten[l-1] = 0;
03935          }
03936 /*       chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
03937          
03938          /* Check for Pickup Request first */
03939          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
03940             int ret;/** Sending SETUP_ACK**/
03941             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03942             if (ast_pickup_call(ch->ast)) {
03943                hangup_chan(ch);
03944             } else {
03945                struct ast_channel *chan=ch->ast;
03946                ch->state = MISDN_CALLING_ACKNOWLEDGE;
03947                ast_setstate(chan, AST_STATE_DOWN);
03948                hangup_chan(ch);
03949                ch->ast=NULL;
03950                break;
03951             }
03952          }
03953          
03954          if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03955 
03956             chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
03957             if (bc->nt)
03958                hanguptone_indicate(ch);
03959             ch->state=MISDN_EXTCANTMATCH;
03960             bc->out_cause=1;
03961 
03962             misdn_lib_send_event(bc, EVENT_DISCONNECT );
03963 
03964             break;
03965          }
03966 
03967          if (ch->overlap_dial) {
03968             ast_mutex_lock(&ch->overlap_tv_lock);
03969             ch->overlap_tv = ast_tvnow();
03970             ast_mutex_unlock(&ch->overlap_tv_lock);
03971             if (ch->overlap_dial_task == -1) {
03972                ch->overlap_dial_task = 
03973                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
03974             }
03975             break;
03976          }
03977 
03978          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03979             ch->state=MISDN_DIALING;
03980      
03981             stop_indicate(ch);
03982 /*          chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/
03983             if (pbx_start_chan(ch)<0) {
03984                hangup_chan(ch);
03985 
03986                chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
03987                if (bc->nt) hanguptone_indicate(ch);
03988 
03989                misdn_lib_send_event(bc, EVENT_DISCONNECT );
03990             }
03991          }
03992    
03993       } else {
03994          /*  sending INFOS as DTMF-Frames :) */
03995          struct ast_frame fr;
03996          fr.frametype = AST_FRAME_DTMF;
03997          fr.subclass = bc->info_dad[0] ;
03998          fr.src=NULL;
03999          fr.data = NULL ;
04000          fr.datalen = 0;
04001          fr.samples = 0 ;
04002          fr.mallocd =0 ;
04003          fr.offset= 0 ;
04004          fr.delivery= ast_tv(0,0) ;
04005 
04006          
04007          int digits;
04008          misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
04009          if (ch->state != MISDN_CONNECTED ) {
04010             if (digits) {
04011                int l = sizeof(bc->dad);
04012                strncat(bc->dad,bc->info_dad, l);
04013                bc->dad[l-1] = 0;
04014                l = sizeof(ch->ast->exten);
04015                strncpy(ch->ast->exten, bc->dad, l);
04016                ch->ast->exten[l-1] = 0;
04017 
04018                ast_cdr_update(ch->ast);
04019             }
04020             
04021             ast_queue_frame(ch->ast, &fr);
04022          }
04023       }
04024    }
04025    break;
04026    case EVENT_SETUP:
04027    {
04028       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
04029       if (ch) {
04030          switch (ch->state) {
04031             case MISDN_NOTHING:
04032             ch=NULL;
04033             break;
04034             default:
04035             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04036             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
04037          }
04038       }
04039    }
04040    
04041 
04042    int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04043    if (!bc->nt && ! msn_valid) {
04044       chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04045       return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04046    }
04047 
04048    
04049    if (bc->cw) {
04050       chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04051       int cause;
04052       misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04053       bc->out_cause=cause?cause:16;
04054       return RESPONSE_RELEASE_SETUP;
04055    }
04056 
04057    print_bearer(bc);
04058     
04059    {
04060       struct chan_list *ch=init_chan_list(ORG_MISDN);
04061       struct ast_channel *chan;
04062       int exceed;
04063 
04064       if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
04065       
04066       ch->bc = bc;
04067       ch->l3id=bc->l3_id;
04068       ch->addr=bc->addr;
04069       ch->originator = ORG_MISDN;
04070 
04071       chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04072       ch->ast = chan;
04073 
04074       if ((exceed=add_in_calls(bc->port))) {
04075          char tmp[16];
04076          sprintf(tmp,"%d",exceed);
04077          pbx_builtin_setvar_helper(chan,"MAX_OVERFLOW",tmp);
04078       }
04079 
04080       read_config(ch, ORG_MISDN);
04081       
04082       export_ch(chan, bc, ch);
04083 
04084       ch->ast->rings=1;
04085       ast_setstate(ch->ast, AST_STATE_RINGING);
04086 
04087       int pres,screen;
04088 
04089       switch (bc->pres) {
04090          case 1:
04091          pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
04092          break;
04093          case 2:
04094          pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
04095          break;
04096          default:
04097          pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
04098       }
04099 
04100       switch (bc->screen) {
04101          case 0:
04102          screen=AST_PRES_USER_NUMBER_UNSCREENED;  chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
04103          break;
04104          case 1:
04105          screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
04106          break;
04107          case 2:
04108          screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
04109          break;
04110          case 3:
04111          screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
04112          break;
04113          default:
04114          screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
04115       }
04116 
04117       chan->cid.cid_pres=pres+screen;
04118 
04119       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04120       chan->transfercapability=bc->capability;
04121       
04122       switch (bc->capability) {
04123       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04124          pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
04125          break;
04126       default:
04127          pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
04128       }
04129 
04130       /** queue new chan **/
04131       cl_queue_chan(&cl_te, ch) ;
04132 
04133 
04134       if (!strstr(ch->allowed_bearers,"all")) {
04135          int i;
04136          for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
04137             if (allowed_bearers_array[i].cap == bc->capability) {
04138                if (  !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
04139                   chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
04140                   bc->out_cause=88;
04141                   
04142                   ch->state=MISDN_EXTCANTMATCH;
04143                   misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04144                   return RESPONSE_OK;
04145                }
04146             }
04147             
04148          }
04149       }
04150       
04151       /* Check for Pickup Request first */
04152       if (!strcmp(chan->exten, ast_pickup_ext())) {
04153          if (!ch->noautorespond_on_setup) {
04154             int ret;/** Sending SETUP_ACK**/
04155             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04156          } else {
04157             ch->state = MISDN_INCOMING_SETUP;
04158          }
04159          if (ast_pickup_call(chan)) {
04160             hangup_chan(ch);
04161          } else {
04162             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04163             ast_setstate(chan, AST_STATE_DOWN);
04164             hangup_chan(ch);
04165             ch->ast=NULL;
04166             break;
04167          }
04168       }
04169       
04170       /*
04171         added support for s extension hope it will help those poor cretains
04172         which haven't overlap dial.
04173       */
04174       {
04175          int ai;
04176          misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04177          if ( ai ) {
04178             do_immediate_setup(bc, ch , chan);
04179             break;
04180          }
04181          
04182          
04183          
04184       }
04185 
04186       /* check if we should jump into s when we have no dad */
04187       {
04188          int im;
04189          misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04190          if ( im && ast_strlen_zero(bc->dad) ) {
04191             do_immediate_setup(bc, ch , chan);
04192             break;
04193          }
04194       }
04195 
04196       
04197          chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
04198          if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04199          
04200          chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
04201 
04202          if (bc->nt)
04203             hanguptone_indicate(ch);
04204          ch->state=MISDN_EXTCANTMATCH;
04205          bc->out_cause=1;
04206 
04207          if (bc->nt)
04208             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04209          else
04210             misdn_lib_send_event(bc, EVENT_RELEASE );
04211             
04212          break;
04213       }
04214       
04215       if (!ch->overlap_dial && ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04216          
04217          if (!ch->noautorespond_on_setup) {
04218             ch->state=MISDN_DIALING;
04219 
04220             if (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)) ) {
04221                int ret; 
04222                ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04223             } else {
04224                int ret;
04225                ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
04226             }
04227          } else {
04228             ch->state = MISDN_INCOMING_SETUP;
04229          }
04230    
04231          if (pbx_start_chan(ch)<0) {
04232             hangup_chan(ch);
04233 
04234             chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04235             chan=NULL;
04236 
04237             if (bc->nt) {
04238                hanguptone_indicate(ch);
04239                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04240             } else
04241                misdn_lib_send_event(bc, EVENT_RELEASE);
04242          }
04243       } else {
04244 
04245          if (bc->sending_complete) {
04246             ch->state=MISDN_EXTCANTMATCH;
04247             bc->out_cause=1;
04248 
04249             if (bc->nt)  {
04250                chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
04251                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04252             } else {
04253                chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
04254                misdn_lib_send_event(bc, EVENT_RELEASE);
04255             }
04256 
04257          } else {
04258             int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04259             if (ret == -ENOCHAN) {
04260                ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
04261                misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04262             }
04263             /*  send tone to phone :) */
04264             
04265             /** ADD IGNOREPAT **/
04266             
04267             int stop_tone, dad_len;
04268             ch->state=MISDN_WAITING4DIGS;
04269 
04270             misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
04271 
04272             dad_len = ast_strlen_zero(bc->dad);
04273             
04274             if ( !dad_len && stop_tone )
04275                stop_indicate(ch);
04276             else
04277                dialtone_indicate(ch);
04278             
04279             
04280             if (ch->overlap_dial && !dad_len) {
04281                ast_mutex_lock(&ch->overlap_tv_lock);
04282                ch->overlap_tv = ast_tvnow();
04283                ast_mutex_unlock(&ch->overlap_tv_lock);
04284                if (ch->overlap_dial_task == -1) {
04285                   ch->overlap_dial_task = 
04286                      misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04287                }
04288             }
04289          }
04290       }
04291       
04292    }
04293    break;
04294    case EVENT_SETUP_ACKNOWLEDGE:
04295    {
04296       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04297 
04298       if (bc->channel) 
04299          update_name(ch->ast,bc->port,bc->channel);
04300       
04301       if (!ast_strlen_zero(bc->infos_pending)) {
04302          /* TX Pending Infos */
04303          
04304          {
04305             int l = sizeof(bc->dad);
04306             strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
04307             bc->dad[l-1] = 0;
04308          }  
04309       
04310          if (!ch->ast) break;
04311          {
04312             int l = sizeof(ch->ast->exten);
04313             strncpy(ch->ast->exten, bc->dad, l);
04314             ch->ast->exten[l-1] = 0;
04315          }
04316          {
04317             int l = sizeof(bc->info_dad);
04318             strncpy(bc->info_dad, bc->infos_pending, l);
04319             bc->info_dad[l-1] = 0;
04320          }
04321          strncpy(bc->infos_pending,"", 1);
04322 
04323          misdn_lib_send_event(bc, EVENT_INFORMATION);
04324       }
04325    }
04326    break;
04327    case EVENT_PROCEEDING:
04328    {
04329       if (bc->channel) 
04330          update_name(ch->ast,bc->port,bc->channel);
04331 
04332       if ( misdn_cap_is_speech(bc->capability) &&
04333            misdn_inband_avail(bc) ) {
04334          start_bc_tones(ch);
04335       }
04336 
04337       ch->state = MISDN_PROCEEDING;
04338       
04339       if (!ch->ast) break;
04340 
04341       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04342    }
04343    break;
04344    case EVENT_PROGRESS:
04345       if (bc->channel) 
04346          update_name(ch->ast,bc->port,bc->channel);
04347 
04348       if (!bc->nt ) {
04349          if ( misdn_cap_is_speech(bc->capability) &&
04350               misdn_inband_avail(bc)
04351             ) {
04352             start_bc_tones(ch);
04353          }
04354          
04355          ch->state=MISDN_PROGRESS;
04356 
04357          if (!ch->ast) break;
04358          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04359       }
04360       break;
04361       
04362       
04363    case EVENT_ALERTING:
04364    {
04365       if (bc->channel) 
04366          update_name(ch->ast,bc->port,bc->channel);
04367 
04368       ch->state = MISDN_ALERTING;
04369       
04370       if (!ch->ast) break;
04371 
04372       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04373       ast_setstate(ch->ast, AST_STATE_RINGING);
04374       
04375       cb_log(7,bc->port," --> Set State Ringing\n");
04376       
04377       if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04378          cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
04379          start_bc_tones(ch);
04380       } else {
04381          cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
04382          if (ch->far_alerting) {
04383             cb_log(1,bc->port," --> The other end can not do ringing eh ?.. we must do all ourself..");
04384             start_bc_tones(ch);
04385             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04386          }
04387       }
04388    }
04389    break;
04390    case EVENT_CONNECT:
04391    {
04392       /*we answer when we've got our very new L3 ID from the NT stack */
04393       misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
04394 
04395       if (!ch->ast) break;
04396 
04397       struct ast_channel *bridged=ast_bridged_channel(ch->ast);
04398       stop_indicate(ch);
04399 
04400       if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
04401          struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
04402 
04403          chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
04404          if (bridged_ch) {
04405             bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
04406             ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
04407          }
04408       }
04409    }
04410    
04411    /* notice that we don't break here!*/
04412    case EVENT_CONNECT_ACKNOWLEDGE:
04413    {
04414       ch->l3id=bc->l3_id;
04415       ch->addr=bc->addr;
04416       
04417       start_bc_tones(ch);
04418       
04419       ch->state = MISDN_CONNECTED;
04420       
04421       if (!ch->ast) break;
04422 
04423       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04424    }
04425    break;
04426    case EVENT_DISCONNECT:
04427    /*we might not have an ch->ast ptr here anymore*/
04428    if (ch) {
04429       struct chan_list *holded_ch=find_holded(cl_te, bc);
04430       
04431       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);
04432       if ( ch->originator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04433          /* If there's inband information available (e.g. a
04434             recorded message saying what was wrong with the
04435             dialled number, or perhaps even giving an
04436             alternative number, then play it instead of
04437             immediately releasing the call */
04438          chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04439       
04440          ch->state=MISDN_DISCONNECTED;
04441          start_bc_tones(ch);
04442 
04443          if (ch->ast) {
04444             ch->ast->hangupcause=bc->cause;
04445             if (bc->cause == 17)
04446                ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04447          }
04448          ch->need_busy=0;
04449          break;
04450       }
04451       
04452       /*Check for holded channel, to implement transfer*/
04453       if (  holded_ch && 
04454          holded_ch != ch && 
04455          ch->ast && 
04456          ch->state == MISDN_CONNECTED  ) {
04457          cb_log(1,bc->port," --> found holded ch\n");
04458          misdn_transfer_bc(ch, holded_ch) ;
04459       }
04460 
04461       bc->need_disconnect=0;
04462       
04463       stop_bc_tones(ch);
04464       hangup_chan(ch);
04465    } else {
04466    /* ch=find_holded_l3(cl_te, bc->l3_id,1);
04467       if (ch) {
04468          hangup_chan(ch);
04469       }
04470    */
04471    }
04472    bc->out_cause=-1;
04473    if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
04474    break;
04475    
04476    case EVENT_RELEASE:
04477       {
04478          bc->need_disconnect=0;
04479          bc->need_release=0;
04480 
04481          hangup_chan(ch);
04482          release_chan(bc);
04483       
04484          if (bc->need_release_complete) 
04485             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04486       }
04487       break;
04488    case EVENT_RELEASE_COMPLETE:
04489    {
04490       bc->need_disconnect=0;
04491       bc->need_release=0;
04492       bc->need_release_complete=0;
04493 
04494       stop_bc_tones(ch);
04495       hangup_chan(ch);
04496 
04497       if(ch)   
04498          ch->state=MISDN_CLEANING;
04499 
04500       release_chan(bc);
04501    }
04502    break;
04503    case EVENT_BCHAN_ERROR:
04504    case EVENT_CLEANUP:
04505    {
04506       stop_bc_tones(ch);
04507       
04508       switch(ch->state) {
04509          case MISDN_CALLING:
04510             bc->cause=27; /* Destination out of order */
04511          break;
04512          default:
04513          break;
04514       }
04515       
04516       hangup_chan(ch);
04517       release_chan(bc);
04518    }
04519    break;
04520 
04521    case EVENT_TONE_GENERATE:
04522    {
04523       int tone_len=bc->tone_cnt;
04524       struct ast_channel *ast=ch->ast;
04525       void *tmp;
04526       int res;
04527       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04528 
04529       chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
04530 
04531       if (!ast) break;
04532 
04533       if (!ast->generator) break;
04534    
04535       
04536    
04537       tmp = ast->generatordata;
04538       ast->generatordata = NULL;
04539       generate = ast->generator->generate;
04540 
04541       if (tone_len <0 || tone_len > 512 ) {
04542          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
04543          tone_len=128;
04544       }
04545 
04546       res = generate(ast, tmp, tone_len, tone_len);
04547       ast->generatordata = tmp;
04548       
04549       if (res) {
04550          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04551          ast_deactivate_generator(ast);
04552       } else {
04553          bc->tone_cnt=0;
04554       }
04555    }
04556    break;
04557       
04558    case EVENT_BCHAN_DATA:
04559    {
04560       if ( !misdn_cap_is_speech(ch->bc->capability) ) {
04561          struct ast_frame frame;
04562          /*In Data Modes we queue frames*/
04563          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
04564          frame.subclass = AST_FORMAT_ALAW;
04565          frame.datalen = bc->bframe_len;
04566          frame.samples = bc->bframe_len ;
04567          frame.mallocd =0 ;
04568          frame.offset= 0 ;
04569          frame.delivery= ast_tv(0,0) ;
04570          frame.src = NULL;
04571          frame.data = bc->bframe ;
04572          
04573          if (ch->ast) 
04574             ast_queue_frame(ch->ast,&frame);
04575       } else {
04576          fd_set wrfs;
04577          struct timeval tv;
04578          tv.tv_sec=0;
04579          tv.tv_usec=0;
04580          
04581          
04582          FD_ZERO(&wrfs);
04583          FD_SET(ch->pipe[1],&wrfs);
04584          
04585          int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
04586 
04587          if (!t) {
04588             chan_misdn_log(9, bc->port, "Select Timed out\n");
04589             break;
04590          }
04591          
04592          if (t<0) {
04593             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
04594             break;
04595          }
04596          
04597          if (FD_ISSET(ch->pipe[1],&wrfs)) {
04598             chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
04599             int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
04600             
04601             if (ret<=0) {
04602                chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno));
04603 
04604                stop_bc_tones(ch);
04605                hangup_chan(ch);
04606                release_chan(bc);
04607             }
04608          } else {
04609             chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
04610          }
04611       }
04612    }
04613    break;
04614    case EVENT_TIMEOUT:
04615       {
04616       if (ch && bc)
04617          chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
04618 
04619       switch (ch->state) {
04620          case MISDN_DIALING:
04621          case MISDN_PROGRESS:
04622             if (bc->nt && !ch->nttimeout) break;
04623          
04624          case MISDN_CALLING:
04625          case MISDN_ALERTING:
04626          case MISDN_PROCEEDING:
04627          case MISDN_CALLING_ACKNOWLEDGE:
04628             if (bc->nt) {
04629                bc->progress_indicator=8;
04630                hanguptone_indicate(ch);
04631             }
04632             
04633             bc->out_cause=1;
04634             misdn_lib_send_event(bc,EVENT_DISCONNECT);
04635          break;
04636 
04637          case MISDN_WAITING4DIGS:
04638             if (bc->nt) {
04639                bc->progress_indicator=8;
04640                bc->out_cause=1;
04641                hanguptone_indicate(ch);
04642                misdn_lib_send_event(bc,EVENT_DISCONNECT);
04643             } else {
04644                bc->out_cause=16;
04645                misdn_lib_send_event(bc,EVENT_RELEASE);
04646             }
04647             
04648          break;
04649 
04650 
04651          case MISDN_CLEANING: 
04652             chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
04653          break;
04654 
04655          default:
04656             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04657          }
04658       }
04659       break;
04660 
04661     
04662    /***************************/
04663    /** Suplementary Services **/
04664    /***************************/
04665    case EVENT_RETRIEVE:
04666    {
04667       if (!ch) {
04668          chan_misdn_log(4, bc->port, " --> no CH, searching in holded");
04669          ch=find_holded_l3(cl_te, bc->l3_id,1);
04670       }
04671 
04672       if (!ch) {
04673          ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
04674          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04675          break;
04676       }
04677 
04678       /*remember the channel again*/
04679       ch->bc=bc;
04680       ch->state = MISDN_CONNECTED;
04681 
04682       ch->hold_info.port=0;
04683       ch->hold_info.channel=0;
04684       
04685       struct ast_channel *hold_ast=ast_bridged_channel(ch->ast);
04686       
04687       if (hold_ast) {
04688          ast_moh_stop(hold_ast);
04689       }
04690    
04691       if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
04692          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04693    }
04694    break;
04695     
04696    case EVENT_HOLD:
04697    {
04698       int hold_allowed;
04699       misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04700       
04701       if (!hold_allowed) {
04702 
04703          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04704          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04705          break;
04706       }
04707       
04708       struct ast_channel *bridged=ast_bridged_channel(ch->ast);
04709 
04710       if (bridged) {
04711          chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
04712          ch->state = MISDN_HOLDED;
04713          ch->l3id = bc->l3_id;
04714          
04715          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04716 
04717          /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
04718           * instead of starting moh on the bridged channel directly */
04719          ast_moh_start(bridged, NULL, NULL);
04720 
04721          /*forget the channel now*/
04722          ch->bc=NULL;
04723          ch->hold_info.port=bc->port;
04724          ch->hold_info.channel=bc->channel;
04725 
04726       } else {
04727          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04728          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04729       }
04730    } 
04731    break;
04732    
04733    case EVENT_FACILITY:
04734       if (!ch) {
04735          /* This may come from a call we don't know nothing about, so we ignore it. */
04736          chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
04737          break;
04738       }
04739 
04740       print_facility(&(bc->fac_in), bc);
04741       
04742       switch (bc->fac_in.Function) {
04743       case Fac_CD:
04744          {
04745             struct ast_channel *bridged=ast_bridged_channel(ch->ast);
04746             struct chan_list *ch_br;
04747             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04748                ch_br=MISDN_ASTERISK_TECH_PVT(bridged);
04749                /*ch->state=MISDN_FACILITY_DEFLECTED;*/
04750                if (ch_br->bc) {
04751                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
04752                      ch_br->state=MISDN_DIALING;
04753                      if (pbx_start_chan(ch_br) < 0) {
04754                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
04755                      }
04756                   }
04757                }
04758 
04759             }
04760             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04761          } 
04762          break;
04763       case Fac_AOCDCurrency:
04764          bc->AOCDtype = Fac_AOCDCurrency;
04765          memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
04766          export_aoc_vars(ch->originator, ch->ast, bc);
04767          break;
04768       case Fac_AOCDChargingUnit:
04769          bc->AOCDtype = Fac_AOCDChargingUnit;
04770          memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
04771          export_aoc_vars(ch->originator, ch->ast, bc);
04772          break;
04773       default:
04774          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%p\n", bc->fac_in.Function);
04775       }
04776       
04777       break;
04778 
04779    case EVENT_RESTART:
04780 
04781       stop_bc_tones(ch);
04782       release_chan(bc);
04783       
04784       break;
04785             
04786    default:
04787       chan_misdn_log(1,0, "Got Unknown Event\n");
04788       break;
04789    }
04790    
04791    return RESPONSE_OK;
04792 }

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

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

05325 {
05326    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
05327    
05328    if (ch && ch->jb) {
05329       return misdn_jb_empty(ch->jb, buf, len);
05330    }
05331    
05332    return -1;
05333 }

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

Definition at line 5509 of file chan_misdn.c.

References ast_console_puts(), ast_log(), ast_strlen_zero(), global_tracefile, 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(), stop_indicate(), update_config(), and update_name().

05510 {
05511    if (! ((0 <= port) && (port <= max_ports))) {
05512       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05513       port=0;
05514       level=-1;
05515    }
05516       
05517    va_list ap;
05518    char buf[1024];
05519    char port_buf[8];
05520    sprintf(port_buf,"P[%2d] ",port);
05521    
05522    va_start(ap, tmpl);
05523    vsnprintf( buf, 1023, tmpl, ap );
05524    va_end(ap);
05525 
05526    if (level == -1)
05527       ast_log(LOG_WARNING, buf);
05528 
05529    else if (misdn_debug_only[port] ? 
05530          (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) 
05531        : level <= misdn_debug[port]) {
05532       
05533       ast_console_puts(port_buf);
05534       ast_console_puts(buf);
05535    }
05536    
05537    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05538       time_t tm = time(NULL);
05539       char *tmp=ctime(&tm),*p;
05540       
05541       FILE *fp= fopen(global_tracefile, "a+");
05542       
05543       p=strchr(tmp,'\n');
05544       if (p) *p=':';
05545       
05546       if (!fp) {
05547          ast_console_puts("Error opening Tracefile: [ ");
05548          ast_console_puts(global_tracefile);
05549          ast_console_puts(" ] ");
05550          
05551          ast_console_puts(strerror(errno));
05552          ast_console_puts("\n");
05553          return ;
05554       }
05555       
05556       fputs(tmp,fp);
05557       fputs(" ", fp);
05558       fputs(port_buf,fp);
05559       fputs(" ", fp);
05560       fputs(buf, fp);
05561 
05562       fclose(fp);
05563    }
05564 }

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

Definition at line 3389 of file chan_misdn.c.

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

Referenced by misdn_hangup(), and release_chan().

03390 {
03391    if (chan->dsp) 
03392       ast_dsp_free(chan->dsp);
03393    if (chan->trans)
03394       ast_translator_free_path(chan->trans);
03395 
03396    
03397 
03398    ast_mutex_lock(&cl_te_lock);
03399    if (!*list) {
03400       ast_mutex_unlock(&cl_te_lock);
03401       return;
03402    }
03403   
03404    if (*list == chan) {
03405       *list=(*list)->next;
03406       ast_mutex_unlock(&cl_te_lock);
03407       return ;
03408    }
03409   
03410    {
03411       struct chan_list *help=*list;
03412       for (;help->next; help=help->next) {
03413          if (help->next == chan) {
03414             help->next=help->next->next;
03415             ast_mutex_unlock(&cl_te_lock);
03416             return;
03417          }
03418       }
03419    }
03420    
03421    ast_mutex_unlock(&cl_te_lock);
03422 }

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

Definition at line 3373 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_request().

03374 {
03375    chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
03376   
03377    ast_mutex_lock(&cl_te_lock);
03378    if (!*list) {
03379       *list = chan;
03380    } else {
03381       struct chan_list *help=*list;
03382       for (;help->next; help=help->next); 
03383       help->next=chan;
03384    }
03385    chan->next=NULL;
03386    ast_mutex_unlock(&cl_te_lock);
03387 }

static char* complete_ch ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 1412 of file chan_misdn.c.

References complete_ch_helper().

01413 {
01414    return complete_ch_helper(line, word, pos, state, 3);
01415 }

static char* complete_ch_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos 
) [static]

Definition at line 1388 of file chan_misdn.c.

References ast_channel_walk_locked(), ast_mutex_unlock(), ast_channel::lock, and strdup.

Referenced by complete_ch().

01389 {
01390    struct ast_channel *c;
01391    int which=0;
01392    char *ret;
01393    if (pos != rpos)
01394       return NULL;
01395    c = ast_channel_walk_locked(NULL);
01396    while(c) {
01397       if (!strncasecmp(word, c->name, strlen(word))) {
01398          if (++which > state)
01399             break;
01400       }
01401       ast_mutex_unlock(&c->lock);
01402       c = ast_channel_walk_locked(c);
01403    }
01404    if (c) {
01405       ret = strdup(c->name);
01406       ast_mutex_unlock(&c->lock);
01407    } else
01408       ret = NULL;
01409    return ret;
01410 }

static char* complete_debug_port ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 1417 of file chan_misdn.c.

References strdup.

01418 {
01419    if (state)
01420       return NULL;
01421 
01422    switch (pos) {
01423    case 4: if (*word == 'p')
01424             return strdup("port");
01425          else if (*word == 'o')
01426             return strdup("only");
01427          break;
01428    case 6: if (*word == 'o')
01429             return strdup("only");
01430          break;
01431    }
01432    return NULL;
01433 }

static char* complete_show_config ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 1435 of file chan_misdn.c.

References BUFFERSIZE, MISDN_CFG_FIRST, misdn_cfg_get_name(), misdn_cfg_get_next_port(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, and strdup.

01436 {
01437    char buffer[BUFFERSIZE];
01438    enum misdn_cfg_elements elem;
01439    int wordlen = strlen(word);
01440    int which = 0;
01441    int port = 0;
01442 
01443    switch (pos) {
01444    case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
01445             return strdup("description");
01446          if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
01447             return strdup("descriptions");
01448          if ((!strncmp(word, "0", wordlen)) && (++which > state))
01449             return strdup("0");
01450          while ((port = misdn_cfg_get_next_port(port)) != -1) {
01451             snprintf(buffer, sizeof(buffer), "%d", port);
01452             if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
01453                return strdup(buffer);
01454             }
01455          }
01456          break;
01457    case 4:
01458          if (strstr(line, "description ")) {
01459             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01460                if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
01461                   continue;
01462                misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
01463                if (!wordlen || !strncmp(word, buffer, wordlen)) {
01464                   if (++which > state)
01465                      return strdup(buffer);
01466                }
01467             }
01468          } else if (strstr(line, "descriptions ")) {
01469             if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
01470                return strdup("general");
01471             if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
01472                return strdup("ports");
01473          }
01474          break;
01475    }
01476    return NULL;
01477 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

01631 {
01632    struct misdn_bchannel *bc=ch->bc;
01633    int len=ch->jb_len, threshold=ch->jb_upper_threshold;
01634    
01635    chan_misdn_log(5,bc->port, "config_jb: Called\n");
01636    
01637    if ( ! len ) {
01638       chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
01639       bc->nojitter=1;
01640    } else {
01641       
01642       if (len <=100 || len > 8000) {
01643          chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
01644          len=1000;
01645       }
01646       
01647       if ( threshold > len ) {
01648          chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
01649       }
01650       
01651       if ( ch->jb) {
01652          cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
01653          misdn_jb_destroy(ch->jb);
01654          ch->jb=NULL;
01655       }
01656       
01657       ch->jb=misdn_jb_init(len, threshold);
01658 
01659       if (!ch->jb ) 
01660          bc->nojitter=1;
01661    }
01662 }

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

Definition at line 1665 of file chan_misdn.c.

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

Referenced by read_config().

01666 {
01667    switch (numplan) {
01668    case NUMPLAN_INTERNATIONAL:
01669       chan_misdn_log(2, port, " --> %s: International\n",type);
01670       break;
01671    case NUMPLAN_NATIONAL:
01672       chan_misdn_log(2, port, " --> %s: National\n",type);
01673       break;
01674    case NUMPLAN_SUBSCRIBER:
01675       chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
01676       break;
01677    case NUMPLAN_UNKNOWN:
01678       chan_misdn_log(2, port, " --> %s: Unknown\n",type);
01679       break;
01680       /* Maybe we should cut off the prefix if present ? */
01681    default:
01682       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01683       break;
01684    }
01685 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

Definition at line 2890 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, misdn_lib_tone_generator_start(), chan_list::norxtone, chan_list::notxtone, misdn_bchannel::port, chan_list::ts, and ast_channel::zone.

Referenced by do_immediate_setup().

02891 {
02892    const struct tone_zone_sound *ts= NULL;
02893    struct ast_channel *ast=cl->ast;
02894 
02895    if (!ast) {
02896       chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
02897       return -1;
02898    }
02899 
02900    int nd=0;
02901    misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
02902 
02903    if (nd) {
02904       chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
02905       return 0;
02906    }
02907    
02908    chan_misdn_log(3,cl->bc->port," --> Dial\n");
02909    ts=ast_get_indication_tone(ast->zone,"dial");
02910    cl->ts=ts;  
02911    
02912    if (ts) {
02913       cl->notxtone=0;
02914       cl->norxtone=0;
02915       ast_playtones_start(ast,0, ts->data, 0);
02916       chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
02917       misdn_lib_tone_generator_start(cl->bc);
02918    }
02919 
02920    return 0;
02921 }

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

Definition at line 3558 of file chan_misdn.c.

References chan_list::ast, AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_frame::data, ast_frame::datalen, ast_frame::delivery, dialtone_indicate(), EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_RELEASE_COMPLETE, EVENT_SETUP_ACKNOWLEDGE, ast_channel::exten, ast_frame::frametype, hangup_chan(), hanguptone_indicate(), chan_list::incoming_early_audio, 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, ORG_MISDN, chan_list::originator, pbx_start_chan(), misdn_bchannel::port, ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

03559 {
03560    char predial[256]="";
03561    char *p = predial;
03562   
03563    struct ast_frame fr;
03564   
03565    strncpy(predial, ast->exten, sizeof(predial) -1 );
03566   
03567    ch->state=MISDN_DIALING;
03568 
03569    if (!ch->noautorespond_on_setup) {
03570       if (bc->nt) {
03571          int ret; 
03572          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03573       } else {
03574          int ret;
03575          if ( misdn_lib_is_ptp(bc->port)) {
03576             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03577          } else {
03578             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03579          }
03580       }
03581    } else {
03582       ch->state = MISDN_INCOMING_SETUP;
03583    }
03584 
03585    if ( !bc->nt && (ch->originator==ORG_MISDN) && !ch->incoming_early_audio ) 
03586       chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
03587     else  
03588       dialtone_indicate(ch);
03589   
03590    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);
03591   
03592    strncpy(ast->exten,"s", 2);
03593   
03594    if (pbx_start_chan(ch)<0) {
03595       ast=NULL;
03596       hangup_chan(ch);
03597       hanguptone_indicate(ch);
03598 
03599       if (bc->nt)
03600          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03601       else
03602          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03603    }
03604   
03605   
03606    while (!ast_strlen_zero(p) ) {
03607       fr.frametype = AST_FRAME_DTMF;
03608       fr.subclass = *p ;
03609       fr.src=NULL;
03610       fr.data = NULL ;
03611       fr.datalen = 0;
03612       fr.samples = 0 ;
03613       fr.mallocd =0 ;
03614       fr.offset= 0 ;
03615       fr.delivery= ast_tv(0,0) ;
03616 
03617       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03618          ast_queue_frame(ch->ast, &fr);
03619       }
03620       p++;
03621    }
03622 }

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

Definition at line 491 of file chan_misdn.c.

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

00492 {
00493    char buf[128];
00494 
00495    if (!ast)
00496       return;
00497 
00498    if (originator == ORG_AST) {
00499       ast = ast_bridged_channel(ast);
00500       if (!ast)
00501          return;
00502    }
00503 
00504    switch (bc->AOCDtype) {
00505    case Fac_AOCDCurrency:
00506       pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
00507       if (bc->AOCD.currency.chargeNotAvailable)
00508          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00509       else {
00510          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00511          if (bc->AOCD.currency.freeOfCharge)
00512             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00513          else {
00514             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00515             if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
00516                pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
00517                if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
00518                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00519             }
00520          }
00521       }
00522       break;
00523    case Fac_AOCDChargingUnit:
00524       pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
00525       if (bc->AOCD.chargingUnit.chargeNotAvailable)
00526          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00527       else {
00528          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00529          if (bc->AOCD.chargingUnit.freeOfCharge)
00530             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00531          else {
00532             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00533             if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
00534                pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
00535                if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
00536                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00537             }
00538          }
00539       }
00540       break;
00541    default:
00542       break;
00543    }
00544 }

void export_ch ( struct ast_channel chan,
struct misdn_bchannel bc,
struct chan_list ch 
)

Definition at line 3718 of file chan_misdn.c.

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

03719 {
03720    char tmp[32];
03721    chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
03722    sprintf(tmp,"%d",bc->pid);
03723    pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
03724 
03725    if (bc->sending_complete) {
03726       sprintf(tmp,"%d",bc->sending_complete);
03727       pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
03728    }
03729 
03730    if (bc->urate) {
03731       sprintf(tmp,"%d",bc->urate);
03732       pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp);
03733    }
03734 
03735    if (bc->uulen) {
03736       pbx_builtin_setvar_helper(chan,"MISDN_USERUSER",bc->uu);
03737    }
03738 
03739    if (bc->keypad[0]) 
03740       pbx_builtin_setvar_helper(chan,"MISDN_KEYPAD",bc->keypad);
03741 }

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

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

03318 {
03319    struct chan_list *help=list;
03320    for (;help; help=help->next) {
03321       if (help->bc == bc) return help;
03322    }
03323   
03324    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03325   
03326    return NULL;
03327 }

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

Definition at line 3329 of file chan_misdn.c.

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

Referenced by import_ch().

03330 {
03331    struct chan_list *help=list;
03332    for (;help; help=help->next) {
03333       if ( help->bc && (help->bc->pid == pid) ) return help;
03334    }
03335   
03336    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
03337   
03338    return NULL;
03339 }

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

Definition at line 3341 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, and chan_list::state.

Referenced by cb_events().

03342 {
03343    struct chan_list *help=list;
03344    
03345    chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
03346    for (;help; help=help->next) {
03347       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel);
03348       if (  (help->state == MISDN_HOLDED) && 
03349          (help->hold_info.port == bc->port) ) 
03350          return help;
03351    }  
03352    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03353   
03354    return NULL;
03355 }

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

Definition at line 3358 of file chan_misdn.c.

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

03360 {
03361    struct chan_list *help=list;
03362 
03363    for (;help; help=help->next) {
03364       if ( (help->state == MISDN_HOLDED) &&
03365           (help->l3id == l3_id)   
03366          ) 
03367          return help;
03368    }
03369 
03370    return NULL;
03371 }

static void free_robin_list ( void   )  [static]

Definition at line 252 of file chan_misdn.c.

References free_robin_list_r(), and robin.

Referenced by reload_config(), and unload_module().

00253 {
00254    free_robin_list_r(robin);
00255    robin = NULL;
00256 }

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

Definition at line 243 of file chan_misdn.c.

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

Referenced by free_robin_list().

00244 {
00245         if (r) {
00246                 if (r->next) free_robin_list_r(r->next);
00247                 if (r->group) free(r->group);
00248                 free(r);
00249         }
00250 }

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

Definition at line 367 of file chan_misdn.c.

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

Referenced by misdn_bridge().

00368 {
00369    struct chan_list *tmp;
00370   
00371    for (tmp=cl_te; tmp; tmp = tmp->next) {
00372       if ( tmp->ast == ast ) return tmp;
00373    }
00374   
00375    return NULL;
00376 }

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

Definition at line 378 of file chan_misdn.c.

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

Referenced by misdn_send_cd(), misdn_send_digit(), misdn_send_display(), and misdn_toggle_echocancel().

00379 {
00380    struct chan_list *tmp;
00381   
00382    for (tmp=cl_te; tmp; tmp = tmp->next) {
00383       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
00384    }
00385   
00386    return NULL;
00387 }

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

Definition at line 258 of file chan_misdn.c.

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

Referenced by misdn_request().

00259 {
00260    struct robin_list *iter = robin;
00261    for (; iter; iter = iter->next) {
00262       if (!strcasecmp(iter->group, group))
00263          return iter;
00264    }
00265    struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
00266    new->group = strndup(group, strlen(group));
00267    new->channel = 1;
00268    if (robin) {
00269       new->next = robin;
00270       robin->prev = new;
00271    }
00272    robin = new;
00273    return robin;
00274 }

static void hangup_chan ( struct chan_list ch  )  [static]

Definition at line 3439 of file chan_misdn.c.

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

Referenced by cb_events(), and do_immediate_setup().

03440 {
03441    int port=ch?ch->bc?ch->bc->port:0:0;
03442    if (!ch) {
03443       cb_log(1,0,"Cannot hangup chan, no ch\n");
03444       return;
03445    }
03446 
03447    cb_log(5,port,"hangup_chan called\n");
03448 
03449    if (ch->need_hangup) 
03450    {
03451       cb_log(2,port," --> hangup\n");
03452       send_cause2ast(ch->ast,ch->bc,ch);
03453       ch->need_hangup=0;
03454       ch->need_queue_hangup=0;
03455       if (ch->ast)
03456          ast_hangup(ch->ast);
03457       return;
03458    }
03459 
03460    if (!ch->need_queue_hangup) {
03461       cb_log(2,port," --> No need to queue hangup\n");
03462    }
03463 
03464    ch->need_queue_hangup=0;
03465    if (ch->ast) {
03466       send_cause2ast(ch->ast,ch->bc,ch);
03467 
03468       if (ch->ast)
03469          ast_queue_hangup(ch->ast);
03470       cb_log(2,port," --> queue_hangup\n");
03471    } else {
03472       cb_log(1,port,"Cannot hangup chan, no ast\n");
03473    }
03474 }

static int hanguptone_indicate ( struct chan_list cl  )  [static]

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

02924 {
02925    misdn_lib_send_tone(cl->bc,TONE_HANGUP);
02926    return 0;
02927 }

void import_ch ( struct ast_channel chan,
struct misdn_bchannel bc,
struct chan_list ch 
)

Definition at line 3684 of file chan_misdn.c.

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

03685 {
03686    const char *tmp;
03687    tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
03688    if (tmp) {
03689       ch->other_pid=atoi(tmp);
03690       chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp);
03691       if (ch->other_pid >0) {
03692          ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
03693          if (ch->other_ch) ch->other_ch->other_ch=ch;
03694       }
03695    }
03696 
03697    tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
03698    if (tmp && (atoi(tmp) == 1)) {
03699       bc->sending_complete=1;
03700    }
03701    
03702    tmp=pbx_builtin_getvar_helper(chan,"MISDN_USERUSER");
03703    if (tmp) {
03704       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
03705       strcpy(bc->uu, tmp);
03706       bc->uulen=strlen(bc->uu);
03707    }
03708 
03709    tmp=pbx_builtin_getvar_helper(chan,"MISDN_KEYPAD");
03710    if (tmp) {
03711       strncpy(bc->keypad,tmp,sizeof(bc->keypad));
03712       bc->keypad[sizeof(bc->keypad)-1]=0;
03713    }
03714    
03715    
03716 }

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

Definition at line 2966 of file chan_misdn.c.

References chan_misdn_log(), malloc, chan_list::need_busy, chan_list::need_hangup, chan_list::need_queue_hangup, chan_list::originator, and chan_list::overlap_dial_task.

Referenced by cb_events(), and misdn_request().

02967 {
02968    struct chan_list *cl=malloc(sizeof(struct chan_list));
02969    
02970    if (!cl) {
02971       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
02972       return NULL;
02973    }
02974    
02975    memset(cl,0,sizeof(struct chan_list));
02976 
02977    cl->originator=orig;
02978    cl->need_queue_hangup=1;
02979    cl->need_hangup=1;
02980    cl->need_busy=1;
02981    cl->overlap_dial_task=-1;
02982    
02983    return cl;
02984    
02985 }

static int load_module ( void   )  [static]

Definition at line 4837 of file chan_misdn.c.

References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init(), ast_register_application(), BUFFERSIZE, calloc, misdn_lib_iface::cb_event, cb_events(), chan_misdn_clis, chan_misdn_jb_empty(), chan_misdn_log(), cl_te_lock, g_config_initialized, global_tracefile, LOG_ERROR, malloc, 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_TRACEFILE, misdn_in_calls, misdn_l1_task(), misdn_lib_init(), misdn_lib_maxports_get(), misdn_lib_nt_debug_init(), misdn_out_calls, misdn_ports, misdn_set_opt_exec(), misdn_tasks_add(), misdn_tech, misdn_type, tracing, and unload_module().

04838 {
04839    int i, port;
04840    
04841    char ports[256]="";
04842 
04843    max_ports=misdn_lib_maxports_get();
04844    
04845    if (max_ports<=0) {
04846       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
04847       return AST_MODULE_LOAD_DECLINE;
04848    }
04849    
04850    if (misdn_cfg_init(max_ports)) {
04851       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
04852       return AST_MODULE_LOAD_DECLINE;
04853    }
04854    g_config_initialized=1;
04855    
04856    misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
04857    misdn_ports = (int *)malloc(sizeof(int) * (max_ports+1));
04858    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
04859    for (i = 1; i <= max_ports; i++) {
04860       misdn_debug[i] = misdn_debug[0];
04861       misdn_ports[i] = i;
04862    }
04863    *misdn_ports = 0;
04864    misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
04865 
04866    {
04867       char tempbuf[BUFFERSIZE+1];
04868       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
04869       if (strlen(tempbuf))
04870          tracing = 1;
04871    }
04872    
04873    misdn_in_calls = (int *)malloc(sizeof(int) * (max_ports+1));
04874    misdn_out_calls = (int *)malloc(sizeof(int) * (max_ports+1));
04875 
04876    for (i=1; i <= max_ports; i++) {
04877       misdn_in_calls[i]=0;
04878       misdn_out_calls[i]=0;
04879    }
04880    
04881    ast_mutex_init(&cl_te_lock);
04882 
04883    misdn_cfg_update_ptp();
04884    misdn_cfg_get_ports_string(ports);
04885 
04886    if (strlen(ports))
04887       chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
04888    
04889    {
04890       struct misdn_lib_iface iface = {
04891          .cb_event = cb_events,
04892          .cb_log = chan_misdn_log,
04893          .cb_jb_empty = chan_misdn_jb_empty,
04894       };
04895       
04896       if (misdn_lib_init(ports, &iface, NULL))
04897          chan_misdn_log(0, 0, "No te ports initialized\n");
04898    
04899       int ntflags=0;
04900       char ntfile[BUFFERSIZE+1];
04901 
04902       misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
04903       misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
04904 
04905       misdn_lib_nt_debug_init(ntflags,ntfile);
04906 
04907    }
04908 
04909    {
04910       if (ast_channel_register(&misdn_tech)) {
04911          ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
04912          unload_module();
04913          return -1;
04914       }
04915    }
04916   
04917    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
04918   
04919    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
04920              "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
04921              "Sets mISDN opts. and optargs\n"
04922              "\n"
04923              "The available options are:\n"
04924              "    d - Send display text on called phone, text is the optparam\n"
04925              "    n - don't detect dtmf tones on called channel\n"
04926              "    h - make digital outgoing call\n" 
04927              "    c - make crypted outgoing call, param is keyindex\n"
04928              "    e - perform echo cancelation on this channel,\n"
04929              "        takes taps as arguments (32,64,128,256)\n"
04930              "    s - send Non Inband DTMF as inband\n"
04931              "   vr - rxgain control\n"
04932              "   vt - txgain control\n"
04933       );
04934 
04935    
04936    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
04937              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
04938              "Sends the Facility Message FACILITY_TYPE with \n"
04939              "the given Arguments to the current ISDN Channel\n"
04940              "Supported Facilities are:\n"
04941              "\n"
04942              "type=calldeflect args=Nr where to deflect\n"
04943       );
04944 
04945 
04946    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
04947              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
04948              "Checks if the L2 and L1 are up on either the given <port> or\n"
04949              "on the ports in the group with <groupname>\n"
04950              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
04951              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
04952              "\n"
04953              "This application, ensures the L1/L2 state of the Ports in a group\n"
04954              "it is intended to make the pmp_l1_check option redundant and to\n"
04955              "fix a buggy switch config from your provider\n"
04956              "\n"
04957              "a sample dialplan would look like:\n\n"
04958              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
04959              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
04960              "\n"
04961       );
04962 
04963 
04964    misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
04965 
04966    /* start the l1 watchers */
04967    
04968    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
04969       int l1timeout;
04970       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
04971       if (l1timeout) {
04972          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
04973          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
04974       }
04975    }
04976    
04977    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
04978 
04979    return 0;
04980 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2119 of file chan_misdn.c.

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

02120 {
02121    struct chan_list *p;
02122 
02123    
02124    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02125    
02126    chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
02127    
02128    if (!p) {
02129       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02130       ast_queue_hangup(ast);
02131    }
02132 
02133    if (!p->bc) {
02134       chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
02135 
02136       ast_queue_hangup(ast);
02137    }
02138 
02139    {
02140       const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
02141       
02142       if (tmp_key ) {
02143          chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02144          {
02145             int l = sizeof(p->bc->crypt_key);
02146             strncpy(p->bc->crypt_key,tmp_key, l);
02147             p->bc->crypt_key[l-1] = 0;
02148          }
02149       } else {
02150          chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02151       }
02152     
02153    }
02154 
02155    {
02156       const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02157       if (nodsp) {
02158          chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02159          p->bc->nodsp=1;
02160          p->bc->hdlc=0;
02161          p->bc->nojitter=1;
02162       }
02163    }
02164    
02165    p->state = MISDN_CONNECTED;
02166    stop_indicate(p);
02167 
02168    if ( ast_strlen_zero(p->bc->cad) ) {
02169       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
02170       ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
02171    }
02172 
02173    misdn_lib_send_event( p->bc, EVENT_CONNECT);
02174    start_bc_tones(p);
02175    
02176    return 0;
02177 }

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_read(), ast_verbose(), 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_get(), MISDN_GEN_BRIDGING, misdn_lib_bridge(), misdn_lib_split_bridge(), misdn_bchannel::oad, option_verbose, misdn_bchannel::pid, misdn_bchannel::port, and VERBOSE_PREFIX_3.

02796 {
02797    struct chan_list *ch1,*ch2;
02798    struct ast_channel *carr[2], *who;
02799    int to=-1;
02800    struct ast_frame *f;
02801   
02802    ch1=get_chan_by_ast(c0);
02803    ch2=get_chan_by_ast(c1);
02804 
02805    carr[0]=c0;
02806    carr[1]=c1;
02807   
02808    if (ch1 && ch2 ) ;
02809    else
02810       return -1;
02811 
02812    int bridging;
02813    misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02814    if (bridging) {
02815       /* trying to make a mISDN_dsp conference */
02816       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
02817       misdn_lib_bridge(ch1->bc,ch2->bc);
02818    }
02819    
02820    if (option_verbose > 2) 
02821       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
02822 
02823    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
02824  
02825    if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
02826       ch1->ignore_dtmf=1;
02827 
02828    if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
02829       ch2->ignore_dtmf=1;
02830 
02831    while(1) {
02832       to=-1;
02833       who = ast_waitfor_n(carr, 2, &to);
02834 
02835       if (!who) {
02836          ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
02837          break;
02838       }
02839       f = ast_read(who);
02840     
02841       if (!f || f->frametype == AST_FRAME_CONTROL) {
02842          /* got hangup .. */
02843 
02844          if (!f) 
02845             chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
02846          else
02847             chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
02848          
02849          *fo=f;
02850          *rc=who;
02851       
02852          break;
02853       }
02854       
02855       if ( f->frametype == AST_FRAME_DTMF ) {
02856          chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
02857 
02858          *fo=f;
02859          *rc=who;
02860          break;
02861       }
02862    
02863 #if 0
02864       if (f->frametype == AST_FRAME_VOICE) {
02865          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
02866    
02867          continue;
02868       }
02869 #endif
02870 
02871       if (who == c0) {
02872          ast_write(c1,f);
02873       }
02874       else {
02875          ast_write(c0,f);
02876       }
02877     
02878    }
02879    
02880    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
02881    
02882    misdn_lib_split_bridge(ch1->bc,ch2->bc);
02883    
02884    
02885    return AST_BRIDGE_COMPLETE;
02886 }

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

Definition at line 1962 of file chan_misdn.c.

References ast_channel::_state, add_out_calls(), chan_list::ast, ast_log(), ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), 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(), 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, chan_list::state, stop_bc_tones(), strsep(), ast_channel::transfercapability, and update_config().

01963 {
01964    int port=0;
01965    int r;
01966    struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01967    struct misdn_bchannel *newbc;
01968    char *opts=NULL, *ext;
01969    char dest_cp[256];
01970 
01971    {
01972       strncpy(dest_cp,dest,sizeof(dest_cp)-1);
01973       dest_cp[sizeof(dest_cp)]=0;
01974 
01975       ext=dest_cp;
01976       strsep(&ext,"/");
01977       if (ext) {
01978          opts=ext;
01979          strsep(&opts,"/");
01980       }  else {
01981          ast_log(LOG_WARNING, "Malformed dialstring\n");
01982          return -1;
01983       }
01984    }
01985 
01986    if (!ast) {
01987       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
01988       return -1;
01989    }
01990 
01991    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
01992       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01993       ast->hangupcause=41;
01994       ast_setstate(ast, AST_STATE_DOWN);
01995       return -1;
01996    }
01997 
01998    if (!ch) {
01999       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02000       ast->hangupcause=41;
02001       ast_setstate(ast, AST_STATE_DOWN);
02002       return -1;
02003    }
02004    
02005    newbc=ch->bc;
02006    
02007    if (!newbc) {
02008       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02009       ast->hangupcause=41;
02010       ast_setstate(ast, AST_STATE_DOWN);
02011       return -1;
02012    }
02013    
02014    port=newbc->port;
02015 
02016 
02017    int exceed;
02018    if ((exceed=add_out_calls(port))) {
02019       char tmp[16];
02020       sprintf(tmp,"%d",exceed);
02021       pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
02022       return -1;
02023    }
02024    
02025    chan_misdn_log(1, port, "* CALL: %s\n",dest);
02026    
02027    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
02028    
02029    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
02030    if (ast->exten) {
02031       int l = sizeof(newbc->dad);
02032       strncpy(ast->exten,ext,sizeof(ast->exten));
02033 
02034       strncpy(newbc->dad,ext,l);
02035 
02036       newbc->dad[l-1] = 0;
02037    }
02038 
02039    if (ast->cid.cid_rdnis)  
02040       strcpy(newbc->rad, ast->cid.cid_rdnis);
02041    else 
02042       newbc->rad[0]=0;
02043 
02044    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",ast->cid.cid_num);
02045    if (ast_strlen_zero(newbc->oad) && ast->cid.cid_num ) {
02046 
02047       if (ast->cid.cid_num) {
02048          int l = sizeof(newbc->oad);
02049          strncpy(newbc->oad,ast->cid.cid_num, l);
02050          newbc->oad[l-1] = 0;
02051       }
02052    }
02053 
02054    {
02055       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
02056       if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
02057       
02058       newbc->capability=ast->transfercapability;
02059       pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
02060       if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
02061          chan_misdn_log(2, port, " --> * Call with flag Digital\n");
02062       }
02063       
02064 
02065       /* update screening and presentation */ 
02066       update_config(ch,ORG_AST);
02067       
02068       /* fill in some ies from channel vary*/
02069       import_ch(ast, newbc, ch);
02070       
02071       /* Finally The Options Override Everything */
02072       if (opts)
02073          misdn_set_opt_exec(ast,opts);
02074       else
02075          chan_misdn_log(2,port,"NO OPTS GIVEN\n");
02076 
02077       /*check for bridging*/
02078       int bridging;
02079       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02080       if (bridging && ch->other_ch) {
02081 #ifdef MISDN_1_2
02082          chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
02083          *ch->bc->pipeline=0;
02084          *ch->other_ch->bc->pipeline=0;
02085 #else
02086          chan_misdn_log(1, port, "Disabling EC on both Sides\n");
02087          ch->bc->ec_enable=0;
02088          ch->other_ch->bc->ec_enable=0;
02089 #endif
02090       }
02091       
02092       r=misdn_lib_send_event( newbc, EVENT_SETUP );
02093       
02094       /** we should have l3id after sending setup **/
02095       ch->l3id=newbc->l3_id;
02096    }
02097    
02098    if ( r == -ENOCHAN  ) {
02099       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
02100       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
02101       ast->hangupcause=34;
02102       ast_setstate(ast, AST_STATE_DOWN);
02103       return -1;
02104    }
02105    
02106    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
02107 
02108    ast_setstate(ast, AST_STATE_DIALING);
02109    ast->hangupcause=16;
02110    
02111    if (newbc->nt) stop_bc_tones(ch);
02112 
02113    ch->state=MISDN_CALLING;
02114 
02115    return 0; 
02116 }

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

Definition at line 5039 of file chan_misdn.c.

References AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), BUFFERSIZE, chan_misdn_log(), group, LOG_WARNING, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_CFG_GROUPNAME, misdn_lib_get_port_up(), misdn_lib_port_up(), ast_channel::tech, timeout, and ast_channel_tech::type.

Referenced by load_module().

05040 {
05041    if (strcasecmp(chan->tech->type,"mISDN")) {
05042       ast_log(LOG_WARNING, "misdn_check_l2l1 makes only sense with chan_misdn channels!\n");
05043       return -1;
05044    }
05045 
05046    AST_DECLARE_APP_ARGS(args,
05047          AST_APP_ARG(grouppar);
05048          AST_APP_ARG(timeout);
05049    );
05050 
05051    if (ast_strlen_zero((char *)data)) {
05052       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05053       return -1;
05054    }
05055 
05056    AST_STANDARD_APP_ARGS(args, data);
05057 
05058    if (args.argc != 2) {
05059       ast_log(LOG_WARNING, "Wrong argument count\n");
05060       return 0;
05061    }
05062 
05063    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05064    char group[BUFFERSIZE+1];
05065    char *port_str;
05066 
05067    int port=0;
05068    int timeout=atoi(args.timeout);
05069    int dowait=0;
05070 
05071    port_str=args.grouppar;
05072 
05073    int port_up;
05074    if (port_str[0]=='g' && port_str[1]==':' ) {
05075       /* We make a group call lets checkout which ports are in my group */
05076       port_str += 2;
05077       strncpy(group, port_str, BUFFERSIZE);
05078       group[BUFFERSIZE-1] = 0;
05079       chan_misdn_log(2, 0, "Checking Ports in group: %s\n",group);
05080 
05081       for ( port = misdn_cfg_get_next_port(port); 
05082          port > 0;
05083          port = misdn_cfg_get_next_port(port)) {
05084          
05085          chan_misdn_log(2,0,"trying port %d\n",port);
05086 
05087          char cfg_group[BUFFERSIZE+1];
05088          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05089 
05090          if (!strcasecmp(cfg_group, group)) {
05091             port_up = misdn_lib_port_up(port, 1);
05092 
05093             if (!port_up) {
05094                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05095                misdn_lib_get_port_up(port);
05096                dowait=1;
05097             }
05098          }
05099       }
05100 
05101    } else {
05102       port = atoi(port_str);
05103       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05104       port_up = misdn_lib_port_up(port, 1);
05105       if (!port_up) {
05106          misdn_lib_get_port_up(port);
05107          dowait=1;
05108       }
05109 
05110    }
05111 
05112    if (dowait) {
05113       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n",timeout);
05114       sleep(timeout);
05115    }
05116 
05117    return 0;
05118 }

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

Definition at line 2179 of file chan_misdn.c.

02180 {
02181    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02182    return 0;
02183 }

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

Definition at line 2185 of file chan_misdn.c.

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

02186 {
02187    struct chan_list *p;
02188    
02189    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02190 
02191    struct misdn_bchannel *bc=p->bc;
02192    chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
02193    
02194    if (!bc) {
02195       ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
02196       return -1;
02197    }
02198    
02199    switch (p->state ) {
02200       case MISDN_CALLING:
02201       {
02202          
02203          char buf[8];
02204          buf[0]=digit;
02205          buf[1]=0;
02206          
02207          int l = sizeof(bc->infos_pending);
02208          strncat(bc->infos_pending,buf,l);
02209          bc->infos_pending[l-1] = 0;
02210       }
02211       break;
02212       case MISDN_CALLING_ACKNOWLEDGE:
02213       {
02214          bc->info_dad[0]=digit;
02215          bc->info_dad[1]=0;
02216          
02217          {
02218             int l = sizeof(bc->dad);
02219             strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
02220             bc->dad[l-1] = 0;
02221       }
02222          {
02223             int l = sizeof(p->ast->exten);
02224             strncpy(p->ast->exten, bc->dad, l);
02225             p->ast->exten[l-1] = 0;
02226          }
02227          
02228          misdn_lib_send_event( bc, EVENT_INFORMATION);
02229       }
02230       break;
02231       
02232       default:
02233          if ( bc->send_dtmf ) {
02234             send_digit_to_chan(p,digit);
02235          }
02236       break;
02237    }
02238    
02239    return 0;
02240 }

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

Definition at line 4993 of file chan_misdn.c.

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

Referenced by load_module().

04994 {
04995    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
04996    char *tok, *tokb;
04997 
04998    chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
04999    
05000    if (strcasecmp(chan->tech->type,"mISDN")) {
05001       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05002       return -1;
05003    }
05004    
05005    if (ast_strlen_zero((char *)data)) {
05006       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05007       return -1;
05008    }
05009    
05010    tok=strtok_r((char*)data,"|", &tokb) ;
05011    
05012    if (!tok) {
05013       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05014       return -1;
05015    }
05016    
05017    if (!strcasecmp(tok,"calldeflect")) {
05018       tok=strtok_r(NULL,"|", &tokb) ;
05019       
05020       if (!tok) {
05021          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05022       }
05023    
05024       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05025          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05026          return 0; 
05027       }
05028       ch->bc->fac_out.Function = Fac_CD;
05029       strncpy((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05030       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05031    } else {
05032       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n",tok);
05033    }
05034    
05035    return 0;
05036    
05037 }

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

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

02244 {
02245    struct chan_list *p;
02246    
02247    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02248    
02249    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);
02250    
02251    p->ast = ast ;
02252   
02253    return 0;
02254 }

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

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

01025 {
01026    int i;
01027    static char state[8];
01028    
01029    if( !p) return NULL;
01030   
01031    for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
01032       if ( state_array[i].state == p->state) return state_array[i].txt; 
01033    }
01034 
01035    sprintf(state,"%d",p->state) ;
01036 
01037    return state;
01038 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2390 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, ast_log(), 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, free, ast_channel::hangupcause, hanguptone_indicate(), chan_list::l3id, LOG_DEBUG, 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, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, 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, start_bc_tones(), chan_list::state, and stop_bc_tones().

02391 {
02392    struct chan_list *p;
02393    struct misdn_bchannel *bc=NULL;
02394    
02395    ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
02396    
02397    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
02398    
02399    if (!p) {
02400       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
02401       return 0 ;
02402    }
02403    
02404    bc=p->bc;
02405 
02406    MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02407    p->ast=NULL;
02408 
02409    if (ast->_state == AST_STATE_RESERVED || 
02410       p->state == MISDN_NOTHING || 
02411       p->state == MISDN_HOLDED || 
02412       p->state == MISDN_HOLD_DISCONNECT ) {
02413 
02414       CLEAN_CH:
02415       /* between request and call */
02416       ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
02417       MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02418       
02419       cl_dequeue_chan(&cl_te, p);
02420       close(p->pipe[0]);
02421       close(p->pipe[1]);
02422       free(p);
02423       
02424       if (bc)
02425          misdn_lib_release(bc);
02426       
02427       return 0;
02428    }
02429 
02430    if (!bc) {
02431       ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02432       goto CLEAN_CH;
02433    }
02434 
02435 
02436    p->need_hangup=0;
02437    p->need_queue_hangup=0;
02438    p->need_busy=0;
02439 
02440 
02441    if (!p->bc->nt) 
02442       stop_bc_tones(p);
02443 
02444    
02445    {
02446       const char *varcause=NULL;
02447       bc->out_cause=ast->hangupcause?ast->hangupcause:16;
02448       
02449       if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02450            (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02451          int tmpcause=atoi(varcause);
02452          bc->out_cause=tmpcause?tmpcause:16;
02453       }
02454     
02455       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));
02456       chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
02457       chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
02458       chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
02459       chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02460       
02461       switch (p->state) {
02462       case MISDN_INCOMING_SETUP:
02463       case MISDN_CALLING:
02464          p->state=MISDN_CLEANING;
02465          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02466          break;
02467       case MISDN_HOLDED:
02468       case MISDN_DIALING:
02469          start_bc_tones(p);
02470          hanguptone_indicate(p);
02471       
02472          if (bc->need_disconnect)
02473             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02474          break;
02475 
02476       case MISDN_CALLING_ACKNOWLEDGE:
02477          start_bc_tones(p);
02478          hanguptone_indicate(p);
02479       
02480          if (bc->need_disconnect)
02481             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02482          break;
02483       
02484       case MISDN_ALERTING:
02485       case MISDN_PROGRESS:
02486       case MISDN_PROCEEDING:
02487          if (p->originator != ORG_AST) 
02488             hanguptone_indicate(p);
02489       
02490          /*p->state=MISDN_CLEANING;*/
02491          if (bc->need_disconnect)
02492             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02493          break;
02494       case MISDN_CONNECTED:
02495       case MISDN_PRECONNECTED:
02496          /*  Alerting or Disconect */
02497          if (p->bc->nt) {
02498             start_bc_tones(p);
02499             hanguptone_indicate(p);
02500             p->bc->progress_indicator=8;
02501          }
02502          if (bc->need_disconnect)
02503             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02504 
02505          /*p->state=MISDN_CLEANING;*/
02506          break;
02507       case MISDN_DISCONNECTED:
02508          misdn_lib_send_event( bc, EVENT_RELEASE);
02509          p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
02510          break;
02511 
02512       case MISDN_RELEASED:
02513       case MISDN_CLEANING:
02514          p->state=MISDN_CLEANING;
02515          break;
02516 
02517       case MISDN_BUSY:
02518          break;
02519       
02520       case MISDN_HOLD_DISCONNECT:
02521          /* need to send release here */
02522          chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
02523          chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
02524          
02525          bc->out_cause=-1;
02526          misdn_lib_send_event(bc,EVENT_RELEASE);
02527          p->state=MISDN_CLEANING;
02528          break;
02529       default:
02530          if (bc->nt) {
02531             bc->out_cause=-1;
02532             misdn_lib_send_event(bc, EVENT_RELEASE);
02533             p->state=MISDN_CLEANING; 
02534          } else {
02535             if (bc->need_disconnect)
02536                misdn_lib_send_event(bc, EVENT_DISCONNECT);
02537          }
02538       }
02539 
02540       p->state=MISDN_CLEANING;
02541     
02542    }
02543    
02544 
02545    chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
02546    
02547    return 0;
02548 }

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

Definition at line 2258 of file chan_misdn.c.

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

02259 {
02260    struct chan_list *p;
02261 
02262   
02263    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02264       ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
02265       return -1;
02266    }
02267    
02268    if (!p->bc ) {
02269       chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
02270       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02271       return -1;
02272    }
02273    
02274    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
02275    
02276    switch (cond) {
02277    case AST_CONTROL_BUSY:
02278       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
02279       ast_setstate(ast,AST_STATE_BUSY);
02280 
02281       p->bc->out_cause=17;
02282       if (p->state != MISDN_CONNECTED) {
02283          start_bc_tones(p);
02284          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02285       } else {
02286          chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
02287       }
02288       return -1;
02289       break;
02290    case AST_CONTROL_RING:
02291       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
02292       return -1;
02293       break;
02294       
02295    case AST_CONTROL_RINGING:
02296       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
02297       switch (p->state) {
02298          case MISDN_ALERTING:
02299             chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
02300             break;
02301          case MISDN_CONNECTED:
02302             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);
02303             return -1;
02304             break;
02305          default:
02306             p->state=MISDN_ALERTING;
02307             chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
02308             misdn_lib_send_event( p->bc, EVENT_ALERTING);
02309          
02310             if (p->other_ch && p->other_ch->bc) {
02311                if (misdn_inband_avail(p->other_ch->bc)) {
02312                   chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
02313                   break;
02314                }
02315 
02316                if (!p->other_ch->bc->nt) {
02317                   chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02318                   break;
02319                }
02320             }
02321 
02322             chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
02323             ast_setstate(ast,AST_STATE_RINGING);
02324          
02325             if ( !p->bc->nt && (p->originator==ORG_MISDN) && !p->incoming_early_audio ) 
02326                chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
02327             else 
02328                return -1;
02329       }
02330       break;
02331    case AST_CONTROL_ANSWER:
02332       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
02333       start_bc_tones(p);
02334       break;
02335    case AST_CONTROL_TAKEOFFHOOK:
02336       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
02337       return -1;
02338       break;
02339    case AST_CONTROL_OFFHOOK:
02340       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
02341       return -1;
02342       break; 
02343    case AST_CONTROL_FLASH:
02344       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
02345       break;
02346    case AST_CONTROL_PROGRESS:
02347       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
02348       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02349       break;
02350    case AST_CONTROL_PROCEEDING:
02351       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
02352       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02353       break;
02354    case AST_CONTROL_CONGESTION:
02355       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
02356 
02357       p->bc->out_cause=42;
02358       start_bc_tones(p);
02359       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02360 
02361       if (p->bc->nt) {
02362          hanguptone_indicate(p);
02363       }
02364       break;
02365    case -1 :
02366       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
02367       
02368       stop_indicate(p);
02369 
02370       if (p->state == MISDN_CONNECTED) 
02371          start_bc_tones(p);
02372 
02373       break;
02374 
02375    case AST_CONTROL_HOLD:
02376       ast_moh_start(ast,data,ast->musicclass); 
02377       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
02378       break;
02379    case AST_CONTROL_UNHOLD:
02380       ast_moh_stop(ast);
02381       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
02382       break;
02383    default:
02384       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
02385    }
02386   
02387    return 0;
02388 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

Definition at line 5377 of file chan_misdn.c.

References ast_mutex_destroy(), free, misdn_jb::mutexjb, and misdn_jb::samples.

Referenced by config_jitterbuffer(), and release_chan().

05378 {
05379    ast_mutex_destroy(&jb->mutexjb);
05380    
05381    free(jb->samples);
05382    free(jb);
05383 }

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

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

05450 {
05451     int i, wp, rp, read=0;
05452 
05453     ast_mutex_lock (&jb->mutexjb);
05454 
05455     rp=jb->rp;
05456     wp=jb->wp;
05457 
05458     if(jb->state_empty)
05459     { 
05460    for(i=0; i<len; i++)
05461    {
05462        if(wp==rp)
05463        {
05464       jb->rp=rp;
05465       jb->state_empty=0;
05466 
05467       ast_mutex_unlock (&jb->mutexjb);
05468       
05469       return read;
05470        }
05471        else
05472        {
05473       if(jb->ok[rp]==1)
05474       {
05475           data[i]=jb->samples[rp];
05476           jb->ok[rp]=0;
05477           rp=(rp!=jb->size-1 ? rp+1 : 0);
05478           read+=1;
05479       }
05480        }
05481    }
05482 
05483    if(wp >= rp)
05484       jb->state_buffer=wp-rp;
05485    else
05486       jb->state_buffer= jb->size-rp+wp;
05487    chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05488    
05489    jb->rp=rp;
05490     }
05491     else
05492        chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
05493     
05494     ast_mutex_unlock (&jb->mutexjb);
05495 
05496     return read;
05497 }

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

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

05388 {
05389     int i, j, rp, wp;
05390 
05391     if (!jb || ! data) return 0;
05392 
05393     ast_mutex_lock (&jb->mutexjb);
05394     
05395     wp=jb->wp;
05396     rp=jb->rp;
05397    
05398     for(i=0; i<len; i++)
05399     {
05400    jb->samples[wp]=data[i];
05401    jb->ok[wp]=1;
05402    wp = (wp!=jb->size-1 ? wp+1 : 0);
05403 
05404    if(wp==jb->rp)
05405        jb->state_full=1;
05406     }
05407     
05408     if(wp>=rp)
05409       jb->state_buffer=wp-rp;
05410     else
05411       jb->state_buffer= jb->size-rp+wp;
05412     chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05413     
05414     if(jb->state_full)
05415     {
05416    jb->wp=wp;
05417 
05418    rp=wp;
05419    for(j=0; j<jb->upper_threshold; j++)
05420        rp = (rp!=0 ? rp-1 : jb->size-1);
05421    jb->rp=rp;
05422    jb->state_full=0;
05423    jb->state_empty=1;
05424 
05425    ast_mutex_unlock (&jb->mutexjb);
05426    
05427    return -1;
05428     }
05429 
05430     if(!jb->state_empty)
05431     {
05432    jb->bytes_wrote+=len;
05433    if(jb->bytes_wrote>=jb->upper_threshold)
05434    {
05435        jb->state_empty=1;
05436        jb->bytes_wrote=0;
05437    }
05438     }
05439     jb->wp=wp;
05440 
05441     ast_mutex_unlock (&jb->mutexjb);
05442     
05443     return 0;
05444 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

Definition at line 5343 of file chan_misdn.c.

References ast_mutex_init(), misdn_jb::bytes_wrote, chan_misdn_log(), malloc, misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::rp, misdn_jb::samples, misdn_jb::size, misdn_jb::state_empty, misdn_jb::state_full, misdn_jb::upper_threshold, and misdn_jb::wp.

Referenced by config_jitterbuffer().

05344 {
05345     int i;
05346     struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
05347     jb->size = size;
05348     jb->upper_threshold = upper_threshold;
05349     jb->wp = 0;
05350     jb->rp = 0;
05351     jb->state_full = 0;
05352     jb->state_empty = 0;
05353     jb->bytes_wrote = 0;
05354     jb->samples = (char *)malloc(size*sizeof(char));
05355 
05356     if (!jb->samples) {
05357        chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
05358        return NULL;
05359     }
05360     
05361     jb->ok = (char *)malloc(size*sizeof(char));
05362 
05363     if (!jb->ok) {
05364        chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
05365        return NULL;
05366     }
05367 
05368     for(i=0; i<size; i++)
05369    jb->ok[i]=0;
05370 
05371     ast_mutex_init(&jb->mutexjb);
05372 
05373     return jb;
05374 }

static int misdn_l1_task ( void *  data  )  [static]

Definition at line 639 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

00640 {
00641    misdn_lib_isdn_l1watcher(*(int *)data);
00642    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00643    return 1;
00644 }

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

References ast_callerid_parse(), ast_channel_alloc(), AST_STATE_RING, ast_strdup, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, cid_name, ast_callerid::cid_num, cid_num, ast_channel::exten, ast_channel::fds, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_GEN_BRIDGING, 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().

03239 {
03240    struct ast_channel *tmp;
03241    char *cid_name = 0, *cid_num = 0;
03242    int chan_offset=0;
03243    int tmp_port = misdn_cfg_get_next_port(0);
03244 
03245    for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
03246    if (tmp_port == port) break;
03247       chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2; 
03248    }
03249    if (c<0) c=0;
03250 
03251    
03252    if (callerid) 
03253       ast_callerid_parse(callerid, &cid_name, &cid_num);
03254 
03255    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03256    
03257    if (tmp) {
03258       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
03259       
03260       tmp->nativeformats = prefformat;
03261 
03262       tmp->readformat = format;
03263       tmp->rawreadformat = format;
03264       tmp->writeformat = format;
03265       tmp->rawwriteformat = format;
03266     
03267       tmp->tech_pvt = chlist;
03268       
03269       int bridging;
03270       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03271       if (bridging)
03272          tmp->tech = &misdn_tech;
03273       else
03274          tmp->tech = &misdn_tech_wo_bridge;
03275       
03276       tmp->writeformat = format;
03277       tmp->readformat = format;
03278       tmp->priority=1;
03279       
03280       if (exten) 
03281          ast_copy_string(tmp->exten, exten,  sizeof(tmp->exten));
03282       else
03283          chan_misdn_log(1,0,"misdn_new: no exten given.\n");
03284       
03285       if (callerid) {
03286          char *cid_name, *cid_num;
03287       
03288          ast_callerid_parse(callerid, &cid_name, &cid_num);
03289          /* Don't use ast_set_callerid() here because it will
03290           * generate a needless NewCallerID event */
03291          tmp->cid.cid_num = ast_strdup(cid_num);
03292          tmp->cid.cid_ani = ast_strdup(cid_num);
03293          tmp->cid.cid_name = ast_strdup(cid_name);
03294       }
03295 
03296       {
03297          if (pipe(chlist->pipe)<0)
03298             perror("Pipe failed\n");
03299          
03300          tmp->fds[0]=chlist->pipe[0];
03301          
03302       }
03303       
03304       if (state == AST_STATE_RING)
03305          tmp->rings = 1;
03306       else
03307          tmp->rings = 0;
03308       
03309       
03310    } else {
03311       chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
03312    }
03313    
03314    return tmp;
03315 }

static int misdn_overlap_dial_task ( void *  data  )  [static]

Definition at line 646 of file chan_misdn.c.

References chan_list::ast, ast_exists_extension(), ast_mutex_lock(), ast_mutex_unlock(), chan_list::bc, chan_misdn_log(), chan_list::context, misdn_bchannel::dad, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, hanguptone_indicate(), MISDN_DIALING, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::nt, misdn_bchannel::oad, 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().

00647 {
00648    struct timeval tv_end, tv_now;
00649    int diff;
00650    struct chan_list *ch = (struct chan_list *)data;
00651 
00652    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
00653 
00654    if (ch->state != MISDN_WAITING4DIGS) {
00655       ch->overlap_dial_task = -1;
00656       return 0;
00657    }
00658    
00659    ast_mutex_lock(&ch->overlap_tv_lock);
00660    tv_end = ch->overlap_tv;
00661    ast_mutex_unlock(&ch->overlap_tv_lock);
00662    
00663    tv_end.tv_sec += ch->overlap_dial;
00664    tv_now = ast_tvnow();
00665 
00666    diff = ast_tvdiff_ms(tv_end, tv_now);
00667 
00668    if (diff <= 100) {
00669       /* if we are 100ms near the timeout, we are satisfied.. */
00670       stop_indicate(ch);
00671       if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) {
00672          ch->state=MISDN_DIALING;
00673          if (pbx_start_chan(ch) < 0) {
00674             chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
00675             goto misdn_overlap_dial_task_disconnect;
00676          }
00677       } else {
00678 misdn_overlap_dial_task_disconnect:
00679          hanguptone_indicate(ch);
00680          if (ch->bc->nt)
00681             misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE );
00682          else
00683             misdn_lib_send_event(ch->bc, EVENT_RELEASE);
00684       }
00685       ch->overlap_dial_task = -1;
00686       return 0;
00687    } else
00688       return diff;
00689 }

static int misdn_port_block ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 793 of file chan_misdn.c.

References misdn_lib_port_block(), and RESULT_SHOWUSAGE.

00794 {
00795    int port;
00796   
00797    if (argc != 4)
00798       return RESULT_SHOWUSAGE;
00799   
00800    port = atoi(argv[3]);
00801 
00802    misdn_lib_port_block(port);
00803 
00804    return 0;
00805 }

static int misdn_port_down ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 878 of file chan_misdn.c.

References misdn_lib_get_port_down(), and RESULT_SHOWUSAGE.

00879 {
00880    int port;
00881    
00882    if (argc != 4)
00883       return RESULT_SHOWUSAGE;
00884    
00885    port = atoi(argv[3]);
00886    
00887    misdn_lib_get_port_down(port);
00888   
00889    return 0;
00890 }

static int misdn_port_unblock ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 807 of file chan_misdn.c.

References misdn_lib_port_unblock(), and RESULT_SHOWUSAGE.

00808 {
00809    int port;
00810   
00811    if (argc != 4)
00812       return RESULT_SHOWUSAGE;
00813   
00814    port = atoi(argv[3]);
00815 
00816    misdn_lib_port_unblock(port);
00817 
00818    return 0;
00819 }

static int misdn_port_up ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 864 of file chan_misdn.c.

References misdn_lib_get_port_up(), and RESULT_SHOWUSAGE.

00865 {
00866    int port;
00867    
00868    if (argc != 4)
00869       return RESULT_SHOWUSAGE;
00870    
00871    port = atoi(argv[3]);
00872    
00873    misdn_lib_get_port_up(port);
00874   
00875    return 0;
00876 }

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

Definition at line 2621 of file chan_misdn.c.

References chan_list::ast, chan_list::ast_dsp, AST_FORMAT_ALAW, AST_FRAME_VOICE, chan_list::ast_rd_buf, chan_list::bc, chan_misdn_log(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, chan_list::faxdetect, chan_list::faxdetect_timeout, chan_list::faxdetect_tv, chan_list::faxhandled, chan_list::frame, ast_frame::frametype, len, ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, MISDN_HOLDED, ast_frame::offset, chan_list::pipe, misdn_bchannel::port, process_ast_dsp(), ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

02622 {
02623    struct chan_list *tmp;
02624    int len;
02625    
02626    if (!ast) {
02627       chan_misdn_log(1,0,"misdn_read called without ast\n");
02628       return NULL;
02629    }
02630    if (!(tmp=MISDN_ASTERISK_TECH_PVT(ast))) {
02631       chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
02632       return NULL;
02633    }
02634 
02635    if (!tmp->bc && !(tmp->state==MISDN_HOLDED)) {
02636       chan_misdn_log(1,0,"misdn_read called without bc\n");
02637       return NULL;
02638    }
02639 
02640    len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
02641 
02642    if (len<=0) {
02643       /* we hangup here, since our pipe is closed */
02644       chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
02645       return NULL;
02646    }
02647 
02648    tmp->frame.frametype  = AST_FRAME_VOICE;
02649    tmp->frame.subclass = AST_FORMAT_ALAW;
02650    tmp->frame.datalen = len;
02651    tmp->frame.samples = len;
02652    tmp->frame.mallocd = 0;
02653    tmp->frame.offset = 0;
02654    tmp->frame.delivery= ast_tv(0,0) ;
02655    tmp->frame.src = NULL;
02656    tmp->frame.data = tmp->ast_rd_buf;
02657 
02658    if (tmp->faxdetect && !tmp->faxhandled) {
02659       if (tmp->faxdetect_timeout) {
02660          if (ast_tvzero(tmp->faxdetect_tv)) {
02661             tmp->faxdetect_tv = ast_tvnow();
02662             chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
02663             return process_ast_dsp(tmp, &tmp->frame);
02664          } else {
02665             struct timeval tv_now = ast_tvnow();
02666             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
02667             if (diff <= (tmp->faxdetect_timeout * 1000)) {
02668                chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n");
02669                return process_ast_dsp(tmp, &tmp->frame);
02670             } else {
02671                chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n");
02672                tmp->faxdetect = 0;
02673                return &tmp->frame;
02674             }
02675          }
02676       } else {
02677          chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n");
02678          return process_ast_dsp(tmp, &tmp->frame);
02679       }
02680    } else {
02681       if (tmp->ast_dsp)
02682          return process_ast_dsp(tmp, &tmp->frame);
02683       else
02684          return &tmp->frame;
02685    }
02686 }

static int misdn_reload ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1063 of file chan_misdn.c.

References ast_cli(), and reload_config().

01064 {
01065    ast_cli(fd, "Reloading mISDN Config\n");
01066    reload_config();
01067    return 0;
01068 }

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

Definition at line 2987 of file chan_misdn.c.

References chan_list::ast, ast_log(), AST_STATE_RESERVED, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, cl_queue_chan(), cl_te, misdn_bchannel::dec, ext, get_robin_position(), group, init_chan_list(), 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().

02989 {
02990    struct ast_channel *tmp = NULL;
02991    char group[BUFFERSIZE+1]="";
02992    char buf[128];
02993    char buf2[128], *ext=NULL, *port_str;
02994    char *tokb=NULL, *p=NULL;
02995    int channel=0, port=0;
02996    struct misdn_bchannel *newbc = NULL;
02997    int dec=0;
02998    
02999    struct chan_list *cl=init_chan_list(ORG_AST);
03000    
03001    sprintf(buf,"%s/%s",misdn_type,(char*)data);
03002    ast_copy_string(buf2,data, 128);
03003    
03004    port_str=strtok_r(buf2,"/", &tokb);
03005 
03006    ext=strtok_r(NULL,"/", &tokb);
03007 
03008    if (port_str) {
03009       if (port_str[0]=='g' && port_str[1]==':' ) {
03010          /* We make a group call lets checkout which ports are in my group */
03011          port_str += 2;
03012          strncpy(group, port_str, BUFFERSIZE);
03013          group[127] = 0;
03014          chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
03015       } 
03016       else if ((p = strchr(port_str, ':'))) {
03017          /* we have a preselected channel */
03018          *p = 0;
03019          channel = atoi(++p);
03020          port = atoi(port_str);
03021          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03022       }
03023       else {
03024          port = atoi(port_str);
03025       }
03026    } else {
03027       ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
03028       return NULL;
03029    }
03030 
03031    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03032       chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
03033       dec=1;
03034    }
03035 
03036    if (!ast_strlen_zero(group)) {
03037    
03038       char cfg_group[BUFFERSIZE+1];
03039       struct robin_list *rr = NULL;
03040 
03041       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03042          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03043          rr = get_robin_position(group);
03044       }
03045       
03046          
03047       if (rr) {
03048          int robin_channel = rr->channel;
03049          int port_start;
03050          int next_chan = 1;
03051 
03052          do {
03053             port_start = 0;
03054             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
03055                 port = misdn_cfg_get_next_port_spin(port)) {
03056 
03057                if (!port_start)
03058                   port_start = port;
03059 
03060                if (port >= port_start)
03061                   next_chan = 1;
03062                
03063                if (port <= port_start && next_chan) {
03064                   int maxbchans=misdn_lib_get_maxchans(port);
03065                   if (++robin_channel >= maxbchans) {
03066                      robin_channel = 1;
03067                   }
03068                   next_chan = 0;
03069                }
03070 
03071                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03072                
03073                if (!strcasecmp(cfg_group, group)) {
03074                   int port_up;
03075                   int check;
03076                   misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03077                   port_up = misdn_lib_port_up(port, check);
03078 
03079                   if (check && !port_up) 
03080                      chan_misdn_log(1,port,"L1 is not Up on this Port\n");
03081                   
03082                   if (check && port_up<0) {
03083                      ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
03084                   }
03085                   
03086                   
03087                   if ( port_up>0 )  {
03088                      newbc = misdn_lib_get_free_bc(port, robin_channel,0, 0);
03089                      if (newbc) {
03090                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03091                         if (port_up)
03092                            chan_misdn_log(4, port, "portup:%d\n",  port_up);
03093                         rr->port = newbc->port;
03094                         rr->channel = newbc->channel;
03095                         break;
03096                      }
03097                   }
03098                }
03099             }
03100          } while (!newbc && robin_channel != rr->channel);
03101          
03102       } else {    
03103          for (port=misdn_cfg_get_next_port(0); port > 0;
03104              port=misdn_cfg_get_next_port(port)) {
03105             
03106             misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03107 
03108             chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
03109             if (!strcasecmp(cfg_group, group)) {
03110                int port_up;
03111                int check;
03112                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03113                port_up = misdn_lib_port_up(port, check);
03114                
03115                chan_misdn_log(4, port, "portup:%d\n", port_up);
03116                
03117                if ( port_up>0 ) {
03118                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03119                   if (newbc)
03120                      break;
03121                }
03122             }
03123          }
03124       }
03125       
03126       /* Group dial failed ?*/
03127       if (!newbc) {
03128          ast_log(LOG_WARNING, 
03129                "Could not Dial out on group '%s'.\n"
03130                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03131                "\tOr there was no free channel on none of the ports\n\n"
03132                , group);
03133          return NULL;
03134       }
03135    } else { /* 'Normal' Port dial * Port dial */
03136       if (channel)
03137          chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
03138       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03139 
03140       if (!newbc) {
03141          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n",port,ext);
03142          return NULL;
03143       }
03144    }
03145    
03146 
03147    /* create ast_channel and link all the objects together */
03148    cl->bc=newbc;
03149    
03150    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03151    cl->ast=tmp;
03152    
03153    /* register chan in local list */
03154    cl_queue_chan(&cl_te, cl) ;
03155    
03156    /* fill in the config into the objects */
03157    read_config(cl, ORG_AST);
03158 
03159    /* important */
03160    cl->need_hangup=0;
03161    
03162    return tmp;
03163 }

static int misdn_restart_pid ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 836 of file chan_misdn.c.

References misdn_lib_pid_restart(), and RESULT_SHOWUSAGE.

00837 {
00838    int pid;
00839   
00840    if (argc != 4)
00841       return RESULT_SHOWUSAGE;
00842   
00843    pid = atoi(argv[3]);
00844 
00845    misdn_lib_pid_restart(pid);
00846 
00847    return 0;
00848 }

static int misdn_restart_port ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 822 of file chan_misdn.c.

References misdn_lib_port_restart(), and RESULT_SHOWUSAGE.

00823 {
00824    int port;
00825   
00826    if (argc != 4)
00827       return RESULT_SHOWUSAGE;
00828   
00829    port = atoi(argv[3]);
00830 
00831    misdn_lib_port_restart(port);
00832 
00833    return 0;
00834 }

static int misdn_send_cd ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1250 of file chan_misdn.c.

References ast_cli(), chan_list::bc, EVENT_FACILITY, misdn_bchannel::fac_out, get_chan_by_ast_name(), misdn_lib_send_event(), and RESULT_SHOWUSAGE.

01251 {
01252    char *channame; 
01253    char *nr; 
01254   
01255    if (argc != 5)
01256       return RESULT_SHOWUSAGE;
01257   
01258    channame = argv[3];
01259    nr = argv[4];
01260 
01261    ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
01262    
01263    {
01264       struct chan_list *tmp=get_chan_by_ast_name(channame);
01265       
01266       if (!tmp) {
01267          ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
01268          return 0; 
01269       } else {
01270          if (strlen(nr) >= 15) {
01271             ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
01272             return 0; 
01273          }
01274          tmp->bc->fac_out.Function = Fac_CD;
01275          strncpy((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
01276          misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
01277       }
01278    }
01279   
01280    return 0; 
01281 }

static int misdn_send_digit ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1283 of file chan_misdn.c.

References chan_list::ast, ast_cli(), ast_dtmf_stream(), get_chan_by_ast_name(), RESULT_SHOWUSAGE, and send_digit_to_chan().

01284 {
01285    char *channame; 
01286    char *msg; 
01287   
01288    if (argc != 5)
01289       return RESULT_SHOWUSAGE;
01290   
01291    channame = argv[3];
01292    msg = argv[4];
01293 
01294    ast_cli(fd, "Sending %s to %s\n",msg, channame);
01295   
01296    {
01297       struct chan_list *tmp=get_chan_by_ast_name(channame);
01298     
01299       if (!tmp) {
01300          ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
01301          return 0; 
01302       } else {
01303 #if 1
01304          int i;
01305          int msglen = strlen(msg);
01306          for (i=0; i<msglen; i++) {
01307             ast_cli(fd, "Sending: %c\n",msg[i]);
01308             send_digit_to_chan(tmp, msg[i]);
01309             /* res = ast_safe_sleep(tmp->ast, 250); */
01310             usleep(250000);
01311             /* res = ast_waitfor(tmp->ast,100); */
01312          }
01313 #else
01314          int res;
01315          res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
01316 #endif
01317       }
01318    }
01319   
01320    return 0; 
01321 }

static int misdn_send_display ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1360 of file chan_misdn.c.

References ast_cli(), chan_list::bc, misdn_bchannel::display, EVENT_INFORMATION, get_chan_by_ast_name(), misdn_lib_send_event(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01361 {
01362    char *channame; 
01363    char *msg; 
01364   
01365    if (argc != 5)
01366       return RESULT_SHOWUSAGE;
01367   
01368    channame = argv[3];
01369    msg = argv[4];
01370 
01371    ast_cli(fd, "Sending %s to %s\n",msg, channame);
01372    {
01373       struct chan_list *tmp;
01374       tmp=get_chan_by_ast_name(channame);
01375     
01376       if (tmp && tmp->bc) {
01377          ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01378          misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01379       } else {
01380          ast_cli(fd,"No such channel %s\n",channame);
01381          return RESULT_FAILURE;
01382       }
01383    }
01384 
01385    return RESULT_SUCCESS ;
01386 }

static int misdn_send_restart ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 850 of file chan_misdn.c.

References misdn_lib_send_restart(), and RESULT_SHOWUSAGE.

00851 {
00852    int port;
00853    
00854    if (argc != 4)
00855       return RESULT_SHOWUSAGE;
00856  
00857    port = atoi(argv[3]);
00858  
00859    misdn_lib_send_restart(port);
00860    
00861    return 0;
00862 }

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

Definition at line 3166 of file chan_misdn.c.

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

03167 {
03168    struct chan_list *tmp=chan->tech_pvt;
03169    
03170    if (tmp && tmp->bc) {
03171       ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
03172       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03173    } else {
03174       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03175       return -1;
03176    }
03177    
03178    return 0;
03179 }

static int misdn_set_crypt_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 785 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

00786 {
00787    if (argc != 5) return RESULT_SHOWUSAGE; 
00788 
00789    return 0;
00790 }

static int misdn_set_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 728 of file chan_misdn.c.

References ast_cli(), and RESULT_SHOWUSAGE.

00729 {
00730    if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
00731       return RESULT_SHOWUSAGE; 
00732 
00733    int level = atoi(argv[3]);
00734 
00735    switch (argc) {
00736       case 4:  
00737       case 5: {
00738                int only = 0;
00739                if (argc == 5) {
00740                   if (strncasecmp(argv[4], "only", strlen(argv[4])))
00741                      return RESULT_SHOWUSAGE;
00742                   else
00743                      only = 1;
00744                }
00745                int i;
00746                for (i=0; i<=max_ports; i++) {
00747                   misdn_debug[i] = level;
00748                   misdn_debug_only[i] = only;
00749                }
00750                ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00751             }
00752             break;
00753       case 6: 
00754       case 7: {
00755                if (strncasecmp(argv[4], "port", strlen(argv[4])))
00756                   return RESULT_SHOWUSAGE;
00757                int port = atoi(argv[5]);
00758                if (port <= 0 || port > max_ports) {
00759                   switch (max_ports) {
00760                      case 0:
00761                         ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00762                         break;
00763                      case 1:
00764                         ast_cli(fd, "port number not valid! only port 1 is availble.\n");
00765                         break;
00766                      default:
00767                         ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00768                      }
00769                      return 0;
00770                }
00771                if (argc == 7) {
00772                   if (strncasecmp(argv[6], "only", strlen(argv[6])))
00773                      return RESULT_SHOWUSAGE;
00774                   else
00775                      misdn_debug_only[port] = 1;
00776                } else
00777                   misdn_debug_only[port] = 0;
00778                misdn_debug[port] = level;
00779                ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
00780             }
00781    }
00782    return 0;
00783 }

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

Definition at line 5120 of file chan_misdn.c.

References chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, key(), keys, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_GEN_CRYPT_KEYS, misdn_lib_setup_bc(), misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_bchannel::orig, chan_list::originator, 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().

05121 {
05122    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05123    char *tok,*tokb;
05124    int  keyidx=0;
05125    int rxgain=0;
05126    int txgain=0;
05127    int change_jitter=0;
05128    
05129    if (strcasecmp(chan->tech->type,"mISDN")) {
05130       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05131       return -1;
05132    }
05133    
05134    if (ast_strlen_zero((char *)data)) {
05135       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05136       return -1;
05137    }
05138 
05139    for (tok=strtok_r((char*)data, ":",&tokb);
05140         tok;
05141         tok=strtok_r(NULL,":",&tokb) ) {
05142       int neglect=0;
05143       
05144       if (tok[0] == '!' ) {
05145          neglect=1;
05146          tok++;
05147       }
05148       
05149       switch(tok[0]) {
05150          
05151       case 'd' :
05152          ast_copy_string(ch->bc->display,++tok,84);
05153          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
05154          break;
05155          
05156       case 'n':
05157          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05158          ch->bc->nodsp=1;
05159          break;
05160 
05161       case 'j':
05162          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05163          tok++;
05164          change_jitter=1;
05165          
05166          switch ( tok[0] ) {
05167          case 'b' :
05168             ch->jb_len=atoi(++tok);
05169             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
05170             break;
05171          case 't' :
05172             ch->jb_upper_threshold=atoi(++tok);
05173             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
05174             break;
05175 
05176          case 'n':
05177             ch->bc->nojitter=1;
05178             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05179             break;
05180             
05181          default:
05182             ch->jb_len=4000;
05183             ch->jb_upper_threshold=0;
05184             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
05185             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
05186          }
05187          
05188          break;
05189       
05190       case 'v':
05191          tok++;
05192 
05193          switch ( tok[0] ) {
05194          case 'r' :
05195             rxgain=atoi(++tok);
05196             if (rxgain<-8) rxgain=-8;
05197             if (rxgain>8) rxgain=8;
05198             ch->bc->rxgain=rxgain;
05199             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
05200             break;
05201          case 't':
05202             txgain=atoi(++tok);
05203             if (txgain<-8) txgain=-8;
05204             if (txgain>8) txgain=8;
05205             ch->bc->txgain=txgain;
05206             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
05207             break;
05208          }
05209          break;
05210       
05211       case 'c':
05212          keyidx=atoi(++tok);
05213       
05214          char keys[4096];
05215          char *key=NULL, *tmp;
05216          int i;
05217          misdn_cfg_get( 0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05218 
05219          tmp=keys;
05220 
05221          for (i=0; i<keyidx; i++) {
05222             key=strsep(&tmp,",");
05223          }
05224 
05225          if (key) {
05226             ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05227          }
05228          
05229          chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",ch->bc->crypt_key);
05230          break;
05231 
05232       case 'e':
05233          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05234          
05235          if (neglect) {
05236             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05237 #ifdef MISDN_1_2
05238             *ch->bc->pipeline=0;
05239 #else
05240             ch->bc->ec_enable=0;
05241 #endif
05242          } else {
05243 #ifdef MISDN_1_2
05244             update_pipeline_config(ch->bc);
05245 #else
05246             ch->bc->ec_enable=1;
05247             ch->bc->orig=ch->originator;
05248             tok++;
05249             if (*tok) {
05250                ch->bc->ec_deftaps=atoi(tok);
05251             }
05252 #endif
05253          }
05254          
05255          break;
05256       
05257       case 'h':
05258          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05259          
05260          if (strlen(tok) > 1 && tok[1]=='1') {
05261             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05262             if (!ch->bc->hdlc) {
05263                ch->bc->hdlc=1;
05264                misdn_lib_setup_bc(ch->bc);
05265             }
05266          }  
05267          ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05268          break;
05269             
05270       case 's':
05271          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05272          ch->bc->send_dtmf=1;
05273          break;
05274          
05275       case 'f':
05276          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05277          ch->faxdetect=1;
05278          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05279          break;
05280 
05281       case 'a':
05282          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05283          ch->ast_dsp=1;
05284          break;
05285 
05286       case 'p':
05287          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
05288          /* CRICH: callingpres!!! */
05289          if (strstr(tok,"allowed") ) {
05290             ch->bc->pres=0;
05291          } else if (strstr(tok,"not_screened")) {
05292             ch->bc->pres=1;
05293          }
05294          
05295          
05296          break;
05297       
05298       
05299       default:
05300          break;
05301       }
05302    }
05303 
05304    if (change_jitter)
05305       config_jitterbuffer(ch);
05306    
05307    
05308    if (ch->faxdetect || ch->ast_dsp) {
05309       if (!ch->dsp) ch->dsp = ast_dsp_new();
05310       if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
05311       if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05312    }
05313 
05314    if (ch->ast_dsp) {
05315       chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05316       ch->bc->nodsp=1;
05317       ch->bc->nojitter=1;
05318    }
05319    
05320    return 0;
05321 }

static int misdn_set_tics ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1187 of file chan_misdn.c.

References MAXTICS, and RESULT_SHOWUSAGE.

01188 {
01189    if (argc != 4)
01190       return RESULT_SHOWUSAGE;
01191   
01192    MAXTICS=atoi(argv[3]);
01193   
01194    return 0;
01195 }

static int misdn_show_cl ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1161 of file chan_misdn.c.

References chan_list::ast, chan_list::bc, cl_te, chan_list::next, print_bc_info(), and RESULT_SHOWUSAGE.

01162 {
01163    struct chan_list *help=cl_te;
01164 
01165    if (argc != 4)
01166       return RESULT_SHOWUSAGE;
01167   
01168    for (;help; help=help->next) {
01169       struct misdn_bchannel *bc=help->bc;   
01170       struct ast_channel *ast=help->ast;
01171     
01172       if (bc && ast) {
01173          if (!strcasecmp(ast->name,argv[3])) {
01174             print_bc_info(fd, help, bc);
01175             break; 
01176          }
01177       } 
01178    }
01179   
01180   
01181    return 0;
01182 }

static int misdn_show_cls ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1125 of file chan_misdn.c.

References chan_list::ast, ast_cli(), chan_list::bc, hold_info::channel, ast_channel::cid, ast_callerid::cid_num, cl_te, ast_channel::exten, chan_list::hold_info, chan_list::l3id, MISDN_HOLDED, chan_list::next, hold_info::port, print_bc_info(), and chan_list::state.

01126 {
01127    struct chan_list *help=cl_te;
01128   
01129    ast_cli(fd,"Chan List: %p\n",cl_te); 
01130   
01131    for (;help; help=help->next) {
01132       struct misdn_bchannel *bc=help->bc;   
01133       struct ast_channel *ast=help->ast;
01134       if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
01135       if (bc) {
01136          print_bc_info(fd, help, bc);
01137       } else {
01138          if (help->state == MISDN_HOLDED) {
01139             ast_cli(fd, "ITS A HOLDED BC:\n");
01140             ast_cli(fd, " --> l3_id: %x\n"
01141                   " --> dad:%s oad:%s\n"
01142                   " --> hold_port: %d\n"
01143                   " --> hold_channel: %d\n"
01144             
01145                   ,help->l3id
01146                   ,ast->exten
01147                   ,ast->cid.cid_num
01148                   ,help->hold_info.port
01149                   ,help->hold_info.channel
01150                   );
01151          } else {
01152             ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
01153          }
01154       }
01155    }
01156   
01157   
01158    return 0;
01159 }

static int misdn_show_config ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 915 of file chan_misdn.c.

References ast_cli(), BUFFERSIZE, MISDN_CFG_FIRST, misdn_cfg_get_config_string(), misdn_cfg_get_elem(), misdn_cfg_get_next_port(), misdn_cfg_is_port_valid(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, RESULT_SHOWUSAGE, and show_config_description().

00916 {
00917    char buffer[BUFFERSIZE];
00918    enum misdn_cfg_elements elem;
00919    int linebreak;
00920    int onlyport = -1;
00921    int ok = 0;
00922 
00923    if (argc >= 4) {
00924       if (!strcmp(argv[3], "description")) {
00925          if (argc == 5) {
00926             enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]);
00927             if (elem == MISDN_CFG_FIRST)
00928                ast_cli(fd, "Unknown element: %s\n", argv[4]);
00929             else
00930                show_config_description(fd, elem);
00931             return 0;
00932          }
00933          return RESULT_SHOWUSAGE;
00934       }
00935       if (!strcmp(argv[3], "descriptions")) {
00936          if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
00937             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
00938                show_config_description(fd, elem);
00939                ast_cli(fd, "\n");
00940             }
00941             ok = 1;
00942          }
00943          if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
00944             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
00945                show_config_description(fd, elem);
00946                ast_cli(fd, "\n");
00947             }
00948             ok = 1;
00949          }
00950          return ok ? 0 : RESULT_SHOWUSAGE;
00951       }
00952       if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
00953          ast_cli(fd, "Unknown option: %s\n", argv[3]);
00954          return RESULT_SHOWUSAGE;
00955       }
00956    }
00957    
00958    if (argc == 3 || onlyport == 0) {
00959       ast_cli(fd,"Misdn General-Config: \n"); 
00960       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
00961          misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
00962          ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00963       }
00964       ast_cli(fd, "\n");
00965    }
00966 
00967    if (onlyport < 0) {
00968       int port = misdn_cfg_get_next_port(0);
00969       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
00970          ast_cli(fd, "\n[PORT %d]\n", port);
00971          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00972             misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
00973             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00974          }  
00975          ast_cli(fd, "\n");
00976       }
00977    }
00978    
00979    if (onlyport > 0) {
00980       if (misdn_cfg_is_port_valid(onlyport)) {
00981          ast_cli(fd, "[PORT %d]\n", onlyport);
00982          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00983             misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
00984             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00985          }  
00986          ast_cli(fd, "\n");
00987       } else {
00988          ast_cli(fd, "Port %d is not active!\n", onlyport);
00989       }
00990    }
00991    return 0;
00992 }

static int misdn_show_port ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1231 of file chan_misdn.c.

References ast_cli(), get_show_stack_details(), misdn_debug, misdn_debug_only, and RESULT_SHOWUSAGE.

01232 {
01233    int port;
01234    
01235    if (argc != 4)
01236       return RESULT_SHOWUSAGE;
01237   
01238    port = atoi(argv[3]);
01239   
01240    ast_cli(fd, "BEGIN STACK_LIST:\n");
01241 
01242    char buf[128];
01243    get_show_stack_details(port,buf);
01244    ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
01245 
01246    
01247    return 0;
01248 }

static int misdn_show_ports_stats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1214 of file chan_misdn.c.

References ast_cli(), misdn_cfg_get_next_port(), misdn_in_calls, and misdn_out_calls.

01215 {
01216    int port;
01217 
01218    ast_cli(fd, "Port\tin_calls\tout_calls\n");
01219    
01220    for (port=misdn_cfg_get_next_port(0); port > 0;
01221         port=misdn_cfg_get_next_port(port)) {
01222       ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]);
01223    }
01224    ast_cli(fd,"\n");
01225    
01226    return 0;
01227 
01228 }

static int misdn_show_stacks ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1197 of file chan_misdn.c.

References ast_cli(), get_show_stack_details(), misdn_cfg_get_next_port(), misdn_debug, and misdn_debug_only.

01198 {
01199    int port;
01200 
01201    ast_cli(fd, "BEGIN STACK_LIST:\n");
01202 
01203    for (port=misdn_cfg_get_next_port(0); port > 0;
01204         port=misdn_cfg_get_next_port(port)) {
01205       char buf[128];
01206       get_show_stack_details(port,buf);
01207       ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
01208    }
01209       
01210    return 0;
01211 }

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

Definition at line 624 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

00625 {
00626    return _misdn_tasks_add_variable(timeout, callback, data, 0);
00627 }

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

Definition at line 629 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

00630 {
00631    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00632 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 594 of file chan_misdn.c.

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

Referenced by unload_module().

00595 {
00596    if (misdn_tasks) {
00597       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
00598       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
00599          cb_log(4, 0, "Joining misdn_tasks thread\n");
00600          pthread_join(misdn_tasks_thread, NULL);
00601       }
00602       sched_context_destroy(misdn_tasks);
00603    }
00604 }

static void misdn_tasks_init ( void   )  [static]

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

00576 {
00577    sem_t blocker;
00578    int i = 5;
00579 
00580    if (sem_init(&blocker, 0, 0)) {
00581       perror("chan_misdn: Failed to initialize semaphore!");
00582       exit(1);
00583    }
00584 
00585    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
00586    
00587    misdn_tasks = sched_context_create();
00588    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
00589 
00590    while (sem_wait(&blocker) && --i);
00591    sem_destroy(&blocker);
00592 }

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 634 of file chan_misdn.c.

References ast_sched_del(), and misdn_tasks.

Referenced by release_chan().

00635 {
00636    ast_sched_del(misdn_tasks, task_id);
00637 }

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

Definition at line 551 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

00552 {
00553    int wait;
00554    struct sigaction sa;
00555 
00556    sa.sa_handler = sighandler;
00557    sa.sa_flags = SA_NODEFER;
00558    sigemptyset(&sa.sa_mask);
00559    sigaddset(&sa.sa_mask, SIGUSR1);
00560    sigaction(SIGUSR1, &sa, NULL);
00561    
00562    sem_post((sem_t *)data);
00563 
00564    while (1) {
00565       wait = ast_sched_wait(misdn_tasks);
00566       if (wait < 0)
00567          wait = 8000;
00568       if (poll(NULL, 0, wait) < 0)
00569          chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
00570       ast_sched_runq(misdn_tasks);
00571    }
00572    return NULL;
00573 }

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 606 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

00607 {
00608    pthread_kill(misdn_tasks_thread, SIGUSR1);
00609 }

static int misdn_toggle_echocancel ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1323 of file chan_misdn.c.

References ast_cli(), chan_list::bc, get_chan_by_ast_name(), manager_ec_disable(), manager_ec_enable(), RESULT_SHOWUSAGE, chan_list::toggle_ec, and update_ec_config().

01324 {
01325    char *channame; 
01326 
01327    if (argc != 4)
01328       return RESULT_SHOWUSAGE;
01329    
01330    channame = argv[3];
01331   
01332    ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
01333   
01334    {
01335       struct chan_list *tmp=get_chan_by_ast_name(channame);
01336     
01337       if (!tmp) {
01338          ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
01339          return 0; 
01340       } else {
01341          
01342          tmp->toggle_ec=tmp->toggle_ec?0:1;
01343 
01344          if (tmp->toggle_ec) {
01345 #ifdef MISDN_1_2
01346             update_pipeline_config(tmp->bc);
01347 #else
01348             update_ec_config(tmp->bc);
01349 #endif
01350             manager_ec_enable(tmp->bc);
01351          } else {
01352             manager_ec_disable(tmp->bc);
01353          }
01354       }
01355    }
01356   
01357    return 0; 
01358 }

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

Definition at line 3544 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, and chan_list::state.

03545 {
03546    chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
03547    
03548    tmp_ch->state=MISDN_HOLD_DISCONNECT;
03549   
03550    ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03551 
03552    holded_chan->state=MISDN_CONNECTED;
03553    //misdn_lib_transfer(holded_chan->bc);
03554    ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03555 }

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

Definition at line 2689 of file chan_misdn.c.

References misdn_bchannel::addr, chan_list::ast, 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_WAITING4DIGS, chan_list::notxtone, misdn_bchannel::port, prefformat, ast_frame::samples, chan_list::state, and ast_frame::subclass.

02690 {
02691    struct chan_list *ch;
02692    int i  = 0;
02693    
02694    if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02695 
02696    if (ch->state == MISDN_HOLDED) {
02697       chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
02698       return 0;
02699    }
02700    
02701    if (!ch->bc ) {
02702       ast_log(LOG_WARNING, "private but no bc\n");
02703       return -1;
02704    }
02705    
02706    if (ch->notxtone) {
02707       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxone\n");
02708       return 0;
02709    }
02710 
02711 
02712    if ( !frame->subclass) {
02713       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
02714       return 0;
02715    }
02716    
02717    if ( !(frame->subclass & prefformat)) {
02718       
02719       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
02720       return 0;
02721    }
02722    
02723 
02724    if ( !frame->samples ) {
02725       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
02726       
02727       if (ch->state == MISDN_WAITING4DIGS) {
02728          chan_misdn_log(4, ch->bc->port, "misdn_write: WAIT4DIGS ..\n");
02729          return 0;
02730       }
02731       return -1;
02732    }
02733 
02734    if ( ! ch->bc->addr ) {
02735       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
02736       return 0;
02737    }
02738    
02739 #if MISDN_DEBUG
02740    {
02741       int i, max=5>frame->samples?frame->samples:5;
02742       
02743       printf("write2mISDN %p %d bytes: ", p, frame->samples);
02744       
02745       for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
02746       printf ("\n");
02747    }
02748 #endif
02749 
02750 
02751    switch (ch->bc->bc_state) {
02752       case BCHAN_ACTIVATED:
02753       case BCHAN_BRIDGED:
02754          break;
02755       default:
02756       if (!ch->dropped_frame_cnt)
02757          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %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);
02758       
02759       ch->dropped_frame_cnt++;
02760       if (ch->dropped_frame_cnt > 100) {
02761          ch->dropped_frame_cnt=0;
02762          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x  dropped > 100 frames!\n",frame->samples,ch->bc->addr);
02763 
02764       }
02765 
02766       return 0;
02767    }
02768 
02769    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
02770    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
02771       /* Buffered Transmit (triggert by read from isdn side)*/
02772       if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
02773          if (ch->bc->active)
02774             cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
02775       }
02776       
02777    } else {
02778       /*transmit without jitterbuffer*/
02779       i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
02780    }
02781 
02782    
02783    
02784    return 0;
02785 }

int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

Definition at line 3427 of file chan_misdn.c.

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

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

03428 {
03429    int ret=ast_pbx_start(ch->ast);  
03430 
03431    if (ret>=0) 
03432       ch->need_hangup=0;
03433    else
03434       ch->need_hangup=1;
03435 
03436    return ret;
03437 }

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

Definition at line 1070 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_get_ch_state(), 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 misdn_show_cl(), and misdn_show_cls().

01071 {
01072    struct ast_channel *ast=help->ast;
01073    ast_cli(fd,
01074       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
01075 
01076       bc->pid, bc->port, bc->channel,
01077       bc->nt?"NT":"TE",
01078       help->originator == ORG_AST?"*":"I",
01079       ast?ast->exten:NULL,
01080       ast?ast->cid.cid_num:NULL,
01081       bc->rad,
01082       ast?ast->context:NULL,
01083       misdn_get_ch_state(help)
01084       );
01085    if (misdn_debug[bc->port] > 0)
01086       ast_cli(fd,
01087          "  --> astname: %s\n"
01088          "  --> ch_l3id: %x\n"
01089          "  --> ch_addr: %x\n"
01090          "  --> bc_addr: %x\n"
01091          "  --> bc_l3id: %x\n"
01092          "  --> display: %s\n"
01093          "  --> activated: %d\n"
01094          "  --> state: %s\n"
01095          "  --> capability: %s\n"
01096 #ifdef MISDN_1_2
01097          "  --> pipeline: %s\n"
01098 #else
01099          "  --> echo_cancel: %d\n"
01100 #endif
01101          "  --> notone : rx %d tx:%d\n"
01102          "  --> bc_hold: %d\n",
01103          help->ast->name,
01104          help->l3id,
01105          help->addr,
01106          bc->addr,
01107          bc?bc->l3_id:-1,
01108          bc->display,
01109          
01110          bc->active,
01111          bc_state2str(bc->bc_state),
01112          bearer2str(bc->capability),
01113 #ifdef MISDN_1_2
01114          bc->pipeline,
01115 #else
01116          bc->ec_enable,
01117 #endif
01118 
01119          help->norxtone,help->notxtone,
01120          bc->holded
01121          );
01122   
01123 }

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

00477 {
00478    
00479    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00480    
00481    switch(bc->law) {
00482    case INFO_CODEC_ALAW:
00483       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00484       break;
00485    case INFO_CODEC_ULAW:
00486       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00487       break;
00488    }
00489 }

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

Definition at line 438 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

00439 {
00440    switch (fac->Function) {
00441    case Fac_CD:
00442       chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
00443                   fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
00444       break;
00445    case Fac_AOCDCurrency:
00446       if (fac->u.AOCDcur.chargeNotAvailable)
00447          chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
00448       else if (fac->u.AOCDcur.freeOfCharge)
00449          chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
00450       else if (fac->u.AOCDchu.billingId >= 0)
00451          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
00452                      fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00453                      (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
00454       else
00455          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
00456                      fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00457                      (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
00458       break;
00459    case Fac_AOCDChargingUnit:
00460       if (fac->u.AOCDchu.chargeNotAvailable)
00461          chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
00462       else if (fac->u.AOCDchu.freeOfCharge)
00463          chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
00464       else if (fac->u.AOCDchu.billingId >= 0)
00465          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
00466                      fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
00467       else
00468          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
00469                      fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
00470       break;
00471    default:
00472       chan_misdn_log(1,bc->port," --> unknown\n");
00473    }
00474 }

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

Definition at line 2551 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_log(), ast_strlen_zero(), ast_translate(), ast_verbose(), 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_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), option_verbose, pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, chan_list::trans, misdn_bchannel::txgain, and VERBOSE_PREFIX_3.

Referenced by misdn_read().

02552 {
02553    struct ast_frame *f,*f2;
02554  
02555    if (tmp->trans) {
02556       f2 = ast_translate(tmp->trans, frame, 0);
02557       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02558    } else {
02559       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02560       return NULL;
02561    }
02562 
02563  
02564    if (!f || (f->frametype != AST_FRAME_DTMF))
02565       return frame;
02566  
02567    ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
02568  
02569    if (tmp->faxdetect && (f->subclass == 'f')) {
02570       /* Fax tone -- Handle and return NULL */
02571       if (!tmp->faxhandled) {
02572          struct ast_channel *ast = tmp->ast;
02573          tmp->faxhandled++;
02574          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02575          tmp->bc->rxgain = 0;
02576          isdn_lib_update_rxgain(tmp->bc);
02577          tmp->bc->txgain = 0;
02578          isdn_lib_update_txgain(tmp->bc);
02579 #ifdef MISDN_1_2
02580          *tmp->bc->pipeline = 0;
02581 #else
02582          tmp->bc->ec_enable = 0;
02583 #endif
02584          isdn_lib_update_ec(tmp->bc);
02585          isdn_lib_stop_dtmf(tmp->bc);
02586          switch (tmp->faxdetect) {
02587          case 1:
02588             if (strcmp(ast->exten, "fax")) {
02589                char *context;
02590                char context_tmp[BUFFERSIZE];
02591                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02592                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02593                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02594                   if (option_verbose > 2)
02595                      ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02596                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02597                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02598                   if (ast_async_goto(ast, context, "fax", 1))
02599                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02600                } else
02601                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02602             } else 
02603                ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02604             break;
02605          case 2:
02606             ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02607             break;
02608          }
02609       } else
02610          ast_log(LOG_DEBUG, "Fax already handled\n");
02611    }
02612    
02613    if (tmp->ast_dsp && (f->subclass != 'f')) {
02614       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02615    }
02616 
02617    return frame;
02618 }

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

Definition at line 1728 of file chan_misdn.c.

References chan_list::allowed_bearers, misdn_bchannel::AOCDtype, chan_list::ast, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_mutex_init(), ast_print_group(), ast_set_callerid(), ast_string_field_set, ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, BUFFERSIZE, ast_channel::callgroup, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_rdnis, config_jitterbuffer(), ast_channel::context, chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::dad, debug_numplan(), misdn_bchannel::dnumplan, chan_list::dsp, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::early_bconnect, ast_channel::exten, chan_list::far_alerting, chan_list::faxdetect, chan_list::faxdetect_timeout, free, misdn_bchannel::hdlc, 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_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, musicclass, 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, strdup, misdn_bchannel::te_choose_channel, chan_list::trans, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

01728                                                        {
01729 
01730    if (!ch) {
01731       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01732       return -1;
01733    }
01734 
01735    struct ast_channel *ast=ch->ast;
01736    struct misdn_bchannel *bc=ch->bc;
01737    if (! ast || ! bc ) {
01738       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01739       return -1;
01740    }
01741    
01742    int port=bc->port;
01743    
01744    chan_misdn_log(1,port,"read_config: Getting Config\n");
01745 
01746    char lang[BUFFERSIZE+1];
01747    
01748 
01749    misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
01750    ast_string_field_set(ast, language, lang);
01751 
01752    char localmusicclass[BUFFERSIZE+1];
01753    
01754    misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
01755    ast_string_field_set(ast, musicclass, localmusicclass);
01756    
01757    
01758    misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
01759    misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
01760    
01761    misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
01762    
01763    misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
01764 
01765    misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
01766    misdn_cfg_get( port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
01767    
01768    misdn_cfg_get( port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
01769    
01770    misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
01771 
01772    misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
01773    
01774    char faxdetect[BUFFERSIZE+1];
01775    misdn_cfg_get( port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
01776    
01777    int hdlc=0;
01778    misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01779    
01780    if (hdlc) {
01781       switch (bc->capability) {
01782       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01783       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01784          chan_misdn_log(1,bc->port," --> CONF HDLC\n");
01785          bc->hdlc=1;
01786          break;
01787       }
01788       
01789    }
01790    /*Initialize new Jitterbuffer*/
01791    {
01792       misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
01793       misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
01794       
01795       config_jitterbuffer(ch);
01796    }
01797    
01798    misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
01799    
01800    ast_copy_string (ast->context,ch->context,sizeof(ast->context));  
01801 
01802 #ifdef MISDN_1_2
01803    update_pipeline_config(bc);
01804 #else
01805    update_ec_config(bc);
01806 #endif
01807 
01808    {
01809       int eb3;
01810       
01811       misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
01812       bc->early_bconnect=eb3;
01813    }
01814    
01815    port=bc->port;
01816    
01817    {
01818       char buf[256];
01819       ast_group_t pg,cg;
01820       
01821       misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
01822       misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
01823       
01824       chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
01825       ast->pickupgroup=pg;
01826       ast->callgroup=cg;
01827    }
01828    
01829    if ( orig  == ORG_AST) {
01830       misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
01831       
01832       if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
01833          if (strstr(faxdetect, "nojump"))
01834             ch->faxdetect=2;
01835          else
01836             ch->faxdetect=1;
01837       }
01838 
01839       {
01840          char callerid[BUFFERSIZE+1];
01841          misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
01842          if ( ! ast_strlen_zero(callerid) ) {
01843             chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
01844             {
01845                int l = sizeof(bc->oad);
01846                strncpy(bc->oad,callerid, l);
01847                bc->oad[l-1] = 0;
01848             }
01849 
01850          }
01851 
01852          
01853          misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
01854          misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
01855          misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
01856          debug_numplan(port, bc->dnumplan,"TON");
01857          debug_numplan(port, bc->onumplan,"LTON");
01858          debug_numplan(port, bc->cpnnumplan,"CTON");
01859       }
01860 
01861       ch->overlap_dial = 0;
01862    } else { /** ORIGINATOR MISDN **/
01863       if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
01864          if (strstr(faxdetect, "nojump"))
01865             ch->faxdetect=2;
01866          else
01867             ch->faxdetect=1;
01868       }
01869    
01870       misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
01871       debug_numplan(port, bc->cpnnumplan,"CTON");
01872       
01873       char prefix[BUFFERSIZE+1]="";
01874       switch( bc->onumplan ) {
01875       case NUMPLAN_INTERNATIONAL:
01876          misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
01877          break;
01878          
01879       case NUMPLAN_NATIONAL:
01880          misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
01881          break;
01882       default:
01883          break;
01884       }
01885       
01886       {
01887          int l = strlen(prefix) + strlen(bc->oad);
01888          char tmp[l+1];
01889          strcpy(tmp,prefix);
01890          strcat(tmp,bc->oad);
01891          strcpy(bc->oad,tmp);
01892       }
01893       
01894       if (!ast_strlen_zero(bc->dad)) {
01895          ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
01896       }
01897       
01898       if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
01899          ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
01900       }
01901 
01902       prefix[0] = 0;
01903       
01904       switch( bc->dnumplan ) {
01905       case NUMPLAN_INTERNATIONAL:
01906          misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
01907          break;
01908       case NUMPLAN_NATIONAL:
01909          misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
01910          break;
01911       default:
01912          break;
01913       }
01914       
01915       {
01916          int l = strlen(prefix) + strlen(bc->dad);
01917          char tmp[l+1];
01918          strcpy(tmp,prefix);
01919          strcat(tmp,bc->dad);
01920          strcpy(bc->dad,tmp);
01921       }
01922       
01923       if ( strcmp(bc->dad,ast->exten)) {
01924          ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
01925       }
01926       
01927       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
01928       
01929       if ( !ast_strlen_zero(bc->rad) ) {
01930          if (ast->cid.cid_rdnis)
01931             free(ast->cid.cid_rdnis);
01932          ast->cid.cid_rdnis = strdup(bc->rad);
01933       }
01934    
01935       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
01936       ast_mutex_init(&ch->overlap_tv_lock);
01937    } /* ORIG MISDN END */
01938 
01939    ch->overlap_dial_task = -1;
01940    
01941    if (ch->faxdetect) {
01942       misdn_cfg_get( port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
01943       if (!ch->dsp)
01944          ch->dsp = ast_dsp_new();
01945       if (ch->dsp)
01946          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
01947       if (!ch->trans)
01948          ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
01949    }
01950 
01951    /* AOCD initialization */
01952    bc->AOCDtype = Fac_None;
01953 
01954    return 0;
01955 }

static void release_chan ( struct misdn_bchannel bc  )  [static]

Isdn asks us to release channel, pendant to misdn_hangup

Definition at line 3477 of file chan_misdn.c.

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

03477                                                     {
03478    struct ast_channel *ast=NULL;
03479    {
03480       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03481       if (!ch)  {
03482          chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03483          return;
03484       }
03485       
03486       if (ch->ast) {
03487          ast=ch->ast;
03488       } 
03489       
03490       chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
03491       
03492       /*releaseing jitterbuffer*/
03493       if (ch->jb ) {
03494          misdn_jb_destroy(ch->jb);
03495          ch->jb=NULL;
03496       } else {
03497          if (!bc->nojitter)
03498             chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
03499       }
03500 
03501       if (ch->overlap_dial) {
03502          if (ch->overlap_dial_task != -1) {
03503             misdn_tasks_remove(ch->overlap_dial_task);
03504             ch->overlap_dial_task = -1;
03505          }
03506          ast_mutex_destroy(&ch->overlap_tv_lock);
03507       }
03508 
03509       if (ch->originator == ORG_AST) {
03510          misdn_out_calls[bc->port]--;
03511       } else {
03512          misdn_in_calls[bc->port]--;
03513       }
03514       
03515       if (ch) {
03516          
03517          close(ch->pipe[0]);
03518          close(ch->pipe[1]);
03519 
03520          
03521          if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03522             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));
03523             chan_misdn_log(3, bc->port, " --> * State Down\n");
03524             MISDN_ASTERISK_TECH_PVT(ast)=NULL;
03525             
03526       
03527             if (ast->_state != AST_STATE_RESERVED) {
03528                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03529                ast_setstate(ast, AST_STATE_DOWN);
03530             }
03531          }
03532             
03533          ch->state=MISDN_CLEANING;
03534          cl_dequeue_chan(&cl_te, ch);
03535          
03536          free(ch);
03537       } else {
03538          /* chan is already cleaned, so exiting  */
03539       }
03540    }
03541 }

static int reload ( void   )  [static]

Definition at line 4984 of file chan_misdn.c.

References reload_config().

04985 {
04986    reload_config();
04987 
04988    return 0;
04989 }

static void reload_config ( void   )  [static]

Definition at line 1042 of file chan_misdn.c.

References ast_log(), BUFFERSIZE, free_robin_list(), LOG_WARNING, misdn_cfg_get(), misdn_cfg_reload(), misdn_cfg_update_ptp(), MISDN_GEN_DEBUG, and MISDN_GEN_TRACEFILE.

01043 {
01044    int i, cfg_debug;
01045 
01046    if (!g_config_initialized) {
01047       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
01048       return ;
01049    }
01050    
01051    free_robin_list();
01052    misdn_cfg_reload();
01053    misdn_cfg_update_ptp();
01054    misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
01055    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
01056 
01057    for (i = 0;  i <= max_ports; i++) {
01058       misdn_debug[i] = cfg_debug;
01059       misdn_debug_only[i] = 0;
01060    }
01061 }

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

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

03626                                                                                                     {
03627    if (!ast) {
03628       chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
03629       return;
03630    }
03631    if (!bc) {
03632       chan_misdn_log(1,0,"send_cause2ast: No BC\n");
03633       return;
03634    }
03635    if (!ch) {
03636       chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
03637       return;
03638    }
03639    
03640    ast->hangupcause=bc->cause;
03641    
03642    switch ( bc->cause) {
03643       
03644    case 1: /** Congestion Cases **/
03645    case 2:
03646    case 3:
03647    case 4:
03648    case 22:
03649    case 27:
03650       /*
03651        * Not Queueing the Congestion anymore, since we want to hear
03652        * the inband message
03653        *
03654       chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
03655       ch->state=MISDN_BUSY;
03656       
03657       ast_queue_control(ast, AST_CONTROL_CONGESTION);
03658       */
03659       break;
03660       
03661    case 21:
03662    case 17: /* user busy */
03663    
03664       ch->state=MISDN_BUSY;
03665          
03666       if (!ch->need_busy) {
03667          chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
03668          break;
03669       }
03670       
03671       chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
03672       
03673       ast_queue_control(ast, AST_CONTROL_BUSY);
03674       
03675       ch->need_busy=0;
03676       
03677       break;
03678    }
03679 }

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

Definition at line 691 of file chan_misdn.c.

References chan_list::ast, ast_log(), ast_playtones_start(), and LOG_DEBUG.

Referenced by misdn_digit_end(), and misdn_send_digit().

00692 {
00693    static const char* dtmf_tones[] = {
00694       "!941+1336/100,!0/100", /* 0 */
00695       "!697+1209/100,!0/100", /* 1 */
00696       "!697+1336/100,!0/100", /* 2 */
00697       "!697+1477/100,!0/100", /* 3 */
00698       "!770+1209/100,!0/100", /* 4 */
00699       "!770+1336/100,!0/100", /* 5 */
00700       "!770+1477/100,!0/100", /* 6 */
00701       "!852+1209/100,!0/100", /* 7 */
00702       "!852+1336/100,!0/100", /* 8 */
00703       "!852+1477/100,!0/100", /* 9 */
00704       "!697+1633/100,!0/100", /* A */
00705       "!770+1633/100,!0/100", /* B */
00706       "!852+1633/100,!0/100", /* C */
00707       "!941+1633/100,!0/100", /* D */
00708       "!941+1209/100,!0/100", /* * */
00709       "!941+1477/100,!0/100" };  /* # */
00710    struct ast_channel *chan=cl->ast; 
00711   
00712    if (digit >= '0' && digit <='9')
00713       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00714    else if (digit >= 'A' && digit <= 'D')
00715       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00716    else if (digit == '*')
00717       ast_playtones_start(chan,0,dtmf_tones[14], 0);
00718    else if (digit == '#')
00719       ast_playtones_start(chan,0,dtmf_tones[15], 0);
00720    else {
00721       /* not handled */
00722       ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00723     
00724     
00725    }
00726 }

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

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

00893 {
00894    char section[BUFFERSIZE];
00895    char name[BUFFERSIZE];
00896    char desc[BUFFERSIZE];
00897    char def[BUFFERSIZE];
00898    char tmp[BUFFERSIZE];
00899 
00900    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
00901    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
00902    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
00903 
00904    if (elem < MISDN_CFG_LAST)
00905       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
00906    else
00907       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
00908 
00909    if (*def)
00910       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
00911    else
00912       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
00913 }

static void sighandler ( int  sig  )  [static]

Definition at line 548 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00549 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

Definition at line 2947 of file chan_misdn.c.

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

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

02948 {
02949    misdn_lib_tone_generator_stop(cl->bc);
02950    cl->notxtone=0;
02951    cl->norxtone=0;
02952    return 0;
02953 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 2955 of file chan_misdn.c.

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

Referenced by misdn_call(), and misdn_hangup().

02956 {
02957    if (!cl) return -1;
02958 
02959    cl->notxtone=1;
02960    cl->norxtone=1;
02961    
02962    return 0;
02963 }

static int stop_indicate ( struct chan_list cl  )  [static]

Definition at line 2929 of file chan_misdn.c.

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

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

02930 {
02931    struct ast_channel *ast=cl->ast;
02932 
02933    if (!ast) {
02934       chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
02935       return -1;
02936    }
02937 
02938    chan_misdn_log(3,cl->bc->port," --> None\n");
02939    misdn_lib_tone_generator_stop(cl->bc);
02940    ast_playtones_stop(ast);
02941    /*ast_deactivate_generator(ast);*/
02942    
02943    return 0;
02944 }

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 4805 of file chan_misdn.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_unregister_application(), chan_misdn_clis, free, free_robin_list(), g_config_initialized, LOG_VERBOSE, misdn_cfg_destroy(), misdn_debug, misdn_debug_only, misdn_lib_destroy(), misdn_ports, misdn_tasks_destroy(), and misdn_tech.

04806 {
04807    /* First, take us out of the channel loop */
04808    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
04809 
04810    misdn_tasks_destroy();
04811    
04812    if (!g_config_initialized) return 0;
04813    
04814    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
04815    
04816    /* ast_unregister_application("misdn_crypt"); */
04817    ast_unregister_application("misdn_set_opt");
04818    ast_unregister_application("misdn_facility");
04819    ast_unregister_application("misdn_check_l2l1");
04820   
04821    ast_channel_unregister(&misdn_tech);
04822 
04823 
04824    free_robin_list();
04825    misdn_cfg_destroy();
04826    misdn_lib_destroy();
04827   
04828    if (misdn_debug)
04829       free(misdn_debug);
04830    if (misdn_debug_only)
04831       free(misdn_debug_only);
04832    free(misdn_ports);
04833    
04834    return 0;
04835 }

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

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

01531 {
01532    if (!ch) {
01533       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01534       return -1;
01535    }
01536    
01537    struct ast_channel *ast=ch->ast;
01538    struct misdn_bchannel *bc=ch->bc;
01539    if (! ast || ! bc ) {
01540       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01541       return -1;
01542    }
01543    
01544    int port=bc->port;
01545    
01546    chan_misdn_log(7,port,"update_config: Getting Config\n");
01547 
01548    int hdlc=0;
01549    misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01550    
01551    if (hdlc) {
01552       switch (bc->capability) {
01553       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01554       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01555          chan_misdn_log(1,bc->port," --> CONF HDLC\n");
01556          bc->hdlc=1;
01557          break;
01558       }
01559       
01560    }
01561    
01562    
01563    int pres, screen;
01564          
01565    misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
01566    misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
01567    chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
01568       
01569    if ( (pres + screen) < 0 ) {
01570 
01571       chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
01572          
01573       switch (ast->cid.cid_pres & 0x60){
01574             
01575       case AST_PRES_RESTRICTED:
01576          bc->pres=1;
01577          chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
01578          break;
01579             
01580             
01581       case AST_PRES_UNAVAILABLE:
01582          bc->pres=2;
01583          chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
01584          break;
01585             
01586       default:
01587          bc->pres=0;
01588          chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
01589       }
01590          
01591       switch (ast->cid.cid_pres & 0x3){
01592             
01593       case AST_PRES_USER_NUMBER_UNSCREENED:
01594          bc->screen=0;
01595          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01596          break;
01597 
01598       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
01599          bc->screen=1;
01600          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
01601          break;
01602       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
01603          bc->screen=2;
01604          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
01605          break;
01606             
01607       case AST_PRES_NETWORK_NUMBER:
01608          bc->screen=3;
01609          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
01610          break;
01611             
01612       default:
01613          bc->screen=0;
01614          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01615       }
01616 
01617          
01618    } else {
01619       bc->screen=screen;
01620       bc->pres=pres;
01621    }
01622 
01623    return 0;
01624    
01625 }

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

Definition at line 1709 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 misdn_toggle_echocancel(), and read_config().

01710 {
01711    int ec;
01712    int port=bc->port;
01713       
01714    misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
01715    
01716    if (ec == 1 ) {
01717       bc->ec_enable=1;
01718    } else if ( ec > 1 ) {
01719       bc->ec_enable=1;
01720       bc->ec_deftaps=ec;
01721    }
01722 
01723    return 0;
01724 }

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

Definition at line 3221 of file chan_misdn.c.

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

Referenced by cb_events().

03222 {
03223    int chan_offset=0;
03224    int tmp_port = misdn_cfg_get_next_port(0);
03225    for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
03226    if (tmp_port == port) break;
03227       chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2; 
03228    }
03229    if (c<0) c=0;
03230 
03231    ast_string_field_build(tmp, name, "%s/%d-u%d",
03232              misdn_type, chan_offset+c, glob_channel++);
03233 
03234    chan_misdn_log(3,port," --> updating channel name to [%s]\n",tmp->name);
03235    
03236 }


Variable Documentation

struct allowed_bearers allowed_bearers_array[]

Definition at line 397 of file chan_misdn.c.

Referenced by cb_events().

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1479 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

struct chan_list* cl_te = NULL

Definition at line 315 of file chan_misdn.c.

Referenced by cb_events(), chan_misdn_jb_empty(), get_chan_by_ast(), get_chan_by_ast_name(), import_ch(), misdn_hangup(), misdn_request(), misdn_show_cl(), misdn_show_cls(), and release_chan().

ast_mutex_t cl_te_lock

Definition at line 316 of file chan_misdn.c.

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

struct chan_list dummy_cl

Definition at line 313 of file chan_misdn.c.

int g_config_initialized = 0 [static]

Definition at line 81 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

int glob_channel = 0 [static]

Definition at line 3219 of file chan_misdn.c.

char global_tracefile[BUFFERSIZE+1]

Definition at line 79 of file chan_misdn.c.

Referenced by chan_misdn_log(), and load_module().

ast_mutex_t lock

Definition at line 1184 of file chan_misdn.c.

Referenced by load_config(), load_module(), load_rpt_vars(), rpt_master(), unload_module(), zap_show_channel(), zap_show_channels(), and zt_request().

int max_ports [static]

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

int MAXTICS = 8

Definition at line 1185 of file chan_misdn.c.

Referenced by misdn_set_tics().

int* misdn_debug [static]

Definition at line 305 of file chan_misdn.c.

Referenced by chan_misdn_log(), load_module(), misdn_show_port(), misdn_show_stacks(), and unload_module().

int* misdn_debug_only [static]

Definition at line 306 of file chan_misdn.c.

Referenced by chan_misdn_log(), load_module(), misdn_show_port(), misdn_show_stacks(), and unload_module().

int* misdn_in_calls [static]

Definition at line 309 of file chan_misdn.c.

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

int* misdn_out_calls [static]

Definition at line 310 of file chan_misdn.c.

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

int* misdn_ports [static]

Definition at line 281 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

struct sched_context* misdn_tasks = NULL [static]

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

struct ast_channel_tech misdn_tech [static]

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

Referenced by misdn_new().

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

Definition at line 298 of file chan_misdn.c.

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

int prefformat = AST_FORMAT_ALAW [static]

Definition at line 303 of file chan_misdn.c.

Referenced by misdn_new(), and misdn_write().

struct robin_list* robin = NULL [static]

Definition at line 235 of file chan_misdn.c.

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 999 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 300 of file chan_misdn.c.

Referenced by load_module().


Generated on Mon May 14 04:45:38 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1