Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:10 2007

Asterisk developer's documentation :: Codename Pineapple


chan_misdn.c File Reference


Detailed Description

the chan_misdn channel driver for Asterisk

Author:
Christian Richter <crich@beronet.com>

Definition in file chan_misdn.c.

#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 AST_BRIDGED_P(ast)   ast_bridged_channel(ast)
#define AST_CID_P(ast)   ast->cid.cid_num
#define AST_DESTROY_CFG   ast_config_destroy
#define AST_LOAD_CFG   ast_config_load
#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_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)
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_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_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 char ** misdn_key_vector = NULL
static int misdn_key_vector_size = 0
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


Define Documentation

#define AST_BRIDGED_P ast   )     ast_bridged_channel(ast)
 

Definition at line 290 of file chan_misdn.c.

Referenced by misdn_transfer_bc().

#define AST_CID_P ast   )     ast->cid.cid_num
 

Definition at line 289 of file chan_misdn.c.

Referenced by do_immediate_setup(), misdn_call(), misdn_hangup(), print_bc_info(), process_ast_dsp(), and release_chan().

#define AST_DESTROY_CFG   ast_config_destroy
 

Definition at line 292 of file chan_misdn.c.

#define AST_LOAD_CFG   ast_config_load
 

Definition at line 291 of file chan_misdn.c.

Referenced by misdn_cfg_init().

#define MISDN_ASTERISK_PVT ast   )     1
 

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

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

#define ORG_MISDN   2
 

Definition at line 139 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_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_DIALING, /*!<  when pbx_start */
00118    MISDN_PROGRESS, /*!<  we got a progress */
00119    MISDN_PROCEEDING, /*!<  we got a progress */
00120    MISDN_CALLING, /*!<  when misdn_call is called */
00121    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
00122    MISDN_ALERTING, /*!<  when Alerting */
00123    MISDN_BUSY, /*!<  when BUSY */
00124    MISDN_CONNECTED, /*!<  when connected */
00125    MISDN_PRECONNECTED, /*!<  when connected */
00126    MISDN_DISCONNECTED, /*!<  when connected */
00127    MISDN_RELEASED, /*!<  when connected */
00128    MISDN_BRIDGED, /*!<  when bridged */
00129    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00130    MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
00131    MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
00132    /* misdn_hangup */
00133    MISDN_HOLDED, /*!< if this chan is holded */
00134    MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
00135   
00136 };


Function Documentation

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

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

00557 {
00558    int task_id;
00559 
00560    if (!misdn_tasks) {
00561       misdn_tasks_init();
00562    }
00563    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00564    misdn_tasks_wakeup();
00565 
00566    return task_id;
00567 }

int add_in_calls int  port  ) 
 

Definition at line 3593 of file chan_misdn.c.

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

Referenced by cb_events().

03594 {
03595    int max_in_calls;
03596    
03597    misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
03598 
03599    misdn_in_calls[port]++;
03600 
03601    if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) {
03602       ast_log(LOG_NOTICE,"Marking Incoming Call on port[%d]\n",port);
03603       return misdn_in_calls[port]-max_in_calls;
03604    }
03605    
03606    return 0;
03607 }

int add_out_calls int  port  ) 
 

Definition at line 3609 of file chan_misdn.c.

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

Referenced by misdn_call().

03610 {
03611    int max_out_calls;
03612    
03613    misdn_cfg_get( port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
03614    
03615 
03616    if (max_out_calls >=0 && max_out_calls<=misdn_out_calls[port]) {
03617       ast_log(LOG_NOTICE,"Rejecting Outgoing Call on port[%d]\n",port);
03618       return (misdn_out_calls[port]+1)-max_out_calls;
03619    }
03620 
03621    misdn_out_calls[port]++;
03622    
03623    return 0;
03624 }

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

Referenced by print_bc_info(), and print_bearer().

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

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

Sending SETUP_ACK

queue new chan

Sending SETUP_ACK

ADD IGNOREPAT

Suplementary Services

Definition at line 3632 of file chan_misdn.c.

References add_in_calls(), 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, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), cl_te, chan_list::context, ast_frame::data, ast_frame::datalen, ast_frame::delivery, export_ch(), ast_channel::exten, find_chan_by_bc(), find_holded(), ast_frame::frametype, hangup_chan(), hanguptone_indicate(), chan_list::ignore_dtmf, init_chan_list(), chan_list::l3id, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING_ACKNOWLEDGE, misdn_cfg_get(), misdn_cfg_is_msn_valid(), MISDN_CONNECTED, MISDN_DIALING, MISDN_EXTCANTMATCH, misdn_get_ch_state(), misdn_new(), MISDN_NOTHING, misdn_overlap_dial_task(), misdn_tasks_add_variable(), MISDN_WAITING4DIGS, allowed_bearers::name, ast_frame::offset, ORG_MISDN, chan_list::orginator, 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(), print_bearer(), read_config(), ast_channel::rings, ast_frame::samples, ast_frame::src, chan_list::state, stop_indicate(), ast_frame::subclass, ast_channel::transfercapability, and update_name().

03633 {
03634    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03635    
03636    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
03637       int debuglevel=1;
03638       if ( event==EVENT_CLEANUP && !user_data)
03639          debuglevel=5;
03640 
03641       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");
03642       if (debuglevel==1) {
03643          misdn_lib_log_ies(bc);
03644          chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
03645       }
03646    }
03647    
03648    if (!ch) {
03649       switch(event) {
03650          case EVENT_SETUP:
03651          case EVENT_DISCONNECT:
03652          case EVENT_PORT_ALARM:
03653          case EVENT_RETRIEVE:
03654          case EVENT_NEW_BC:
03655          case EVENT_FACILITY:
03656             break;
03657          case EVENT_RELEASE_COMPLETE:
03658             chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
03659             break;
03660          case EVENT_CLEANUP:
03661          case EVENT_TONE_GENERATE:
03662          case EVENT_BCHAN_DATA:
03663             return -1;
03664 
03665          default:
03666             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);
03667             return -1;
03668       }
03669    }
03670    
03671    if (ch ) {
03672       switch (event) {
03673       case EVENT_TONE_GENERATE:
03674       break;
03675       case EVENT_DISCONNECT:
03676       case EVENT_RELEASE:
03677       case EVENT_RELEASE_COMPLETE:
03678       case EVENT_CLEANUP:
03679       case EVENT_TIMEOUT:
03680          if (!ch->ast)
03681             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));
03682          break;
03683       default:
03684          if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03685             if (event!=EVENT_BCHAN_DATA)
03686                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
03687             return -1;
03688          }
03689       }
03690    }
03691    
03692    
03693    switch (event) {
03694    case EVENT_PORT_ALARM:
03695       {
03696          int boa=0;
03697          misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
03698          if (boa) {
03699             cb_log(1,bc->port," --> blocking\n");
03700             misdn_lib_port_block(bc->port); 
03701          }
03702       }
03703    break;
03704    case EVENT_BCHAN_ACTIVATED:
03705       break;
03706       
03707    case EVENT_NEW_CHANNEL:
03708       update_name(ch->ast,bc->port,bc->channel);
03709       break;
03710       
03711    case EVENT_NEW_L3ID:
03712       ch->l3id=bc->l3_id;
03713       ch->addr=bc->addr;
03714       break;
03715 
03716    case EVENT_NEW_BC:
03717       if (!ch) {
03718          ch=find_holded(cl_te,bc);
03719       }
03720       
03721       if (!ch) {
03722          ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
03723          break;
03724       }
03725 
03726       if (bc)
03727          ch->bc=(struct misdn_bchannel*)user_data;
03728       break;
03729       
03730    case EVENT_DTMF_TONE:
03731    {
03732       /*  sending INFOS as DTMF-Frames :) */
03733       struct ast_frame fr;
03734       memset(&fr, 0 , sizeof(fr));
03735       fr.frametype = AST_FRAME_DTMF;
03736       fr.subclass = bc->dtmf ;
03737       fr.src=NULL;
03738       fr.data = NULL ;
03739       fr.datalen = 0;
03740       fr.samples = 0 ;
03741       fr.mallocd =0 ;
03742       fr.offset= 0 ;
03743       fr.delivery= ast_tv(0,0) ;
03744       
03745       if (!ch->ignore_dtmf) {
03746          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
03747          ast_queue_frame(ch->ast, &fr);
03748       } else {
03749          chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
03750       }
03751    }
03752    break;
03753    case EVENT_STATUS:
03754       break;
03755     
03756    case EVENT_INFORMATION:
03757    {
03758       int stop_tone;
03759       misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03760       if ( stop_tone ) {
03761          stop_indicate(ch);
03762       }
03763       
03764       if (ch->state == MISDN_WAITING4DIGS ) {
03765          /*  Ok, incomplete Setup, waiting till extension exists */
03766 
03767          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
03768             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
03769             strcpy(bc->info_dad,bc->keypad);
03770          }
03771 
03772          {
03773             int l = sizeof(bc->dad);
03774             strncat(bc->dad,bc->info_dad, l);
03775             bc->dad[l-1] = 0;
03776          }
03777          
03778          
03779          {
03780             int l = sizeof(ch->ast->exten);
03781             strncpy(ch->ast->exten, bc->dad, l);
03782             ch->ast->exten[l-1] = 0;
03783          }
03784 /*       chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
03785          
03786          /* Check for Pickup Request first */
03787          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
03788             int ret;/** Sending SETUP_ACK**/
03789             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03790             if (ast_pickup_call(ch->ast)) {
03791                hangup_chan(ch);
03792             } else {
03793                struct ast_channel *chan=ch->ast;
03794                ch->state = MISDN_CALLING_ACKNOWLEDGE;
03795                ast_setstate(chan, AST_STATE_DOWN);
03796                hangup_chan(ch);
03797                ch->ast=NULL;
03798                break;
03799             }
03800          }
03801          
03802          if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03803 
03804             chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
03805             if (bc->nt)
03806                hanguptone_indicate(ch);
03807             ch->state=MISDN_EXTCANTMATCH;
03808             bc->out_cause=1;
03809 
03810             misdn_lib_send_event(bc, EVENT_DISCONNECT );
03811 
03812             break;
03813          }
03814 
03815          if (ch->overlap_dial) {
03816             ast_mutex_lock(&ch->overlap_tv_lock);
03817             ch->overlap_tv = ast_tvnow();
03818             ast_mutex_unlock(&ch->overlap_tv_lock);
03819             if (ch->overlap_dial_task == -1) {
03820                ch->overlap_dial_task = 
03821                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
03822             }
03823             break;
03824          }
03825 
03826          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03827             ch->state=MISDN_DIALING;
03828      
03829             stop_indicate(ch);
03830 /*          chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/
03831             if (pbx_start_chan(ch)<0) {
03832                hangup_chan(ch);
03833 
03834                chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
03835                if (bc->nt) hanguptone_indicate(ch);
03836 
03837                misdn_lib_send_event(bc, EVENT_DISCONNECT );
03838             }
03839          }
03840    
03841       } else {
03842          /*  sending INFOS as DTMF-Frames :) */
03843          struct ast_frame fr;
03844          fr.frametype = AST_FRAME_DTMF;
03845          fr.subclass = bc->info_dad[0] ;
03846          fr.src=NULL;
03847          fr.data = NULL ;
03848          fr.datalen = 0;
03849          fr.samples = 0 ;
03850          fr.mallocd =0 ;
03851          fr.offset= 0 ;
03852          fr.delivery= ast_tv(0,0) ;
03853 
03854          
03855          int digits;
03856          misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
03857          if (ch->state != MISDN_CONNECTED ) {
03858             if (digits) {
03859                int l = sizeof(bc->dad);
03860                strncat(bc->dad,bc->info_dad, l);
03861                bc->dad[l-1] = 0;
03862                l = sizeof(ch->ast->exten);
03863                strncpy(ch->ast->exten, bc->dad, l);
03864                ch->ast->exten[l-1] = 0;
03865 
03866                ast_cdr_update(ch->ast);
03867             }
03868             
03869             ast_queue_frame(ch->ast, &fr);
03870          }
03871       }
03872    }
03873    break;
03874    case EVENT_SETUP:
03875    {
03876       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03877       if (ch) {
03878          switch (ch->state) {
03879             case MISDN_NOTHING:
03880             ch=NULL;
03881             break;
03882             default:
03883             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
03884             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
03885          }
03886       }
03887    }
03888    
03889 
03890    int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
03891    if (!bc->nt && ! msn_valid) {
03892       chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
03893       return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
03894    }
03895 
03896    
03897    if (bc->cw) {
03898       chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
03899       int cause;
03900       misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
03901       bc->out_cause=cause?cause:16;
03902       return RESPONSE_RELEASE_SETUP;
03903    }
03904 
03905    print_bearer(bc);
03906     
03907    {
03908       struct chan_list *ch=init_chan_list(ORG_MISDN);
03909       struct ast_channel *chan;
03910       int exceed;
03911 
03912       if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
03913       
03914       ch->bc = bc;
03915       ch->l3id=bc->l3_id;
03916       ch->addr=bc->addr;
03917       ch->orginator = ORG_MISDN;
03918 
03919       chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
03920       ch->ast = chan;
03921 
03922       if ((exceed=add_in_calls(bc->port))) {
03923          char tmp[16];
03924          sprintf(tmp,"%d",exceed);
03925          pbx_builtin_setvar_helper(chan,"MAX_OVERFLOW",tmp);
03926       }
03927 
03928       read_config(ch, ORG_MISDN);
03929       
03930       export_ch(chan, bc, ch);
03931 
03932       ch->ast->rings=1;
03933       ast_setstate(ch->ast, AST_STATE_RINGING);
03934 
03935       int pres,screen;
03936 
03937       switch (bc->pres) {
03938          case 1:
03939          pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
03940          break;
03941          case 2:
03942          pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
03943          break;
03944          default:
03945          pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
03946       }
03947 
03948       switch (bc->screen) {
03949          case 0:
03950          screen=AST_PRES_USER_NUMBER_UNSCREENED;  chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
03951          break;
03952          case 1:
03953          screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
03954          break;
03955          case 2:
03956          screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
03957          break;
03958          case 3:
03959          screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
03960          break;
03961          default:
03962          screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
03963       }
03964 
03965       chan->cid.cid_pres=pres+screen;
03966 
03967       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
03968       chan->transfercapability=bc->capability;
03969       
03970       switch (bc->capability) {
03971       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
03972          pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
03973          break;
03974       default:
03975          pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
03976       }
03977 
03978       /** queue new chan **/
03979       cl_queue_chan(&cl_te, ch) ;
03980 
03981 
03982       if (!strstr(ch->allowed_bearers,"all")) {
03983          int i;
03984          for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
03985             if (allowed_bearers_array[i].cap == bc->capability) {
03986                if (  !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
03987                   chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
03988                   bc->out_cause=88;
03989                   
03990                   ch->state=MISDN_EXTCANTMATCH;
03991                   misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03992                   return RESPONSE_OK;
03993                }
03994             }
03995             
03996          }
03997       }
03998       
03999       /* Check for Pickup Request first */
04000       if (!strcmp(chan->exten, ast_pickup_ext())) {
04001          int ret;/** Sending SETUP_ACK**/
04002          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04003          if (ast_pickup_call(chan)) {
04004             hangup_chan(ch);
04005          } else {
04006             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04007             ast_setstate(chan, AST_STATE_DOWN);
04008             hangup_chan(ch);
04009             ch->ast=NULL;
04010             break;
04011          }
04012       }
04013       
04014       /*
04015         added support for s extension hope it will help those poor cretains
04016         which haven't overlap dial.
04017       */
04018       {
04019          int ai;
04020          misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04021          if ( ai ) {
04022             do_immediate_setup(bc, ch , chan);
04023             break;
04024          }
04025          
04026          
04027          
04028       }
04029 
04030       /* check if we should jump into s when we have no dad */
04031       {
04032          int im;
04033          misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04034          if ( im && ast_strlen_zero(bc->dad) ) {
04035             do_immediate_setup(bc, ch , chan);
04036             break;
04037          }
04038       }
04039 
04040       
04041          chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
04042          if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04043          
04044          chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
04045 
04046          if (bc->nt)
04047             hanguptone_indicate(ch);
04048          ch->state=MISDN_EXTCANTMATCH;
04049          bc->out_cause=1;
04050 
04051          if (bc->nt)
04052             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04053          else
04054             misdn_lib_send_event(bc, EVENT_RELEASE );
04055             
04056          break;
04057       }
04058       
04059       if (!ch->overlap_dial && ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04060          ch->state=MISDN_DIALING;
04061          
04062          if (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)) ) {
04063             int ret; 
04064             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04065          } else {
04066             int ret;
04067             ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
04068          }
04069    
04070          if (pbx_start_chan(ch)<0) {
04071             hangup_chan(ch);
04072 
04073             chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04074             chan=NULL;
04075 
04076             if (bc->nt) {
04077                hanguptone_indicate(ch);
04078                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04079             } else
04080                misdn_lib_send_event(bc, EVENT_RELEASE);
04081          }
04082       } else {
04083 
04084          if (bc->sending_complete) {
04085             ch->state=MISDN_EXTCANTMATCH;
04086             bc->out_cause=1;
04087 
04088             if (bc->nt)  {
04089                chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
04090                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04091             } else {
04092                chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
04093                misdn_lib_send_event(bc, EVENT_RELEASE);
04094             }
04095 
04096          } else {
04097 
04098             int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04099             if (ret == -ENOCHAN) {
04100                ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
04101                misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04102             }
04103             /*  send tone to phone :) */
04104             
04105             /** ADD IGNOREPAT **/
04106             
04107             int stop_tone, dad_len;
04108             misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
04109 
04110             dad_len = ast_strlen_zero(bc->dad);
04111             
04112             if ( !dad_len && stop_tone )
04113                stop_indicate(ch);
04114             else
04115                dialtone_indicate(ch);
04116             
04117             ch->state=MISDN_WAITING4DIGS;
04118             
04119             if (ch->overlap_dial && !dad_len) {
04120                ast_mutex_lock(&ch->overlap_tv_lock);
04121                ch->overlap_tv = ast_tvnow();
04122                ast_mutex_unlock(&ch->overlap_tv_lock);
04123                if (ch->overlap_dial_task == -1) {
04124                   ch->overlap_dial_task = 
04125                      misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04126                }
04127             }
04128          }
04129       }
04130       
04131    }
04132    break;
04133    case EVENT_SETUP_ACKNOWLEDGE:
04134    {
04135       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04136 
04137       if (bc->channel) 
04138          update_name(ch->ast,bc->port,bc->channel);
04139       
04140       if (!ast_strlen_zero(bc->infos_pending)) {
04141          /* TX Pending Infos */
04142          
04143          {
04144             int l = sizeof(bc->dad);
04145             strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
04146             bc->dad[l-1] = 0;
04147          }  
04148          {
04149             int l = sizeof(ch->ast->exten);
04150             strncpy(ch->ast->exten, bc->dad, l);
04151             ch->ast->exten[l-1] = 0;
04152          }
04153          {
04154             int l = sizeof(bc->info_dad);
04155             strncpy(bc->info_dad, bc->infos_pending, l);
04156             bc->info_dad[l-1] = 0;
04157          }
04158          strncpy(bc->infos_pending,"", 1);
04159 
04160          misdn_lib_send_event(bc, EVENT_INFORMATION);
04161       }
04162    }
04163    break;
04164    case EVENT_PROCEEDING:
04165    {
04166       
04167       if ( misdn_cap_is_speech(bc->capability) &&
04168            misdn_inband_avail(bc) ) {
04169          start_bc_tones(ch);
04170       }
04171 
04172       ch->state = MISDN_PROCEEDING;
04173       
04174       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04175    }
04176    break;
04177    case EVENT_PROGRESS:
04178       if (!bc->nt ) {
04179          if ( misdn_cap_is_speech(bc->capability) &&
04180               misdn_inband_avail(bc)
04181             ) {
04182             start_bc_tones(ch);
04183          }
04184          
04185          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04186          
04187          ch->state=MISDN_PROGRESS;
04188       }
04189       break;
04190       
04191       
04192    case EVENT_ALERTING:
04193    {
04194       ch->state = MISDN_ALERTING;
04195       
04196       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04197       ast_setstate(ch->ast, AST_STATE_RINGING);
04198       
04199       cb_log(7,bc->port," --> Set State Ringing\n");
04200       
04201       if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04202          cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
04203          start_bc_tones(ch);
04204       } else {
04205          cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
04206          if (ch->far_alerting) {
04207             cb_log(1,bc->port," --> The other end can not do ringing eh ?.. we must do all ourself..");
04208             start_bc_tones(ch);
04209             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04210          }
04211       }
04212    }
04213    break;
04214    case EVENT_CONNECT:
04215    {
04216       /*we answer when we've got our very new L3 ID from the NT stack */
04217       misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
04218    
04219       struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
04220       stop_indicate(ch);
04221 
04222       if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
04223          struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
04224 
04225          chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
04226          if (bridged_ch) {
04227             bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
04228             ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
04229          }
04230       }
04231    }
04232    
04233    /* notice that we don't break here!*/
04234    case EVENT_CONNECT_ACKNOWLEDGE:
04235    {
04236       ch->l3id=bc->l3_id;
04237       ch->addr=bc->addr;
04238       
04239       start_bc_tones(ch);
04240       
04241       
04242       ch->state = MISDN_CONNECTED;
04243       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04244    }
04245    break;
04246    case EVENT_DISCONNECT:
04247    /*we might not have an ch->ast ptr here anymore*/
04248    if (ch) {
04249       struct chan_list *holded_ch=find_holded(cl_te, bc);
04250    
04251       chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->orginator, bc->nt, misdn_inband_avail(bc), ch->state);
04252       if ( ch->orginator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04253          /* If there's inband information available (e.g. a
04254             recorded message saying what was wrong with the
04255             dialled number, or perhaps even giving an
04256             alternative number, then play it instead of
04257             immediately releasing the call */
04258          chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04259       
04260          ch->state=MISDN_DISCONNECTED;
04261          start_bc_tones(ch);
04262          break;
04263       }
04264       
04265       /*Check for holded channel, to implement transfer*/
04266       if (  holded_ch && 
04267          holded_ch != ch && 
04268          ch->ast && 
04269          ch->state == MISDN_CONNECTED  ) {
04270          cb_log(1,bc->port," --> found holded ch\n");
04271          misdn_transfer_bc(ch, holded_ch) ;
04272       }
04273       
04274       stop_bc_tones(ch);
04275       hangup_chan(ch);
04276    } else {
04277    /* ch=find_holded_l3(cl_te, bc->l3_id,1);
04278       if (ch) {
04279          hangup_chan(ch);
04280       }
04281    */
04282    }
04283    bc->out_cause=-1;
04284    if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
04285    break;
04286    
04287    case EVENT_RELEASE:
04288       {
04289          bc->out_cause=16;
04290          
04291          hangup_chan(ch);
04292          release_chan(bc);
04293       
04294          if (bc->need_release_complete) 
04295             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04296       }
04297       break;
04298    case EVENT_RELEASE_COMPLETE:
04299    {
04300       stop_bc_tones(ch);
04301       hangup_chan(ch);
04302       release_chan(bc);
04303       if(ch)   
04304          ch->state=MISDN_CLEANING;
04305    }
04306    break;
04307    case EVENT_BCHAN_ERROR:
04308    case EVENT_CLEANUP:
04309    {
04310       stop_bc_tones(ch);
04311       
04312       switch(ch->state) {
04313          case MISDN_CALLING:
04314             bc->cause=27; /* Destination out of order */
04315          break;
04316          default:
04317          break;
04318       }
04319       
04320       hangup_chan(ch);
04321       release_chan(bc);
04322    }
04323    break;
04324 
04325    case EVENT_TONE_GENERATE:
04326    {
04327       int tone_len=bc->tone_cnt;
04328       struct ast_channel *ast=ch->ast;
04329       void *tmp;
04330       int res;
04331       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04332 
04333       chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
04334 
04335       if (!ast) break;
04336 
04337       if (!ast->generator) break;
04338    
04339       
04340    
04341       tmp = ast->generatordata;
04342       ast->generatordata = NULL;
04343       generate = ast->generator->generate;
04344 
04345       if (tone_len <0 || tone_len > 512 ) {
04346          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
04347          tone_len=128;
04348       }
04349 
04350       res = generate(ast, tmp, tone_len, tone_len);
04351       ast->generatordata = tmp;
04352       
04353       if (res) {
04354          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04355          ast_deactivate_generator(ast);
04356       } else {
04357          bc->tone_cnt=0;
04358       }
04359    }
04360    break;
04361       
04362    case EVENT_BCHAN_DATA:
04363    {
04364       if ( !misdn_cap_is_speech(ch->bc->capability) ) {
04365          struct ast_frame frame;
04366          /*In Data Modes we queue frames*/
04367          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
04368          frame.subclass = AST_FORMAT_ALAW;
04369          frame.datalen = bc->bframe_len;
04370          frame.samples = bc->bframe_len ;
04371          frame.mallocd =0 ;
04372          frame.offset= 0 ;
04373          frame.delivery= ast_tv(0,0) ;
04374          frame.src = NULL;
04375          frame.data = bc->bframe ;
04376          
04377          ast_queue_frame(ch->ast,&frame);
04378       } else {
04379          fd_set wrfs;
04380          struct timeval tv;
04381          tv.tv_sec=0;
04382          tv.tv_usec=0;
04383          
04384          
04385          FD_ZERO(&wrfs);
04386          FD_SET(ch->pipe[1],&wrfs);
04387          
04388          int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
04389 
04390          if (!t) {
04391             chan_misdn_log(9, bc->port, "Select Timed out\n");
04392             break;
04393          }
04394          
04395          if (t<0) {
04396             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
04397             break;
04398          }
04399          
04400          if (FD_ISSET(ch->pipe[1],&wrfs)) {
04401             chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
04402             int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
04403             
04404             if (ret<=0) {
04405                chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno));
04406 
04407                stop_bc_tones(ch);
04408                hangup_chan(ch);
04409                release_chan(bc);
04410             }
04411          } else {
04412             chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
04413          }
04414       }
04415    }
04416    break;
04417    case EVENT_TIMEOUT:
04418       {
04419       if (ch && bc)
04420          chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
04421 
04422       switch (ch->state) {
04423          case MISDN_DIALING:
04424          case MISDN_PROGRESS:
04425             if (bc->nt && !ch->nttimeout) break;
04426          
04427          case MISDN_CALLING:
04428          case MISDN_ALERTING:
04429          case MISDN_PROCEEDING:
04430          case MISDN_CALLING_ACKNOWLEDGE:
04431             if (bc->nt) {
04432                bc->progress_indicator=8;
04433                hanguptone_indicate(ch);
04434             }
04435             
04436             bc->out_cause=1;
04437             misdn_lib_send_event(bc,EVENT_DISCONNECT);
04438          break;
04439 
04440          case MISDN_WAITING4DIGS:
04441             if (bc->nt) {
04442                bc->progress_indicator=8;
04443                bc->out_cause=1;
04444                hanguptone_indicate(ch);
04445                misdn_lib_send_event(bc,EVENT_DISCONNECT);
04446             } else {
04447                bc->out_cause=16;
04448                misdn_lib_send_event(bc,EVENT_RELEASE);
04449             }
04450             
04451          break;
04452 
04453 
04454          case MISDN_CLEANING: 
04455             chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
04456          break;
04457 
04458          default:
04459             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04460          }
04461       }
04462       break;
04463 
04464     
04465    /***************************/
04466    /** Suplementary Services **/
04467    /***************************/
04468    case EVENT_RETRIEVE:
04469    {
04470       ch=find_holded_l3(cl_te, bc->l3_id,1);
04471       if (!ch) {
04472          ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
04473          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04474          break;
04475       }
04476 
04477       /*remember the channel again*/
04478       ch->bc=bc;
04479       ch->state = MISDN_CONNECTED;
04480 
04481       ch->hold_info.port=0;
04482       ch->hold_info.channel=0;
04483       
04484       struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
04485       
04486       if (hold_ast) {
04487          ast_moh_stop(hold_ast);
04488       }
04489    
04490       if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
04491          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04492    }
04493    break;
04494     
04495    case EVENT_HOLD:
04496    {
04497       int hold_allowed;
04498       misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04499       
04500       if (!hold_allowed) {
04501 
04502          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04503          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04504          break;
04505       }
04506       
04507       struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
04508 
04509       if (bridged) {
04510          chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
04511          ch->state = MISDN_HOLDED;
04512          ch->l3id = bc->l3_id;
04513          
04514          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04515 
04516          /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
04517           * instead of starting moh on the bridged channel directly */
04518          ast_moh_start(bridged, NULL, NULL);
04519 
04520          /*forget the channel now*/
04521          ch->bc=NULL;
04522          ch->hold_info.port=bc->port;
04523          ch->hold_info.channel=bc->channel;
04524 
04525       } else {
04526          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04527          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04528       }
04529    } 
04530    break;
04531    
04532    case EVENT_FACILITY:
04533       print_facility(&(bc->fac_in), bc);
04534       
04535       switch (bc->fac_in.Function) {
04536       case Fac_CD:
04537          {
04538             struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
04539             struct chan_list *ch_br;
04540             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04541                ch_br=MISDN_ASTERISK_TECH_PVT(bridged);
04542                /*ch->state=MISDN_FACILITY_DEFLECTED;*/
04543                if (ch_br->bc) {
04544                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
04545                      ch_br->state=MISDN_DIALING;
04546                      if (pbx_start_chan(ch_br) < 0) {
04547                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
04548                      }
04549                   }
04550                }
04551 
04552             }
04553             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04554          } 
04555          break;
04556       case Fac_AOCDCurrency:
04557          bc->AOCDtype = Fac_AOCDCurrency;
04558          memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
04559          break;
04560       case Fac_AOCDChargingUnit:
04561          bc->AOCDtype = Fac_AOCDChargingUnit;
04562          memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
04563          break;
04564       default:
04565          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%p\n", bc->fac_in.Function);
04566       }
04567       
04568       break;
04569 
04570    case EVENT_RESTART:
04571 
04572       stop_bc_tones(ch);
04573       release_chan(bc);
04574       
04575       break;
04576             
04577    default:
04578       chan_misdn_log(1,0, "Got Unknown Event\n");
04579       break;
04580    }
04581    
04582    return RESPONSE_OK;
04583 }

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

Definition at line 5002 of file chan_misdn.c.

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

05003 {
05004    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
05005    
05006    if (ch && ch->jb) {
05007       return misdn_jb_empty(ch->jb, buf, len);
05008    }
05009    
05010    return -1;
05011 }

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

Definition at line 5187 of file chan_misdn.c.

References ast_console_puts(), ast_log(), ast_strlen_zero(), 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_holded(), import_ch(), init_chan_list(), misdn_answer(), misdn_bridge(), misdn_call(), misdn_digit_end(), misdn_facility_exec(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_jb_init(), misdn_l1_task(), 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(), and update_config().

05188 {
05189    if (! ((0 <= port) && (port <= max_ports))) {
05190       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05191       port=0;
05192       level=-1;
05193    }
05194       
05195    va_list ap;
05196    char buf[1024];
05197    char port_buf[8];
05198    sprintf(port_buf,"P[%2d] ",port);
05199    
05200    va_start(ap, tmpl);
05201    vsnprintf( buf, 1023, tmpl, ap );
05202    va_end(ap);
05203 
05204    if (level == -1)
05205       ast_log(LOG_WARNING, buf);
05206 
05207    else if (misdn_debug_only[port] ? 
05208          (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) 
05209        : level <= misdn_debug[port]) {
05210       
05211       ast_console_puts(port_buf);
05212       ast_console_puts(buf);
05213    }
05214    
05215    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05216       time_t tm = time(NULL);
05217       char *tmp=ctime(&tm),*p;
05218       
05219       FILE *fp= fopen(global_tracefile, "a+");
05220       
05221       p=strchr(tmp,'\n');
05222       if (p) *p=':';
05223       
05224       if (!fp) {
05225          ast_console_puts("Error opening Tracefile: [ ");
05226          ast_console_puts(global_tracefile);
05227          ast_console_puts(" ] ");
05228          
05229          ast_console_puts(strerror(errno));
05230          ast_console_puts("\n");
05231          return ;
05232       }
05233       
05234       fputs(tmp,fp);
05235       fputs(" ", fp);
05236       fputs(port_buf,fp);
05237       fputs(" ", fp);
05238       fputs(buf, fp);
05239 
05240       fclose(fp);
05241    }
05242 }

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

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

03266 {
03267    if (chan->dsp) 
03268       ast_dsp_free(chan->dsp);
03269    if (chan->trans)
03270       ast_translator_free_path(chan->trans);
03271 
03272    
03273 
03274    ast_mutex_lock(&cl_te_lock);
03275    if (!*list) {
03276       ast_mutex_unlock(&cl_te_lock);
03277       return;
03278    }
03279   
03280    if (*list == chan) {
03281       *list=(*list)->next;
03282       ast_mutex_unlock(&cl_te_lock);
03283       return ;
03284    }
03285   
03286    {
03287       struct chan_list *help=*list;
03288       for (;help->next; help=help->next) {
03289          if (help->next == chan) {
03290             help->next=help->next->next;
03291             ast_mutex_unlock(&cl_te_lock);
03292             return;
03293          }
03294       }
03295    }
03296    
03297    ast_mutex_unlock(&cl_te_lock);
03298 }

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

Definition at line 3249 of file chan_misdn.c.

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

Referenced by cb_events().

03250 {
03251    chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
03252   
03253    ast_mutex_lock(&cl_te_lock);
03254    if (!*list) {
03255       *list = chan;
03256    } else {
03257       struct chan_list *help=*list;
03258       for (;help->next; help=help->next); 
03259       help->next=chan;
03260    }
03261    chan->next=NULL;
03262    ast_mutex_unlock(&cl_te_lock);
03263 }

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

Definition at line 1329 of file chan_misdn.c.

References complete_ch_helper().

01330 {
01331    return complete_ch_helper(line, word, pos, state, 3);
01332 }

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

Definition at line 1305 of file chan_misdn.c.

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

Referenced by complete_ch().

01306 {
01307    struct ast_channel *c;
01308    int which=0;
01309    char *ret;
01310    if (pos != rpos)
01311       return NULL;
01312    c = ast_channel_walk_locked(NULL);
01313    while(c) {
01314       if (!strncasecmp(word, c->name, strlen(word))) {
01315          if (++which > state)
01316             break;
01317       }
01318       ast_mutex_unlock(&c->lock);
01319       c = ast_channel_walk_locked(c);
01320    }
01321    if (c) {
01322       ret = strdup(c->name);
01323       ast_mutex_unlock(&c->lock);
01324    } else
01325       ret = NULL;
01326    return ret;
01327 }

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

Definition at line 1334 of file chan_misdn.c.

References strdup.

01335 {
01336    if (state)
01337       return NULL;
01338 
01339    switch (pos) {
01340    case 4: if (*word == 'p')
01341             return strdup("port");
01342          else if (*word == 'o')
01343             return strdup("only");
01344          break;
01345    case 6: if (*word == 'o')
01346             return strdup("only");
01347          break;
01348    }
01349    return NULL;
01350 }

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

Definition at line 1352 of file chan_misdn.c.

References misdn_cfg_get_name(), misdn_cfg_get_next_port(), and strdup.

01353 {
01354    char buffer[BUFFERSIZE];
01355    enum misdn_cfg_elements elem;
01356    int wordlen = strlen(word);
01357    int which = 0;
01358    int port = 0;
01359 
01360    switch (pos) {
01361    case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
01362             return strdup("description");
01363          if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
01364             return strdup("descriptions");
01365          if ((!strncmp(word, "0", wordlen)) && (++which > state))
01366             return strdup("0");
01367          while ((port = misdn_cfg_get_next_port(port)) != -1) {
01368             snprintf(buffer, sizeof(buffer), "%d", port);
01369             if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
01370                return strdup(buffer);
01371             }
01372          }
01373          break;
01374    case 4:
01375          if (strstr(line, "description ")) {
01376             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01377                if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
01378                   continue;
01379                misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
01380                if (!wordlen || !strncmp(word, buffer, wordlen)) {
01381                   if (++which > state)
01382                      return strdup(buffer);
01383                }
01384             }
01385          } else if (strstr(line, "descriptions ")) {
01386             if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
01387                return strdup("general");
01388             if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
01389                return strdup("ports");
01390          }
01391          break;
01392    }
01393    return NULL;
01394 }

static void config_jitterbuffer struct chan_list ch  )  [static]
 

Definition at line 1544 of file chan_misdn.c.

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

Referenced by read_config().

01545 {
01546    struct misdn_bchannel *bc=ch->bc;
01547    int len=ch->jb_len, threshold=ch->jb_upper_threshold;
01548    
01549    chan_misdn_log(5,bc->port, "config_jb: Called\n");
01550    
01551    if ( ! len ) {
01552       chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
01553       bc->nojitter=1;
01554    } else {
01555       
01556       if (len <=100 || len > 8000) {
01557          chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
01558          len=1000;
01559       }
01560       
01561       if ( threshold > len ) {
01562          chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
01563       }
01564       
01565       if ( ch->jb) {
01566          cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
01567          misdn_jb_destroy(ch->jb);
01568          ch->jb=NULL;
01569       }
01570       
01571       ch->jb=misdn_jb_init(len, threshold);
01572 
01573       if (!ch->jb ) 
01574          bc->nojitter=1;
01575    }
01576 }

void debug_numplan int  port,
int  numplan,
char *  type
 

Definition at line 1579 of file chan_misdn.c.

References chan_misdn_log().

Referenced by read_config().

01580 {
01581    switch (numplan) {
01582    case NUMPLAN_INTERNATIONAL:
01583       chan_misdn_log(2, port, " --> %s: International\n",type);
01584       break;
01585    case NUMPLAN_NATIONAL:
01586       chan_misdn_log(2, port, " --> %s: National\n",type);
01587       break;
01588    case NUMPLAN_SUBSCRIBER:
01589       chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
01590       break;
01591    case NUMPLAN_UNKNOWN:
01592       chan_misdn_log(2, port, " --> %s: Unknown\n",type);
01593       break;
01594       /* Maybe we should cut off the prefix if present ? */
01595    default:
01596       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01597       break;
01598    }
01599 }

static int dialtone_indicate struct chan_list cl  )  [static]
 

AST INDICATIONS END

Definition at line 2777 of file chan_misdn.c.

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

Referenced by do_immediate_setup().

02778 {
02779    const struct ind_tone_zone_sound *ts= NULL;
02780    struct ast_channel *ast=cl->ast;
02781 
02782    if (!ast) {
02783       chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
02784       return -1;
02785    }
02786 
02787    int nd=0;
02788    misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
02789 
02790    if (nd) {
02791       chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
02792       return 0;
02793    }
02794    
02795    chan_misdn_log(3,cl->bc->port," --> Dial\n");
02796    ts=ast_get_indication_tone(ast->zone,"dial");
02797    cl->ts=ts;  
02798    
02799    if (ts) {
02800       cl->notxtone=0;
02801       cl->norxtone=0;
02802       ast_playtones_start(ast,0, ts->data, 0);
02803       chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
02804       misdn_lib_tone_generator_start(cl->bc);
02805    }
02806 
02807    return 0;
02808 }

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

Definition at line 3434 of file chan_misdn.c.

References chan_list::ast, AST_CID_P, AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), chan_misdn_log(), ast_channel::context, ast_frame::data, ast_frame::datalen, ast_frame::delivery, dialtone_indicate(), 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, ast_frame::offset, ORG_MISDN, chan_list::orginator, pbx_start_chan(), ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

03435 {
03436    char predial[256]="";
03437    char *p = predial;
03438   
03439    struct ast_frame fr;
03440   
03441    strncpy(predial, ast->exten, sizeof(predial) -1 );
03442   
03443    ch->state=MISDN_DIALING;
03444 
03445    if (bc->nt) {
03446       int ret; 
03447       ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03448    } else {
03449       int ret;
03450       if ( misdn_lib_is_ptp(bc->port)) {
03451          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03452       } else {
03453          ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03454       }
03455    }
03456 
03457    if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio ) 
03458       chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
03459     else  
03460       dialtone_indicate(ch);
03461   
03462    chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
03463   
03464    strncpy(ast->exten,"s", 2);
03465   
03466    if (pbx_start_chan(ch)<0) {
03467       ast=NULL;
03468       hangup_chan(ch);
03469       hanguptone_indicate(ch);
03470 
03471       if (bc->nt)
03472          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03473       else
03474          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03475    }
03476   
03477   
03478    while (!ast_strlen_zero(p) ) {
03479       fr.frametype = AST_FRAME_DTMF;
03480       fr.subclass = *p ;
03481       fr.src=NULL;
03482       fr.data = NULL ;
03483       fr.datalen = 0;
03484       fr.samples = 0 ;
03485       fr.mallocd =0 ;
03486       fr.offset= 0 ;
03487       fr.delivery= ast_tv(0,0) ;
03488 
03489       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03490          ast_queue_frame(ch->ast, &fr);
03491       }
03492       p++;
03493    }
03494 }

void export_ch struct ast_channel chan,
struct misdn_bchannel *  bc,
struct chan_list ch
 

Definition at line 3575 of file chan_misdn.c.

References chan_misdn_log(), and pbx_builtin_setvar_helper().

Referenced by cb_events().

03576 {
03577    char tmp[32];
03578    chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
03579    sprintf(tmp,"%d",bc->pid);
03580    pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
03581 
03582    if (bc->sending_complete) {
03583       sprintf(tmp,"%d",bc->sending_complete);
03584       pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
03585    }
03586 
03587    if (bc->urate) {
03588       sprintf(tmp,"%d",bc->urate);
03589       pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp);
03590    }
03591 }

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

Definition at line 3193 of file chan_misdn.c.

References chan_list::bc, and chan_list::next.

Referenced by cb_events(), chan_misdn_jb_empty(), and release_chan().

03194 {
03195    struct chan_list *help=list;
03196    for (;help; help=help->next) {
03197       if (help->bc == bc) return help;
03198    }
03199   
03200    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03201   
03202    return NULL;
03203 }

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

Definition at line 3205 of file chan_misdn.c.

References chan_list::bc, and chan_list::next.

Referenced by import_ch().

03206 {
03207    struct chan_list *help=list;
03208    for (;help; help=help->next) {
03209       if ( help->bc && (help->bc->pid == pid) ) return help;
03210    }
03211   
03212    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
03213   
03214    return NULL;
03215 }

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

Definition at line 3217 of file chan_misdn.c.

References chan_misdn_log(), hold_info::channel, chan_list::hold_info, MISDN_HOLDED, chan_list::next, hold_info::port, and chan_list::state.

Referenced by cb_events().

03218 {
03219    struct chan_list *help=list;
03220    
03221    chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
03222    for (;help; help=help->next) {
03223       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel);
03224       if (  (help->state == MISDN_HOLDED) && 
03225          (help->hold_info.port == bc->port) ) 
03226          return help;
03227    }  
03228    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03229   
03230    return NULL;
03231 }

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

Definition at line 3234 of file chan_misdn.c.

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

03236 {
03237    struct chan_list *help=list;
03238 
03239    for (;help; help=help->next) {
03240       if ( (help->state == MISDN_HOLDED) &&
03241           (help->l3id == l3_id)   
03242          ) 
03243          return help;
03244    }
03245 
03246    return NULL;
03247 }

static void free_robin_list void   )  [static]
 

Definition at line 249 of file chan_misdn.c.

References free_robin_list_r(), and robin.

Referenced by reload_config(), and unload_module().

00250 {
00251    free_robin_list_r(robin);
00252    robin = NULL;
00253 }

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

Definition at line 240 of file chan_misdn.c.

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

Referenced by free_robin_list().

00241 {
00242         if (r) {
00243                 if (r->next) free_robin_list_r(r->next);
00244                 if (r->group) free(r->group);
00245                 free(r);
00246         }
00247 }

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

Definition at line 368 of file chan_misdn.c.

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

Referenced by misdn_bridge().

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

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

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

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

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

Definition at line 255 of file chan_misdn.c.

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

Referenced by misdn_request().

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

static void hangup_chan struct chan_list ch  )  [static]
 

Definition at line 3315 of file chan_misdn.c.

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

Referenced by cb_events(), and do_immediate_setup().

03316 {
03317    int port=ch?ch->bc?ch->bc->port:0:0;
03318    if (!ch) {
03319       cb_log(1,0,"Cannot hangup chan, no ch\n");
03320       return;
03321    }
03322 
03323    cb_log(5,port,"hangup_chan called\n");
03324 
03325    if (ch->need_hangup) 
03326    {
03327       cb_log(2,port," --> hangup\n");
03328       send_cause2ast(ch->ast,ch->bc,ch);
03329       ch->need_hangup=0;
03330       ch->need_queue_hangup=0;
03331       if (ch->ast)
03332          ast_hangup(ch->ast);
03333       return;
03334    }
03335 
03336    if (!ch->need_queue_hangup) {
03337       cb_log(2,port," --> No need to queue hangup\n");
03338    }
03339 
03340    ch->need_queue_hangup=0;
03341    if (ch->ast) {
03342       send_cause2ast(ch->ast,ch->bc,ch);
03343 
03344       if (ch->ast)
03345          ast_queue_hangup(ch->ast);
03346       cb_log(2,port," --> queue_hangup\n");
03347    } else {
03348       cb_log(1,port,"Cannot hangup chan, no ast\n");
03349    }
03350 }

static int hanguptone_indicate struct chan_list cl  )  [static]
 

Definition at line 2810 of file chan_misdn.c.

References chan_list::bc.

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

02811 {
02812    misdn_lib_send_tone(cl->bc,TONE_HANGUP);
02813    return 0;
02814 }

void import_ch struct ast_channel chan,
struct misdn_bchannel *  bc,
struct chan_list ch
 

Definition at line 3556 of file chan_misdn.c.

References chan_misdn_log(), cl_te, find_chan_by_pid(), chan_list::other_ch, chan_list::other_pid, and pbx_builtin_getvar_helper().

Referenced by misdn_call().

03557 {
03558    const char *tmp;
03559    tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
03560    if (tmp) {
03561       ch->other_pid=atoi(tmp);
03562       chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp);
03563       if (ch->other_pid >0) {
03564          ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
03565          if (ch->other_ch) ch->other_ch->other_ch=ch;
03566       }
03567    }
03568 
03569    tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
03570    if (tmp && (atoi(tmp) == 1)) {
03571       bc->sending_complete=1;
03572    }
03573 }

static struct chan_list* init_chan_list int  orig  )  [static]
 

Definition at line 2853 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::orginator, and chan_list::overlap_dial_task.

Referenced by cb_events(), and misdn_request().

02854 {
02855    struct chan_list *cl=malloc(sizeof(struct chan_list));
02856    
02857    if (!cl) {
02858       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
02859       return NULL;
02860    }
02861    
02862    memset(cl,0,sizeof(struct chan_list));
02863 
02864    cl->orginator=orig;
02865    cl->need_queue_hangup=1;
02866    cl->need_hangup=1;
02867    cl->need_busy=1;
02868    cl->overlap_dial_task=-1;
02869    
02870    return cl;
02871    
02872 }

static int load_module void   )  [static]
 

Definition at line 4627 of file chan_misdn.c.

References ast_log(), AST_MODULE_LOAD_DECLINE, LOG_ERROR, malloc, max_ports, misdn_cfg_get(), misdn_cfg_init(), misdn_debug, and misdn_ports.

04628 {
04629    int i, port;
04630    
04631    char ports[256]="";
04632 
04633    max_ports=misdn_lib_maxports_get();
04634    
04635    if (max_ports<=0) {
04636       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
04637       return AST_MODULE_LOAD_DECLINE;
04638    }
04639    
04640    if (misdn_cfg_init(max_ports)) {
04641       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
04642       return AST_MODULE_LOAD_DECLINE;
04643    }
04644    g_config_initialized=1;
04645    
04646    misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
04647    misdn_ports = (int *)malloc(sizeof(int) * (max_ports+1));
04648    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
04649    for (i = 1; i <= max_ports; i++) {
04650       misdn_debug[i] = misdn_debug[0];
04651       misdn_ports[i] = i;
04652    }
04653    *misdn_ports = 0;
04654    misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
04655 
04656    {
04657       char tempbuf[BUFFERSIZE+1];
04658       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
04659       if (strlen(tempbuf))
04660          tracing = 1;
04661    }
04662    
04663    misdn_in_calls = (int *)malloc(sizeof(int) * (max_ports+1));
04664    misdn_out_calls = (int *)malloc(sizeof(int) * (max_ports+1));
04665 
04666    for (i=1; i <= max_ports; i++) {
04667       misdn_in_calls[i]=0;
04668       misdn_out_calls[i]=0;
04669    }
04670    
04671    ast_mutex_init(&cl_te_lock);
04672 
04673    misdn_cfg_update_ptp();
04674    misdn_cfg_get_ports_string(ports);
04675 
04676    if (strlen(ports))
04677       chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
04678    
04679    {
04680       struct misdn_lib_iface iface = {
04681          .cb_event = cb_events,
04682          .cb_log = chan_misdn_log,
04683          .cb_jb_empty = chan_misdn_jb_empty,
04684       };
04685       
04686       if (misdn_lib_init(ports, &iface, NULL))
04687          chan_misdn_log(0, 0, "No te ports initialized\n");
04688    
04689       int ntflags=0;
04690       char ntfile[BUFFERSIZE+1];
04691 
04692       misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
04693       misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
04694 
04695       misdn_lib_nt_debug_init(ntflags,ntfile);
04696 
04697    }
04698 
04699    {
04700       if (ast_channel_register(&misdn_tech)) {
04701          ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
04702          unload_module();
04703          return -1;
04704       }
04705    }
04706   
04707    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
04708   
04709    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
04710              "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
04711              "Sets mISDN opts. and optargs\n"
04712              "\n"
04713              "The available options are:\n"
04714              "    d - Send display text on called phone, text is the optparam\n"
04715              "    n - don't detect dtmf tones on called channel\n"
04716              "    h - make digital outgoing call\n" 
04717              "    c - make crypted outgoing call, param is keyindex\n"
04718              "    e - perform echo cancelation on this channel,\n"
04719              "        takes taps as arguments (32,64,128,256)\n"
04720              "    s - send Non Inband DTMF as inband\n"
04721              "   vr - rxgain control\n"
04722              "   vt - txgain control\n"
04723       );
04724 
04725    
04726    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
04727              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
04728              "Sends the Facility Message FACILITY_TYPE with \n"
04729              "the given Arguments to the current ISDN Channel\n"
04730              "Supported Facilities are:\n"
04731              "\n"
04732              "type=calldeflect args=Nr where to deflect\n"
04733       );
04734 
04735 
04736    misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
04737 
04738    /* start the l1 watchers */
04739    
04740    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
04741       int l1timeout;
04742       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
04743       if (l1timeout) {
04744          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
04745          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
04746       }
04747    }
04748    
04749    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
04750 
04751    return 0;
04752 }

static int misdn_answer struct ast_channel ast  )  [static]
 

Definition at line 2004 of file chan_misdn.c.

References chan_list::ast, ast_log(), ast_queue_hangup(), ast_strlen_zero(), chan_list::bc, chan_misdn_log(), LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, pbx_builtin_getvar_helper(), start_bc_tones(), chan_list::state, and stop_indicate().

02005 {
02006    struct chan_list *p;
02007 
02008    
02009    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02010    
02011    chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
02012    
02013    if (!p) {
02014       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02015       ast_queue_hangup(ast);
02016    }
02017 
02018    if (!p->bc) {
02019       chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
02020 
02021       ast_queue_hangup(ast);
02022    }
02023 
02024    {
02025       const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
02026       
02027       if (tmp_key ) {
02028          chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02029          {
02030             int l = sizeof(p->bc->crypt_key);
02031             strncpy(p->bc->crypt_key,tmp_key, l);
02032             p->bc->crypt_key[l-1] = 0;
02033          }
02034       } else {
02035          chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02036       }
02037     
02038    }
02039 
02040    {
02041       const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02042       if (nodsp) {
02043          chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02044          p->bc->nodsp=1;
02045          p->bc->hdlc=0;
02046          p->bc->nojitter=1;
02047       }
02048    }
02049    
02050    p->state = MISDN_CONNECTED;
02051    stop_indicate(p);
02052 
02053    if ( ast_strlen_zero(p->bc->cad) ) {
02054       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
02055       ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
02056    }
02057 
02058    misdn_lib_send_event( p->bc, EVENT_CONNECT);
02059    start_bc_tones(p);
02060    
02061    return 0;
02062 }

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 2677 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, ast_frame::frametype, get_chan_by_ast(), chan_list::ignore_dtmf, LOG_NOTICE, misdn_cfg_get(), option_verbose, ast_frame::subclass, and VERBOSE_PREFIX_3.

02683 {
02684    struct chan_list *ch1,*ch2;
02685    struct ast_channel *carr[2], *who;
02686    int to=-1;
02687    struct ast_frame *f;
02688   
02689    ch1=get_chan_by_ast(c0);
02690    ch2=get_chan_by_ast(c1);
02691 
02692    carr[0]=c0;
02693    carr[1]=c1;
02694   
02695    if (ch1 && ch2 ) ;
02696    else
02697       return -1;
02698 
02699    int bridging;
02700    misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02701    if (bridging) {
02702       /* trying to make a mISDN_dsp conference */
02703       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
02704       misdn_lib_bridge(ch1->bc,ch2->bc);
02705    }
02706    
02707    if (option_verbose > 2) 
02708       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
02709 
02710    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
02711  
02712    if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
02713       ch1->ignore_dtmf=1;
02714 
02715    if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
02716       ch2->ignore_dtmf=1;
02717 
02718    while(1) {
02719       to=-1;
02720       who = ast_waitfor_n(carr, 2, &to);
02721 
02722       if (!who) {
02723          ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
02724          break;
02725       }
02726       f = ast_read(who);
02727     
02728       if (!f || f->frametype == AST_FRAME_CONTROL) {
02729          /* got hangup .. */
02730 
02731          if (!f) 
02732             chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
02733          else
02734             chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
02735          
02736          *fo=f;
02737          *rc=who;
02738       
02739          break;
02740       }
02741       
02742       if ( f->frametype == AST_FRAME_DTMF ) {
02743          chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
02744 
02745          *fo=f;
02746          *rc=who;
02747          break;
02748       }
02749    
02750 #if 0
02751       if (f->frametype == AST_FRAME_VOICE) {
02752          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
02753    
02754          continue;
02755       }
02756 #endif
02757 
02758       if (who == c0) {
02759          ast_write(c1,f);
02760       }
02761       else {
02762          ast_write(c0,f);
02763       }
02764     
02765    }
02766    
02767    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
02768    
02769    misdn_lib_split_bridge(ch1->bc,ch2->bc);
02770    
02771    
02772    return AST_BRIDGE_COMPLETE;
02773 }

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

we should have l3id after sending setup

Definition at line 1858 of file chan_misdn.c.

References ast_channel::_state, add_out_calls(), chan_list::ast, AST_CID_P, ast_log(), ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), chan_list::bc, chan_misdn_log(), ast_channel::context, ext, ast_channel::exten, ast_channel::hangupcause, import_ch(), chan_list::l3id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, misdn_cfg_get(), misdn_set_opt_exec(), ORG_AST, chan_list::other_ch, pbx_builtin_setvar_helper(), chan_list::state, stop_bc_tones(), ast_channel::transfercapability, and update_config().

01859 {
01860    int port=0;
01861    int r;
01862    struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01863    struct misdn_bchannel *newbc;
01864    char *opts=NULL, *ext,*tokb;
01865    char dest_cp[256];
01866 
01867    {
01868       strncpy(dest_cp,dest,sizeof(dest_cp)-1);
01869       dest_cp[sizeof(dest_cp)]=0;
01870       
01871       ext=strtok_r(dest_cp,"/",&tokb);
01872       
01873       if (ext) {
01874          ext=strtok_r(NULL,"/",&tokb);
01875          if (ext) {
01876             opts=strtok_r(NULL,"/",&tokb);
01877          } else {
01878             chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
01879             return -1;
01880          }
01881       }
01882    }
01883 
01884    if (!ast) {
01885       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
01886       return -1;
01887    }
01888 
01889    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
01890       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01891       ast->hangupcause=41;
01892       ast_setstate(ast, AST_STATE_DOWN);
01893       return -1;
01894    }
01895 
01896    if (!ch) {
01897       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01898       ast->hangupcause=41;
01899       ast_setstate(ast, AST_STATE_DOWN);
01900       return -1;
01901    }
01902    
01903    newbc=ch->bc;
01904    
01905    if (!newbc) {
01906       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01907       ast->hangupcause=41;
01908       ast_setstate(ast, AST_STATE_DOWN);
01909       return -1;
01910    }
01911    
01912    port=newbc->port;
01913    strncpy(newbc->dad,ext,sizeof( newbc->dad));
01914    strncpy(ast->exten,ext,sizeof(ast->exten));
01915 
01916    int exceed;
01917    if ((exceed=add_out_calls(port))) {
01918       char tmp[16];
01919       sprintf(tmp,"%d",exceed);
01920       pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
01921       return -1;
01922    }
01923    
01924    chan_misdn_log(1, port, "* CALL: %s\n",dest);
01925    
01926    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
01927    
01928    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
01929    if (ast->exten) {
01930       int l = sizeof(newbc->dad);
01931       strncpy(newbc->dad,ast->exten, l);
01932       newbc->dad[l-1] = 0;
01933    }
01934    newbc->rad[0]=0;
01935    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
01936    if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
01937 
01938       if (AST_CID_P(ast)) {
01939          int l = sizeof(newbc->oad);
01940          strncpy(newbc->oad,AST_CID_P(ast), l);
01941          newbc->oad[l-1] = 0;
01942       }
01943    }
01944    
01945    {
01946       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01947       if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
01948       
01949       newbc->capability=ast->transfercapability;
01950       pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
01951       if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
01952          chan_misdn_log(2, port, " --> * Call with flag Digital\n");
01953       }
01954       
01955 
01956       /* update screening and presentation */ 
01957       update_config(ch,ORG_AST);
01958       
01959       /* fill in some ies from channel vary*/
01960       import_ch(ast, newbc, ch);
01961       
01962       /* Finally The Options Override Everything */
01963       if (opts)
01964          misdn_set_opt_exec(ast,opts);
01965       else
01966          chan_misdn_log(2,port,"NO OPTS GIVEN\n");
01967 
01968       /*check for bridging*/
01969       int bridging;
01970       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
01971       if (bridging && ch->other_ch) {
01972          chan_misdn_log(0, port, "Disabling EC on both Sides\n"); 
01973          ch->bc->ec_enable=0;
01974          ch->other_ch->bc->ec_enable=0;
01975       }
01976       
01977       r=misdn_lib_send_event( newbc, EVENT_SETUP );
01978       
01979       /** we should have l3id after sending setup **/
01980       ch->l3id=newbc->l3_id;
01981    }
01982    
01983    if ( r == -ENOCHAN  ) {
01984       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
01985       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
01986       ast->hangupcause=34;
01987       ast_setstate(ast, AST_STATE_DOWN);
01988       return -1;
01989    }
01990    
01991    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
01992 
01993    ast_setstate(ast, AST_STATE_DIALING);
01994    ast->hangupcause=16;
01995    
01996    if (newbc->nt) stop_bc_tones(ch);
01997 
01998    ch->state=MISDN_CALLING;
01999    
02000    return 0; 
02001 }

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

Definition at line 2064 of file chan_misdn.c.

02065 {
02066    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02067    return 0;
02068 }

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

Definition at line 2070 of file chan_misdn.c.

References chan_list::ast, ast_log(), chan_list::bc, chan_misdn_log(), ast_channel::exten, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, send_digit_to_chan(), and chan_list::state.

02071 {
02072    struct chan_list *p;
02073    
02074    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02075 
02076    struct misdn_bchannel *bc=p->bc;
02077    chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
02078    
02079    if (!bc) {
02080       ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
02081       return -1;
02082    }
02083    
02084    switch (p->state ) {
02085       case MISDN_CALLING:
02086       {
02087          
02088          char buf[8];
02089          buf[0]=digit;
02090          buf[1]=0;
02091          
02092          int l = sizeof(bc->infos_pending);
02093          strncat(bc->infos_pending,buf,l);
02094          bc->infos_pending[l-1] = 0;
02095       }
02096       break;
02097       case MISDN_CALLING_ACKNOWLEDGE:
02098       {
02099          bc->info_dad[0]=digit;
02100          bc->info_dad[1]=0;
02101          
02102          {
02103             int l = sizeof(bc->dad);
02104             strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
02105             bc->dad[l-1] = 0;
02106       }
02107          {
02108             int l = sizeof(p->ast->exten);
02109             strncpy(p->ast->exten, bc->dad, l);
02110             p->ast->exten[l-1] = 0;
02111          }
02112          
02113          misdn_lib_send_event( bc, EVENT_INFORMATION);
02114       }
02115       break;
02116       
02117       default:
02118          if ( bc->send_dtmf ) {
02119             send_digit_to_chan(p,digit);
02120          }
02121       break;
02122    }
02123    
02124    return 0;
02125 }

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

Definition at line 4765 of file chan_misdn.c.

References ast_log(), ast_strlen_zero(), chan_list::bc, chan_misdn_log(), LOG_WARNING, MISDN_ASTERISK_TECH_PVT, ast_channel::tech, and ast_channel_tech::type.

04766 {
04767    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
04768    char *tok, *tokb;
04769 
04770    chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
04771    
04772    if (strcasecmp(chan->tech->type,"mISDN")) {
04773       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
04774       return -1;
04775    }
04776    
04777    if (ast_strlen_zero((char *)data)) {
04778       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
04779       return -1;
04780    }
04781    
04782    tok=strtok_r((char*)data,"|", &tokb) ;
04783    
04784    if (!tok) {
04785       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
04786       return -1;
04787    }
04788    
04789    if (!strcasecmp(tok,"calldeflect")) {
04790       tok=strtok_r(NULL,"|", &tokb) ;
04791       
04792       if (!tok) {
04793          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
04794       }
04795    
04796       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
04797          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
04798          return 0; 
04799       }
04800       ch->bc->fac_out.Function = Fac_CD;
04801       strncpy((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
04802       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
04803    } else {
04804       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n",tok);
04805    }
04806    
04807    return 0;
04808    
04809 }

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

Definition at line 2128 of file chan_misdn.c.

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

02129 {
02130    struct chan_list *p;
02131    
02132    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02133    
02134    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);
02135    
02136    p->ast = ast ;
02137   
02138    return 0;
02139 }

static char* misdn_get_ch_state struct chan_list p  )  [static]
 

Definition at line 953 of file chan_misdn.c.

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

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

00954 {
00955    int i;
00956    static char state[8];
00957    
00958    if( !p) return NULL;
00959   
00960    for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
00961       if ( state_array[i].state == p->state) return state_array[i].txt; 
00962    }
00963 
00964    sprintf(state,"%d",p->state) ;
00965 
00966    return state;
00967 }

static int misdn_hangup struct ast_channel ast  )  [static]
 

Definition at line 2277 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CID_P, ast_log(), AST_STATE_RESERVED, chan_list::bc, chan_misdn_log(), cl_dequeue_chan(), cl_te, ast_channel::context, 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_NOTHING, MISDN_PRECONNECTED, MISDN_PROCEEDING, MISDN_PROGRESS, MISDN_RELEASED, chan_list::need_busy, chan_list::need_hangup, chan_list::need_queue_hangup, option_debug, ORG_AST, chan_list::orginator, pbx_builtin_getvar_helper(), chan_list::pipe, start_bc_tones(), chan_list::state, and stop_bc_tones().

02278 {
02279    struct chan_list *p;
02280    struct misdn_bchannel *bc=NULL;
02281 
02282    if (option_debug)
02283       ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
02284    
02285    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
02286    
02287    if (!p) {
02288       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
02289       return 0 ;
02290    }
02291    
02292    bc=p->bc;
02293 
02294 
02295    
02296    MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02297    p->ast=NULL;
02298 
02299    bc=p->bc;
02300    
02301    if (ast->_state == AST_STATE_RESERVED || 
02302       p->state == MISDN_NOTHING || 
02303       p->state == MISDN_HOLDED || 
02304       p->state == MISDN_HOLD_DISCONNECT ) {
02305 
02306       CLEAN_CH:
02307       /* between request and call */
02308       if (option_debug)
02309          ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
02310       MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02311       
02312       cl_dequeue_chan(&cl_te, p);
02313       close(p->pipe[0]);
02314       close(p->pipe[1]);
02315       free(p);
02316       
02317       if (bc)
02318          misdn_lib_release(bc);
02319       
02320       return 0;
02321    }
02322 
02323    if (!bc) {
02324       ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02325       goto CLEAN_CH;
02326    }
02327 
02328 
02329    p->need_hangup=0;
02330    p->need_queue_hangup=0;
02331    p->need_busy=0;
02332 
02333 
02334    if (!p->bc->nt) 
02335       stop_bc_tones(p);
02336 
02337    
02338    {
02339       const char *varcause=NULL;
02340       bc->out_cause=ast->hangupcause?ast->hangupcause:16;
02341       
02342       if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02343            (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02344          int tmpcause=atoi(varcause);
02345          bc->out_cause=tmpcause?tmpcause:16;
02346       }
02347     
02348       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_P(ast), misdn_get_ch_state(p));
02349       chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
02350       chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
02351       chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
02352       chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02353       
02354       switch (p->state) {
02355       case MISDN_CALLING:
02356          p->state=MISDN_CLEANING;
02357          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02358          break;
02359       case MISDN_HOLDED:
02360       case MISDN_DIALING:
02361          start_bc_tones(p);
02362          hanguptone_indicate(p);
02363       
02364          if (bc->need_disconnect)
02365             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02366          break;
02367 
02368       case MISDN_CALLING_ACKNOWLEDGE:
02369          start_bc_tones(p);
02370          hanguptone_indicate(p);
02371       
02372          if (bc->need_disconnect)
02373             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02374          break;
02375       
02376       case MISDN_ALERTING:
02377       case MISDN_PROGRESS:
02378       case MISDN_PROCEEDING:
02379          if (p->orginator != ORG_AST) 
02380             hanguptone_indicate(p);
02381       
02382          /*p->state=MISDN_CLEANING;*/
02383          if (bc->need_disconnect)
02384             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02385          break;
02386       case MISDN_CONNECTED:
02387       case MISDN_PRECONNECTED:
02388          /*  Alerting or Disconect */
02389          if (p->bc->nt) {
02390             start_bc_tones(p);
02391             hanguptone_indicate(p);
02392             p->bc->progress_indicator=8;
02393          }
02394          if (bc->need_disconnect)
02395             misdn_lib_send_event( bc, EVENT_DISCONNECT);
02396 
02397          /*p->state=MISDN_CLEANING;*/
02398          break;
02399       case MISDN_DISCONNECTED:
02400          misdn_lib_send_event( bc, EVENT_RELEASE);
02401          p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
02402          break;
02403 
02404       case MISDN_RELEASED:
02405       case MISDN_CLEANING:
02406          p->state=MISDN_CLEANING;
02407          break;
02408 
02409       case MISDN_BUSY:
02410          break;
02411       
02412       case MISDN_HOLD_DISCONNECT:
02413          /* need to send release here */
02414          chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
02415          chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
02416          
02417          bc->out_cause=-1;
02418          misdn_lib_send_event(bc,EVENT_RELEASE);
02419          p->state=MISDN_CLEANING;
02420          break;
02421       default:
02422          if (bc->nt) {
02423             bc->out_cause=-1;
02424             misdn_lib_send_event(bc, EVENT_RELEASE);
02425             p->state=MISDN_CLEANING; 
02426          } else {
02427             if (bc->need_disconnect)
02428                misdn_lib_send_event(bc, EVENT_DISCONNECT);
02429          }
02430       }
02431 
02432       p->state=MISDN_CLEANING;
02433     
02434    }
02435    
02436 
02437    chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
02438    
02439    return 0;
02440 }

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

Definition at line 2143 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_setstate(), AST_STATE_BUSY, AST_STATE_RINGING, chan_list::bc, chan_misdn_log(), ast_channel::exten, hanguptone_indicate(), chan_list::incoming_early_audio, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, ORG_MISDN, chan_list::orginator, chan_list::other_ch, start_bc_tones(), chan_list::state, and stop_indicate().

02144 {
02145    struct chan_list *p;
02146 
02147   
02148    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02149       ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
02150       return -1;
02151    }
02152    
02153    if (!p->bc ) {
02154       chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
02155       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02156       return -1;
02157    }
02158    
02159    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
02160    
02161    switch (cond) {
02162    case AST_CONTROL_BUSY:
02163       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
02164       ast_setstate(ast,AST_STATE_BUSY);
02165 
02166       p->bc->out_cause=17;
02167       if (p->state != MISDN_CONNECTED) {
02168          start_bc_tones(p);
02169          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02170       } else {
02171          chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
02172       }
02173       return -1;
02174       break;
02175    case AST_CONTROL_RING:
02176       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
02177       return -1;
02178       break;
02179       
02180    case AST_CONTROL_RINGING:
02181       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
02182       switch (p->state) {
02183          case MISDN_ALERTING:
02184             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);
02185             break;
02186          case MISDN_CONNECTED:
02187             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);
02188             return -1;
02189             break;
02190          default:
02191             p->state=MISDN_ALERTING;
02192             chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
02193             misdn_lib_send_event( p->bc, EVENT_ALERTING);
02194          
02195             if (p->other_ch && p->other_ch->bc) {
02196                if (misdn_inband_avail(p->other_ch->bc)) {
02197                   chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
02198                   break;
02199                }
02200 
02201                if (!p->other_ch->bc->nt) {
02202                   chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02203                   break;
02204                }
02205             }
02206 
02207             chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
02208             ast_setstate(ast,AST_STATE_RINGING);
02209          
02210             if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio ) 
02211                chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
02212             else 
02213                return -1;
02214       }
02215       break;
02216    case AST_CONTROL_ANSWER:
02217       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
02218       start_bc_tones(p);
02219       break;
02220    case AST_CONTROL_TAKEOFFHOOK:
02221       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
02222       return -1;
02223       break;
02224    case AST_CONTROL_OFFHOOK:
02225       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
02226       return -1;
02227       break; 
02228    case AST_CONTROL_FLASH:
02229       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
02230       break;
02231    case AST_CONTROL_PROGRESS:
02232       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
02233       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02234       break;
02235    case AST_CONTROL_PROCEEDING:
02236       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
02237       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02238       break;
02239    case AST_CONTROL_CONGESTION:
02240       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
02241 
02242       p->bc->out_cause=42;
02243       if (p->state != MISDN_CONNECTED) {
02244          start_bc_tones(p);
02245          misdn_lib_send_event( p->bc, EVENT_RELEASE);
02246       } else {
02247          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02248       }
02249 
02250       if (p->bc->nt) {
02251          hanguptone_indicate(p);
02252       }
02253       break;
02254    case -1 :
02255       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
02256       
02257       stop_indicate(p);
02258 
02259       if (p->state == MISDN_CONNECTED) 
02260          start_bc_tones(p);
02261 
02262       break;
02263 
02264    case AST_CONTROL_HOLD:
02265       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
02266       break;
02267    case AST_CONTROL_UNHOLD:
02268       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
02269       break;
02270    default:
02271       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
02272    }
02273   
02274    return 0;
02275 }

void misdn_jb_destroy struct misdn_jb jb  ) 
 

Definition at line 5055 of file chan_misdn.c.

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

Referenced by config_jitterbuffer(), and release_chan().

05056 {
05057    ast_mutex_destroy(&jb->mutexjb);
05058    
05059    free(jb->samples);
05060    free(jb);
05061 }

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

Definition at line 5127 of file chan_misdn.c.

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

Referenced by chan_misdn_jb_empty().

05128 {
05129     int i, wp, rp, read=0;
05130 
05131     ast_mutex_lock (&jb->mutexjb);
05132 
05133     rp=jb->rp;
05134     wp=jb->wp;
05135 
05136     if(jb->state_empty)
05137     { 
05138    for(i=0; i<len; i++)
05139    {
05140        if(wp==rp)
05141        {
05142       jb->rp=rp;
05143       jb->state_empty=0;
05144 
05145       ast_mutex_unlock (&jb->mutexjb);
05146       
05147       return read;
05148        }
05149        else
05150        {
05151       if(jb->ok[rp]==1)
05152       {
05153           data[i]=jb->samples[rp];
05154           jb->ok[rp]=0;
05155           rp=(rp!=jb->size-1 ? rp+1 : 0);
05156           read+=1;
05157       }
05158        }
05159    }
05160 
05161    if(wp >= rp)
05162       jb->state_buffer=wp-rp;
05163    else
05164       jb->state_buffer= jb->size-rp+wp;
05165    chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05166    
05167    jb->rp=rp;
05168     }
05169     else
05170        chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
05171     
05172     ast_mutex_unlock (&jb->mutexjb);
05173 
05174     return read;
05175 }

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

Definition at line 5065 of file chan_misdn.c.

References ast_mutex_lock(), misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::rp, misdn_jb::samples, misdn_jb::size, misdn_jb::state_full, and misdn_jb::wp.

05066 {
05067     int i, j, rp, wp;
05068 
05069     if (!jb || ! data) return 0;
05070 
05071     ast_mutex_lock (&jb->mutexjb);
05072     
05073     wp=jb->wp;
05074     rp=jb->rp;
05075    
05076     for(i=0; i<len; i++)
05077     {
05078    jb->samples[wp]=data[i];
05079    jb->ok[wp]=1;
05080    wp = (wp!=jb->size-1 ? wp+1 : 0);
05081 
05082    if(wp==jb->rp)
05083        jb->state_full=1;
05084     }
05085     
05086     if(wp>=rp)
05087       jb->state_buffer=wp-rp;
05088     else
05089       jb->state_buffer= jb->size-rp+wp;
05090     chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05091     
05092     if(jb->state_full)
05093     {
05094    jb->wp=wp;
05095 
05096    rp=wp;
05097    for(j=0; j<jb->upper_threshold; j++)
05098        rp = (rp!=0 ? rp-1 : jb->size-1);
05099    jb->rp=rp;
05100    jb->state_full=0;
05101    jb->state_empty=1;
05102 
05103    ast_mutex_unlock (&jb->mutexjb);
05104    
05105    return -1;
05106     }
05107 
05108     if(!jb->state_empty)
05109     {
05110    jb->bytes_wrote+=len;
05111    if(jb->bytes_wrote>=jb->upper_threshold)
05112    {
05113        jb->state_empty=1;
05114        jb->bytes_wrote=0;
05115    }
05116     }
05117     jb->wp=wp;
05118 
05119     ast_mutex_unlock (&jb->mutexjb);
05120     
05121     return 0;
05122 }

struct misdn_jb * misdn_jb_init int  size,
int  upper_threshold
 

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

05022 {
05023     int i;
05024     struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
05025     jb->size = size;
05026     jb->upper_threshold = upper_threshold;
05027     jb->wp = 0;
05028     jb->rp = 0;
05029     jb->state_full = 0;
05030     jb->state_empty = 0;
05031     jb->bytes_wrote = 0;
05032     jb->samples = (char *)malloc(size*sizeof(char));
05033 
05034     if (!jb->samples) {
05035        chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
05036        return NULL;
05037     }
05038     
05039     jb->ok = (char *)malloc(size*sizeof(char));
05040 
05041     if (!jb->ok) {
05042        chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
05043        return NULL;
05044     }
05045 
05046     for(i=0; i<size; i++)
05047    jb->ok[i]=0;
05048 
05049     ast_mutex_init(&jb->mutexjb);
05050 
05051     return jb;
05052 }

static int misdn_l1_task void *  data  )  [static]
 

Definition at line 584 of file chan_misdn.c.

References chan_misdn_log().

00585 {
00586    misdn_lib_isdn_l1watcher(*(int *)data);
00587    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00588    return 1;
00589 }

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

References cid_name, cid_num, and misdn_cfg_get_next_port().

Referenced by cb_events().

03115 {
03116    struct ast_channel *tmp;
03117    char *cid_name = 0, *cid_num = 0;
03118    int chan_offset=0;
03119    int tmp_port = misdn_cfg_get_next_port(0);
03120 
03121    for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
03122    if (tmp_port == port) break;
03123       chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2; 
03124    }
03125    if (c<0) c=0;
03126 
03127    
03128    if (callerid) 
03129       ast_callerid_parse(callerid, &cid_name, &cid_num);
03130 
03131    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03132    
03133    if (tmp) {
03134       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
03135       
03136       tmp->nativeformats = prefformat;
03137 
03138       tmp->readformat = format;
03139       tmp->rawreadformat = format;
03140       tmp->writeformat = format;
03141       tmp->rawwriteformat = format;
03142     
03143       tmp->tech_pvt = chlist;
03144       
03145       int bridging;
03146       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03147       if (bridging)
03148          tmp->tech = &misdn_tech;
03149       else
03150          tmp->tech = &misdn_tech_wo_bridge;
03151       
03152       tmp->writeformat = format;
03153       tmp->readformat = format;
03154       tmp->priority=1;
03155       
03156       if (exten) 
03157          ast_copy_string(tmp->exten, exten,  sizeof(tmp->exten));
03158       else
03159          chan_misdn_log(1,0,"misdn_new: no exten given.\n");
03160       
03161       if (callerid) {
03162          char *cid_name, *cid_num;
03163       
03164          ast_callerid_parse(callerid, &cid_name, &cid_num);
03165          /* Don't use ast_set_callerid() here because it will
03166           * generate a needless NewCallerID event */
03167          tmp->cid.cid_num = ast_strdup(cid_num);
03168          tmp->cid.cid_ani = ast_strdup(cid_num);
03169          tmp->cid.cid_name = ast_strdup(cid_name);
03170       }
03171 
03172       {
03173          if (pipe(chlist->pipe)<0)
03174             perror("Pipe failed\n");
03175          
03176          tmp->fds[0]=chlist->pipe[0];
03177          
03178       }
03179       
03180       if (state == AST_STATE_RING)
03181          tmp->rings = 1;
03182       else
03183          tmp->rings = 0;
03184       
03185       
03186    } else {
03187       chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
03188    }
03189    
03190    return tmp;
03191 }

static int misdn_overlap_dial_task void *  data  )  [static]
 

Definition at line 591 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, hanguptone_indicate(), MISDN_DIALING, MISDN_WAITING4DIGS, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_start_chan(), chan_list::state, and stop_indicate().

Referenced by cb_events().

00592 {
00593    struct timeval tv_end, tv_now;
00594    int diff;
00595    struct chan_list *ch = (struct chan_list *)data;
00596 
00597    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
00598 
00599    if (ch->state != MISDN_WAITING4DIGS) {
00600       ch->overlap_dial_task = -1;
00601       return 0;
00602    }
00603    
00604    ast_mutex_lock(&ch->overlap_tv_lock);
00605    tv_end = ch->overlap_tv;
00606    ast_mutex_unlock(&ch->overlap_tv_lock);
00607    
00608    tv_end.tv_sec += ch->overlap_dial;
00609    tv_now = ast_tvnow();
00610 
00611    diff = ast_tvdiff_ms(tv_end, tv_now);
00612 
00613    if (diff <= 100) {
00614       /* if we are 100ms near the timeout, we are satisfied.. */
00615       stop_indicate(ch);
00616       if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) {
00617          ch->state=MISDN_DIALING;
00618          if (pbx_start_chan(ch) < 0) {
00619             chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
00620             goto misdn_overlap_dial_task_disconnect;
00621          }
00622       } else {
00623 misdn_overlap_dial_task_disconnect:
00624          hanguptone_indicate(ch);
00625          if (ch->bc->nt)
00626             misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE );
00627          else
00628             misdn_lib_send_event(ch->bc, EVENT_RELEASE);
00629       }
00630       ch->overlap_dial_task = -1;
00631       return 0;
00632    } else
00633       return diff;
00634 }

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