Sun Aug 6 15:06:06 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

chan_misdn.c File Reference

the chan_misdn channel driver for Asterisk More...

#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 <sys/file.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 "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.

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 MISDN_ASTERISK_TYPE(ast)   ast->tech->type
#define ORG_AST   1
#define ORG_MISDN   2
#define release_lock   ast_mutex_lock(&release_lock_mutex)
#define release_unlock   ast_mutex_unlock(&release_lock_mutex)

Enumerations

enum  misdn_chan_state {
  MISDN_NOTHING, MISDN_WAITING4DIGS, MISDN_EXTCANTMATCH, MISDN_DIALING,
  MISDN_PROGRESS, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, MISDN_ALERTING,
  MISDN_BUSY, MISDN_CONNECTED, MISDN_BRIDGED, MISDN_CLEANING,
  MISDN_HUNGUP_FROM_MISDN, MISDN_HUNGUP_FROM_AST, MISDN_HOLDED, MISDN_HOLD_DISCONNECT
}

Functions

static char * bearer2str (int cap)
enum event_response_e cb_events (enum event_e event, struct misdn_bchannel *bc, void *user_data)
void chan_misdn_log (int level, int port, char *tmpl,...)
void chan_misdn_trace_call (struct ast_channel *chan, int debug, char *tmpl,...)
void cl_dequeue_chan (struct chan_list **list, struct chan_list *chan)
void cl_queue_chan (struct chan_list **list, struct chan_list *chan)
int clearl3_true (void)
static char * complete_ch (char *line, char *word, int pos, int state)
static char * complete_ch_helper (char *line, char *word, int pos, int state, int rpos)
static char * complete_debug_port (char *line, char *word, int pos, int state)
char * description (void)
 Provides a description of the module.
void do_immediate_setup (struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
chan_listfind_chan_by_bc (struct chan_list *list, struct misdn_bchannel *bc)
chan_listfind_chan_by_l3id (struct chan_list *list, unsigned long l3id)
chan_listfind_holded (struct chan_list *list, struct misdn_bchannel *bc)
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)
robin_listget_robin_position (char *group)
chan_listinit_chan_list (void)
char * key (void)
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
int misdn_answer (struct ast_channel *ast)
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)
int misdn_digit (struct ast_channel *ast, char digit)
static int misdn_facility_exec (struct ast_channel *chan, void *data)
int misdn_fixup (struct ast_channel *oldast, struct ast_channel *ast)
char * misdn_get_ch_state (struct chan_list *p)
int misdn_hangup (struct ast_channel *ast)
int misdn_indication (struct ast_channel *ast, int cond)
ast_channelmisdn_new (struct chan_list *cl, int state, char *name, char *context, char *exten, char *callerid, int format, int port, int c)
static int misdn_port_up (int fd, int argc, char *argv[])
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_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_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_stacks (int fd, int argc, char *argv[])
static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
int misdn_transfer (struct ast_channel *ast, char *dest)
void misdn_transfer_bc (struct chan_list *tmp_ch, struct chan_list *holded_chan)
int misdn_tx2ast_frm (struct chan_list *tmp, char *buf, int len)
int misdn_write (struct ast_channel *ast, struct ast_frame *frame)
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 release_chan (struct misdn_bchannel *bc)
void send_cause2ast (struct ast_channel *ast, struct misdn_bchannel *bc)
void send_digit_to_chan (struct chan_list *cl, char digit)
static int start_bc_tones (struct chan_list *cl)
static int stop_bc_tones (struct chan_list *cl)
static char * tone2str (struct misdn_bchannel *bc)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

chan_listcl_te = NULL
ast_mutex_t cl_te_lock
static struct ast_cli_entry cli_port_up
static struct ast_cli_entry cli_reload
static struct ast_cli_entry cli_restart_port
static struct ast_cli_entry cli_send_cd
static struct ast_cli_entry cli_send_digit
static struct ast_cli_entry cli_send_display
static struct ast_cli_entry cli_set_crypt_debug
static struct ast_cli_entry cli_set_debug
static struct ast_cli_entry cli_set_tics
static struct ast_cli_entry cli_show_cl
static struct ast_cli_entry cli_show_cls
static struct ast_cli_entry cli_show_config
static struct ast_cli_entry cli_show_port
static struct ast_cli_entry cli_show_stacks
static struct ast_cli_entry cli_toggle_echocancel
static char * desc = "Channel driver for mISDN Support (Bri/Pri)"
chan_list dummy_cl
int g_config_initialized = 0
unsigned long glob_channel = 0
ast_mutex_t lock
int max_ports
int MAXTICS = 8
int * misdn_debug
int * misdn_debug_only
char ** misdn_key_vector = NULL
int misdn_key_vector_size = 0
ast_channel_tech misdn_tech
ast_channel_tech misdn_tech_wo_bridge
static int prefformat = AST_FORMAT_ALAW
ast_mutex_t release_lock_mutex
static struct robin_listrobin = NULL
state_struct state_array []
int tracing = 0
static char * type = "mISDN"
static int usecnt = 0
static ast_mutex_t usecnt_lock


Detailed Description

the chan_misdn channel driver for Asterisk

Author:
Christian Richter <crich@beronet.com>

Definition in file chan_misdn.c.


Define Documentation

#define AST_BRIDGED_P ast   )     ast_bridged_channel(ast)
 

Definition at line 181 of file chan_misdn.c.

Referenced by cb_events(), and misdn_transfer_bc().

#define AST_CID_P ast   )     ast->cid.cid_num
 

Definition at line 180 of file chan_misdn.c.

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

#define AST_DESTROY_CFG   ast_config_destroy
 

Definition at line 183 of file chan_misdn.c.

Referenced by misdn_cfg_init().

#define AST_LOAD_CFG   ast_config_load
 

Definition at line 182 of file chan_misdn.c.

Referenced by misdn_cfg_init().

#define MISDN_ASTERISK_PVT ast   )     1
 

Definition at line 186 of file chan_misdn.c.

Referenced by cb_events(), do_immediate_setup(), misdn_answer(), misdn_digit(), misdn_fixup(), misdn_indication(), misdn_transfer(), misdn_tx2ast_frm(), and release_chan().

#define MISDN_ASTERISK_TECH_PVT ast   )     ast->tech_pvt
 

Definition at line 185 of file chan_misdn.c.

Referenced by cb_events(), do_immediate_setup(), misdn_answer(), misdn_call(), misdn_digit(), misdn_facility_exec(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_read(), misdn_set_opt_exec(), misdn_transfer(), misdn_tx2ast_frm(), misdn_write(), and release_chan().

#define MISDN_ASTERISK_TYPE ast   )     ast->tech->type
 

Definition at line 187 of file chan_misdn.c.

Referenced by misdn_facility_exec(), and misdn_set_opt_exec().

#define ORG_AST   1
 

Definition at line 94 of file chan_misdn.c.

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

#define ORG_MISDN   2
 

Definition at line 95 of file chan_misdn.c.

Referenced by cb_events().

#define release_lock   ast_mutex_lock(&release_lock_mutex)
 

Definition at line 67 of file chan_misdn.c.

Referenced by misdn_hangup(), and release_chan().

#define release_unlock   ast_mutex_unlock(&release_lock_mutex)
 

Definition at line 68 of file chan_misdn.c.

Referenced by misdn_hangup(), and release_chan().


Enumeration Type Documentation

enum misdn_chan_state
 

Enumeration values:
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_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_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 73 of file chan_misdn.c.

00073                       {
00074    MISDN_NOTHING,    /*!< at beginning */
00075    MISDN_WAITING4DIGS, /*!<  when waiting for infos */
00076    MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
00077    MISDN_DIALING, /*!<  when pbx_start */
00078    MISDN_PROGRESS, /*!<  we got a progress */
00079    MISDN_CALLING, /*!<  when misdn_call is called */
00080    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
00081    MISDN_ALERTING, /*!<  when Alerting */
00082    MISDN_BUSY, /*!<  when BUSY */
00083    MISDN_CONNECTED, /*!<  when connected */
00084    MISDN_BRIDGED, /*!<  when bridged */
00085    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00086    MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
00087    MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
00088    /* misdn_hangup */
00089    MISDN_HOLDED, /*!< if this chan is holded */
00090    MISDN_HOLD_DISCONNECT /*!< if this chan is holded */
00091   
00092 };


Function Documentation

static char* bearer2str int  cap  )  [static]
 

Definition at line 281 of file chan_misdn.c.

Referenced by print_bc_info(), and print_bearer().

00281                                  {
00282    static char *bearers[]={
00283       "Speech",
00284       "Audio 3.1k",
00285       "Unres Digital",
00286       "Res Digital",
00287       "Unknown Bearer"
00288    };
00289    
00290    switch (cap) {
00291    case INFO_CAPABILITY_SPEECH:
00292       return bearers[0];
00293       break;
00294    case INFO_CAPABILITY_AUDIO_3_1K:
00295       return bearers[1];
00296       break;
00297    case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00298       return bearers[2];
00299       break;
00300    case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00301       return bearers[3];
00302       break;
00303    default:
00304       return bearers[4];
00305       break;
00306    }
00307 }

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

queue new chan

from here on we start the PBX, so no configuration should be considered anymore

Sending SETUP_ACK

Now after we've finished configuring our channel object we'll jump into the dialplan

Suplementary Services

Definition at line 2620 of file chan_misdn.c.

References chan_list::addr, chan_list::ast, AST_BRIDGED_P, ast_canmatch_extension(), ast_cdr_update(), AST_CONTROL_ANSWER, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, ast_hangup(), ast_log(), ast_moh_start(), ast_moh_stop(), ast_pbx_start(), ast_pickup_call(), ast_pickup_ext(), AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, ast_queue_control(), ast_queue_frame(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_RINGING, ast_strlen_zero(), ast_transfercapability2str(), chan_list::bc, chan_misdn_log(), chan_misdn_trace_call(), ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), ast_frame::data, ast_frame::datalen, do_immediate_setup(), ast_channel::exten, find_chan_by_bc(), find_chan_by_l3id(), find_holded(), ast_frame::frametype, free, immediate, init_chan_list(), chan_list::l3id, ast_channel::language, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, MISDN_ALERTING, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, misdn_cfg_get(), misdn_cfg_is_msn_valid(), MISDN_CONNECTED, MISDN_DIALING, MISDN_EXTCANTMATCH, MISDN_HOLDED, misdn_new(), MISDN_NOTHING, MISDN_PROGRESS, misdn_transfer_bc(), misdn_tx2ast_frm(), MISDN_WAITING4DIGS, name, ast_frame::offset, ORG_MISDN, chan_list::orginator, pbx_builtin_setvar_helper(), chan_list::pipe, print_bearer(), release_chan(), ast_frame::samples, send_cause2ast(), ast_frame::src, start_bc_tones(), chan_list::state, stop_bc_tones(), ast_frame::subclass, and ast_channel::transfercapability.

Referenced by load_module().

02621 {
02622    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02623    
02624    if (!ch)
02625       ch=find_chan_by_l3id(cl_te, bc->l3_id);
02626    
02627    if (event != EVENT_BCHAN_DATA) { /*  Debug Only Non-Bchan */
02628       chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s port:%d\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->port);
02629       misdn_lib_log_ies(bc);
02630    }
02631    
02632    if (event != EVENT_SETUP) {
02633       if (!ch) {
02634          if (event != EVENT_CLEANUP )
02635             ast_log(LOG_WARNING, "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);
02636          return -1;
02637       }
02638    }
02639    
02640    if (ch ) {
02641       switch (event) {
02642       case EVENT_RELEASE:
02643       case EVENT_RELEASE_COMPLETE:
02644       case EVENT_CLEANUP:
02645          break;
02646       default:
02647          if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02648             if (event!=EVENT_BCHAN_DATA)
02649                ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
02650             return -1;
02651          }
02652       }
02653    }
02654    
02655    
02656    switch (event) {
02657    case EVENT_NEW_L3ID:
02658       ch->l3id=bc->l3_id;
02659       break;
02660 
02661    case EVENT_NEW_BC:
02662       if (bc)
02663          ch->bc=bc;
02664       break;
02665       
02666    case EVENT_DTMF_TONE:
02667    {
02668       /*  sending INFOS as DTMF-Frames :) */
02669       struct ast_frame fr;
02670       memset(&fr, 0 , sizeof(fr));
02671       fr.frametype = AST_FRAME_DTMF;
02672       fr.subclass = bc->dtmf ;
02673       fr.src=NULL;
02674       fr.data = NULL ;
02675       fr.datalen = 0;
02676       fr.samples = 0 ;
02677       fr.mallocd =0 ;
02678       fr.offset= 0 ;
02679       
02680       chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
02681       
02682       ast_queue_frame(ch->ast, &fr);
02683    }
02684    break;
02685    case EVENT_STATUS:
02686       break;
02687     
02688    case EVENT_INFORMATION:
02689    {
02690       int stop_tone;
02691       misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
02692       if ( stop_tone && bc->tone != TONE_NONE) {
02693          manager_send_tone(bc,TONE_NONE);
02694       }
02695       
02696       if (ch->state == MISDN_WAITING4DIGS ) {
02697          /*  Ok, incomplete Setup, waiting till extension exists */
02698          {
02699             int l = sizeof(bc->dad);
02700             strncat(bc->dad,bc->info_dad, l);
02701             bc->dad[l-1] = 0;
02702          }
02703          
02704          
02705          {
02706             int l = sizeof(ch->ast->exten);
02707             strncpy(ch->ast->exten, bc->dad, l);
02708             ch->ast->exten[l-1] = 0;
02709          }
02710 /*       chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
02711          
02712          char bc_context[BUFFERSIZE];
02713          misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02714          if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02715             chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
02716             manager_send_tone(bc,TONE_BUSY);
02717             ch->state=MISDN_EXTCANTMATCH;
02718             bc->out_cause=1;
02719             if (bc->nt)
02720                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02721             else
02722                misdn_lib_send_event(bc, EVENT_DISCONNECT );
02723             break;
02724          }
02725          if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02726             ch->state=MISDN_DIALING;
02727      
02728             manager_send_tone(bc,TONE_NONE);
02729 /*          chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
02730             if (ast_pbx_start(ch->ast)<0) {
02731                chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
02732                manager_send_tone(bc,TONE_BUSY);
02733                if (bc->nt)
02734                   misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02735                else
02736                   misdn_lib_send_event(bc, EVENT_DISCONNECT );
02737             }
02738          }
02739    
02740       } else {
02741          /*  sending INFOS as DTMF-Frames :) */
02742          struct ast_frame fr;
02743          fr.frametype = AST_FRAME_DTMF;
02744          fr.subclass = bc->info_dad[0] ;
02745          fr.src=NULL;
02746          fr.data = NULL ;
02747          fr.datalen = 0;
02748          fr.samples = 0 ;
02749          fr.mallocd =0 ;
02750          fr.offset= 0 ;
02751 
02752          
02753          int digits;
02754          misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
02755          if (ch->state != MISDN_CONNECTED ) {
02756             if (digits) {
02757                int l = sizeof(bc->dad);
02758                strncat(bc->dad,bc->info_dad, l);
02759                bc->dad[l-1] = 0;
02760                l = sizeof(ch->ast->exten);
02761                strncpy(ch->ast->exten, bc->dad, l);
02762                ch->ast->exten[l-1] = 0;
02763 
02764                ast_cdr_update(ch->ast);
02765             }
02766             
02767             ast_queue_frame(ch->ast, &fr);
02768          }
02769          
02770       }
02771    }
02772    break;
02773    case EVENT_SETUP:
02774    {
02775       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02776       if (ch && ch->state != MISDN_NOTHING ) {
02777          chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
02778          return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
02779       }
02780    }
02781    
02782    int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
02783    if (!bc->nt && ! msn_valid) {
02784       chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
02785       return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
02786    }
02787    
02788    print_bearer(bc);
02789     
02790    {
02791       struct chan_list *ch=init_chan_list();
02792       struct ast_channel *chan;
02793       char name[128];
02794       if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
02795       
02796       ch->bc = bc;
02797       ch->l3id=bc->l3_id;
02798       ch->addr=bc->addr;
02799       ch->orginator = ORG_MISDN;
02800 
02801       
02802       {
02803          char prefix[BUFFERSIZE]="";
02804          switch( bc->onumplan ) {
02805          case NUMPLAN_INTERNATIONAL:
02806             misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02807             break;
02808      
02809          case NUMPLAN_NATIONAL:
02810             misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02811             break;
02812      
02813      
02814          case NUMPLAN_SUBSCRIBER:
02815             /* dunno what to do here ? */
02816             break;
02817 
02818          case NUMPLAN_UNKNOWN:
02819             break;
02820          default:
02821             break;
02822          }
02823 
02824          {
02825             int l = strlen(prefix) + strlen(bc->oad);
02826             char tmp[l+1];
02827             strcpy(tmp,prefix);
02828             strcat(tmp,bc->oad);
02829             strcpy(bc->oad,tmp);
02830          }
02831          
02832          if (!ast_strlen_zero(bc->oad))
02833             sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
02834          else
02835             sprintf(name,"mISDN/%d",bc->port);
02836 
02837 
02838          if (!ast_strlen_zero(bc->dad)) {
02839             strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
02840             bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
02841          }
02842          
02843          if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02844             strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
02845             bc->dad[sizeof(bc->dad)-1] = 0;
02846          }
02847          prefix[0] = 0;
02848          
02849          switch( bc->dnumplan ) {
02850          case NUMPLAN_INTERNATIONAL:
02851             misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02852             break;
02853             
02854          case NUMPLAN_NATIONAL:
02855             misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02856             break;
02857             
02858             
02859          case NUMPLAN_SUBSCRIBER:
02860             /* dunno what to do here ? */
02861             break;
02862             
02863          case NUMPLAN_UNKNOWN:
02864             break;
02865          default:
02866             break;
02867          }
02868       
02869          {
02870             int l = strlen(prefix) + strlen(bc->dad);
02871             char tmp[l+1];
02872             strcpy(tmp,prefix);
02873             strcat(tmp,bc->dad);
02874             strcpy(bc->dad,tmp);
02875          }
02876          
02877          char bc_context[BUFFERSIZE];
02878          misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02879          chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
02880          
02881          if (!chan) {
02882             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02883             return 0;
02884          }
02885          
02886          ch->ast = chan;
02887          pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
02888          
02889       }
02890 
02891       
02892 
02893       chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
02894       
02895       if ( bc->pres ) {
02896          chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
02897       }  else {
02898          chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
02899       }
02900       
02901       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
02902       chan->transfercapability=bc->capability;
02903       
02904       switch (bc->capability) {
02905       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02906          pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
02907          break;
02908       default:
02909          pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
02910       }
02911 
02912       /** queue new chan **/
02913       cl_queue_chan(&cl_te, ch) ;
02914 
02915       
02916       /*
02917         added support for s extension hope it will help those poor cretains
02918         which haven't overlap dial.
02919       */
02920       {
02921          
02922          misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));        
02923          
02924       }
02925 
02926       {
02927          int eb3;
02928          
02929          misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
02930          bc->early_bconnect=eb3;
02931          
02932       }
02933 
02934       {
02935          int ec, ectr;
02936          
02937          misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
02938          
02939          misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
02940          if (ec == 1 ) {
02941             bc->ec_enable=1;
02942          } else if ( ec > 1 ) {
02943             bc->ec_enable=1;
02944             bc->ec_deftaps=ec;
02945          }
02946          
02947          if ( ectr>=0 ) {
02948             bc->ec_training=ectr;
02949          }
02950       }
02951       
02952 
02953       if (bc->urate>0) {
02954          char buf[16];
02955          snprintf(buf,16,"%d",bc->urate);
02956          pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
02957       }
02958 
02959 
02960 
02961       /**
02962          from here on  we start the PBX, so no configuration should
02963          be considered anymore
02964       **/
02965       
02966       int ai;
02967       misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
02968       if ( ai ) {
02969          do_immediate_setup(bc, ch , chan);
02970          break;
02971       }
02972       
02973          
02974       int immediate;
02975       misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
02976       
02977       if (ast_strlen_zero(bc->orig_dad) && immediate ) {
02978          do_immediate_setup(bc, ch , chan);
02979          break;
02980       }
02981       
02982       /* Check for Pickup Request first */
02983       if (!strcmp(chan->exten, ast_pickup_ext())) {
02984          int ret;/** Sending SETUP_ACK**/
02985          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02986    
02987          if (ast_pickup_call(chan)) {
02988             ast_hangup(chan);
02989          } else {
02990             ch->state = MISDN_CALLING_ACKNOWLEDGE;
02991      
02992             ch->ast=NULL;
02993      
02994             ast_setstate(chan, AST_STATE_DOWN);
02995             ast_hangup(chan); 
02996      
02997             break;
02998          }
02999       }
03000       
03001       /** Now after we've finished configuring our channel object
03002           we'll jump into the dialplan **/
03003       
03004       char bc_context[BUFFERSIZE];
03005       misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
03006       if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03007          chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
03008          manager_send_tone(bc,TONE_BUSY);
03009          ch->state=MISDN_EXTCANTMATCH;
03010          bc->out_cause=1;
03011          if (bc->nt)
03012             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03013          else
03014             misdn_lib_send_event(bc, EVENT_DISCONNECT );
03015          break;
03016       }
03017       
03018       if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03019          ch->state=MISDN_DIALING;
03020    
03021          if (bc->nt) {
03022             int ret; 
03023             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03024          } else {
03025             int ret;
03026             ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
03027          }
03028    
03029          if (ast_pbx_start(chan)<0) {
03030             chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03031             chan=NULL;
03032             manager_send_tone(bc,TONE_BUSY);
03033             if (bc->nt)
03034                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03035             else
03036                misdn_lib_send_event(bc, EVENT_DISCONNECT );
03037          }
03038       } else {
03039          int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03040          if (ret == -ENOCHAN) {
03041             ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
03042             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03043          }
03044          /*  send tone to phone :) */
03045          
03046          int stop_tone;
03047          misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03048          if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) 
03049             manager_send_tone(bc,TONE_NONE);
03050          else
03051             manager_send_tone(bc,TONE_DIAL);
03052    
03053          ch->state=MISDN_WAITING4DIGS;
03054       }
03055       
03056    }
03057    break;
03058    case EVENT_SETUP_ACKNOWLEDGE:
03059    {
03060       ch->state = MISDN_CALLING_ACKNOWLEDGE;
03061       if (!ast_strlen_zero(bc->infos_pending)) {
03062          /* TX Pending Infos */
03063          
03064          {
03065             int l = sizeof(bc->dad);
03066             strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
03067             bc->dad[l-1] = 0;
03068          }  
03069          {
03070             int l = sizeof(ch->ast->exten);
03071             strncpy(ch->ast->exten, bc->dad, l);
03072             ch->ast->exten[l-1] = 0;
03073          }
03074          {
03075             int l = sizeof(bc->info_dad);
03076             strncpy(bc->info_dad, bc->infos_pending, l);
03077             bc->info_dad[l-1] = 0;
03078          }
03079          strncpy(bc->infos_pending,"", 1);
03080 
03081          misdn_lib_send_event(bc, EVENT_INFORMATION);
03082       }
03083    }
03084    break;
03085    case EVENT_PROCEEDING:
03086    {
03087       
03088       if ( misdn_cap_is_speech(bc->capability) &&
03089            misdn_inband_avail(bc) ) {
03090          start_bc_tones(ch);
03091       }
03092    }
03093    break;
03094    case EVENT_PROGRESS:
03095       if (!bc->nt ) {
03096          if ( misdn_cap_is_speech(bc->capability) &&
03097               misdn_inband_avail(bc)
03098             ) {
03099             start_bc_tones(ch);
03100          }
03101          
03102          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
03103          
03104          ch->state=MISDN_PROGRESS;
03105       }
03106       break;
03107       
03108       
03109    case EVENT_ALERTING:
03110    {
03111       ch->state = MISDN_ALERTING;
03112       
03113       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
03114       ast_setstate(ch->ast, AST_STATE_RINGING);
03115       
03116       cb_log(1,bc->port,"Set State Ringing\n");
03117       
03118       if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
03119           start_bc_tones(ch);
03120        }
03121    }
03122    break;
03123    case EVENT_CONNECT:
03124       misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
03125    case EVENT_CONNECT_ACKNOWLEDGE:
03126    {
03127       bc->state=STATE_CONNECTED;
03128       
03129       ch->l3id=bc->l3_id;
03130       ch->addr=bc->addr;
03131       
03132       start_bc_tones(ch);
03133       
03134       chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
03135       
03136       ch->state = MISDN_CONNECTED;
03137       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
03138    }
03139    break;
03140    case EVENT_DISCONNECT:
03141    {
03142       
03143       struct chan_list *holded_ch=find_holded(cl_te, bc);
03144       
03145       
03146       send_cause2ast(ch->ast,bc);
03147 
03148       if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
03149          /* If there's inband information available (e.g. a
03150             recorded message saying what was wrong with the
03151             dialled number, or perhaps even giving an
03152             alternative number, then play it instead of
03153             immediately releasing the call */
03154          start_bc_tones(ch);
03155          break;
03156       }
03157       
03158       /*Check for holded channel, to implement transfer*/
03159       if (holded_ch ) {
03160          if  (ch->state == MISDN_CONNECTED ) {
03161             misdn_transfer_bc(ch, holded_ch) ;
03162             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03163             break;
03164          }
03165       }
03166       
03167       stop_bc_tones(ch);
03168       bc->out_cause=16;
03169       misdn_lib_send_event(bc,EVENT_RELEASE);
03170       
03171    }
03172    break;
03173    
03174    case EVENT_RELEASE:
03175       {
03176          
03177          switch ( bc->cause) {
03178             
03179          case -1:
03180             /*
03181               OK, it really sucks, this is a RELEASE from NT-Stack So we take
03182               it and return easylie, It seems that we've send a DISCONNECT
03183               before, so we should RELEASE_COMPLETE after that Disconnect
03184               (looks like ALERTING State at misdn_hangup !!
03185             */
03186             return RESPONSE_OK;
03187             break;
03188          }
03189          
03190          
03191          bc->out_cause=16;
03192          
03193          stop_bc_tones(ch);
03194          release_chan(bc);
03195       }
03196       break;
03197    case EVENT_RELEASE_COMPLETE:
03198    {
03199       stop_bc_tones(ch);
03200       release_chan(bc);
03201    }
03202    break;
03203    
03204    case EVENT_BCHAN_DATA:
03205    {
03206       chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
03207       
03208       if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
03209          misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
03210       } else {
03211          int len=bc->bframe_len;
03212          int free=misdn_ibuf_freecount(bc->astbuf);
03213          
03214          
03215          if (bc->bframe_len > free) {
03216             ast_log(LOG_DEBUG, "sbuf overflow!\n");
03217             len=misdn_ibuf_freecount(bc->astbuf);
03218 
03219             if (len == 0) {
03220                ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
03221             }
03222          }
03223          
03224          misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
03225          
03226          {
03227             char blah[1]="\0";
03228 #ifdef FLATTEN_JITTER
03229             {
03230                struct timeval tv;
03231                gettimeofday(&tv,NULL);
03232                
03233                if (tv.tv_usec % 10000 > 0 ) {
03234                   write(ch->pipe[1], blah,sizeof(blah));
03235                   bc->time_usec=tv.tv_usec;
03236                }
03237             }
03238 #else
03239             write(ch->pipe[1], blah,sizeof(blah));
03240 #endif
03241             
03242             
03243          }
03244       }
03245       
03246    }
03247    break;
03248    case EVENT_TIMEOUT:
03249       break; /* Ignore now .. */
03250       {
03251          switch (ch->state) {
03252          case MISDN_CALLING:
03253             chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
03254                break;
03255          case MISDN_DIALING:
03256          case MISDN_PROGRESS:
03257             break;
03258          default:
03259             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03260          }
03261       }
03262       break;
03263    case EVENT_CLEANUP:
03264    {
03265       stop_bc_tones(ch);
03266       release_chan(bc);
03267    }
03268    break;
03269     
03270    /***************************/
03271    /** Suplementary Services **/
03272    /***************************/
03273    case EVENT_RETRIEVE:
03274    {
03275       struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
03276       ch->state = MISDN_CONNECTED;
03277       
03278       if (hold_ast) {
03279          ast_moh_stop(hold_ast);
03280       }
03281       
03282       if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
03283          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
03284       
03285       
03286    }
03287    break;
03288     
03289    case EVENT_HOLD:
03290    {
03291       int hold_allowed;
03292       misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
03293       
03294       if (!hold_allowed) {
03295          chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
03296          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03297          break;
03298       }
03299 
03300       {
03301          struct chan_list *holded_ch=find_holded(cl_te, bc);
03302          if (holded_ch) {
03303             misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03304             chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
03305             break;
03306          }
03307       }
03308       
03309       if (AST_BRIDGED_P(ch->ast)){
03310          ch->state = MISDN_HOLDED;
03311          ch->l3id = bc->l3_id;
03312          
03313          ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
03314          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
03315       } else {
03316          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03317          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
03318       }
03319    } 
03320    break;
03321    default:
03322       ast_log(LOG_WARNING, "Got Unknown Event\n");
03323       break;
03324    }
03325    
03326    return RESPONSE_OK;
03327 }

void chan_misdn_log int  level,
int  port,
char *  tmpl,
  ...
 

Definition at line 3509 of file chan_misdn.c.

References ast_console_puts(), ast_log(), LOG_WARNING, max_ports, misdn_cfg_get(), misdn_debug, misdn_debug_only, and tracing.

Referenced by cb_events(), cl_queue_chan(), do_immediate_setup(), find_chan_by_bc(), find_chan_by_l3id(), find_holded(), init_chan_list(), load_module(), misdn_answer(), misdn_bridge(), misdn_call(), misdn_digit(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_new(), misdn_reload(), misdn_request(), misdn_set_opt_exec(), misdn_show_cls(), misdn_transfer(), misdn_transfer_bc(), misdn_tx2ast_frm(), misdn_write(), print_bearer(), release_chan(), and send_cause2ast().

03510 {
03511    if (! ((0 <= port) && (port <= max_ports))) {
03512       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
03513       return;
03514    }
03515       
03516    va_list ap;
03517    char buf[1024];
03518   
03519    va_start(ap, tmpl);
03520    vsnprintf( buf, 1023, tmpl, ap );
03521    va_end(ap);
03522    
03523    if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
03524       ast_console_puts(buf);
03525    }
03526    
03527    if (level <= misdn_debug[0] && tracing) {
03528       time_t tm = time(NULL);
03529       char *tmp=ctime(&tm),*p;
03530       char file[BUFFERSIZE];
03531       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
03532       FILE *fp= fopen(file, "a+");
03533 
03534       p=strchr(tmp,'\n');
03535       if (p) *p=':';
03536     
03537       if (!fp) {
03538          ast_console_puts("Error opening Tracefile: ");
03539          ast_console_puts(strerror(errno));
03540          ast_console_puts("\n");
03541          return ;
03542       }
03543       
03544       fputs(tmp,fp);
03545       fputs(" ", fp);
03546       fputs(buf, fp);
03547 
03548       fclose(fp);
03549    }
03550 }

void chan_misdn_trace_call struct ast_channel chan,
int  debug,
char *  tmpl,
  ...
 

Definition at line 3553 of file chan_misdn.c.

References ast_console_puts(), ast_channel::cid, ast_callerid::cid_num, misdn_cfg_get(), misdn_debug, name, and ast_channel::uniqueid.

Referenced by cb_events(), misdn_answer(), misdn_call(), misdn_hangup(), misdn_read(), misdn_write(), and release_chan().

03554 {
03555    va_list ap;
03556    char buf[1024];
03557    char name[1024];
03558 
03559    int trace;
03560    misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
03561    if (!trace) return ;
03562    
03563    if (misdn_debug[0] < debug) return ; 
03564    
03565    char tracedir[BUFFERSIZE];
03566    misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
03567    sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
03568    
03569    va_start(ap, tmpl);
03570    
03571    vsprintf( buf, tmpl, ap );
03572    
03573    va_end(ap);
03574    
03575    time_t tm = time(NULL);
03576    char *tmp=ctime(&tm),*p;
03577    FILE *fp= fopen(name, "a");
03578    int fd;
03579    
03580    if (!fp) {
03581       ast_console_puts("Error opening Tracefile");
03582       ast_console_puts(strerror(errno));
03583       ast_console_puts("\n");
03584       return ;
03585    }
03586    
03587    fd=fileno(fp) ;
03588    
03589    flock(fd, LOCK_EX);
03590    
03591    p=strchr(tmp,'\n');
03592    if (p) *p=':';
03593    
03594    
03595    
03596    fputs(tmp,fp);
03597    fputs(" ", fp);
03598    fputs(buf, fp);
03599 
03600    flock(fd, LOCK_UN);
03601    
03602    fclose(fp);
03603    
03604 }

void cl_dequeue_chan struct chan_list **  list,
struct chan_list chan
 

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

02381 {
02382    if (chan->dsp) 
02383       ast_dsp_free(chan->dsp);
02384    if (chan->trans)
02385       ast_translator_free_path(chan->trans);
02386    
02387 
02388    ast_mutex_lock(&cl_te_lock);
02389    if (!*list) {
02390       ast_mutex_unlock(&cl_te_lock);
02391       return;
02392    }
02393   
02394    if (*list == chan) {
02395       *list=(*list)->next;
02396       ast_mutex_unlock(&cl_te_lock);
02397       return ;
02398    }
02399   
02400    {
02401       struct chan_list *help=*list;
02402       for (;help->next; help=help->next) {
02403          if (help->next == chan) {
02404             help->next=help->next->next;
02405             ast_mutex_unlock(&cl_te_lock);
02406             return;
02407          }
02408       }
02409    }
02410    
02411    ast_mutex_unlock(&cl_te_lock);
02412 }

void cl_queue_chan struct chan_list **  list,
struct chan_list chan
 

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

02365 {
02366    chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
02367   
02368    ast_mutex_lock(&cl_te_lock);
02369    if (!*list) {
02370       *list = chan;
02371    } else {
02372       struct chan_list *help=*list;
02373       for (;help->next; help=help->next); 
02374       help->next=chan;
02375    }
02376    chan->next=NULL;
02377    ast_mutex_unlock(&cl_te_lock);
02378 }

int clearl3_true void   ) 
 

TE STUFF END

Definition at line 3339 of file chan_misdn.c.

References misdn_cfg_get().

Referenced by load_module().

03339                           {
03340    int default_clearl3;
03341    misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
03342    return default_clearl3;
03343 }

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

Definition at line 881 of file chan_misdn.c.

References complete_ch_helper().

00882 {
00883    return complete_ch_helper(line, word, pos, state, 3);
00884 }

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

Definition at line 857 of file chan_misdn.c.

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

00858 {
00859    struct ast_channel *c;
00860    int which=0;
00861    char *ret;
00862    if (pos != rpos)
00863       return NULL;
00864    c = ast_channel_walk_locked(NULL);
00865    while(c) {
00866       if (!strncasecmp(word, c->name, strlen(word))) {
00867          if (++which > state)
00868             break;
00869       }
00870       ast_mutex_unlock(&c->lock);
00871       c = ast_channel_walk_locked(c);
00872    }
00873    if (c) {
00874       ret = strdup(c->name);
00875       ast_mutex_unlock(&c->lock);
00876    } else
00877       ret = NULL;
00878    return ret;
00879 }

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

Definition at line 886 of file chan_misdn.c.

References strdup.

00887 {
00888    if (state)
00889       return NULL;
00890 
00891    switch (pos) {
00892    case 4: if (*word == 'p')
00893             return strdup("port");
00894          else if (*word == 'o')
00895             return strdup("only");
00896          break;
00897    case 6: if (*word == 'o')
00898             return strdup("only");
00899          break;
00900    }
00901    return NULL;
00902 }

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 3499 of file chan_misdn.c.

References desc.

03500 {
03501    return desc;
03502 }

void do_immediate_setup struct misdn_bchannel *  bc,
struct chan_list ch,
struct ast_channel ast
 

Definition at line 2531 of file chan_misdn.c.

References chan_list::ast, AST_CID_P, AST_FRAME_DTMF, ast_pbx_start(), ast_queue_frame(), ast_strlen_zero(), chan_misdn_log(), ast_channel::context, ast_frame::data, ast_frame::datalen, ast_channel::exten, ast_frame::frametype, ast_frame::mallocd, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_DIALING, ast_frame::offset, ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

Referenced by cb_events().

02532 {
02533    char predial[256]="";
02534    char *p = predial;
02535   
02536    struct ast_frame fr;
02537   
02538    strncpy(predial, ast->exten, sizeof(predial) -1 );
02539   
02540    ch->state=MISDN_DIALING;
02541    
02542    if (bc->nt) {
02543       int ret; 
02544       ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02545    } else {
02546       int ret;
02547       if ( misdn_lib_is_ptp(bc->port)) {
02548          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02549       } else {
02550          ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
02551       }
02552    }
02553 
02554    manager_send_tone(bc,TONE_DIAL);  
02555   
02556    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));
02557   
02558    strncpy(ast->exten,"s", 2);
02559   
02560    if (ast_pbx_start(ast)<0) {
02561       ast=NULL;
02562       manager_send_tone(bc,TONE_BUSY);
02563       if (bc->nt)
02564          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02565       else
02566          misdn_lib_send_event(bc, EVENT_DISCONNECT );
02567    }
02568   
02569   
02570    while (!ast_strlen_zero(p) ) {
02571       fr.frametype = AST_FRAME_DTMF;
02572       fr.subclass = *p ;
02573       fr.src=NULL;
02574       fr.data = NULL ;
02575       fr.datalen = 0;
02576       fr.samples = 0 ;
02577       fr.mallocd =0 ;
02578       fr.offset= 0 ;
02579 
02580       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02581          ast_queue_frame(ch->ast, &fr);
02582       }
02583       p++;
02584    }
02585 }

struct chan_list * find_chan_by_bc struct chan_list list,
struct misdn_bchannel *  bc
 

Definition at line 2335 of file chan_misdn.c.

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

Referenced by cb_events(), and release_chan().

02336 {
02337    struct chan_list *help=list;
02338    for (;help; help=help->next) {
02339       if (help->bc == bc) return help;
02340    }
02341   
02342    chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02343   
02344    return NULL;
02345 }

struct chan_list* find_chan_by_l3id struct chan_list list,
unsigned long  l3id
 

Channel Queue

Definition at line 2323 of file chan_misdn.c.

References chan_list::bc, chan_misdn_log(), chan_list::l3id, and chan_list::next.

Referenced by cb_events(), and release_chan().

02324 {
02325    struct chan_list *help=list;
02326    for (;help; help=help->next) {
02327       if (help->l3id == l3id ) return help;
02328    }
02329   
02330    chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
02331   
02332    return NULL;
02333 }

struct chan_list* find_holded struct chan_list list,
struct misdn_bchannel *  bc
 

Definition at line 2348 of file chan_misdn.c.

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

Referenced by cb_events().

02349 {
02350    struct chan_list *help=list;
02351    
02352    chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
02353    for (;help; help=help->next) {
02354       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
02355       if (help->bc->port == bc->port
02356           && help->bc->holded ) return help;
02357    }
02358    
02359    chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02360   
02361    return NULL;
02362 }

static void free_robin_list void   )  [static]
 

Definition at line 152 of file chan_misdn.c.

References free_robin_list_r().

Referenced by misdn_reload(), and unload_module().

00153 {
00154    free_robin_list_r(robin);
00155    robin = NULL;
00156 }

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

Definition at line 143 of file chan_misdn.c.

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

Referenced by free_robin_list().

00144 {
00145    if (r) {
00146       if (r->next) free_robin_list_r(r->next);
00147       if (r->group) free(r->group);
00148       free(r);
00149    }
00150 }

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

Definition at line 239 of file chan_misdn.c.

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

Referenced by misdn_bridge().

00240 {
00241    struct chan_list *tmp;
00242   
00243    for (tmp=cl_te; tmp; tmp = tmp->next) {
00244       if ( tmp->ast == ast ) return tmp;
00245    }
00246   
00247    return NULL;
00248 }

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

Definition at line 250 of file chan_misdn.c.

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

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

00251 {
00252    struct chan_list *tmp;
00253   
00254    for (tmp=cl_te; tmp; tmp = tmp->next) {
00255       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
00256    }
00257   
00258    return NULL;
00259 }

struct robin_list* get_robin_position char *  group  ) 
 

Definition at line 158 of file chan_misdn.c.

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

Referenced by misdn_request().

00159 {
00160    struct robin_list *iter = robin;
00161    for (; iter; iter = iter->next) {
00162       if (!strcasecmp(iter->group, group))
00163          return iter;
00164    }
00165    struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
00166    new->group = strndup(group, strlen(group));
00167    new->channel = 1;
00168    if (robin) {
00169       new->next = robin;
00170       robin->prev = new;
00171    }
00172    robin = new;
00173    return robin;
00174 }

struct chan_list* init_chan_list void   ) 
 

Definition at line 1902 of file chan_misdn.c.

References chan_misdn_log(), and malloc.

Referenced by cb_events(), and misdn_request().

01903 {
01904    struct chan_list *cl=malloc(sizeof(struct chan_list));
01905    
01906    if (!cl) {
01907       chan_misdn_log(0, 0, "misdn_request: malloc failed!");
01908       return NULL;
01909    }
01910    
01911    memset(cl,0,sizeof(struct chan_list));
01912    
01913    return cl;
01914    
01915 }

char* key void   ) 
 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 3504 of file chan_misdn.c.

References ASTERISK_GPL_KEY.

03505 {
03506    return ASTERISK_GPL_KEY;
03507 }

int load_module void   ) 
 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 3347 of file chan_misdn.c.

References ast_channel_register(), ast_cli_register(), ast_log(), ast_mutex_init(), ast_register_application(), calloc, cb_events(), chan_misdn_log(), cl_te_lock, clearl3_true(), g_config_initialized, LOG_ERROR, malloc, max_ports, misdn_cfg_get(), misdn_cfg_get_ports_string(), misdn_cfg_init(), misdn_debug, misdn_debug_only, misdn_facility_exec(), misdn_set_opt_exec(), release_lock_mutex, tracing, type, and unload_module().

03348 {
03349    int i;
03350    
03351    char ports[256]="";
03352    
03353    max_ports=misdn_lib_maxports_get();
03354    
03355    if (max_ports<=0) {
03356       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
03357       return -1;
03358    }
03359    
03360    
03361    misdn_cfg_init(max_ports);
03362    g_config_initialized=1;
03363    
03364    misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
03365    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
03366    for (i = 1; i <= max_ports; i++)
03367       misdn_debug[i] = misdn_debug[0];
03368    misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
03369 
03370    
03371    {
03372       char tempbuf[BUFFERSIZE];
03373       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
03374       if (strlen(tempbuf))
03375          tracing = 1;
03376    }
03377 
03378    ast_mutex_init(&cl_te_lock);
03379    ast_mutex_init(&release_lock_mutex);
03380 
03381    misdn_cfg_get_ports_string(ports);
03382    if (strlen(ports))
03383       chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
03384    
03385    {
03386       struct misdn_lib_iface iface = {
03387          .cb_event = cb_events,
03388          .cb_log = chan_misdn_log,
03389          .cb_clearl3_true = clearl3_true
03390       };
03391       if (misdn_lib_init(ports, &iface, NULL))
03392          chan_misdn_log(0, 0, "No te ports initialized\n");
03393    }
03394 
03395 
03396    {
03397       if (ast_channel_register(&misdn_tech)) {
03398          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
03399          unload_module();
03400          return -1;
03401       }
03402    }
03403   
03404    ast_cli_register(&cli_send_display);
03405    ast_cli_register(&cli_send_cd);
03406    ast_cli_register(&cli_send_digit);
03407    ast_cli_register(&cli_toggle_echocancel);
03408    ast_cli_register(&cli_set_tics);
03409 
03410    ast_cli_register(&cli_show_cls);
03411    ast_cli_register(&cli_show_cl);
03412    ast_cli_register(&cli_show_config);
03413    ast_cli_register(&cli_show_port);
03414    ast_cli_register(&cli_show_stacks);
03415 
03416    ast_cli_register(&cli_restart_port);
03417    ast_cli_register(&cli_port_up);
03418    ast_cli_register(&cli_set_debug);
03419    ast_cli_register(&cli_set_crypt_debug);
03420    ast_cli_register(&cli_reload);
03421 
03422   
03423    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
03424              "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
03425              "Sets mISDN opts. and optargs\n"
03426              "\n"
03427       );
03428 
03429    
03430    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
03431              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
03432              "Sends the Facility Message FACILITY_TYPE with \n"
03433              "the given Arguments to the current ISDN Channel\n"
03434              "Supported Facilities are:\n"
03435              "\n"
03436              "type=calldeflect args=Nr where to deflect\n"
03437              "\n"
03438       );
03439   
03440    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
03441 
03442    return 0;
03443 }

int misdn_answer struct ast_channel ast  ) 
 

Definition at line 1341 of file chan_misdn.c.

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

01342 {
01343    struct chan_list *p;
01344 
01345    
01346    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01347    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01348    
01349    chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
01350    
01351    chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
01352    
01353    if (!p) {
01354       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
01355       ast_queue_hangup(ast);
01356    }
01357 
01358    if (!p->bc) {
01359       chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
01360 
01361       ast_queue_hangup(ast);
01362    }
01363 
01364    {
01365       char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
01366       
01367       if (tmp_key ) {
01368          chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
01369          {
01370             int l = sizeof(p->bc->crypt_key);
01371             strncpy(p->bc->crypt_key,tmp_key, l);
01372             p->bc->crypt_key[l-1] = 0;
01373          }
01374       } else {
01375          chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
01376       }
01377     
01378    }
01379 
01380    {
01381       char *async=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
01382       if (async) {
01383          chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
01384          p->bc->async=1;
01385       }
01386    }
01387    
01388    p->state = MISDN_CONNECTED;
01389    misdn_lib_send_event( p->bc, EVENT_CONNECT);
01390    start_bc_tones(p);
01391    
01392    return 0;
01393 }

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
 

Definition at line 1795 of file chan_misdn.c.

References AST_FRAME_CONTROL, ast_log(), ast_read(), ast_waitfor_n(), ast_write(), chan_list::bc, chan_misdn_log(), ast_frame::frametype, get_chan_by_ast(), LOG_DEBUG, and misdn_cfg_get().

01801 {
01802    struct chan_list *ch1,*ch2;
01803    struct ast_channel *carr[2], *who;
01804    int to=-1;
01805    struct ast_frame *f;
01806   
01807    ch1=get_chan_by_ast(c0);
01808    ch2=get_chan_by_ast(c1);
01809 
01810    carr[0]=c0;
01811    carr[1]=c1;
01812   
01813   
01814    if (ch1 && ch2 ) ;
01815    else
01816       return -1;
01817   
01818 
01819    int bridging;
01820    misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
01821    if (bridging) {
01822       int ecwb;
01823       misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
01824       if ( !ecwb ) {
01825          chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
01826          ch1->bc->ec_enable=0;
01827          manager_ec_disable(ch1->bc);
01828       }
01829       misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
01830       if ( !ecwb ) {
01831          chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
01832          ch2->bc->ec_enable=0;
01833          manager_ec_disable(ch2->bc);
01834       }
01835       
01836       /* trying to make a mISDN_dsp conference */
01837       chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
01838 
01839       misdn_lib_bridge(ch1->bc,ch2->bc);
01840    }
01841    
01842    chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
01843   
01844    while(1) {
01845       to=-1;
01846       who = ast_waitfor_n(carr, 2, &to);
01847 
01848       if (!who) {
01849          ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
01850          continue;
01851       }
01852       f = ast_read(who);
01853     
01854       if (!f || f->frametype == AST_FRAME_CONTROL) {
01855          /* got hangup .. */
01856          *fo=f;
01857          *rc=who;
01858       
01859          break;
01860       }
01861     
01862     
01863       if (who == c0) {
01864          ast_write(c1,f);
01865       }
01866       else {
01867          ast_write(c0,f);
01868       }
01869     
01870    }
01871   
01872    if (bridging) {
01873       misdn_lib_split_bridge(ch1->bc,ch2->bc);
01874    }
01875   
01876    return 0;
01877 }

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

we should have l3id after sending setup

Definition at line 1038 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CID_P, ast_log(), AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), chan_list::bc, chan_misdn_log(), chan_misdn_trace_call(), ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), context, ast_channel::context, ast_channel::exten, ast_channel::hangupcause, chan_list::l3id, ast_channel::language, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, misdn_cfg_get(), misdn_set_opt_exec(), ast_channel::name, ORG_AST, chan_list::orginator, pbx_builtin_setvar_helper(), chan_list::state, and ast_channel::transfercapability.

01039 {
01040    int port=0;
01041    int r;
01042    struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01043    struct misdn_bchannel *newbc;
01044    char *opts=NULL, *ext=NULL;
01045    char dest_cp[256];
01046    char *tokb;
01047    
01048    {
01049       strncpy(dest_cp,dest,sizeof(dest_cp)-1);
01050       dest_cp[sizeof(dest_cp)]=0;
01051       
01052       ext=strtok_r(dest_cp,"/",&tokb);
01053       
01054       if (ext) {
01055          ext=strtok_r(NULL,"/",&tokb);
01056          if (ext) {
01057             opts=strtok_r(NULL,"/",&tokb);
01058          } else {
01059             chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
01060             return -1;
01061          }
01062       }
01063       
01064       
01065    }
01066 
01067    if (!ast) {
01068       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
01069       return -1;
01070    }
01071 
01072    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
01073       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01074       ast->hangupcause=41;
01075       ast_setstate(ast, AST_STATE_DOWN);
01076       return -1;
01077    }
01078 
01079 
01080    if (!ch) {
01081       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01082       ast->hangupcause=41;
01083       ast_setstate(ast, AST_STATE_DOWN);
01084       return -1;
01085    }
01086    
01087    newbc=ch->bc;
01088    
01089    if (!newbc) {
01090       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01091       ast->hangupcause=41;
01092       ast_setstate(ast, AST_STATE_DOWN);
01093       return -1;
01094    }
01095 
01096    port=newbc->port;
01097 
01098    ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
01099    ast_copy_string(ast->exten, ext, sizeof(ast->exten));
01100    
01101    chan_misdn_log(1, 0, "* CALL: %s\n",dest);
01102    
01103    chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
01104    
01105    {
01106       char context[BUFFERSIZE];
01107       
01108       misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
01109       {
01110          int l = sizeof(ast->context);
01111          strncpy(ast->context,context, l);
01112          ast->context[l-1] = 0;
01113       }
01114       chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
01115       misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
01116       
01117       misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
01118       misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
01119       
01120       misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
01121       
01122 
01123       {
01124          char callerid[BUFFERSIZE];
01125          misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
01126          if ( ! ast_strlen_zero(callerid) ) {
01127             chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
01128             {
01129                int l = sizeof(newbc->oad);
01130                strncpy(newbc->oad,callerid, l);
01131                newbc->oad[l-1] = 0;
01132             }
01133          }
01134 
01135          
01136          misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
01137          switch (newbc->dnumplan) {
01138          case NUMPLAN_INTERNATIONAL:
01139             chan_misdn_log(2, port, " --> TON: International\n");
01140             break;
01141          case NUMPLAN_NATIONAL:
01142             chan_misdn_log(2, port, " --> TON: National\n");
01143             break;
01144          case NUMPLAN_SUBSCRIBER:
01145             chan_misdn_log(2, port, " --> TON: Subscriber\n");
01146             break;
01147          case NUMPLAN_UNKNOWN:
01148             chan_misdn_log(2, port, " --> TON: Unknown\n");
01149             break;
01150             /* Maybe we should cut off the prefix if present ? */
01151          default:
01152                chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01153                break;
01154          }
01155 
01156 
01157          misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &newbc->onumplan, sizeof(int));
01158          switch (newbc->onumplan) {
01159          case NUMPLAN_INTERNATIONAL:
01160             chan_misdn_log(2, port, " --> TON: International\n");
01161             break;
01162          case NUMPLAN_NATIONAL:
01163             chan_misdn_log(2, port, " --> TON: National\n");
01164             break;
01165          case NUMPLAN_SUBSCRIBER:
01166             chan_misdn_log(2, port, " --> TON: Subscriber\n");
01167             break;
01168          case NUMPLAN_UNKNOWN:
01169             chan_misdn_log(2, port, " --> TON: Unknown\n");
01170             break;
01171             /* Maybe we should cut off the prefix if present ? */
01172          default:
01173                chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01174                break;
01175          }
01176       }
01177 
01178 
01179 
01180       
01181       {
01182          int eb3;
01183          
01184          misdn_cfg_get( port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
01185          newbc->early_bconnect=eb3;
01186          
01187       }
01188       
01189 
01190       
01191       /* Will be overridden by asterisk in head! */
01192       {
01193          int pres;
01194          
01195          misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
01196          newbc->pres=pres?0:1;
01197          
01198       }
01199       
01200       int def_callingpres;
01201       misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
01202       if ( def_callingpres) {
01203          
01204          switch (ast->cid.cid_pres & 0x60){
01205             
01206          case AST_PRES_RESTRICTED:
01207             chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
01208             newbc->pres=1;
01209             break;
01210             
01211             
01212          case AST_PRES_UNAVAILABLE:
01213             chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
01214             newbc->pres=2;
01215             break;
01216             
01217          default:
01218             chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
01219             newbc->pres=0;
01220          }
01221          
01222          switch (ast->cid.cid_pres & 0x3){
01223             
01224          case AST_PRES_USER_NUMBER_UNSCREENED:
01225             chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01226             newbc->screen=0;
01227             break;
01228 
01229          case AST_PRES_USER_NUMBER_PASSED_SCREEN:
01230             chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
01231             newbc->screen=1;
01232             break;
01233          case AST_PRES_USER_NUMBER_FAILED_SCREEN:
01234             chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
01235             newbc->screen=2;
01236             break;
01237             
01238          case AST_PRES_NETWORK_NUMBER:
01239             chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
01240             newbc->screen=3;
01241             break;
01242             
01243          default:
01244             chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01245             newbc->screen=0;
01246          }
01247       }
01248 
01249       
01250       {
01251          int ec, ectr;
01252          
01253          misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
01254          
01255          misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
01256          if (ec == 1 ) {
01257             newbc->ec_enable=1;
01258          } else if ( ec > 1 ) {
01259             newbc->ec_enable=1;
01260             newbc->ec_deftaps=ec;
01261          }
01262 
01263 
01264          if (ectr>=0) {
01265             newbc->ec_training=ectr;
01266          }
01267          
01268       }
01269       
01270    } 
01271    
01272    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
01273    if (ast->exten) {
01274       int l = sizeof(newbc->dad);
01275       strncpy(newbc->dad,ast->exten, l);
01276       newbc->dad[l-1] = 0;
01277    }
01278    newbc->rad[0]=0;
01279    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
01280    if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
01281       if (AST_CID_P(ast)) {
01282          int l = sizeof(newbc->oad);
01283          strncpy(newbc->oad,AST_CID_P(ast), l);
01284          newbc->oad[l-1] = 0;
01285       }
01286    }
01287    
01288    {
01289       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01290       if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
01291       ch->bc = newbc;
01292       ch->orginator=ORG_AST;
01293       ch->ast = ast;
01294       
01295       MISDN_ASTERISK_TECH_PVT(ast) = ch ;
01296       
01297       
01298       
01299       newbc->capability=ast->transfercapability;
01300       pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
01301       if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
01302          chan_misdn_log(2, port, " --> * Call with flag Digital\n");
01303       }
01304       
01305 
01306       /* Finally The Options Override Everything */
01307       if (opts)
01308          misdn_set_opt_exec(ast,opts);
01309       else
01310          chan_misdn_log(1,0,"NO OPTS GIVEN\n");
01311       
01312       
01313       cl_queue_chan(&cl_te, ch) ;
01314       ch->state=MISDN_CALLING;
01315 
01316       chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
01317       
01318       r=misdn_lib_send_event( newbc, EVENT_SETUP );
01319       
01320       /** we should have l3id after sending setup **/
01321       ch->l3id=newbc->l3_id;
01322    }
01323    
01324    if ( r == -ENOCHAN  ) {
01325       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
01326       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
01327       ast->hangupcause=34;
01328       ast_setstate(ast, AST_STATE_DOWN);
01329       return -1;
01330    }
01331    
01332    chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
01333 
01334    ast_setstate(ast, AST_STATE_DIALING);
01335    
01336    ast->hangupcause=16;
01337    return 0; 
01338 }

int misdn_digit struct ast_channel ast,
char  digit
 

Definition at line 1395 of file chan_misdn.c.

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

01396 {
01397    struct chan_list *p;
01398    
01399    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01400    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01401    
01402 
01403    struct misdn_bchannel *bc=p->bc;
01404    chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
01405    
01406    if (!bc) {
01407       ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
01408       return -1;
01409    }
01410    
01411    switch (p->state ) {
01412       case MISDN_CALLING:
01413       {
01414          
01415          char buf[8];
01416          buf[0]=digit;
01417          buf[1]=0;
01418          
01419          int l = sizeof(bc->infos_pending);
01420          strncat(bc->infos_pending,buf,l);
01421          bc->infos_pending[l-1] = 0;
01422       }
01423       break;
01424       case MISDN_CALLING_ACKNOWLEDGE:
01425       {
01426          bc->info_dad[0]=digit;
01427          bc->info_dad[1]=0;
01428          
01429          {
01430             int l = sizeof(bc->dad);
01431             strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
01432             bc->dad[l-1] = 0;
01433       }
01434          {
01435             int l = sizeof(p->ast->exten);
01436             strncpy(p->ast->exten, bc->dad, l);
01437             p->ast->exten[l-1] = 0;
01438          }
01439          
01440          misdn_lib_send_event( bc, EVENT_INFORMATION);
01441       }
01442       break;
01443       
01444       default:
01445          if ( bc->send_dtmf ) {
01446             send_digit_to_chan(p,digit);
01447          }
01448       break;
01449    }
01450    
01451    return 0;
01452 }

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

Definition at line 3609 of file chan_misdn.c.

References ast_log(), ast_strlen_zero(), chan_list::bc, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, and MISDN_ASTERISK_TYPE.

Referenced by load_module().

03610 {
03611    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03612    char *tok, *tokb;
03613    
03614 
03615    if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03616       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
03617       return -1;
03618    }
03619    
03620    if (ast_strlen_zero((char *)data)) {
03621       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03622       return -1;
03623    }
03624    
03625    tok=strtok_r((char*)data,"|", &tokb) ;
03626    
03627    if (!tok) {
03628       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03629       return -1;
03630    }
03631    
03632    if (!strcasecmp(tok,"calldeflect")) {
03633       tok=strtok_r(NULL,"|", &tokb) ;
03634       
03635       if (!tok) {
03636          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
03637       }
03638       
03639       misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
03640       
03641    } else {
03642       ast_log(LOG_WARNING, "Unknown Facility: %s\n",tok);
03643    }
03644    
03645    return 0;
03646    
03647 }

int misdn_fixup struct ast_channel oldast,
struct ast_channel ast
 

Definition at line 1455 of file chan_misdn.c.

References chan_list::ast, chan_list::bc, chan_misdn_log(), chan_list::holded, chan_list::l3id, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_get_ch_state(), and chan_list::state.

01456 {
01457    struct chan_list *p;
01458    
01459    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01460    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01461    
01462    chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s Holded:%d L3id:%x\n", misdn_get_ch_state(p), p->holded, p->l3id);
01463    
01464    p->ast = ast ;
01465    p->state=MISDN_CONNECTED;
01466   
01467    return 0;
01468 }

char* misdn_get_ch_state struct chan_list p  ) 
 

Definition at line 537 of file chan_misdn.c.

References chan_list::state.

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

00538 {
00539    int i;
00540    if( !p) return NULL;
00541   
00542    for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
00543       if ( state_array[i].state == p->state) return state_array[i].txt; 
00544    }
00545   
00546    return NULL;
00547 }

int misdn_hangup struct ast_channel ast  ) 
 

Definition at line 1583 of file chan_misdn.c.

References chan_list::ast, AST_CID_P, ast_log(), AST_STATE_RESERVED, chan_list::bc, chan_misdn_log(), chan_misdn_trace_call(), cl_dequeue_chan(), free, ast_channel::hangupcause, chan_list::l3id, LOG_DEBUG, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, misdn_get_ch_state(), MISDN_HOLD_DISCONNECT, MISDN_HOLDED, ORG_AST, chan_list::orginator, pbx_builtin_getvar_helper(), release_lock, release_unlock, start_bc_tones(), chan_list::state, and stop_bc_tones().

01584 {
01585    struct chan_list *p;
01586    struct misdn_bchannel *bc=NULL;
01587    
01588    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
01589    
01590    release_lock;
01591 
01592    chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
01593    
01594    ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
01595    
01596    if (!p) {
01597       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
01598       release_unlock;
01599       return 0 ;
01600    }
01601    
01602    bc=p->bc;
01603 
01604    if (!bc) {
01605       release_unlock;
01606       ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
01607       return 0;
01608    }
01609 
01610    
01611    MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01612    p->ast=NULL;
01613 
01614    if (ast->_state == AST_STATE_RESERVED) {
01615       /* between request and call */
01616       MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01617       release_unlock;
01618       
01619       cl_dequeue_chan(&cl_te, p);
01620       free(p);
01621 
01622       misdn_lib_release(bc);
01623       
01624       return 0;
01625    }
01626 
01627    stop_bc_tones(p);
01628    
01629    release_unlock;
01630    
01631    
01632    
01633    
01634    
01635    
01636    {
01637       char *varcause=NULL;
01638       bc->cause=ast->hangupcause?ast->hangupcause:16;
01639       
01640       if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
01641            (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
01642          int tmpcause=atoi(varcause);
01643          bc->out_cause=tmpcause?tmpcause:16;
01644       }
01645     
01646       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));
01647       chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
01648       chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
01649       chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
01650       
01651       switch (p->state) {
01652       case MISDN_CALLING:
01653          p->state=MISDN_CLEANING;
01654          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
01655          break;
01656       case MISDN_HOLDED:
01657       case MISDN_DIALING:
01658          start_bc_tones(p);
01659          manager_send_tone(bc, TONE_BUSY);
01660          p->state=MISDN_CLEANING;
01661          
01662          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
01663       
01664          break;
01665       
01666       case MISDN_ALERTING:
01667          chan_misdn_log(2, bc->port, " --> * State Alerting\n");
01668 
01669          if (p->orginator != ORG_AST) 
01670             manager_send_tone(bc, TONE_BUSY);
01671       
01672          p->state=MISDN_CLEANING;
01673          misdn_lib_send_event( bc, EVENT_DISCONNECT);
01674          break;
01675       case MISDN_CONNECTED:
01676          /*  Alerting or Disconect */
01677          chan_misdn_log(2, bc->port, " --> * State Connected\n");
01678          start_bc_tones(p);
01679          manager_send_tone(bc, TONE_BUSY);
01680          misdn_lib_send_event( bc, EVENT_DISCONNECT);
01681       
01682          p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
01683          break;
01684 
01685       case MISDN_CLEANING:
01686          break;
01687       
01688       case MISDN_HOLD_DISCONNECT:
01689          /* need to send release here */
01690          chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
01691          chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
01692          chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
01693          
01694          misdn_lib_send_event(bc,EVENT_RELEASE);
01695          break;
01696       default:
01697          /*  Alerting or Disconect */
01698          if (bc->nt)
01699             misdn_lib_send_event(bc, EVENT_RELEASE);
01700          else
01701             misdn_lib_send_event(bc, EVENT_DISCONNECT);
01702          p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
01703       }
01704     
01705    }
01706    
01707    chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
01708    
01709    return 0;
01710 }

int misdn_indication struct ast_channel ast,
int  cond
 

Definition at line 1484 of file chan_misdn.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, 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, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, ast_channel::name, start_bc_tones(), and chan_list::state.

01485 {
01486    struct chan_list *p;
01487 
01488   
01489    if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
01490       ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
01491       return -1;
01492    }
01493    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01494    
01495    if (!p->bc ) {
01496       chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
01497       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
01498       return -1;
01499    }
01500    
01501    chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
01502    
01503    switch (cond) {
01504    case AST_CONTROL_BUSY:
01505       chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
01506       chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
01507       ast_setstate(ast,AST_STATE_BUSY);
01508       
01509       p->bc->out_cause=17;
01510       if (p->state != MISDN_CONNECTED) {
01511          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01512          manager_send_tone(p->bc, TONE_BUSY);
01513       } else {
01514          chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
01515                    p->bc->port, ast->name);
01516       }
01517       break;
01518    case AST_CONTROL_RING:
01519       chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
01520       break;
01521    case AST_CONTROL_RINGING:
01522       if ( p->state == MISDN_ALERTING) {
01523          chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I ws Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
01524          break;
01525       }
01526       p->state=MISDN_ALERTING;
01527       
01528       chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
01529       
01530       misdn_lib_send_event( p->bc, EVENT_ALERTING);
01531       
01532       manager_send_tone(p->bc, TONE_ALERTING);
01533       chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
01534       ast_setstate(ast,AST_STATE_RINGING);
01535       break;
01536       
01537    case AST_CONTROL_ANSWER:
01538       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
01539       break;
01540    case AST_CONTROL_TAKEOFFHOOK:
01541       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
01542       break;
01543    case AST_CONTROL_OFFHOOK:
01544       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
01545       break; 
01546    case AST_CONTROL_FLASH:
01547       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
01548       break;
01549    case AST_CONTROL_PROGRESS:
01550       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
01551       break;
01552    case AST_CONTROL_CONGESTION:
01553       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
01554 
01555       p->bc->out_cause=42;
01556       if (p->state != MISDN_CONNECTED) {
01557          start_bc_tones(p);
01558          //misdn_lib_send_event( p->bc, EVENT_RELEASE_COMPLETE);
01559          misdn_lib_send_event( p->bc, EVENT_RELEASE);
01560       } else {
01561          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01562       }
01563       if (p->bc->nt) {
01564          manager_send_tone(p->bc, TONE_BUSY);
01565       }
01566       break;
01567    case -1 :
01568       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
01569       break;
01570    case AST_CONTROL_HOLD:
01571       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01572       break;
01573    case AST_CONTROL_UNHOLD:
01574       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01575       break;
01576    default:
01577       ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
01578    }
01579   
01580    return 0;
01581 }

struct ast_channel * misdn_new struct chan_list cl,
int  state,
char *  name,
char *  context,
char *  exten,
char *  callerid,
int  format,
int  port,
int  c
 

Definition at line 2111 of file chan_misdn.c.

References ast_callerid_parse(), ast_channel_alloc(), ast_log(), ast_print_group(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, chan_list::bc, ast_channel::callgroup, chan_misdn_log(), cid_name, cid_num, ast_channel::context, ast_channel::exten, ast_channel::fds, glob_channel, ast_channel::language, LOG_WARNING, misdn_cfg_get(), ast_channel::name, ast_channel::nativeformats, ast_channel::pickupgroup, chan_list::pipe, prefformat, ast_channel::priority, ast_channel::readformat, ast_channel::rings, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, type, and ast_channel::writeformat.

Referenced by cb_events(), and misdn_request().

02112 {
02113    struct ast_channel *tmp;
02114    
02115    tmp = ast_channel_alloc(1);
02116    
02117    if (tmp) {
02118       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
02119       
02120       
02121       if (c<=0) {
02122          c=glob_channel++;
02123          snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
02124              type, port, c);
02125       } else {
02126          snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
02127              type, port, c);
02128       }
02129       
02130       tmp->type = type;
02131     
02132       tmp->nativeformats = prefformat;
02133       tmp->readformat = format;
02134       tmp->writeformat = format;
02135     
02136       tmp->tech_pvt = chlist;
02137 
02138       int bridging;
02139       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02140       if (bridging)
02141          tmp->tech = &misdn_tech;
02142       else
02143          tmp->tech = &misdn_tech_wo_bridge;
02144     
02145     
02146       tmp->writeformat = format;
02147       tmp->readformat = format;
02148       tmp->priority=1;
02149     
02150       
02151       if (context) {
02152          ast_copy_string(tmp->context, context, sizeof(tmp->context));
02153       }  else {
02154          chan_misdn_log(1,0,"misdn_new: no context given.\n");
02155       }
02156       
02157       if (exten) {
02158          ast_copy_string(tmp->exten, exten,  sizeof(tmp->exten));
02159       } else {
02160          chan_misdn_log(1,0,"misdn_new: no exten given.\n");
02161       }
02162       
02163       if (callerid) {
02164          char *cid_name, *cid_num;
02165       
02166          ast_callerid_parse(callerid, &cid_name, &cid_num);
02167          ast_set_callerid(tmp, cid_num, cid_name, cid_num);
02168       }
02169 
02170       {
02171          if (pipe(chlist->pipe)<0)
02172             perror("Pipe failed\n");
02173          
02174          tmp->fds[0]=chlist->pipe[0];
02175          
02176       }
02177       
02178       if (chlist->bc) {
02179          int port=chlist->bc->port;
02180          misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
02181          
02182          {
02183             char buf[256];
02184             ast_group_t pg,cg;
02185             
02186             misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02187             misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02188             
02189             chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
02190             tmp->pickupgroup=pg;
02191             tmp->callgroup=cg;
02192          }
02193          misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
02194          misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
02195          chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
02196          
02197       } else {
02198          chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
02199       }
02200       
02201       ast_setstate(tmp, state);
02202       if (state == AST_STATE_RING)
02203          tmp->rings = 1;
02204       else
02205          tmp->rings = 0;
02206    } else {
02207       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02208       chan_misdn_log(0,0,"Unable to allocate channel structure\n");
02209    }
02210    
02211    return tmp;
02212 }

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

Definition at line 442 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

00443 {
00444    int port;
00445    
00446    if (argc != 4)
00447       return RESULT_SHOWUSAGE;
00448    
00449    port = atoi(argv[3]);
00450    
00451    misdn_lib_get_port_up(port);
00452   
00453    return 0;
00454 }

struct ast_frame* misdn_read struct ast_channel ast  ) 
 

Definition at line 1712 of file chan_misdn.c.

References chan_list::ast, AST_FORMAT_ALAW, AST_FRAME_VOICE, chan_list::ast_rd_buf, chan_list::bc, chan_misdn_trace_call(), ast_frame::data, ast_frame::datalen, chan_list::frame, ast_frame::frametype, ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, ast_frame::offset, chan_list::pipe, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

01713 {
01714    struct chan_list *tmp;
01715    
01716    char blah[255];
01717    int len =0 ;
01718    
01719    if (!ast) return NULL;
01720    if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
01721    if (!tmp->bc) return NULL;
01722    
01723    
01724    read(tmp->pipe[0],blah,sizeof(blah));
01725    
01726    
01727    len = misdn_ibuf_usedcount(tmp->bc->astbuf);
01728 
01729    /*shrinken len if necessary, we transmit at maximum 4k*/
01730    len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
01731    
01732    misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
01733    
01734    tmp->frame.frametype  = AST_FRAME_VOICE;
01735    tmp->frame.subclass = AST_FORMAT_ALAW;
01736    tmp->frame.datalen = len;
01737    tmp->frame.samples = len ;
01738    tmp->frame.mallocd =0 ;
01739    tmp->frame.offset= 0 ;
01740    tmp->frame.src = NULL;
01741    tmp->frame.data = tmp->ast_rd_buf ;
01742 
01743    chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
01744    return &tmp->frame;
01745 }

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

Definition at line 549 of file chan_misdn.c.

References ast_cli(), chan_misdn_log(), free_robin_list(), max_ports, misdn_cfg_get(), misdn_cfg_reload(), misdn_debug, misdn_debug_only, and tracing.

00550 {
00551    int i, cfg_debug;
00552    
00553    ast_cli(fd, "Reloading mISDN Config\n");
00554    chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
00555    
00556    free_robin_list();
00557 
00558    misdn_cfg_reload();
00559 
00560    {
00561       char tempbuf[BUFFERSIZE];
00562       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
00563       if (strlen(tempbuf))
00564          tracing = 1;
00565    }
00566 
00567    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
00568    for (i = 0;  i <= max_ports; i++) {
00569       misdn_debug[i] = cfg_debug;
00570       misdn_debug_only[i] = 0;
00571    }
00572    
00573    return 0;
00574 }

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

Definition at line 1917 of file chan_misdn.c.

References ast_log(), AST_STATE_RESERVED, ast_strlen_zero(), chan_list::bc, chan_misdn_log(), robin_list::channel, get_robin_position(), group, init_chan_list(), LOG_WARNING, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_next_port_spin(), misdn_cfg_is_group_method(), misdn_new(), and robin_list::port.

01919 {
01920    struct ast_channel *tmp = NULL;
01921    char group[BUFFERSIZE]="";
01922    char buf[128];
01923    char buf2[128], *ext=NULL, *port_str;
01924    char *tokb=NULL, *p=NULL;
01925    int channel=0, port=0;
01926    struct misdn_bchannel *newbc = NULL;
01927    
01928    struct chan_list *cl=init_chan_list();
01929    
01930    sprintf(buf,"%s/%s",type,(char*)data);
01931    strncpy(buf2,data, 128);
01932    buf2[127] = 0;
01933    port_str=strtok_r(buf2,"/", &tokb);
01934 
01935    ext=strtok_r(NULL,"/", &tokb);
01936 
01937    /*
01938      if (!ext) {
01939      ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITH WRONG ARGS, check extension.conf\n",ext);
01940      
01941      return NULL;
01942      }
01943    */
01944    
01945    if (port_str) {
01946       if (port_str[0]=='g' && port_str[1]==':' ) {
01947          /* We make a group call lets checkout which ports are in my group */
01948          port_str += 2;
01949          strncpy(group, port_str, BUFFERSIZE);
01950          group[127] = 0;
01951          chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
01952       } 
01953       else if ((p = strchr(port_str, ':'))) {
01954          // we have a preselected channel
01955          *p = 0;
01956          channel = atoi(++p);
01957          port = atoi(port_str);
01958          chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
01959       }
01960       else {
01961          port = atoi(port_str);
01962       }
01963       
01964       
01965    } else {
01966       ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
01967       return NULL;
01968    }
01969 
01970    if (!ast_strlen_zero(group)) {
01971    
01972       char cfg_group[BUFFERSIZE];
01973       struct robin_list *rr = NULL;
01974 
01975       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
01976          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
01977          rr = get_robin_position(group);
01978       }
01979       
01980       if (rr) {
01981          int robin_channel = rr->channel;
01982          int port_start;
01983          int next_chan = 1;
01984 
01985          do {
01986             port_start = 0;
01987             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
01988                 port = misdn_cfg_get_next_port_spin(port)) {
01989 
01990                if (!port_start)
01991                   port_start = port;
01992 
01993                if (port >= port_start)
01994                   next_chan = 1;
01995                
01996                if (port < port_start && next_chan) {
01997                   if (++robin_channel >= MAX_BCHANS) {
01998                      robin_channel = 1;
01999                   }
02000                   next_chan = 0;
02001                }
02002 
02003                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02004                
02005                if (!strcasecmp(cfg_group, group)) {
02006                   int l1, port_up;
02007                
02008                   misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
02009                   port_up = misdn_lib_port_up(port);
02010                   
02011                   if ((l1 && port_up) || !l1)   {
02012                      newbc = misdn_lib_get_free_bc(port, robin_channel);
02013                      if (newbc) {
02014                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
02015                         if (port_up)
02016                            chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
02017                         rr->port = newbc->port;
02018                         rr->channel = newbc->channel;
02019                         break;
02020                      }
02021                   }
02022                }
02023             }
02024          } while (!newbc && robin_channel != rr->channel);
02025          
02026          if (!newbc)
02027             chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
02028       }
02029       
02030       else {      
02031          for (port=misdn_cfg_get_next_port(0); port > 0;
02032              port=misdn_cfg_get_next_port(port)) {
02033             
02034             misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02035             
02036             if (!strcasecmp(cfg_group, group)) {
02037                int l1, port_up;
02038                
02039                misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
02040                port_up = misdn_lib_port_up(port);
02041 
02042                chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
02043                
02044                if ((l1 && port_up) || !l1)   {
02045                   newbc = misdn_lib_get_free_bc(port, 0);
02046                   if (newbc)
02047                      break;
02048                }
02049             }
02050          }
02051       }
02052       
02053    } else {
02054       if (channel)
02055          chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
02056       newbc = misdn_lib_get_free_bc(port, channel);
02057    }
02058    
02059    if (!newbc) {
02060       chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
02061       chan_misdn_log(1, 0, " --> SEND: State Down\n");
02062       return NULL;
02063    }
02064    
02065    cl->bc=newbc;
02066    
02067    tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
02068    
02069    return tmp;
02070 }

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

Definition at line 428 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

00429 {
00430    int port;
00431   
00432    if (argc != 4)
00433       return RESULT_SHOWUSAGE;
00434   
00435    port = atoi(argv[3]);
00436 
00437    misdn_lib_port_restart(port);
00438 
00439    return 0;
00440 }

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

Definition at line 721 of file chan_misdn.c.

References ast_cli(), chan_list::bc, get_chan_by_ast_name(), and RESULT_SHOWUSAGE.

00722 {
00723    char *channame; 
00724    char *nr; 
00725   
00726    if (argc != 5)
00727       return RESULT_SHOWUSAGE;
00728   
00729    channame = argv[3];
00730    nr = argv[4];
00731    
00732    ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
00733    
00734    {
00735       struct chan_list *tmp=get_chan_by_ast_name(channame);
00736       
00737       if (!tmp) {
00738          ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
00739          return 0; 
00740       } else {
00741          
00742          misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
00743       }
00744    }
00745   
00746    return 0; 
00747 }

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

Definition at line 751 of file chan_misdn.c.

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

00752 {
00753    char *channame; 
00754    char *msg; 
00755   
00756    if (argc != 5)
00757       return RESULT_SHOWUSAGE;
00758   
00759    channame = argv[3];
00760    msg = argv[4];
00761 
00762    ast_cli(fd, "Sending %s to %s\n",msg, channame);
00763   
00764    {
00765       struct chan_list *tmp=get_chan_by_ast_name(channame);
00766     
00767       if (!tmp) {
00768          ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
00769          return 0; 
00770       } else {
00771 #if 1
00772          int i;
00773          int msglen = strlen(msg);
00774          for (i=0; i<msglen; i++) {
00775             ast_cli(fd, "Sending: %c\n",msg[i]);
00776             send_digit_to_chan(tmp, msg[i]);
00777             /* res = ast_safe_sleep(tmp->ast, 250); */
00778             usleep(250000);
00779             /* res = ast_waitfor(tmp->ast,100); */
00780          }
00781 #else
00782          int res;
00783          res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
00784 #endif
00785       }
00786    }
00787   
00788    return 0; 
00789 }

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

Definition at line 824 of file chan_misdn.c.

References ast_cli(), chan_list::bc, get_chan_by_ast_name(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00825 {
00826    char *channame; 
00827    char *msg; 
00828   
00829    if (argc != 5)
00830       return RESULT_SHOWUSAGE;
00831   
00832    channame = argv[3];
00833    msg = argv[4];
00834 
00835    ast_cli(fd, "Sending %s to %s\n",msg, channame);
00836    {
00837       struct chan_list *tmp;
00838       tmp=get_chan_by_ast_name(channame);
00839     
00840       if (tmp && tmp->bc) {
00841          int l = sizeof(tmp->bc->display);
00842          strncpy(tmp->bc->display, msg, l);
00843          tmp->bc->display[l-1] = 0;
00844          misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
00845       } else {
00846          ast_cli(fd,"No such channel %s\n",channame);
00847          return RESULT_FAILURE;
00848       }
00849    }
00850 
00851    return RESULT_SUCCESS ;
00852 }

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

Definition at line 420 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

00421 {
00422    if (argc != 5 )return RESULT_SHOWUSAGE; 
00423 
00424    return 0;
00425 }

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

Definition at line 362 of file chan_misdn.c.

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

00363 {
00364    if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
00365       return RESULT_SHOWUSAGE; 
00366 
00367    int level = atoi(argv[3]);
00368 
00369    switch (argc) {
00370       case 4:  
00371       case 5: {
00372                int only = 0;
00373                if (argc == 5) {
00374                   if (strncasecmp(argv[4], "only", strlen(argv[4])))
00375                      return RESULT_SHOWUSAGE;
00376                   else
00377                      only = 1;
00378                }
00379                int i;
00380                for (i=0; i<=max_ports; i++) {
00381                   misdn_debug[i] = level;
00382                   misdn_debug_only[i] = only;
00383                }
00384                ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00385             }
00386             break;
00387       case 6: 
00388       case 7: {
00389                if (strncasecmp(argv[4], "port", strlen(argv[4])))
00390                   return RESULT_SHOWUSAGE;
00391                int port = atoi(argv[5]);
00392                if (port <= 0 || port > max_ports) {
00393                   switch (max_ports) {
00394                      case 0:
00395                         ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00396                         break;
00397                      case 1:
00398                         ast_cli(fd, "port number not valid! only port 1 is availble.\n");
00399                         break;
00400                      default:
00401                         ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00402                      }
00403                      return 0;
00404                }
00405                if (argc == 7) {
00406                   if (strncasecmp(argv[6], "only", strlen(argv[6])))
00407                      return RESULT_SHOWUSAGE;
00408                   else
00409                      misdn_debug_only[port] = 1;
00410                } else
00411                   misdn_debug_only[port] = 0;
00412                misdn_debug[port] = level;
00413                ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
00414             }
00415    }
00416    return 0;
00417 }

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

Definition at line 3650 of file chan_misdn.c.

References chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, chan_misdn_log(), chan_list::dsp, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, chan_list::faxdetect, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_ASTERISK_TYPE, misdn_key_vector, misdn_key_vector_size, chan_list::orginator, rxgain, chan_list::trans, and txgain.

Referenced by load_module(), and misdn_call().

03651 {
03652    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03653    char *tok,*tokb;
03654    int  keyidx=0;
03655    int rxgain=0;
03656    int txgain=0;
03657 
03658    if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03659       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
03660       return -1;
03661    }
03662    
03663    if (ast_strlen_zero((char *)data)) {
03664       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
03665       return -1;
03666    }
03667 
03668    for (tok=strtok_r((char*)data, ":",&tokb);
03669         tok;
03670         tok=strtok_r(NULL,":",&tokb) ) {
03671       int neglect=0;
03672       
03673       if (tok[0] == '!' ) {
03674          neglect=1;
03675          tok++;
03676       }
03677       
03678       switch(tok[0]) {
03679          
03680       case 'd' :
03681          strncpy(ch->bc->display,++tok,84);
03682          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
03683          break;
03684          
03685       case 'n':
03686          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
03687          ch->bc->nodsp=1;
03688          break;
03689 
03690       case 'j':
03691          chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
03692          ch->bc->nojitter=1;
03693          break;
03694       
03695       case 'v':
03696          tok++;
03697 
03698          switch ( tok[0] ) {
03699          case 'r' :
03700             rxgain=atoi(++tok);
03701             if (rxgain<-8) rxgain=-8;
03702             if (rxgain>8) rxgain=8;
03703             ch->bc->rxgain=rxgain;
03704             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
03705             break;
03706          case 't':
03707             txgain=atoi(++tok);
03708             if (txgain<-8) txgain=-8;
03709             if (txgain>8) txgain=8;
03710             ch->bc->txgain=txgain;
03711             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
03712             break;
03713          }
03714          break;
03715       
03716       case 'c':
03717          keyidx=atoi(++tok);
03718       
03719          if (keyidx > misdn_key_vector_size  || keyidx < 0 ) {
03720             ast_log(LOG_WARNING, "You entered the keyidx: %d but we have only %d keys\n",keyidx, misdn_key_vector_size );
03721             continue; 
03722          }
03723       
03724          {
03725             int l = sizeof(ch->bc->crypt_key);
03726             strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
03727             ch->bc->crypt_key[l-1] = 0;
03728          }
03729          chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
03730          break;
03731 
03732       case 'e':
03733          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
03734          
03735          if (neglect) {
03736             ch->bc->ec_enable=0;
03737          } else {
03738             ch->bc->ec_enable=1;
03739             ch->bc->orig=ch->orginator;
03740             tok++;
03741             if (tok) {
03742                ch->bc->ec_deftaps=atoi(tok);
03743             }
03744          }
03745          
03746          break;
03747       
03748       case 'h':
03749          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
03750          if (strlen(tok) > 1 && tok[1]=='1') {
03751             chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
03752             ch->bc->async=1;
03753             ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03754             /*ch->bc->state=STATE_CONNECTED;
03755               misdn_lib_setup_bc(ch->bc);*/
03756          } else {
03757             ch->bc->async=0;
03758             ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03759             /*ch->bc->state=STATE_CONNECTED;
03760               misdn_lib_setup_bc(ch->bc);*/
03761          }
03762          break;
03763             
03764       case 's':
03765          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
03766          ch->bc->send_dtmf=1;
03767          break;
03768          
03769       case 'f':
03770          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
03771          ch->faxdetect=1;
03772          break;
03773 
03774       case 'a':
03775          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
03776          ch->ast_dsp=1;
03777          break;
03778 
03779       case 'p':
03780          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
03781          /* CRICH: callingpres!!! */
03782          if (strstr(tok,"allowed") ) {
03783             ch->bc->pres=0;
03784          } else if (strstr(tok,"not_screened")) {
03785             ch->bc->pres=1;
03786          }
03787          
03788          
03789          break;
03790       
03791       
03792       default:
03793          break;
03794       }
03795    }
03796    
03797    if (ch->faxdetect || ch->ast_dsp) {
03798       
03799       if (!ch->dsp) ch->dsp = ast_dsp_new();
03800       if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
03801       if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
03802    }
03803 
03804    if (ch->ast_dsp) {
03805       chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
03806       ch->bc->nodsp=1;
03807       ch->bc->nojitter=1;
03808    }
03809    
03810    return 0;
03811 }

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

Definition at line 673 of file chan_misdn.c.

References MAXTICS, and RESULT_SHOWUSAGE.

00674 {
00675    if (argc != 4)
00676       return RESULT_SHOWUSAGE;
00677   
00678    MAXTICS=atoi(argv[3]);
00679   
00680    return 0;
00681 }

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

Definition at line 647 of file chan_misdn.c.

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

00648 {
00649    struct chan_list *help=cl_te;
00650 
00651    if (argc != 4)
00652       return RESULT_SHOWUSAGE;
00653   
00654    for (;help; help=help->next) {
00655       struct misdn_bchannel *bc=help->bc;   
00656       struct ast_channel *ast=help->ast;
00657     
00658       if (bc && ast) {
00659          if (!strcasecmp(ast->name,argv[3])) {
00660             print_bc_info(fd, help, bc);
00661             break; 
00662          }
00663       } 
00664    }
00665   
00666   
00667    return 0;
00668 }

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

Definition at line 621 of file chan_misdn.c.

References chan_list::ast, AST_CID_P, ast_cli(), chan_list::bc, chan_misdn_log(), ast_channel::exten, chan_list::holded_bc, misdn_debug, chan_list::next, and print_bc_info().

00622 {
00623    struct chan_list *help=cl_te;
00624   
00625    ast_cli(fd,"Chan List: %p\n",cl_te); 
00626   
00627    for (;help; help=help->next) {
00628       struct misdn_bchannel *bc=help->bc;   
00629       struct ast_channel *ast=help->ast;
00630       if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
00631       if (bc) {
00632          print_bc_info(fd, help, bc);
00633       } else if ( (bc=help->holded_bc) ) {
00634          chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
00635          print_bc_info(fd, help,  bc);
00636       } else {
00637          ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
00638       }
00639    }
00640   
00641   
00642    return 0;
00643 }

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

Definition at line 457 of file chan_misdn.c.

References ast_cli(), misdn_cfg_get_config_string(), misdn_cfg_get_next_port(), misdn_cfg_is_port_valid(), and RESULT_SHOWUSAGE.

00458 {
00459    char buffer[BUFFERSIZE];
00460    enum misdn_cfg_elements elem;
00461    int linebreak;
00462 
00463    int onlyport = -1;
00464    if (argc >= 4) {
00465       if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
00466          ast_cli(fd, "Unknown option: %s\n", argv[3]);
00467          return RESULT_SHOWUSAGE;
00468       }
00469    }
00470    
00471    if (argc == 3 || onlyport == 0) {
00472       ast_cli(fd,"Misdn General-Config: \n"); 
00473       ast_cli(fd," ->  VERSION: " CHAN_MISDN_VERSION "\n");
00474       
00475       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
00476          misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
00477          ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00478       }
00479    }
00480 
00481    if (onlyport < 0) {
00482       int port = misdn_cfg_get_next_port(0);
00483       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
00484          ast_cli(fd, "\n[PORT %d]\n", port);
00485          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00486             misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
00487             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00488          }  
00489          ast_cli(fd, "\n");
00490       }
00491    }
00492    
00493    if (onlyport > 0) {
00494       if (misdn_cfg_is_port_valid(onlyport)) {
00495          ast_cli(fd, "[PORT %d]\n", onlyport);
00496          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00497             misdn_cfg_get_config_string( onlyport, elem, buffer, BUFFERSIZE);
00498             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00499          }  
00500          ast_cli(fd, "\n");
00501       } else {
00502          ast_cli(fd, "Port %d is not active!\n", onlyport);
00503       }
00504    }
00505    return 0;
00506 }

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

Definition at line 702 of file chan_misdn.c.

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

00703 {
00704    int port;
00705    
00706    if (argc != 4)
00707       return RESULT_SHOWUSAGE;
00708   
00709    port = atoi(argv[3]);
00710   
00711    ast_cli(fd, "BEGIN STACK_LIST:\n");
00712 
00713    char buf[128];
00714    get_show_stack_details(port,buf);
00715    ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00716 
00717    
00718    return 0;
00719 }

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

Definition at line 685 of file chan_misdn.c.

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

00686 {
00687    int port;
00688    
00689    ast_cli(fd, "BEGIN STACK_LIST:\n");
00690    for (port=misdn_cfg_get_next_port(0); port > 0;
00691         port=misdn_cfg_get_next_port(port)) {
00692       char buf[128];
00693       get_show_stack_details(port,buf);
00694       ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00695    }
00696       
00697 
00698    return 0;
00699 
00700 }

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

Definition at line 791 of file chan_misdn.c.

References ast_cli(), chan_list::bc, get_chan_by_ast_name(), and RESULT_SHOWUSAGE.

00792 {
00793    char *channame; 
00794 
00795    if (argc != 4)
00796       return RESULT_SHOWUSAGE;
00797    
00798    channame = argv[3];
00799   
00800    ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
00801   
00802    {
00803       struct chan_list *tmp=get_chan_by_ast_name(channame);
00804     
00805       if (!tmp) {
00806          ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
00807          return 0; 
00808       } else {
00809          tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
00810 
00811          if (tmp->bc->ec_enable) {
00812             manager_ec_enable(tmp->bc);
00813          } else {
00814             manager_ec_disable(tmp->bc);
00815          }
00816       }
00817    }
00818   
00819    return 0; 
00820 }

int misdn_transfer struct ast_channel ast,
char *  dest
 

Definition at line 1471 of file chan_misdn.c.

References chan_list::bc, chan_misdn_log(), MISDN_ASTERISK_PVT, and MISDN_ASTERISK_TECH_PVT.

01472 {
01473    struct chan_list *p;
01474    
01475    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01476    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01477 
01478    chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
01479    return 0;
01480 }

void misdn_transfer_bc struct chan_list tmp_ch,
struct chan_list holded_chan
 

Definition at line 2515 of file chan_misdn.c.

References chan_list::ast, AST_BRIDGED_P, ast_channel_masquerade(), ast_moh_stop(), chan_list::bc, chan_misdn_log(), chan_list::holded, chan_list::holded_bc, MISDN_CONNECTED, MISDN_HOLD_DISCONNECT, ast_channel::name, and chan_list::state.

Referenced by cb_events().

02516 {
02517    chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
02518    
02519    tmp_ch->state=MISDN_HOLD_DISCONNECT;
02520   
02521    ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
02522 
02523    holded_chan->state=MISDN_CONNECTED;
02524    holded_chan->holded=0;
02525    misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
02526    
02527    ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
02528 }

int misdn_tx2ast_frm struct chan_list tmp,
char *  buf,
int  len
 

Definition at line 2216 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), AST_CID_P, chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, ast_log(), ast_queue_frame(), ast_strlen_zero(), ast_translate(), ast_verbose(), chan_list::bc, chan_misdn_log(), ast_channel::context, ast_frame::data, ast_frame::datalen, chan_list::dsp, ast_channel::exten, chan_list::faxdetect, chan_list::faxhandled, ast_frame::frametype, chan_list::holded, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_frame::mallocd, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, MISDN_EXTCANTMATCH, MISDN_WAITING4DIGS, ast_channel::name, chan_list::norxtone, ast_frame::offset, option_verbose, pbx_builtin_setvar_helper(), ast_frame::samples, ast_frame::src, chan_list::state, ast_frame::subclass, chan_list::trans, and VERBOSE_PREFIX_3.

Referenced by cb_events().

02217 {
02218    struct ast_frame frame;
02219    
02220    /* If in hold state we drop frame .. */
02221    if (tmp->holded ) return 0;
02222 
02223    switch(tmp->state) {
02224    case MISDN_CLEANING:
02225    case MISDN_EXTCANTMATCH:
02226    case MISDN_WAITING4DIGS:
02227       return 0;
02228    default:
02229       break;
02230    }
02231    
02232    if (tmp->norxtone) {
02233       chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
02234       return 0;
02235    }
02236    
02237    frame.frametype  = AST_FRAME_VOICE;
02238    frame.subclass = AST_FORMAT_ALAW;
02239    frame.datalen = len;
02240    frame.samples = len ;
02241    frame.mallocd =0 ;
02242    frame.offset= 0 ;
02243    frame.src = NULL;
02244    frame.data = buf ;
02245    
02246    if (tmp->faxdetect || tmp->ast_dsp ) {
02247       struct ast_frame *f,*f2;
02248       if (tmp->trans)
02249          f2=ast_translate(tmp->trans, &frame,0);
02250       else {
02251          chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02252          return 0;
02253       }
02254       
02255       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02256       if (f && (f->frametype == AST_FRAME_DTMF)) {
02257          ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
02258          if (f->subclass == 'f' && tmp->faxdetect) {
02259             /* Fax tone -- Handle and return NULL */
02260             struct ast_channel *ast = tmp->ast;
02261             if (!tmp->faxhandled) {
02262                tmp->faxhandled++;
02263                if (strcmp(ast->exten, "fax")) {
02264                   if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
02265                      if (option_verbose > 2)
02266                         ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
02267                      /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02268                      pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02269                      if (ast_async_goto(ast, ast->context, "fax", 1))
02270                         ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
02271                   } else
02272                      ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
02273                } else
02274                   ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02275             } else
02276                ast_log(LOG_DEBUG, "Fax already handled\n");
02277             frame.frametype = AST_FRAME_NULL;
02278             frame.subclass = 0;
02279             f = &frame;
02280          }  else if ( tmp->ast_dsp) {
02281             struct ast_frame fr;
02282             memset(&fr, 0 , sizeof(fr));
02283             fr.frametype = AST_FRAME_DTMF;
02284             fr.subclass = f->subclass ;
02285             fr.src=NULL;
02286             fr.data = NULL ;
02287             fr.datalen = 0;
02288             fr.samples = 0 ;
02289             fr.mallocd =0 ;
02290             fr.offset= 0 ;
02291             
02292             chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
02293             ast_queue_frame(tmp->ast, &fr);
02294             
02295             frame.frametype = AST_FRAME_NULL;
02296             frame.subclass = 0;
02297             f = &frame;
02298          }
02299       }
02300    }
02301    
02302    if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
02303 #if MISDN_DEBUG
02304       int i, max=5>len?len:5;
02305     
02306       printf("write2* %p %d bytes: ",tmp, len);
02307     
02308       for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
02309       printf ("\n");
02310 #endif
02311       chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
02312       ast_queue_frame(tmp->ast,&frame);
02313       
02314    }  else {
02315       ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
02316    }
02317    
02318    return 0;
02319 }

int misdn_write struct ast_channel ast,
struct ast_frame frame
 

Definition at line 1747 of file chan_misdn.c.

References ast_log(), chan_list::bc, chan_misdn_log(), chan_misdn_trace_call(), ast_frame::data, chan_list::holded, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, chan_list::notxtone, prefformat, ast_frame::samples, and ast_frame::subclass.

01748 {
01749    struct chan_list *p;
01750    int i  = 0;
01751    
01752    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
01753    
01754    if (!p->bc ) {
01755       ast_log(LOG_WARNING, "private but no bc\n");
01756       return -1;
01757    }
01758    
01759    if (p->bc->tone != TONE_NONE)
01760       manager_send_tone(p->bc,TONE_NONE);
01761    
01762    
01763    if (p->holded ) {
01764       chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
01765       return 0;
01766    }
01767    
01768    if (p->notxtone) {
01769       chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
01770       return 0;
01771    }
01772    
01773    if ( !(frame->subclass & prefformat)) {
01774       chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
01775    }
01776    
01777    
01778 #if MISDN_DEBUG
01779    {
01780       int i, max=5>frame->samples?frame->samples:5;
01781       
01782       printf("write2mISDN %p %d bytes: ", p, frame->samples);
01783       
01784       for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
01785       printf ("\n");
01786    }
01787 #endif
01788    chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
01789    i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
01790    
01791    return 0;
01792 }

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

Definition at line 576 of file chan_misdn.c.

References chan_list::addr, chan_list::ast, AST_CID_P, ast_cli(), bearer2str(), ast_channel::exten, chan_list::holded_bc, chan_list::l3id, misdn_debug, misdn_get_ch_state(), ast_channel::name, chan_list::norxtone, chan_list::notxtone, ORG_AST, chan_list::orginator, and tone2str().

Referenced by misdn_show_cl(), and misdn_show_cls().

00577 {
00578    struct ast_channel *ast=help->ast;
00579    ast_cli(fd,
00580       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
00581       bc->pid, bc->port, bc->channel,
00582       bc->nt?"NT":"TE",
00583       help->orginator == ORG_AST?"*":"I",
00584       ast?ast->exten:NULL,
00585       ast?AST_CID_P(ast):NULL,
00586       ast?ast->context:NULL,
00587       misdn_get_ch_state(help)
00588       );
00589    if (misdn_debug[bc->port] > 0)
00590       ast_cli(fd,
00591          "  --> astname: %s\n"
00592          "  --> ch_l3id: %x\n"
00593          "  --> ch_addr: %x\n"
00594          "  --> bc_addr: %x\n"
00595          "  --> bc_l3id: %x\n"
00596          "  --> tone: %s\n"
00597          "  --> display: %s\n"
00598          "  --> activated: %d\n"
00599          "  --> capability: %s\n"
00600          "  --> echo_cancel: %d\n"
00601          "  --> notone : rx %d tx:%d\n"
00602          "  --> bc_hold: %d holded_bc :%d\n",
00603          help->ast->name,
00604          help->l3id,
00605          help->addr,
00606          bc->addr,
00607          bc?bc->l3_id:-1,
00608          tone2str(bc),
00609          bc->display,
00610          
00611          bc->active,
00612          bearer2str(bc->capability),
00613          bc->ec_enable,
00614          help->norxtone,help->notxtone,
00615          bc->holded, help->holded_bc?1:0
00616          );
00617   
00618 }

static void print_bearer struct misdn_bchannel *  bc  )  [static]
 

Definition at line 309 of file chan_misdn.c.

References bearer2str(), and chan_misdn_log().

Referenced by cb_events().

00310 {
00311    
00312    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00313    
00314    switch(bc->law) {
00315    case INFO_CODEC_ALAW:
00316       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00317       break;
00318    case INFO_CODEC_ULAW:
00319       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00320       break;
00321    }
00322 }

static void release_chan struct misdn_bchannel *  bc  )  [static]
 

Isdn asks us to release channel, pendant to misdn_hangup

Definition at line 2419 of file chan_misdn.c.

References chan_list::ast, AST_CID_P, ast_hangup(), ast_queue_hangup(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_misdn_log(), chan_misdn_trace_call(), cl_dequeue_chan(), find_chan_by_bc(), find_chan_by_l3id(), free, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, MISDN_CLEANING, MISDN_DIALING, MISDN_EXTCANTMATCH, misdn_get_ch_state(), MISDN_HOLD_DISCONNECT, MISDN_PROGRESS, MISDN_WAITING4DIGS, chan_list::pipe, release_lock, release_unlock, send_cause2ast(), and chan_list::state.

Referenced by cb_events().

02419                                                     {
02420    struct ast_channel *ast=NULL;
02421    
02422    {
02423       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02424       if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
02425       
02426       release_lock;
02427       if (ch->ast) {
02428          ast=ch->ast;
02429       } 
02430       release_unlock;
02431       
02432       chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
02433       if (ch) {
02434          if (ast)
02435             chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
02436          
02437          close(ch->pipe[0]);
02438          close(ch->pipe[1]);
02439          
02440          if (ast && MISDN_ASTERISK_PVT(ast)) {
02441             chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
02442             chan_misdn_log(3, bc->port, " --> * State Down\n");
02443             /* copy cause */
02444             send_cause2ast(ast,bc);
02445             
02446             MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02447             
02448       
02449             if (ast->_state != AST_STATE_RESERVED) {
02450                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
02451                ast_setstate(ast, AST_STATE_DOWN);
02452             }
02453             
02454             switch(ch->state) {
02455             case MISDN_EXTCANTMATCH:
02456             case MISDN_WAITING4DIGS:
02457             {
02458                chan_misdn_log(3,  bc->port, " --> * State Wait4dig | ExtCantMatch\n");
02459                ast_hangup(ast);
02460             }
02461             break;
02462             
02463             case MISDN_DIALING:
02464             case MISDN_CALLING_ACKNOWLEDGE:
02465             case MISDN_PROGRESS:
02466                chan_misdn_log(2,  bc->port, "* --> In State Dialin\n");
02467                chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02468                
02469 
02470                ast_queue_hangup(ast);
02471                break;
02472             case MISDN_CALLING:
02473                
02474                chan_misdn_log(2,  bc->port, "* --> In State Callin\n");
02475                
02476                if (!bc->nt) {
02477                   chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02478                   ast_queue_hangup(ast);
02479                } else {
02480                   chan_misdn_log(2,  bc->port, "* --> Hangup\n");
02481                   ast_queue_hangup(ast);
02482                   //ast_hangup(ast);
02483                }
02484                break;
02485                
02486             case MISDN_CLEANING:
02487                /* this state comes out of ast so we mustnt call a ast function ! */
02488                chan_misdn_log(2,  bc->port, "* --> In StateCleaning\n");
02489                break;
02490             case MISDN_HOLD_DISCONNECT:
02491                chan_misdn_log(2,  bc->port, "* --> In HOLD_DISC\n");
02492                break;
02493             default:
02494                chan_misdn_log(2,  bc->port, "* --> In State Default\n");
02495                chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02496    
02497                
02498                if (ast && MISDN_ASTERISK_PVT(ast)) {
02499                   ast_queue_hangup(ast);
02500                } else {
02501                   chan_misdn_log (0,  bc->port, "!! Not really queued!\n");
02502                }
02503             }
02504          }
02505          cl_dequeue_chan(&cl_te, ch);
02506          
02507          free(ch);
02508       } else {
02509          /* chan is already cleaned, so exiting  */
02510       }
02511    }
02512 }

void send_cause2ast struct ast_channel ast,
struct misdn_bchannel *  bc
 

Congestion Cases

Definition at line 2589 of file chan_misdn.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_queue_control(), chan_misdn_log(), and ast_channel::hangupcause.

Referenced by cb_events(), and release_chan().

02589                                                                        {
02590    
02591    ast->hangupcause=bc->cause;
02592    
02593    switch ( bc->cause) {
02594       
02595    case 1: /** Congestion Cases **/
02596    case 2:
02597    case 3:
02598    case 4:
02599    case 22:
02600    case 27:
02601       chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
02602       
02603       ast_queue_control(ast, AST_CONTROL_CONGESTION);
02604       break;
02605       
02606    case 21:
02607    case 17: /* user busy */
02608       chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
02609       
02610       ast_queue_control(ast, AST_CONTROL_BUSY);
02611       
02612       break;
02613    }
02614 }

void send_digit_to_chan struct chan_list cl,
char  digit
 

Definition at line 325 of file chan_misdn.c.

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

Referenced by misdn_digit(), and misdn_send_digit().

00326 {
00327    static const char* dtmf_tones[] = {
00328       "!941+1336/100,!0/100", /* 0 */
00329       "!697+1209/100,!0/100", /* 1 */
00330       "!697+1336/100,!0/100", /* 2 */
00331       "!697+1477/100,!0/100", /* 3 */
00332       "!770+1209/100,!0/100", /* 4 */
00333       "!770+1336/100,!0/100", /* 5 */
00334       "!770+1477/100,!0/100", /* 6 */
00335       "!852+1209/100,!0/100", /* 7 */
00336       "!852+1336/100,!0/100", /* 8 */
00337       "!852+1477/100,!0/100", /* 9 */
00338       "!697+1633/100,!0/100", /* A */
00339       "!770+1633/100,!0/100", /* B */
00340       "!852+1633/100,!0/100", /* C */
00341       "!941+1633/100,!0/100", /* D */
00342       "!941+1209/100,!0/100", /* * */
00343       "!941+1477/100,!0/100" };  /* # */
00344    struct ast_channel *chan=cl->ast; 
00345   
00346    if (digit >= '0' && digit <='9')
00347       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00348    else if (digit >= 'A' && digit <= 'D')
00349       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00350    else if (digit == '*')
00351       ast_playtones_start(chan,0,dtmf_tones[14], 0);
00352    else if (digit == '#')
00353       ast_playtones_start(chan,0,dtmf_tones[15], 0);
00354    else {
00355       /* not handled */
00356       ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00357     
00358     
00359    }
00360 }

static int start_bc_tones struct chan_list cl  )  [static]
 

AST INDICATIONS END

Definition at line 1881 of file chan_misdn.c.

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

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

01882 {
01883    manager_bchannel_activate(cl->bc);
01884    manager_send_tone(cl->bc ,TONE_NONE);
01885    cl->notxtone=0;
01886    cl->norxtone=0;
01887    return 0;
01888 }

static int stop_bc_tones struct chan_list cl  )  [static]
 

Definition at line 1890 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_hangup().

01891 {
01892    if (cl->bc) {
01893       manager_bchannel_deactivate(cl->bc);
01894    }
01895    cl->notxtone=1;
01896    cl->norxtone=1;
01897    
01898    return 0;
01899 }

static char* tone2str struct misdn_bchannel *  bc  )  [static]
 

Definition at line 261 of file chan_misdn.c.

References name.

Referenced by print_bc_info().

00262 {
00263    static struct {
00264       char name[16];
00265       enum tone_e tone;
00266    } *tone, tone_buf[] = {
00267       {"NOTONE",TONE_NONE},
00268       {"DIAL",TONE_DIAL},
00269       {"BUSY",TONE_BUSY},
00270       {"ALERT",TONE_ALERTING},
00271       {"",TONE_NONE}
00272    };
00273   
00274   
00275    for (tone=&tone_buf[0]; tone->name[0]; tone++) {
00276       if (tone->tone == bc->tone) return tone->name;
00277    }
00278    return NULL;
00279 }

int unload_module void   ) 
 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 3447 of file chan_misdn.c.

References ast_channel_unregister(), ast_cli_unregister(), ast_log(), ast_unregister_application(), free, free_robin_list(), g_config_initialized, LOG_VERBOSE, misdn_cfg_destroy(), misdn_debug, and misdn_debug_only.

03448 {
03449    /* First, take us out of the channel loop */
03450    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
03451    
03452    if (!g_config_initialized) return 0;
03453    
03454    ast_cli_unregister(&cli_send_display);
03455    
03456    ast_cli_unregister(&cli_send_cd);
03457    
03458    ast_cli_unregister(&cli_send_digit);
03459    ast_cli_unregister(&cli_toggle_echocancel);
03460    ast_cli_unregister(&cli_set_tics);
03461   
03462    ast_cli_unregister(&cli_show_cls);
03463    ast_cli_unregister(&cli_show_cl);
03464    ast_cli_unregister(&cli_show_config);
03465    ast_cli_unregister(&cli_show_port);
03466    ast_cli_unregister(&cli_show_stacks);
03467    ast_cli_unregister(&cli_restart_port);
03468    ast_cli_unregister(&cli_port_up);
03469    ast_cli_unregister(&cli_set_debug);
03470    ast_cli_unregister(&cli_set_crypt_debug);
03471    ast_cli_unregister(&cli_reload);
03472    /* ast_unregister_application("misdn_crypt"); */
03473    ast_unregister_application("misdn_set_opt");
03474    ast_unregister_application("misdn_facility");
03475   
03476    ast_channel_unregister(&misdn_tech);
03477 
03478    free_robin_list();
03479    misdn_cfg_destroy();
03480    misdn_lib_destroy();
03481   
03482    if (misdn_debug)
03483       free(misdn_debug);
03484    if (misdn_debug_only)
03485       free(misdn_debug_only);
03486    
03487    return 0;
03488 }

int usecount void   ) 
 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 3490 of file chan_misdn.c.

References ast_mutex_lock(), ast_mutex_unlock(), usecnt, and usecnt_lock.

03491 {
03492    int res;
03493    ast_mutex_lock(&usecnt_lock);
03494    res = usecnt;
03495    ast_mutex_unlock(&usecnt_lock);
03496    return res;
03497 }


Variable Documentation

struct chan_list* cl_te = NULL
 

Definition at line 216 of file chan_misdn.c.

ast_mutex_t cl_te_lock
 

Definition at line 217 of file chan_misdn.c.

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

struct ast_cli_entry cli_port_up [static]
 

Definition at line 993 of file chan_misdn.c.

struct ast_cli_entry cli_reload [static]
 

Definition at line 953 of file chan_misdn.c.

struct ast_cli_entry cli_restart_port [static]
 

Definition at line 985 of file chan_misdn.c.

struct ast_cli_entry cli_send_cd [static]
 

Definition at line 904 of file chan_misdn.c.

struct ast_cli_entry cli_send_digit [static]
 

Definition at line 913 of file chan_misdn.c.

struct ast_cli_entry cli_send_display [static]
 

Definition at line 934 of file chan_misdn.c.

struct ast_cli_entry cli_set_crypt_debug [static]
 

Definition at line 1025 of file chan_misdn.c.

struct ast_cli_entry cli_set_debug [static]
 

Definition at line 1017 of file chan_misdn.c.

struct ast_cli_entry cli_set_tics [static]
 

Definition at line 960 of file chan_misdn.c.

struct ast_cli_entry cli_show_cl [static]
 

Definition at line 975 of file chan_misdn.c.

struct ast_cli_entry cli_show_cls [static]
 

Definition at line 968 of file chan_misdn.c.

struct ast_cli_entry cli_show_config [static]
 

Definition at line 945 of file chan_misdn.c.

struct ast_cli_entry cli_show_port [static]
 

Definition at line 1008 of file chan_misdn.c.

struct ast_cli_entry cli_show_stacks [static]
 

Definition at line 1001 of file chan_misdn.c.

struct ast_cli_entry cli_toggle_echocancel [static]
 

Definition at line 924 of file chan_misdn.c.

char* desc = "Channel driver for mISDN Support (Bri/Pri)" [static]
 

Definition at line 195 of file chan_misdn.c.

struct chan_list dummy_cl
 

Definition at line 214 of file chan_misdn.c.

int g_config_initialized = 0
 

Definition at line 3345 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

unsigned long glob_channel = 0
 

Definition at line 2109 of file chan_misdn.c.

Referenced by misdn_new().

ast_mutex_t lock
 

Definition at line 670 of file chan_misdn.c.

Referenced by ast_waitfor_nandfds(), load_config(), load_module(), mkbrd(), rpt_master(), unload_module(), usecount(), zap_show_channel(), zap_show_channels(), and zt_request().

int max_ports
 

Definition at line 212 of file chan_misdn.c.

Referenced by build_port_config(), chan_misdn_log(), free_port_cfg(), load_module(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), misdn_cfg_is_group_method(), misdn_cfg_is_port_valid(), misdn_reload(), and misdn_set_debug().

int MAXTICS = 8
 

Definition at line 671 of file chan_misdn.c.

Referenced by misdn_set_tics().

int* misdn_debug
 

Definition at line 210 of file chan_misdn.c.

Referenced by chan_misdn_log(), chan_misdn_trace_call(), load_module(), misdn_reload(), misdn_set_debug(), misdn_show_cls(), misdn_show_port(), misdn_show_stacks(), print_bc_info(), and unload_module().

int* misdn_debug_only
 

Definition at line 211 of file chan_misdn.c.

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

char** misdn_key_vector = NULL
 

Definition at line 202 of file chan_misdn.c.

Referenced by misdn_set_opt_exec().

int misdn_key_vector_size = 0
 

Definition at line 203 of file chan_misdn.c.

Referenced by misdn_set_opt_exec().

struct ast_channel_tech misdn_tech
 

Definition at line 2073 of file chan_misdn.c.

struct ast_channel_tech misdn_tech_wo_bridge
 

Definition at line 2091 of file chan_misdn.c.

int prefformat = AST_FORMAT_ALAW [static]
 

Definition at line 206 of file chan_misdn.c.

Referenced by load_module(), misdn_new(), misdn_write(), nbs_new(), and phone_new().

ast_mutex_t release_lock_mutex
 

Definition at line 65 of file chan_misdn.c.

Referenced by load_module().

struct robin_list* robin = NULL [static]
 

Definition at line 141 of file chan_misdn.c.

struct state_struct state_array[]
 

Definition at line 515 of file chan_misdn.c.

int tracing = 0
 

Definition at line 198 of file chan_misdn.c.

Referenced by chan_misdn_log(), load_module(), and misdn_reload().

char* type = "mISDN" [static]
 

Definition at line 196 of file chan_misdn.c.

int usecnt = 0 [static]
 

Definition at line 200 of file chan_misdn.c.

ast_mutex_t usecnt_lock [static]
 

Definition at line 208 of file chan_misdn.c.

Referenced by __oh323_new(), agent_hangup(), agent_new(), alsa_hangup(), alsa_new(), aopen_decusecnt(), aopen_incusecnt(), ast_iax2_new(), ast_modem_new(), bestdata_decusecnt(), bestdata_incusecnt(), features_new(), i4l_decusecnt(), i4l_incusecnt(), iax2_predestroy(), local_hangup(), local_new(), mgcp_hangup(), mgcp_new(), modem_hangup(), nbs_new(), oh323_hangup(), oss_hangup(), oss_new(), phone_check_exception(), phone_hangup(), phone_new(), sip_hangup(), sip_new(), skinny_new(), usecount(), vpb_hangup(), vpb_new(), zt_hangup(), and zt_new().


Generated on Sun Aug 6 15:06:09 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2