Thu Oct 8 00:59:28 2009

Asterisk developer's documentation


chan_misdn.c File Reference

the chan_misdn channel driver for Asterisk More...

#include "asterisk.h"
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <sys/file.h>
#include <semaphore.h>
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/io.h"
#include "asterisk/frame.h"
#include "asterisk/translate.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/indications.h"
#include "asterisk/app.h"
#include "asterisk/features.h"
#include "asterisk/term.h"
#include "asterisk/sched.h"
#include "asterisk/stringfields.h"
#include "asterisk/causes.h"
#include "asterisk/abstract_jb.h"
#include "chan_misdn_config.h"
#include "isdn_lib.h"
#include "asterisk/strings.h"

Go to the source code of this file.

Data Structures

struct  allowed_bearers
struct  chan_list
 Channel call record structure. More...
struct  hold_info
struct  misdn_jb
struct  robin_list
struct  state_struct

Defines

#define MISDN_ASTERISK_PVT(ast)   1
#define MISDN_ASTERISK_TECH_PVT(ast)   ast->tech_pvt
#define ORG_AST   1
#define ORG_MISDN   2

Enumerations

enum  misdn_chan_state {
  MISDN_NOTHING = 0, MISDN_WAITING4DIGS, MISDN_EXTCANTMATCH, MISDN_INCOMING_SETUP,
  MISDN_DIALING, MISDN_PROGRESS, MISDN_PROCEEDING, MISDN_CALLING,
  MISDN_CALLING_ACKNOWLEDGE, MISDN_ALERTING, MISDN_BUSY, MISDN_CONNECTED,
  MISDN_PRECONNECTED, MISDN_DISCONNECTED, MISDN_RELEASED, MISDN_BRIDGED,
  MISDN_CLEANING, MISDN_HUNGUP_FROM_MISDN, MISDN_HUNGUP_FROM_AST, MISDN_HOLDED,
  MISDN_HOLD_DISCONNECT
}

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
int add_in_calls (int port)
int add_out_calls (int port)
static const char * bearer2str (int cap)
static enum event_response_e cb_events (enum event_e event, struct misdn_bchannel *bc, void *user_data)
int chan_misdn_jb_empty (struct misdn_bchannel *bc, char *buf, int len)
static void chan_misdn_log (int level, int port, char *tmpl,...)
static void cl_dequeue_chan (struct chan_list **list, struct chan_list *chan)
static void cl_queue_chan (struct chan_list **list, struct chan_list *chan)
static char * complete_ch (const char *line, const char *word, int pos, int state)
static char * complete_ch_helper (const char *line, const char *word, int pos, int state, int rpos)
static char * complete_debug_port (const char *line, const char *word, int pos, int state)
static char * complete_show_config (const char *line, const char *word, int pos, int state)
static void config_jitterbuffer (struct chan_list *ch)
void debug_numplan (int port, int numplan, char *type)
static int dialtone_indicate (struct chan_list *cl)
static void do_immediate_setup (struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
static void export_aoc_vars (int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
void export_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 Export parameters to the dialplan environment variables.
static struct chan_listfind_chan_by_bc (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_chan_by_pid (struct chan_list *list, int pid)
static struct chan_listfind_holded (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_holded_l3 (struct chan_list *list, unsigned long l3_id, int w)
static void free_robin_list (void)
static void free_robin_list_r (struct robin_list *r)
static struct chan_listget_chan_by_ast (struct ast_channel *ast)
static struct chan_listget_chan_by_ast_name (char *name)
static struct robin_listget_robin_position (char *group)
static void hangup_chan (struct chan_list *ch)
static int hanguptone_indicate (struct chan_list *cl)
void import_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 Import parameters from the dialplan environment variables.
static struct chan_listinit_chan_list (int orig)
static int load_module (void)
static int misdn_answer (struct ast_channel *ast)
static enum ast_bridge_result misdn_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int misdn_call (struct ast_channel *ast, char *dest, int timeout)
static int misdn_check_l2l1 (struct ast_channel *chan, void *data)
static int misdn_digit_begin (struct ast_channel *chan, char digit)
static int misdn_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int misdn_facility_exec (struct ast_channel *chan, void *data)
static int misdn_fixup (struct ast_channel *oldast, struct ast_channel *ast)
static const char * misdn_get_ch_state (struct chan_list *p)
static int misdn_hangup (struct ast_channel *ast)
static int misdn_indication (struct ast_channel *ast, int cond, const void *data, size_t datalen)
void misdn_jb_destroy (struct misdn_jb *jb)
 frees the data and destroys the given jitterbuffer struct
int misdn_jb_empty (struct misdn_jb *jb, char *data, int len)
 gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data.
int misdn_jb_fill (struct misdn_jb *jb, const char *data, int len)
 fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).
misdn_jbmisdn_jb_init (int size, int upper_threshold)
 allocates the jb-structure and initialize the elements
static int misdn_l1_task (const void *data)
static struct ast_channelmisdn_new (struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c)
static int misdn_overlap_dial_task (const void *data)
static int misdn_port_block (int fd, int argc, char *argv[])
static int misdn_port_down (int fd, int argc, char *argv[])
static int misdn_port_unblock (int fd, int argc, char *argv[])
static int misdn_port_up (int fd, int argc, char *argv[])
static struct ast_framemisdn_read (struct ast_channel *ast)
static int misdn_reload (int fd, int argc, char *argv[])
static struct ast_channelmisdn_request (const char *type, int format, void *data, int *cause)
static int misdn_restart_pid (int fd, int argc, char *argv[])
static int misdn_restart_port (int fd, int argc, char *argv[])
static int misdn_send_cd (int fd, int argc, char *argv[])
static int misdn_send_digit (int fd, int argc, char *argv[])
static int misdn_send_display (int fd, int argc, char *argv[])
static int misdn_send_restart (int fd, int argc, char *argv[])
static int misdn_send_text (struct ast_channel *chan, const char *text)
static int misdn_set_crypt_debug (int fd, int argc, char *argv[])
static int misdn_set_debug (int fd, int argc, char *argv[])
static int misdn_set_opt_exec (struct ast_channel *chan, void *data)
static int misdn_set_tics (int fd, int argc, char *argv[])
static int misdn_show_cl (int fd, int argc, char *argv[])
static int misdn_show_cls (int fd, int argc, char *argv[])
static int misdn_show_config (int fd, int argc, char *argv[])
static int misdn_show_port (int fd, int argc, char *argv[])
static int misdn_show_ports_stats (int fd, int argc, char *argv[])
static int misdn_show_stacks (int fd, int argc, char *argv[])
static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data)
static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data)
static void misdn_tasks_destroy (void)
static void misdn_tasks_init (void)
static void misdn_tasks_remove (int task_id)
static void * misdn_tasks_thread_func (void *data)
static void misdn_tasks_wakeup (void)
static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
static void misdn_transfer_bc (struct chan_list *tmp_ch, struct chan_list *holded_chan)
static int misdn_write (struct ast_channel *ast, struct ast_frame *frame)
static int pbx_start_chan (struct chan_list *ch)
static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
static void print_bearer (struct misdn_bchannel *bc)
static void print_facility (struct FacParm *fac, struct misdn_bchannel *bc)
static struct ast_frameprocess_ast_dsp (struct chan_list *tmp, struct ast_frame *frame)
static int read_config (struct chan_list *ch, int orig)
static void release_chan (struct misdn_bchannel *bc)
static int reload (void)
static void reload_config (void)
static void send_cause2ast (struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
static void send_digit_to_chan (struct chan_list *cl, char digit)
static void show_config_description (int fd, enum misdn_cfg_elements elem)
static void sighandler (int sig)
static int start_bc_tones (struct chan_list *cl)
static void start_pbx (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
static int stop_bc_tones (struct chan_list *cl)
static int stop_indicate (struct chan_list *cl)
static int unload_module (void)
static int update_config (struct chan_list *ch, int orig)
 Updates caller ID information from config.
static int update_ec_config (struct misdn_bchannel *bc)
static void update_name (struct ast_channel *tmp, int port, int c)
static void wait_for_digits (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Channel driver for mISDN Support (BRI/PRI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "6989f2ec67f8497e38c12890500c525b" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct allowed_bearers allowed_bearers_array []
static const struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry chan_misdn_clis []
chan_listcl_te = NULL
 Global channel call record list head.
ast_mutex_t cl_te_lock
chan_list dummy_cl
static int g_config_initialized = 0
static int glob_channel = 0
char global_tracefile [BUFFERSIZE+1]
ast_mutex_t lock
static int max_ports
int MAXTICS = 8
static int * misdn_debug
static int * misdn_debug_only
static int * misdn_in_calls
static int * misdn_out_calls
static int * misdn_ports
static struct sched_contextmisdn_tasks = NULL
 the main schedule context for stuff like l1 watcher, overlap dial, ...
static pthread_t misdn_tasks_thread
static struct ast_channel_tech misdn_tech
static struct ast_channel_tech misdn_tech_wo_bridge
static const char misdn_type [] = "mISDN"
static int prefformat = AST_FORMAT_ALAW
 Only alaw and mulaw is allowed for now.
ast_mutex_t release_lock
static struct robin_listrobin = NULL
static struct state_struct state_array []
static int tracing = 0


Detailed Description

the chan_misdn channel driver for Asterisk

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

Definition in file chan_misdn.c.


Define Documentation

#define MISDN_ASTERISK_PVT ( ast   )     1

Definition at line 493 of file chan_misdn.c.

Referenced by cb_events(), and do_immediate_setup().

#define MISDN_ASTERISK_TECH_PVT ( ast   )     ast->tech_pvt

Definition at line 492 of file chan_misdn.c.

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

#define ORG_AST   1

Definition at line 147 of file chan_misdn.c.

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

#define ORG_MISDN   2

Definition at line 148 of file chan_misdn.c.

Referenced by cb_events(), and misdn_indication().


Enumeration Type Documentation

enum misdn_chan_state

Enumerator:
MISDN_NOTHING  at beginning
MISDN_WAITING4DIGS  when waiting for infos
MISDN_EXTCANTMATCH  when asterisk couldn't match our ext
MISDN_INCOMING_SETUP  for incoming setups
MISDN_DIALING  when pbx_start
MISDN_PROGRESS  we got a progress
MISDN_PROCEEDING  we got a progress
MISDN_CALLING  when misdn_call is called
MISDN_CALLING_ACKNOWLEDGE  when we get SETUP_ACK
MISDN_ALERTING  when Alerting
MISDN_BUSY  when BUSY
MISDN_CONNECTED  when connected
MISDN_PRECONNECTED  when connected
MISDN_DISCONNECTED  when connected
MISDN_RELEASED  when connected
MISDN_BRIDGED  when bridged
MISDN_CLEANING  when hangup from * but we were connected before
MISDN_HUNGUP_FROM_MISDN  when DISCONNECT/RELEASE/REL_COMP came from misdn
MISDN_HUNGUP_FROM_AST  when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup
MISDN_HOLDED  if this chan is holded
MISDN_HOLD_DISCONNECT  if this chan is holded

Definition at line 122 of file chan_misdn.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 5781 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

Definition at line 5781 of file chan_misdn.c.

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

Definition at line 797 of file chan_misdn.c.

References ast_sched_add_variable(), misdn_tasks, misdn_tasks_init(), and misdn_tasks_wakeup().

Referenced by misdn_tasks_add(), and misdn_tasks_add_variable().

00798 {
00799    int task_id;
00800 
00801    if (!misdn_tasks) {
00802       misdn_tasks_init();
00803    }
00804    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00805    misdn_tasks_wakeup();
00806 
00807    return task_id;
00808 }

int add_in_calls ( int  port  ) 

Definition at line 3939 of file chan_misdn.c.

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

Referenced by cb_events().

03940 {
03941    int max_in_calls;
03942    
03943    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
03944    misdn_in_calls[port]++;
03945 
03946    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
03947       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
03948       return misdn_in_calls[port] - max_in_calls;
03949    }
03950    
03951    return 0;
03952 }

int add_out_calls ( int  port  ) 

Definition at line 3954 of file chan_misdn.c.

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

Referenced by misdn_call().

03955 {
03956    int max_out_calls;
03957    
03958    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
03959 
03960    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
03961       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
03962       return (misdn_out_calls[port] + 1) - max_out_calls;
03963    }
03964 
03965    misdn_out_calls[port]++;
03966    
03967    return 0;
03968 }

static const char* bearer2str ( int  cap  )  [static]

Definition at line 609 of file chan_misdn.c.

References allowed_bearers_array, ARRAY_LEN, and allowed_bearers::display.

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

00610 {
00611    unsigned index;
00612 
00613    for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
00614       if (allowed_bearers_array[index].cap == cap) {
00615          return allowed_bearers_array[index].display;
00616       }
00617    }  /* end for */
00618 
00619    return "Unknown Bearer";
00620 }

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

Definition at line 3994 of file chan_misdn.c.

References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, allowed_bearers_array, misdn_bchannel::AOCD, misdn_bchannel::AOCDtype, ARRAY_LEN, chan_list::ast, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_cdr_update(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_copy_string(), ast_deactivate_generator(), ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_pickup_call(), ast_pickup_ext(), AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_queue_frame(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_transfercapability2str(), ast_tv(), ast_tvnow(), chan_list::bc, misdn_bchannel::bc_state, bc_state2str(), bearer2str(), misdn_bchannel::bframe, misdn_bchannel::bframe_len, misdn_bchannel::cad, misdn_bchannel::capability, misdn_bchannel::cause, cb_log, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, misdn_bchannel::chargingUnit, ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), cl_te, chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::currency, misdn_bchannel::cw, misdn_bchannel::dad, ast_frame::data, ast_frame::datalen, ast_frame::delivery, do_immediate_setup(), misdn_bchannel::dtmf, misdn_bchannel::dummy, errno, EVENT_ALERTING, EVENT_BCHAN_ACTIVATED, EVENT_BCHAN_DATA, EVENT_BCHAN_ERROR, EVENT_CLEANUP, EVENT_CONNECT, EVENT_CONNECT_ACKNOWLEDGE, EVENT_DISCONNECT, EVENT_DTMF_TONE, EVENT_FACILITY, EVENT_HOLD, EVENT_HOLD_ACKNOWLEDGE, EVENT_HOLD_REJECT, EVENT_INFORMATION, EVENT_NEW_BC, EVENT_NEW_CHANNEL, EVENT_NEW_L3ID, EVENT_PORT_ALARM, EVENT_PROCEEDING, EVENT_PROGRESS, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, EVENT_RESTART, EVENT_RETRIEVE, EVENT_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_REJECT, EVENT_SETUP, EVENT_SETUP_ACKNOWLEDGE, EVENT_STATUS, EVENT_TIMEOUT, EVENT_TONE_GENERATE, export_aoc_vars(), export_ch(), ast_channel::exten, misdn_bchannel::fac_in, chan_list::far_alerting, find_chan_by_bc(), find_holded(), find_holded_l3(), ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, hangup_chan(), ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold_info, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::info_dad, INFO_PI_INBAND_AVAILABLE, misdn_bchannel::infos_pending, init_chan_list(), misdn_bchannel::keypad, misdn_bchannel::l3_id, chan_list::l3id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_isdn_get_info(), MISDN_ALERTING, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, misdn_cap_is_speech(), MISDN_CFG_ALARM_BLOCK, MISDN_CFG_ALWAYS_IMMEDIATE, misdn_cfg_get(), MISDN_CFG_HOLD_ALLOWED, MISDN_CFG_IMMEDIATE, misdn_cfg_is_msn_valid(), MISDN_CFG_REJECT_CAUSE, MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, MISDN_EXTCANTMATCH, MISDN_GEN_APPEND_DIGITS2EXTEN, misdn_get_ch_state(), MISDN_HOLDED, misdn_inband_avail(), MISDN_INCOMING_SETUP, misdn_lib_is_ptp(), misdn_lib_log_ies(), misdn_lib_port_block(), misdn_lib_send_event(), misdn_new(), MISDN_NOTHING, misdn_overlap_dial_task(), MISDN_PROCEEDING, MISDN_PROGRESS, misdn_tasks_add_variable(), misdn_transfer_bc(), MISDN_WAITING4DIGS, allowed_bearers::name, chan_list::need_busy, misdn_bchannel::need_disconnect, misdn_bchannel::need_more_infos, misdn_bchannel::need_release, misdn_bchannel::need_release_complete, chan_list::noautorespond_on_setup, misdn_bchannel::nt, chan_list::nttimeout, misdn_bchannel::oad, ast_frame::offset, ORG_AST, ORG_MISDN, chan_list::originator, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_builtin_setvar_helper(), pbx_start_chan(), misdn_bchannel::pid, chan_list::pipe, hold_info::port, misdn_bchannel::port, misdn_bchannel::pres, print_bearer(), print_facility(), misdn_bchannel::progress_indicator, read_config(), release_chan(), RESPONSE_IGNORE_SETUP, RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE, RESPONSE_OK, RESPONSE_RELEASE_SETUP, ast_channel::rings, ast_frame::samples, misdn_bchannel::screen, misdn_bchannel::sending_complete, ast_frame::src, start_bc_tones(), start_pbx(), chan_list::state, stop_bc_tones(), stop_indicate(), ast_frame::subclass, t, ast_channel::tech, misdn_bchannel::tone_cnt, ast_channel::transfercapability, ast_channel_tech::type, update_name(), and wait_for_digits().

Referenced by load_module().

03995 {
03996    int msn_valid;
03997    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
03998    
03999    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
04000       int debuglevel = 1;
04001       if ( event == EVENT_CLEANUP && !user_data)
04002          debuglevel = 5;
04003 
04004       chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch ? misdn_get_ch_state(ch) : "none");
04005       if (debuglevel == 1) {
04006          misdn_lib_log_ies(bc);
04007          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04008       }
04009    }
04010    
04011    if (!ch) {
04012       switch(event) {
04013       case EVENT_SETUP:
04014       case EVENT_DISCONNECT:
04015       case EVENT_PORT_ALARM:
04016       case EVENT_RETRIEVE:
04017       case EVENT_NEW_BC:
04018       case EVENT_FACILITY:
04019          break;
04020       case EVENT_RELEASE_COMPLETE:
04021          chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
04022          break;
04023       case EVENT_CLEANUP:
04024       case EVENT_TONE_GENERATE:
04025       case EVENT_BCHAN_DATA:
04026          return -1;
04027       default:
04028          chan_misdn_log(1, bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n", bc->l3_id, bc, manager_isdn_get_info(event), bc->port, bc->channel);
04029          return -1;
04030       }
04031    }
04032    
04033    if (ch) {
04034       switch (event) {
04035       case EVENT_TONE_GENERATE:
04036          break;
04037       case EVENT_DISCONNECT:
04038       case EVENT_RELEASE:
04039       case EVENT_RELEASE_COMPLETE:
04040       case EVENT_CLEANUP:
04041       case EVENT_TIMEOUT:
04042          if (!ch->ast)
04043             chan_misdn_log(3, bc->port, "ast_hangup already called, so we have no ast ptr anymore in event(%s)\n", manager_isdn_get_info(event));
04044          break;
04045       default:
04046          if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04047             if (event != EVENT_BCHAN_DATA)
04048                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04049             return -1;
04050          }
04051       }
04052    }
04053    
04054    
04055    switch (event) {
04056    case EVENT_PORT_ALARM:
04057       {
04058          int boa = 0;
04059          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
04060          if (boa) {
04061             cb_log(1, bc->port, " --> blocking\n");
04062             misdn_lib_port_block(bc->port); 
04063          }
04064       }
04065       break;
04066    case EVENT_BCHAN_ACTIVATED:
04067       break;
04068       
04069    case EVENT_NEW_CHANNEL:
04070       update_name(ch->ast,bc->port,bc->channel);
04071       break;
04072       
04073    case EVENT_NEW_L3ID:
04074       ch->l3id=bc->l3_id;
04075       ch->addr=bc->addr;
04076       break;
04077 
04078    case EVENT_NEW_BC:
04079       if (!ch) {
04080          ch = find_holded(cl_te,bc);
04081       }
04082       
04083       if (!ch) {
04084          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04085          break;
04086       }
04087 
04088       if (bc)
04089          ch->bc = (struct misdn_bchannel *)user_data;
04090       break;
04091       
04092    case EVENT_DTMF_TONE:
04093    {
04094       /*  sending INFOS as DTMF-Frames :) */
04095       struct ast_frame fr;
04096 
04097       memset(&fr, 0, sizeof(fr));
04098       fr.frametype = AST_FRAME_DTMF;
04099       fr.subclass = bc->dtmf ;
04100       fr.src = NULL;
04101       fr.data = NULL;
04102       fr.datalen = 0;
04103       fr.samples = 0;
04104       fr.mallocd = 0;
04105       fr.offset = 0;
04106       fr.delivery = ast_tv(0,0);
04107       
04108       if (!ch->ignore_dtmf) {
04109          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04110          ast_queue_frame(ch->ast, &fr);
04111       } else {
04112          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04113       }
04114    }
04115       break;
04116    case EVENT_STATUS:
04117       break;
04118     
04119    case EVENT_INFORMATION:
04120    {
04121       if ( ch->state != MISDN_CONNECTED ) 
04122          stop_indicate(ch);
04123    
04124       if (!ch->ast)
04125          break;
04126 
04127       if (ch->state == MISDN_WAITING4DIGS ) {
04128          /*  Ok, incomplete Setup, waiting till extension exists */
04129          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04130             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04131             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04132          }
04133 
04134          strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04135          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04136 
04137          /* Check for Pickup Request first */
04138          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04139             if (ast_pickup_call(ch->ast)) {
04140                hangup_chan(ch);
04141             } else {
04142                struct ast_channel *chan = ch->ast;
04143                ch->state = MISDN_CALLING_ACKNOWLEDGE;
04144                ast_setstate(chan, AST_STATE_DOWN);
04145                hangup_chan(ch);
04146                ch->ast = NULL;
04147                break;
04148             }
04149          }
04150          
04151          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04152             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04153                ast_log(LOG_WARNING,
04154                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04155                   bc->dad, ch->context, bc->port);
04156                strcpy(ch->ast->exten, "i");
04157 
04158                ch->state = MISDN_DIALING;
04159                start_pbx(ch, bc, ch->ast);
04160                break;
04161             }
04162 
04163             ast_log(LOG_WARNING,
04164                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04165                "\tMaybe you want to add an 'i' extension to catch this case.\n",
04166                bc->dad, ch->context, bc->port);
04167 
04168             if (bc->nt)
04169                hanguptone_indicate(ch);
04170             ch->state = MISDN_EXTCANTMATCH;
04171             bc->out_cause = AST_CAUSE_UNALLOCATED;
04172 
04173             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04174             break;
04175          }
04176 
04177          if (ch->overlap_dial) {
04178             ast_mutex_lock(&ch->overlap_tv_lock);
04179             ch->overlap_tv = ast_tvnow();
04180             ast_mutex_unlock(&ch->overlap_tv_lock);
04181             if (ch->overlap_dial_task == -1) {
04182                ch->overlap_dial_task = 
04183                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04184             }
04185             break;
04186          }
04187 
04188          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04189             
04190             ch->state = MISDN_DIALING;
04191             start_pbx(ch, bc, ch->ast);
04192          }
04193       } else {
04194          /*  sending INFOS as DTMF-Frames :) */
04195          struct ast_frame fr;
04196          int digits;
04197 
04198          memset(&fr, 0, sizeof(fr));
04199          fr.frametype = AST_FRAME_DTMF;
04200          fr.subclass = bc->info_dad[0] ;
04201          fr.src = NULL;
04202          fr.data = NULL;
04203          fr.datalen = 0;
04204          fr.samples = 0;
04205          fr.mallocd = 0;
04206          fr.offset = 0;
04207          fr.delivery = ast_tv(0,0);
04208 
04209          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
04210          if (ch->state != MISDN_CONNECTED ) {
04211             if (digits) {
04212                strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04213                ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04214                ast_cdr_update(ch->ast);
04215             }
04216             
04217             ast_queue_frame(ch->ast, &fr);
04218          }
04219       }
04220    }
04221       break;
04222    case EVENT_SETUP:
04223    {
04224       struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04225       struct ast_channel *chan;
04226       int exceed;
04227       int pres, screen;
04228       int ai;
04229       int im;
04230 
04231       if (ch) {
04232          switch (ch->state) {
04233          case MISDN_NOTHING:
04234             ch = NULL;
04235             break;
04236          default:
04237             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04238             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
04239          }
04240       }
04241 
04242       msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04243       if (!bc->nt && ! msn_valid) {
04244          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04245          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04246       }
04247 
04248       if (bc->cw) {
04249          int cause;
04250          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04251          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04252          bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
04253          return RESPONSE_RELEASE_SETUP;
04254       }
04255 
04256       print_bearer(bc);
04257 
04258       ch = init_chan_list(ORG_MISDN);
04259 
04260       if (!ch) {
04261          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
04262          return 0;
04263       }
04264 
04265       ch->bc = bc;
04266       ch->l3id = bc->l3_id;
04267       ch->addr = bc->addr;
04268       ch->originator = ORG_MISDN;
04269 
04270       chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04271       if (!chan) {
04272          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04273          ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); 
04274          return 0;
04275       }
04276 
04277       ch->ast = chan;
04278 
04279       if ((exceed = add_in_calls(bc->port))) {
04280          char tmp[16];
04281          snprintf(tmp, sizeof(tmp), "%d", exceed);
04282          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
04283       }
04284 
04285       read_config(ch, ORG_MISDN);
04286 
04287       export_ch(chan, bc, ch);
04288 
04289       ch->ast->rings = 1;
04290       ast_setstate(ch->ast, AST_STATE_RINGING);
04291 
04292       switch (bc->pres) {
04293       case 1:
04294          pres = AST_PRES_RESTRICTED;
04295          chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
04296          break;
04297       case 2:
04298          pres = AST_PRES_UNAVAILABLE;
04299          chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
04300          break;
04301       default:
04302          pres = AST_PRES_ALLOWED;
04303          chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
04304          break;
04305       }
04306 
04307       switch (bc->screen) {
04308       default:
04309       case 0:
04310          screen = AST_PRES_USER_NUMBER_UNSCREENED;
04311          chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
04312          break;
04313       case 1:
04314          screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
04315          chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
04316          break;
04317       case 2:
04318          screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
04319          chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
04320          break;
04321       case 3:
04322          screen = AST_PRES_NETWORK_NUMBER;
04323          chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
04324          break;
04325       }
04326 
04327       chan->cid.cid_pres = pres | screen;
04328 
04329       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04330       chan->transfercapability = bc->capability;
04331 
04332       switch (bc->capability) {
04333       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04334          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
04335          break;
04336       default:
04337          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
04338       }
04339 
04340       /** queue new chan **/
04341       cl_queue_chan(&cl_te, ch);
04342 
04343       if (!strstr(ch->allowed_bearers, "all")) {
04344          int i;
04345 
04346          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
04347             if (allowed_bearers_array[i].cap == bc->capability) {
04348                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
04349                   /* The bearer capability is allowed */
04350                   if (allowed_bearers_array[i].deprecated) {
04351                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
04352                         allowed_bearers_array[i].name);
04353                   }
04354                   break;
04355                }
04356             }
04357          }  /* end for */
04358          if (i == ARRAY_LEN(allowed_bearers_array)) {
04359             /* We did not find the bearer capability */
04360             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
04361                bearer2str(bc->capability), bc->capability);
04362             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
04363 
04364             ch->state = MISDN_EXTCANTMATCH;
04365             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04366             return RESPONSE_OK;
04367          }
04368       }
04369 
04370       /* Check for Pickup Request first */
04371       if (!strcmp(chan->exten, ast_pickup_ext())) {
04372          if (!ch->noautorespond_on_setup) {
04373             int ret;/** Sending SETUP_ACK**/
04374             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04375          } else {
04376             ch->state = MISDN_INCOMING_SETUP;
04377          }
04378          if (ast_pickup_call(chan)) {
04379             hangup_chan(ch);
04380          } else {
04381             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04382             ast_setstate(chan, AST_STATE_DOWN);
04383             hangup_chan(ch);
04384             ch->ast = NULL;
04385             break;
04386          }
04387       }
04388 
04389       /*
04390        * added support for s extension hope it will help those poor cretains
04391        * which haven't overlap dial.
04392        */
04393       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04394       if (ai) {
04395          do_immediate_setup(bc, ch, chan);
04396          break;
04397       }
04398 
04399       /* check if we should jump into s when we have no dad */
04400       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04401       if (im && ast_strlen_zero(bc->dad)) {
04402          do_immediate_setup(bc, ch, chan);
04403          break;
04404       }
04405 
04406       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
04407       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04408          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04409             ast_log(LOG_WARNING,
04410                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04411                bc->dad, ch->context, bc->port);
04412             strcpy(ch->ast->exten, "i");
04413             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04414             ch->state = MISDN_DIALING;
04415             start_pbx(ch, bc, chan);
04416             break;
04417          }
04418 
04419          ast_log(LOG_WARNING,
04420             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04421             "\tMaybe you want to add an 'i' extension to catch this case.\n",
04422             bc->dad, ch->context, bc->port);
04423          if (bc->nt)
04424             hanguptone_indicate(ch);
04425 
04426          ch->state = MISDN_EXTCANTMATCH;
04427          bc->out_cause = AST_CAUSE_UNALLOCATED;
04428 
04429          if (bc->nt)
04430             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04431          else
04432             misdn_lib_send_event(bc, EVENT_RELEASE );
04433 
04434          break;
04435       }
04436 
04437       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
04438        * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
04439        * will be used by Asterisk automatically. */
04440       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04441          if (!ch->noautorespond_on_setup) {
04442             ch->state=MISDN_DIALING;
04443             misdn_lib_send_event(bc, EVENT_PROCEEDING );
04444          } else {
04445             ch->state = MISDN_INCOMING_SETUP;
04446          }
04447          start_pbx(ch, bc, chan);
04448          break;
04449       }
04450 
04451 
04452       /*
04453        * When we are NT and overlapdial is set and if 
04454        * the number is empty, we wait for the ISDN timeout
04455        * instead of our own timer.
04456        */
04457       if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04458          wait_for_digits(ch, bc, chan);
04459          break;
04460       }
04461 
04462       /* 
04463        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
04464        * Infos with a Interdigit Timeout.
04465        * */
04466       if (ch->overlap_dial) {
04467          ast_mutex_lock(&ch->overlap_tv_lock);
04468          ch->overlap_tv = ast_tvnow();
04469          ast_mutex_unlock(&ch->overlap_tv_lock);
04470 
04471          wait_for_digits(ch, bc, chan);
04472          if (ch->overlap_dial_task == -1) 
04473             ch->overlap_dial_task = 
04474                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04475 
04476          break;
04477       }
04478 
04479       /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
04480        * without interdigit timeout.
04481        * */
04482       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04483          wait_for_digits(ch, bc, chan);
04484          break;
04485       }
04486 
04487       /*
04488        * If the extension exists let's just jump into it.
04489        * */
04490       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04491          if (bc->need_more_infos)
04492             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04493          else
04494             misdn_lib_send_event(bc, EVENT_PROCEEDING);
04495 
04496          ch->state = MISDN_DIALING;
04497          start_pbx(ch, bc, chan);
04498          break;
04499       }
04500    }
04501    break;
04502 
04503    case EVENT_SETUP_ACKNOWLEDGE:
04504    {
04505       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04506 
04507       if (bc->channel) 
04508          update_name(ch->ast,bc->port,bc->channel);
04509       
04510       if (!ast_strlen_zero(bc->infos_pending)) {
04511          /* TX Pending Infos */
04512          strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04513 
04514          if (!ch->ast)
04515             break;
04516          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04517          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04518          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04519 
04520          misdn_lib_send_event(bc, EVENT_INFORMATION);
04521       }
04522    }
04523    break;
04524    case EVENT_PROCEEDING:
04525    {
04526       if (bc->channel) 
04527          update_name(ch->ast, bc->port, bc->channel);
04528 
04529       if (misdn_cap_is_speech(bc->capability) &&
04530            misdn_inband_avail(bc) ) {
04531          start_bc_tones(ch);
04532       }
04533 
04534       ch->state = MISDN_PROCEEDING;
04535       
04536       if (!ch->ast)
04537          break;
04538 
04539       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04540    }
04541    break;
04542    case EVENT_PROGRESS:
04543       if (bc->channel) 
04544          update_name(ch->ast, bc->port, bc->channel);
04545 
04546       if (!bc->nt ) {
04547          if ( misdn_cap_is_speech(bc->capability) &&
04548               misdn_inband_avail(bc)
04549             ) {
04550             start_bc_tones(ch);
04551          }
04552          
04553          ch->state = MISDN_PROGRESS;
04554 
04555          if (!ch->ast)
04556             break;
04557          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04558       }
04559       break;
04560       
04561       
04562    case EVENT_ALERTING:
04563    {
04564       if (bc->channel) 
04565          update_name(ch->ast, bc->port, bc->channel);
04566 
04567       ch->state = MISDN_ALERTING;
04568       
04569       if (!ch->ast)
04570          break;
04571 
04572       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04573       ast_setstate(ch->ast, AST_STATE_RINGING);
04574       
04575       cb_log(7, bc->port, " --> Set State Ringing\n");
04576       
04577       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04578          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04579          start_bc_tones(ch);
04580       } else {
04581          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04582          if (ch->far_alerting) {
04583             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04584             start_bc_tones(ch);
04585             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04586          }
04587       }
04588    }
04589    break;
04590    case EVENT_CONNECT:
04591    {
04592       struct ast_channel *bridged;
04593 
04594       /*we answer when we've got our very new L3 ID from the NT stack */
04595       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04596 
04597       if (!ch->ast)
04598          break;
04599 
04600       bridged = ast_bridged_channel(ch->ast);
04601       stop_indicate(ch);
04602 
04603       if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04604          struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04605 
04606          chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04607          if (bridged_ch) {
04608             bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04609             ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04610          }
04611       }
04612    }
04613    ch->l3id=bc->l3_id;
04614    ch->addr=bc->addr;
04615 
04616    start_bc_tones(ch);
04617    
04618    ch->state = MISDN_CONNECTED;
04619    
04620    ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04621    break;
04622    case EVENT_CONNECT_ACKNOWLEDGE:
04623    {
04624       ch->l3id = bc->l3_id;
04625       ch->addr = bc->addr;
04626 
04627       start_bc_tones(ch);
04628 
04629       ch->state = MISDN_CONNECTED;
04630    }
04631    break;
04632    case EVENT_DISCONNECT:
04633       /*we might not have an ch->ast ptr here anymore*/
04634       if (ch) {
04635          struct chan_list *holded_ch = find_holded(cl_te, bc);
04636 
04637          chan_misdn_log(3, bc->port, " --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
04638          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04639             /* If there's inband information available (e.g. a
04640                recorded message saying what was wrong with the
04641                dialled number, or perhaps even giving an
04642                alternative number, then play it instead of
04643                immediately releasing the call */
04644             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04645       
04646             ch->state = MISDN_DISCONNECTED;
04647             start_bc_tones(ch);
04648 
04649             if (ch->ast) {
04650                ch->ast->hangupcause = bc->cause;
04651                if (bc->cause == AST_CAUSE_USER_BUSY)
04652                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04653             }
04654             ch->need_busy = 0;
04655             break;
04656          }
04657 
04658          /*Check for holded channel, to implement transfer*/
04659          if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
04660             cb_log(1, bc->port, " --> found holded ch\n");
04661             misdn_transfer_bc(ch, holded_ch) ;
04662          }
04663 
04664          bc->need_disconnect = 0;
04665 
04666          stop_bc_tones(ch);
04667          hangup_chan(ch);
04668 #if 0
04669       } else {
04670          ch = find_holded_l3(cl_te, bc->l3_id,1);
04671          if (ch) {
04672             hangup_chan(ch);
04673          }
04674 #endif
04675       }
04676       bc->out_cause = -1;
04677       if (bc->need_release)
04678          misdn_lib_send_event(bc, EVENT_RELEASE);
04679       break;
04680    
04681    case EVENT_RELEASE:
04682       {
04683          bc->need_disconnect = 0;
04684          bc->need_release = 0;
04685 
04686          hangup_chan(ch);
04687          release_chan(bc);
04688       }
04689       break;
04690    case EVENT_RELEASE_COMPLETE:
04691    {
04692       bc->need_disconnect = 0;
04693       bc->need_release = 0;
04694       bc->need_release_complete = 0;
04695 
04696       stop_bc_tones(ch);
04697       hangup_chan(ch);
04698 
04699       if (ch)
04700          ch->state = MISDN_CLEANING;
04701 
04702       release_chan(bc);
04703    }
04704    break;
04705    case EVENT_BCHAN_ERROR:
04706    case EVENT_CLEANUP:
04707    {
04708       stop_bc_tones(ch);
04709       
04710       switch (ch->state) {
04711       case MISDN_CALLING:
04712          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04713          break;
04714       default:
04715          break;
04716       }
04717       
04718       hangup_chan(ch);
04719       release_chan(bc);
04720    }
04721    break;
04722 
04723    case EVENT_TONE_GENERATE:
04724    {
04725       int tone_len = bc->tone_cnt;
04726       struct ast_channel *ast = ch->ast;
04727       void *tmp;
04728       int res;
04729       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04730 
04731       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
04732 
04733       if (!ast)
04734          break;
04735 
04736       if (!ast->generator)
04737          break;
04738 
04739       tmp = ast->generatordata;
04740       ast->generatordata = NULL;
04741       generate = ast->generator->generate;
04742 
04743       if (tone_len < 0 || tone_len > 512 ) {
04744          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
04745          tone_len = 128;
04746       }
04747 
04748       res = generate(ast, tmp, tone_len, tone_len);
04749       ast->generatordata = tmp;
04750       
04751       if (res) {
04752          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04753          ast_deactivate_generator(ast);
04754       } else {
04755          bc->tone_cnt = 0;
04756       }
04757    }
04758    break;
04759 
04760    case EVENT_BCHAN_DATA:
04761    {
04762       if (!misdn_cap_is_speech(ch->bc->capability)) {
04763          struct ast_frame frame;
04764          /*In Data Modes we queue frames*/
04765          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
04766          frame.subclass = AST_FORMAT_ALAW;
04767          frame.datalen = bc->bframe_len;
04768          frame.samples = bc->bframe_len;
04769          frame.mallocd = 0;
04770          frame.offset = 0;
04771          frame.delivery = ast_tv(0,0);
04772          frame.src = NULL;
04773          frame.data = bc->bframe;
04774 
04775          if (ch->ast) 
04776             ast_queue_frame(ch->ast, &frame);
04777       } else {
04778          fd_set wrfs;
04779          struct timeval tv = { 0, 0 };
04780          int t;
04781 
04782          FD_ZERO(&wrfs);
04783          FD_SET(ch->pipe[1], &wrfs);
04784 
04785          t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
04786 
04787          if (!t) {
04788             chan_misdn_log(9, bc->port, "Select Timed out\n");
04789             break;
04790          }
04791          
04792          if (t < 0) {
04793             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
04794             break;
04795          }
04796          
04797          if (FD_ISSET(ch->pipe[1], &wrfs)) {
04798             chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
04799             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
04800                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
04801 
04802                stop_bc_tones(ch);
04803                hangup_chan(ch);
04804                release_chan(bc);
04805             }
04806          } else {
04807             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
04808          }
04809       }
04810    }
04811    break;
04812    case EVENT_TIMEOUT:
04813    {
04814       if (ch && bc)
04815          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
04816 
04817       switch (ch->state) {
04818       case MISDN_DIALING:
04819       case MISDN_PROGRESS:
04820          if (bc->nt && !ch->nttimeout)
04821             break;
04822          
04823       case MISDN_CALLING:
04824       case MISDN_ALERTING:
04825       case MISDN_PROCEEDING:
04826       case MISDN_CALLING_ACKNOWLEDGE:
04827          if (bc->nt) {
04828             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
04829             hanguptone_indicate(ch);
04830          }
04831             
04832          bc->out_cause = AST_CAUSE_UNALLOCATED;
04833          misdn_lib_send_event(bc, EVENT_DISCONNECT);
04834          break;
04835 
04836       case MISDN_WAITING4DIGS:
04837          if (bc->nt) {
04838             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
04839             bc->out_cause = AST_CAUSE_UNALLOCATED;
04840             hanguptone_indicate(ch);
04841             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04842          } else {
04843             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
04844             misdn_lib_send_event(bc, EVENT_RELEASE);
04845          }
04846             
04847          break;
04848 
04849       case MISDN_CLEANING: 
04850          chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
04851          break;
04852 
04853       default:
04854          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04855       }
04856    }
04857    break;
04858 
04859     
04860    /****************************/
04861    /** Supplementary Services **/
04862    /****************************/
04863    case EVENT_RETRIEVE:
04864    {
04865       struct ast_channel *hold_ast;
04866 
04867       if (!ch) {
04868          chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
04869          ch = find_holded_l3(cl_te, bc->l3_id, 1);
04870       }
04871 
04872       if (!ch) {
04873          ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
04874          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04875          break;
04876       }
04877 
04878       /*remember the channel again*/
04879       ch->bc = bc;
04880       ch->state = MISDN_CONNECTED;
04881 
04882       ch->hold_info.port = 0;
04883       ch->hold_info.channel = 0;
04884 
04885       hold_ast = ast_bridged_channel(ch->ast);
04886 
04887       if (hold_ast) {
04888          ast_moh_stop(hold_ast);
04889       }
04890    
04891       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
04892          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
04893          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04894       }
04895    }
04896    break;
04897     
04898    case EVENT_HOLD:
04899    {
04900       int hold_allowed;
04901       struct ast_channel *bridged;
04902 
04903       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04904 
04905       if (!hold_allowed) {
04906 
04907          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04908          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04909          break;
04910       }
04911 
04912       bridged = ast_bridged_channel(ch->ast);
04913       if (bridged) {
04914          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
04915          ch->state = MISDN_HOLDED;
04916          ch->l3id = bc->l3_id;
04917          
04918          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04919 
04920          /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
04921           * instead of starting moh on the bridged channel directly */
04922          ast_moh_start(bridged, NULL, NULL);
04923 
04924          /*forget the channel now*/
04925          ch->bc = NULL;
04926          ch->hold_info.port = bc->port;
04927          ch->hold_info.channel = bc->channel;
04928 
04929       } else {
04930          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04931          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04932       }
04933    } 
04934    break;
04935    
04936    case EVENT_FACILITY:
04937       if (!ch) {
04938          /* This may come from a call we don't know nothing about, so we ignore it. */
04939          chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
04940          break;
04941       }
04942 
04943       print_facility(&(bc->fac_in), bc);
04944       
04945       switch (bc->fac_in.Function) {
04946       case Fac_CD:
04947          {
04948             struct ast_channel *bridged = ast_bridged_channel(ch->ast);
04949             struct chan_list *ch_br;
04950             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04951                ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
04952                /*ch->state = MISDN_FACILITY_DEFLECTED;*/
04953                if (ch_br->bc) {
04954                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
04955                      ch_br->state = MISDN_DIALING;
04956                      if (pbx_start_chan(ch_br) < 0) {
04957                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
04958                      }
04959                   }
04960                }
04961             }
04962             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04963          } 
04964          break;
04965       case Fac_AOCDCurrency:
04966          {
04967             bc->AOCDtype = Fac_AOCDCurrency;
04968             memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
04969             export_aoc_vars(ch->originator, ch->ast, bc);
04970          }
04971          break;
04972       case Fac_AOCDChargingUnit:
04973          {
04974             bc->AOCDtype = Fac_AOCDChargingUnit;
04975             memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
04976             export_aoc_vars(ch->originator, ch->ast, bc);
04977          }
04978          break;
04979       default:
04980          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
04981       }
04982       
04983       break;
04984 
04985    case EVENT_RESTART:
04986 
04987       if (!bc->dummy) {
04988          stop_bc_tones(ch);
04989          release_chan(bc);
04990       }
04991       break;
04992 
04993    default:
04994       chan_misdn_log(1, 0, "Got Unknown Event\n");
04995       break;
04996    }
04997    
04998    return RESPONSE_OK;
04999 }

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

Definition at line 5535 of file chan_misdn.c.

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

Referenced by load_module().

05536 {
05537    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05538    
05539    if (ch && ch->jb) {
05540       return misdn_jb_empty(ch->jb, buf, len);
05541    }
05542    
05543    return -1;
05544 }

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

Definition at line 5718 of file chan_misdn.c.

References ast_console_puts(), ast_log(), ast_strlen_zero(), errno, LOG_WARNING, max_ports, misdn_debug, and misdn_debug_only.

Referenced by cb_events(), cl_queue_chan(), config_jitterbuffer(), debug_numplan(), dialtone_indicate(), do_immediate_setup(), export_ch(), find_chan_by_bc(), find_chan_by_pid(), find_holded(), import_ch(), init_chan_list(), load_module(), misdn_answer(), misdn_bridge(), misdn_call(), misdn_check_l2l1(), misdn_digit_end(), misdn_facility_exec(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_jb_empty(), misdn_jb_fill(), misdn_jb_init(), misdn_l1_task(), misdn_new(), misdn_overlap_dial_task(), misdn_read(), misdn_request(), misdn_set_opt_exec(), misdn_tasks_destroy(), misdn_tasks_init(), misdn_tasks_thread_func(), misdn_transfer_bc(), misdn_write(), print_bearer(), print_facility(), process_ast_dsp(), read_config(), release_chan(), send_cause2ast(), start_pbx(), stop_indicate(), update_config(), and update_name().

05719 {
05720    va_list ap;
05721    char buf[1024];
05722    char port_buf[8];
05723 
05724    if (! ((0 <= port) && (port <= max_ports))) {
05725       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05726       port = 0;
05727       level = -1;
05728    }
05729 
05730    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05731 
05732    va_start(ap, tmpl);
05733    vsnprintf(buf, sizeof(buf), tmpl, ap);
05734    va_end(ap);
05735 
05736    if (level == -1)
05737       ast_log(LOG_WARNING, "%s", buf);
05738 
05739    else if (misdn_debug_only[port] ? 
05740          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
05741        : level <= misdn_debug[port]) {
05742       
05743       ast_console_puts(port_buf);
05744       ast_console_puts(buf);
05745    }
05746    
05747    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05748       time_t tm = time(NULL);
05749       char *tmp = ctime(&tm), *p;
05750 
05751       FILE *fp = fopen(global_tracefile, "a+");
05752 
05753       p = strchr(tmp, '\n');
05754       if (p)
05755          *p = ':';
05756       
05757       if (!fp) {
05758          ast_console_puts("Error opening Tracefile: [ ");
05759          ast_console_puts(global_tracefile);
05760          ast_console_puts(" ] ");
05761          
05762          ast_console_puts(strerror(errno));
05763          ast_console_puts("\n");
05764          return ;
05765       }
05766       
05767       fputs(tmp, fp);
05768       fputs(" ", fp);
05769       fputs(port_buf, fp);
05770       fputs(" ", fp);
05771       fputs(buf, fp);
05772 
05773       fclose(fp);
05774    }
05775 }

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

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

03593 {
03594    struct chan_list *help;
03595 
03596    if (chan->dsp) 
03597       ast_dsp_free(chan->dsp);
03598    if (chan->trans)
03599       ast_translator_free_path(chan->trans);
03600 
03601    ast_mutex_lock(&cl_te_lock);
03602    if (!*list) {
03603       ast_mutex_unlock(&cl_te_lock);
03604       return;
03605    }
03606   
03607    if (*list == chan) {
03608       *list = (*list)->next;
03609       ast_mutex_unlock(&cl_te_lock);
03610       return;
03611    }
03612   
03613    for (help = *list; help->next; help = help->next) {
03614       if (help->next == chan) {
03615          help->next = help->next->next;
03616          ast_mutex_unlock(&cl_te_lock);
03617          return;
03618       }
03619    }
03620    
03621    ast_mutex_unlock(&cl_te_lock);
03622 }

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

Definition at line 3576 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_request().

03577 {
03578    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03579   
03580    ast_mutex_lock(&cl_te_lock);
03581    if (!*list) {
03582       *list = chan;
03583    } else {
03584       struct chan_list *help = *list;
03585       for (; help->next; help = help->next); 
03586       help->next = chan;
03587    }
03588    chan->next = NULL;
03589    ast_mutex_unlock(&cl_te_lock);
03590 }

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

Definition at line 1612 of file chan_misdn.c.

References complete_ch_helper().

01613 {
01614    return complete_ch_helper(line, word, pos, state, 3);
01615 }

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

Definition at line 1588 of file chan_misdn.c.

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

Referenced by complete_ch().

01589 {
01590    struct ast_channel *c;
01591    int which=0;
01592    char *ret;
01593    if (pos != rpos)
01594       return NULL;
01595    c = ast_channel_walk_locked(NULL);
01596    while(c) {
01597       if (!strncasecmp(word, c->name, strlen(word))) {
01598          if (++which > state)
01599             break;
01600       }
01601       ast_mutex_unlock(&c->lock);
01602       c = ast_channel_walk_locked(c);
01603    }
01604    if (c) {
01605       ret = strdup(c->name);
01606       ast_mutex_unlock(&c->lock);
01607    } else
01608       ret = NULL;
01609    return ret;
01610 }

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

Definition at line 1617 of file chan_misdn.c.

References strdup.

01618 {
01619    if (state)
01620       return NULL;
01621 
01622    switch (pos) {
01623    case 4:
01624       if (*word == 'p')
01625          return strdup("port");
01626       else if (*word == 'o')
01627          return strdup("only");
01628       break;
01629    case 6:
01630       if (*word == 'o')
01631          return strdup("only");
01632       break;
01633    }
01634    return NULL;
01635 }

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

Definition at line 1637 of file chan_misdn.c.

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

01638 {
01639    char buffer[BUFFERSIZE];
01640    enum misdn_cfg_elements elem;
01641    int wordlen = strlen(word);
01642    int which = 0;
01643    int port = 0;
01644 
01645    switch (pos) {
01646    case 3:
01647       if ((!strncmp(word, "description", wordlen)) && (++which > state))
01648          return strdup("description");
01649       if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
01650          return strdup("descriptions");
01651       if ((!strncmp(word, "0", wordlen)) && (++which > state))
01652          return strdup("0");
01653       while ((port = misdn_cfg_get_next_port(port)) != -1) {
01654          snprintf(buffer, sizeof(buffer), "%d", port);
01655          if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
01656             return strdup(buffer);
01657          }
01658       }
01659       break;
01660    case 4:
01661       if (strstr(line, "description ")) {
01662          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01663             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
01664                continue;
01665             misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
01666             if (!wordlen || !strncmp(word, buffer, wordlen)) {
01667                if (++which > state)
01668                   return strdup(buffer);
01669             }
01670          }
01671       } else if (strstr(line, "descriptions ")) {
01672          if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
01673             return strdup("general");
01674          if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
01675             return strdup("ports");
01676       }
01677       break;
01678    }
01679    return NULL;
01680 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

Definition at line 1820 of file chan_misdn.c.

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

Referenced by misdn_set_opt_exec(), and read_config().

01821 {
01822    struct misdn_bchannel *bc = ch->bc;
01823    int len = ch->jb_len, threshold = ch->jb_upper_threshold;
01824    
01825    chan_misdn_log(5, bc->port, "config_jb: Called\n");
01826    
01827    if (! len) {
01828       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
01829       bc->nojitter=1;
01830    } else {
01831       if (len <= 100 || len > 8000) {
01832          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
01833          len = 1000;
01834       }
01835 
01836       if ( threshold > len ) {
01837          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
01838       }
01839 
01840       if ( ch->jb) {
01841          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
01842          misdn_jb_destroy(ch->jb);
01843          ch->jb = NULL;
01844       }
01845 
01846       ch->jb=misdn_jb_init(len, threshold);
01847 
01848       if (!ch->jb ) 
01849          bc->nojitter = 1;
01850    }
01851 }

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

Definition at line 1854 of file chan_misdn.c.

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

Referenced by read_config().

01855 {
01856    switch (numplan) {
01857    case NUMPLAN_INTERNATIONAL:
01858       chan_misdn_log(2, port, " --> %s: International\n", type);
01859       break;
01860    case NUMPLAN_NATIONAL:
01861       chan_misdn_log(2, port, " --> %s: National\n", type);
01862       break;
01863    case NUMPLAN_SUBSCRIBER:
01864       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
01865       break;
01866    case NUMPLAN_UNKNOWN:
01867       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
01868       break;
01869       /* Maybe we should cut off the prefix if present ? */
01870    default:
01871       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01872       break;
01873    }
01874 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

Definition at line 3079 of file chan_misdn.c.

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

Referenced by wait_for_digits().

03080 {
03081    const struct tone_zone_sound *ts = NULL;
03082    struct ast_channel *ast = cl->ast;
03083    int nd = 0;
03084 
03085    if (!ast) {
03086       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03087       return -1;
03088    }
03089 
03090    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03091 
03092    if (nd) {
03093       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03094       return 0;
03095    }
03096    
03097    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03098    ts = ast_get_indication_tone(ast->zone, "dial");
03099    cl->ts = ts;   
03100    
03101    if (ts) {
03102       cl->notxtone = 0;
03103       cl->norxtone = 0;
03104       /* This prods us in misdn_write */
03105       ast_playtones_start(ast, 0, ts->data, 0);
03106    }
03107 
03108    return 0;
03109 }

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

Definition at line 3758 of file chan_misdn.c.

References chan_list::ast, ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), ast_tv(), chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_frame::data, ast_frame::datalen, ast_frame::delivery, EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_RELEASE_COMPLETE, EVENT_SETUP_ACKNOWLEDGE, ast_channel::exten, ast_frame::frametype, hangup_chan(), hanguptone_indicate(), ast_frame::mallocd, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, MISDN_DIALING, MISDN_INCOMING_SETUP, misdn_lib_is_ptp(), misdn_lib_send_event(), chan_list::noautorespond_on_setup, misdn_bchannel::nt, misdn_bchannel::oad, ast_frame::offset, misdn_bchannel::out_cause, pbx_start_chan(), misdn_bchannel::port, ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

Referenced by cb_events().

03759 {
03760    char predial[256]="";
03761    char *p = predial;
03762   
03763    struct ast_frame fr;
03764 
03765    strncpy(predial, ast->exten, sizeof(predial) -1 );
03766 
03767    ch->state = MISDN_DIALING;
03768 
03769    if (!ch->noautorespond_on_setup) {
03770       if (bc->nt) {
03771          int ret; 
03772          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03773       } else {
03774          int ret;
03775          if ( misdn_lib_is_ptp(bc->port)) {
03776             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03777          } else {
03778             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03779          }
03780       }
03781    } else {
03782       ch->state = MISDN_INCOMING_SETUP;
03783    }
03784 
03785    chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, ast->cid.cid_num);
03786   
03787    strcpy(ast->exten, "s");
03788  
03789    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03790       ast = NULL;
03791       bc->out_cause = AST_CAUSE_UNALLOCATED;
03792       hangup_chan(ch);
03793       hanguptone_indicate(ch);
03794 
03795       if (bc->nt)
03796          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03797       else
03798          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03799    }
03800   
03801   
03802    while (!ast_strlen_zero(p) ) {
03803       fr.frametype = AST_FRAME_DTMF;
03804       fr.subclass = *p;
03805       fr.src = NULL;
03806       fr.data = NULL;
03807       fr.datalen = 0;
03808       fr.samples = 0;
03809       fr.mallocd = 0;
03810       fr.offset = 0;
03811       fr.delivery = ast_tv(0,0);
03812 
03813       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03814          ast_queue_frame(ch->ast, &fr);
03815       }
03816       p++;
03817    }
03818 }

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

Definition at line 677 of file chan_misdn.c.

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

Referenced by cb_events().

00678 {
00679    char buf[128];
00680 
00681    if (!ast)
00682       return;
00683 
00684    if (originator == ORG_AST) {
00685       ast = ast_bridged_channel(ast);
00686       if (!ast)
00687          return;
00688    }
00689 
00690    switch (bc->AOCDtype) {
00691    case Fac_AOCDCurrency:
00692       pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
00693       if (bc->AOCD.currency.chargeNotAvailable)
00694          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00695       else {
00696          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00697          if (bc->AOCD.currency.freeOfCharge)
00698             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00699          else {
00700             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00701             if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
00702                pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
00703                if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
00704                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00705             }
00706          }
00707       }
00708       break;
00709    case Fac_AOCDChargingUnit:
00710       pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
00711       if (bc->AOCD.chargingUnit.chargeNotAvailable)
00712          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
00713       else {
00714          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
00715          if (bc->AOCD.chargingUnit.freeOfCharge)
00716             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
00717          else {
00718             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
00719             if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
00720                pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
00721                if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
00722                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
00723             }
00724          }
00725       }
00726       break;
00727    default:
00728       break;
00729    }
00730 }

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

Export parameters to the dialplan environment variables.

Definition at line 3913 of file chan_misdn.c.

References ast_strlen_zero(), chan_misdn_log(), misdn_bchannel::keypad, pbx_builtin_setvar_helper(), misdn_bchannel::pid, misdn_bchannel::port, misdn_bchannel::sending_complete, misdn_bchannel::urate, misdn_bchannel::uu, and misdn_bchannel::uulen.

Referenced by cb_events().

03914 {
03915    char tmp[32];
03916    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
03917    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
03918    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
03919 
03920    if (bc->sending_complete) {
03921       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
03922       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
03923    }
03924 
03925    if (bc->urate) {
03926       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
03927       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
03928    }
03929 
03930    if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
03931       bc->uu[bc->uulen] = 0;
03932       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
03933    }
03934 
03935    if (!ast_strlen_zero(bc->keypad)) 
03936       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
03937 }

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

Definition at line 3519 of file chan_misdn.c.

References chan_list::bc, chan_misdn_log(), misdn_bchannel::dad, chan_list::next, misdn_bchannel::oad, and misdn_bchannel::port.

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

03520 {
03521    struct chan_list *help = list;
03522    for (; help; help = help->next) {
03523       if (help->bc == bc) return help;
03524    }
03525 
03526    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03527 
03528    return NULL;
03529 }

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

Definition at line 3531 of file chan_misdn.c.

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

Referenced by import_ch().

03532 {
03533    struct chan_list *help = list;
03534    for (; help; help = help->next) {
03535       if ( help->bc && (help->bc->pid == pid) ) return help;
03536    }
03537 
03538    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03539 
03540    return NULL;
03541 }

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

Definition at line 3543 of file chan_misdn.c.

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

Referenced by cb_events().

03544 {
03545    struct chan_list *help = list;
03546 
03547    if (bc->pri) return NULL;
03548 
03549    chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03550    for (;help; help = help->next) {
03551       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state == MISDN_HOLDED, help->hold_info.channel);
03552       if ((help->state == MISDN_HOLDED) && 
03553          (help->hold_info.port == bc->port))
03554          return help;
03555    }
03556    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03557 
03558    return NULL;
03559 }

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

Definition at line 3562 of file chan_misdn.c.

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

Referenced by cb_events().

03563 {
03564    struct chan_list *help = list;
03565 
03566    for (; help; help = help->next) {
03567       if ( (help->state == MISDN_HOLDED) &&
03568           (help->l3id == l3_id)   
03569          ) 
03570          return help;
03571    }
03572 
03573    return NULL;
03574 }

static void free_robin_list ( void   )  [static]

Definition at line 450 of file chan_misdn.c.

References free_robin_list_r(), and robin.

Referenced by reload_config(), and unload_module().

00451 {
00452    free_robin_list_r(robin);
00453    robin = NULL;
00454 }

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

Definition at line 439 of file chan_misdn.c.

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

Referenced by free_robin_list().

00440 {
00441    if (r) {
00442       if (r->next)
00443          free_robin_list_r(r->next);
00444       if (r->group)
00445          free(r->group);
00446       free(r);
00447    }
00448 }

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

Definition at line 566 of file chan_misdn.c.

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

Referenced by misdn_bridge().

00567 {
00568    struct chan_list *tmp;
00569   
00570    for (tmp=cl_te; tmp; tmp = tmp->next) {
00571       if ( tmp->ast == ast ) return tmp;
00572    }
00573   
00574    return NULL;
00575 }

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

Definition at line 577 of file chan_misdn.c.

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

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

00578 {
00579    struct chan_list *tmp;
00580   
00581    for (tmp=cl_te; tmp; tmp = tmp->next) {
00582       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
00583    }
00584   
00585    return NULL;
00586 }

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

Definition at line 456 of file chan_misdn.c.

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

Referenced by misdn_request().

00457 {
00458    struct robin_list *new;
00459    struct robin_list *iter = robin;
00460    for (; iter; iter = iter->next) {
00461       if (!strcasecmp(iter->group, group))
00462          return iter;
00463    }
00464    new = (struct robin_list *) calloc(1, sizeof(struct robin_list));
00465    new->group = strndup(group, strlen(group));
00466    new->port = 0;
00467    new->channel = 0;
00468    if (robin) {
00469       new->next = robin;
00470       robin->prev = new;
00471    }
00472    robin = new;
00473    return robin;
00474 }

static void hangup_chan ( struct chan_list ch  )  [static]

Definition at line 3639 of file chan_misdn.c.

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

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

03640 {
03641    int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
03642    if (!ch) {
03643       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03644       return;
03645    }
03646 
03647    cb_log(5, port, "hangup_chan called\n");
03648 
03649    if (ch->need_hangup) {
03650       cb_log(2, port, " --> hangup\n");
03651       send_cause2ast(ch->ast, ch->bc, ch);
03652       ch->need_hangup = 0;
03653       ch->need_queue_hangup = 0;
03654       if (ch->ast)
03655          ast_hangup(ch->ast);
03656       return;
03657    }
03658 
03659    if (!ch->need_queue_hangup) {
03660       cb_log(2, port, " --> No need to queue hangup\n");
03661    }
03662 
03663    ch->need_queue_hangup = 0;
03664    if (ch->ast) {
03665       send_cause2ast(ch->ast, ch->bc, ch);
03666 
03667       if (ch->ast)
03668          ast_queue_hangup(ch->ast);
03669       cb_log(2, port, " --> queue_hangup\n");
03670    } else {
03671       cb_log(1, port, "Cannot hangup chan, no ast\n");
03672    }
03673 }

static int hanguptone_indicate ( struct chan_list cl  )  [static]

Definition at line 3111 of file chan_misdn.c.

References chan_list::bc, misdn_lib_send_tone(), and TONE_HANGUP.

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

03112 {
03113    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03114    return 0;
03115 }

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

Import parameters from the dialplan environment variables.

Definition at line 3879 of file chan_misdn.c.

References ast_copy_string(), ast_log(), chan_misdn_log(), cl_te, find_chan_by_pid(), misdn_bchannel::keypad, LOG_NOTICE, chan_list::other_ch, chan_list::other_pid, pbx_builtin_getvar_helper(), misdn_bchannel::port, misdn_bchannel::sending_complete, misdn_bchannel::uu, and misdn_bchannel::uulen.

Referenced by misdn_call().

03880 {
03881    const char *tmp;
03882 
03883    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
03884    if (tmp) {
03885       ch->other_pid = atoi(tmp);
03886       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
03887       if (ch->other_pid > 0) {
03888          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
03889          if (ch->other_ch)
03890             ch->other_ch->other_ch = ch;
03891       }
03892    }
03893 
03894    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
03895    if (tmp && (atoi(tmp) == 1)) {
03896       bc->sending_complete = 1;
03897    }
03898 
03899    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
03900    if (tmp) {
03901       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
03902       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
03903       bc->uulen = strlen(bc->uu);
03904    }
03905 
03906    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
03907    if (tmp) {
03908       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
03909    }
03910 }

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

Definition at line 3156 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_request().

03157 {
03158    struct chan_list *cl;
03159 
03160    cl = calloc(1, sizeof(struct chan_list));
03161    if (!cl) {
03162       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03163       return NULL;
03164    }
03165    
03166    cl->originator = orig;
03167    cl->need_queue_hangup = 1;
03168    cl->need_hangup = 1;
03169    cl->need_busy = 1;
03170    cl->overlap_dial_task = -1;
03171 
03172    return cl;
03173 }

static int load_module ( void   )  [static]

Definition at line 5044 of file chan_misdn.c.

References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init, ast_register_application(), ast_strlen_zero(), BUFFERSIZE, calloc, misdn_lib_iface::cb_event, cb_events(), chan_misdn_clis, chan_misdn_jb_empty(), chan_misdn_log(), cl_te_lock, LOG_ERROR, malloc, max_ports, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), MISDN_CFG_L1_TIMEOUT, misdn_cfg_update_ptp(), misdn_check_l2l1(), misdn_debug, misdn_debug_only, misdn_facility_exec(), MISDN_GEN_DEBUG, MISDN_GEN_NTDEBUGFILE, MISDN_GEN_NTDEBUGFLAGS, MISDN_GEN_NTKEEPCALLS, MISDN_GEN_TRACEFILE, misdn_in_calls, misdn_l1_task(), misdn_lib_init(), misdn_lib_maxports_get(), misdn_lib_nt_debug_init(), misdn_lib_nt_keepcalls(), misdn_out_calls, misdn_set_opt_exec(), misdn_tasks_add(), misdn_tech, misdn_type, release_lock, tracing, and unload_module().

05045 {
05046    int i, port;
05047    int ntflags = 0, ntkc = 0;
05048    char ports[256] = "";
05049    char tempbuf[BUFFERSIZE + 1];
05050    char ntfile[BUFFERSIZE + 1];
05051    struct misdn_lib_iface iface = {
05052       .cb_event = cb_events,
05053       .cb_log = chan_misdn_log,
05054       .cb_jb_empty = chan_misdn_jb_empty,
05055    };
05056 
05057    max_ports = misdn_lib_maxports_get();
05058    
05059    if (max_ports <= 0) {
05060       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05061       return AST_MODULE_LOAD_DECLINE;
05062    }
05063    
05064    if (misdn_cfg_init(max_ports)) {
05065       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05066       return AST_MODULE_LOAD_DECLINE;
05067    }
05068    g_config_initialized = 1;
05069    
05070    misdn_debug = (int *) malloc(sizeof(int) * (max_ports + 1));
05071    if (!misdn_debug) {
05072       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05073       return AST_MODULE_LOAD_DECLINE;
05074    }
05075    misdn_ports = (int *) malloc(sizeof(int) * (max_ports + 1));
05076    if (!misdn_ports) {
05077       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05078       return AST_MODULE_LOAD_DECLINE;
05079    }
05080    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
05081    for (i = 1; i <= max_ports; i++) {
05082       misdn_debug[i] = misdn_debug[0];
05083       misdn_ports[i] = i;
05084    }
05085    *misdn_ports = 0;
05086    misdn_debug_only = (int *) calloc(max_ports + 1, sizeof(int));
05087 
05088    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
05089    if (!ast_strlen_zero(tempbuf))
05090       tracing = 1;
05091 
05092    misdn_in_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05093    misdn_out_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05094 
05095    for (i = 1; i <= max_ports; i++) {
05096       misdn_in_calls[i] = 0;
05097       misdn_out_calls[i] = 0;
05098    }
05099 
05100    ast_mutex_init(&cl_te_lock);
05101    ast_mutex_init(&release_lock);
05102 
05103    misdn_cfg_update_ptp();
05104    misdn_cfg_get_ports_string(ports);
05105 
05106    if (!ast_strlen_zero(ports))
05107       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05108    if (misdn_lib_init(ports, &iface, NULL))
05109       chan_misdn_log(0, 0, "No te ports initialized\n");
05110 
05111    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
05112    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
05113    misdn_lib_nt_debug_init(ntflags, ntfile);
05114 
05115    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(int));
05116    misdn_lib_nt_keepcalls(ntkc);
05117 
05118    if (ast_channel_register(&misdn_tech)) {
05119       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05120       unload_module();
05121       return -1;
05122    }
05123   
05124    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05125 
05126    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05127       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05128       "Sets mISDN opts. and optargs\n"
05129       "\n"
05130       "The available options are:\n"
05131       "    a - Have Asterisk detect DTMF tones on called channel\n"
05132       "    c - Make crypted outgoing call, optarg is keyindex\n"
05133       "    d - Send display text to called phone, text is the optarg\n"
05134       "    e - Perform echo cancelation on this channel,\n"
05135       "        takes taps as optarg (32,64,128,256)\n"
05136       "   e! - Disable echo cancelation on this channel\n"
05137       "    f - Enable fax detection\n"
05138       "    h - Make digital outgoing call\n"
05139       "   h1 - Make HDLC mode digital outgoing call\n"
05140       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05141       "        they will be transported inband.\n"
05142       "   jb - Set jitter buffer length, optarg is length\n"
05143       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05144       "   jn - Disable jitter buffer\n"
05145       "    n - Disable mISDN DSP on channel.\n"
05146       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05147       "    p - Caller ID presentation,\n"
05148       "        optarg is either 'allowed' or 'restricted'\n"
05149       "    s - Send Non-inband DTMF as inband\n"
05150       "   vr - Rx gain control, optarg is gain\n"
05151       "   vt - Tx gain control, optarg is gain\n"
05152       );
05153 
05154    
05155    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05156              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05157              "Sends the Facility Message FACILITY_TYPE with \n"
05158              "the given Arguments to the current ISDN Channel\n"
05159              "Supported Facilities are:\n"
05160              "\n"
05161              "type=calldeflect args=Nr where to deflect\n"
05162       );
05163 
05164 
05165    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05166              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05167              "Checks if the L2 and L1 are up on either the given <port> or\n"
05168              "on the ports in the group with <groupname>\n"
05169              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05170              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05171              "\n"
05172              "This application, ensures the L1/L2 state of the Ports in a group\n"
05173              "it is intended to make the pmp_l1_check option redundant and to\n"
05174              "fix a buggy switch config from your provider\n"
05175              "\n"
05176              "a sample dialplan would look like:\n\n"
05177              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05178              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05179              "\n"
05180       );
05181 
05182 
05183    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
05184 
05185    /* start the l1 watchers */
05186    
05187    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05188       int l1timeout;
05189       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05190       if (l1timeout) {
05191          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05192          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05193       }
05194    }
05195 
05196    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05197 
05198    return 0;
05199 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2278 of file chan_misdn.c.

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

02279 {
02280    struct chan_list *p;
02281    const char *tmp;
02282 
02283    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02284    
02285    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
02286    
02287    if (!p) {
02288       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02289       ast_queue_hangup(ast);
02290    }
02291 
02292    if (!p->bc) {
02293       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
02294 
02295       ast_queue_hangup(ast);
02296    }
02297 
02298    tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
02299    if (!ast_strlen_zero(tmp)) {
02300       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02301       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
02302    } else {
02303       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02304    }
02305 
02306    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02307    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
02308       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02309       p->bc->nodsp = 1;
02310       p->bc->hdlc = 0;
02311       p->bc->nojitter = 1;
02312    }
02313 
02314    p->state = MISDN_CONNECTED;
02315    stop_indicate(p);
02316 
02317    if ( ast_strlen_zero(p->bc->cad) ) {
02318       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
02319       ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
02320    }
02321 
02322    misdn_lib_send_event( p->bc, EVENT_CONNECT);
02323    start_bc_tones(p);
02324 
02325    return 0;
02326 }

static enum ast_bridge_result misdn_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
) [static]

Definition at line 2974 of file chan_misdn.c.

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_read(), ast_verbose(), ast_waitfor_n(), ast_write(), chan_list::bc, chan_misdn_log(), ast_channel::exten, f, get_chan_by_ast(), chan_list::ignore_dtmf, LOG_NOTICE, MISDN_CFG_BRIDGING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_bridge(), misdn_lib_split_bridge(), ast_channel::name, misdn_bchannel::oad, option_verbose, misdn_bchannel::pid, misdn_bchannel::port, and VERBOSE_PREFIX_3.

02980 {
02981    struct chan_list *ch1, *ch2;
02982    struct ast_channel *carr[2], *who;
02983    int to = -1;
02984    struct ast_frame *f;
02985    int p1_b, p2_b;
02986    int bridging;
02987   
02988    ch1 = get_chan_by_ast(c0);
02989    ch2 = get_chan_by_ast(c1);
02990 
02991    carr[0] = c0;
02992    carr[1] = c1;
02993   
02994    if (!(ch1 && ch2))
02995       return -1;
02996 
02997    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(int));
02998    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(int));
02999 
03000    if (! p1_b || ! p2_b) {
03001       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03002       return AST_BRIDGE_FAILED;
03003    }
03004 
03005    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03006    if (bridging) {
03007       /* trying to make a mISDN_dsp conference */
03008       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03009       misdn_lib_bridge(ch1->bc, ch2->bc);
03010    }
03011 
03012    if (option_verbose > 2) 
03013       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03014 
03015    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03016  
03017    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
03018       ch1->ignore_dtmf = 1;
03019 
03020    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
03021       ch2->ignore_dtmf = 1;
03022 
03023    for (;/*ever*/;) {
03024       to = -1;
03025       who = ast_waitfor_n(carr, 2, &to);
03026 
03027       if (!who) {
03028          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03029          break;
03030       }
03031       f = ast_read(who);
03032 
03033       if (!f || f->frametype == AST_FRAME_CONTROL) {
03034          /* got hangup .. */
03035 
03036          if (!f) 
03037             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03038          else
03039             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03040 
03041          *fo = f;
03042          *rc = who;
03043          break;
03044       }
03045       
03046       if ( f->frametype == AST_FRAME_DTMF ) {
03047          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03048 
03049          *fo = f;
03050          *rc = who;
03051          break;
03052       }
03053    
03054 #if 0
03055       if (f->frametype == AST_FRAME_VOICE) {
03056          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03057    
03058          continue;
03059       }
03060 #endif
03061 
03062       if (who == c0) {
03063          ast_write(c1, f);
03064       }
03065       else {
03066          ast_write(c0, f);
03067       }
03068    }
03069 
03070    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03071 
03072    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03073 
03074    return AST_BRIDGE_COMPLETE;
03075 }

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

Definition at line 2138 of file chan_misdn.c.

References ast_channel::_state, add_out_calls(), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_copy_string(), ast_log(), ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), ast_transfercapability2str(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_callerid::cid_rdnis, ast_channel::context, misdn_bchannel::dad, misdn_bchannel::ec_enable, ENOCHAN, EVENT_SETUP, ext, ast_channel::exten, ast_channel::hangupcause, import_ch(), INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::l3_id, chan_list::l3id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_send_event(), misdn_set_opt_exec(), ast_channel::name, misdn_bchannel::nt, misdn_bchannel::oad, ORG_AST, chan_list::other_ch, pbx_builtin_setvar_helper(), misdn_bchannel::pid, misdn_bchannel::port, misdn_bchannel::rad, S_OR, chan_list::state, stop_bc_tones(), ast_channel::transfercapability, and update_config().

02139 {
02140    int port = 0;
02141    int r;
02142    int exceed;
02143    int bridging;
02144    struct chan_list *ch;
02145    struct misdn_bchannel *newbc;
02146    char *opts, *ext;
02147    char *dest_cp;
02148 
02149    if (!ast) {
02150       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
02151       return -1;
02152    }
02153 
02154    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
02155       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02156       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02157       ast_setstate(ast, AST_STATE_DOWN);
02158       return -1;
02159    }
02160 
02161    ch = MISDN_ASTERISK_TECH_PVT(ast);
02162    if (!ch) {
02163       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02164       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02165       ast_setstate(ast, AST_STATE_DOWN);
02166       return -1;
02167    }
02168    
02169    newbc = ch->bc;
02170    if (!newbc) {
02171       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02172       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02173       ast_setstate(ast, AST_STATE_DOWN);
02174       return -1;
02175    }
02176    
02177    /*
02178     * dest is ---v
02179     * Dial(mISDN/g:group_name[/extension[/options]])
02180     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
02181     *
02182     * The dial extension could be empty if you are using MISDN_KEYPAD
02183     * to control ISDN provider features.
02184     */
02185    dest_cp = ast_strdupa(dest);
02186    strsep(&dest_cp, "/");/* Discard port/group token */
02187    ext = strsep(&dest_cp, "/");
02188    if (!ext) {
02189       ext = "";
02190    }
02191    opts = dest_cp;
02192    
02193    port = newbc->port;
02194 
02195    if ((exceed = add_out_calls(port))) {
02196       char tmp[16];
02197       snprintf(tmp, sizeof(tmp), "%d", exceed);
02198       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
02199       return -1;
02200    }
02201    
02202    chan_misdn_log(1, port, "* CALL: %s\n", dest);
02203    
02204    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
02205    
02206    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
02207    if (ast->exten) {
02208       ast_copy_string(ast->exten, ext, sizeof(ast->exten));
02209       ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
02210    }
02211 
02212    ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
02213 
02214    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
02215    if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
02216       ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
02217    }
02218 
02219    newbc->capability = ast->transfercapability;
02220    pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
02221    if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
02222       chan_misdn_log(2, port, " --> * Call with flag Digital\n");
02223    }
02224 
02225    /* update screening and presentation */ 
02226    update_config(ch, ORG_AST);
02227       
02228    /* fill in some ies from channel vary*/
02229    import_ch(ast, newbc, ch);
02230 
02231    /* Finally The Options Override Everything */
02232    if (opts)
02233       misdn_set_opt_exec(ast, opts);
02234    else
02235       chan_misdn_log(2, port, "NO OPTS GIVEN\n");
02236 
02237    /*check for bridging*/
02238    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
02239    if (bridging && ch->other_ch) {
02240 #ifdef MISDN_1_2
02241       chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
02242       *ch->bc->pipeline = 0;
02243       *ch->other_ch->bc->pipeline = 0;
02244 #else
02245       chan_misdn_log(1, port, "Disabling EC on both Sides\n");
02246       ch->bc->ec_enable = 0;
02247       ch->other_ch->bc->ec_enable = 0;
02248 #endif
02249    }
02250 
02251    r = misdn_lib_send_event( newbc, EVENT_SETUP );
02252 
02253    /** we should have l3id after sending setup **/
02254    ch->l3id = newbc->l3_id;
02255 
02256    if ( r == -ENOCHAN  ) {
02257       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
02258       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
02259       ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
02260       ast_setstate(ast, AST_STATE_DOWN);
02261       return -1;
02262    }
02263    
02264    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
02265 
02266    ast_setstate(ast, AST_STATE_DIALING);
02267    ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
02268    
02269    if (newbc->nt)
02270       stop_bc_tones(ch);
02271 
02272    ch->state = MISDN_CALLING;
02273    
02274    return 0; 
02275 }

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

Definition at line 5257 of file chan_misdn.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), BUFFERSIZE, chan_misdn_log(), group, LOG_WARNING, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_CFG_GROUPNAME, misdn_lib_get_port_up(), and misdn_lib_port_up().

Referenced by load_module().

05258 {
05259    char group[BUFFERSIZE + 1];
05260    char *port_str;
05261    int port = 0;
05262    int timeout;
05263    int dowait = 0;
05264    int port_up;
05265 
05266    AST_DECLARE_APP_ARGS(args,
05267          AST_APP_ARG(grouppar);
05268          AST_APP_ARG(timeout);
05269    );
05270 
05271    if (ast_strlen_zero((char *)data)) {
05272       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05273       return -1;
05274    }
05275 
05276    AST_STANDARD_APP_ARGS(args, data);
05277 
05278    if (args.argc != 2) {
05279       ast_log(LOG_WARNING, "Wrong argument count\n");
05280       return 0;
05281    }
05282 
05283    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05284    timeout = atoi(args.timeout);
05285    port_str = args.grouppar;
05286 
05287    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05288       /* We make a group call lets checkout which ports are in my group */
05289       port_str += 2;
05290       ast_copy_string(group, port_str, sizeof(group));
05291       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05292 
05293       for ( port = misdn_cfg_get_next_port(port); 
05294          port > 0;
05295          port = misdn_cfg_get_next_port(port)) {
05296          char cfg_group[BUFFERSIZE + 1];
05297 
05298          chan_misdn_log(2, 0, "trying port %d\n", port);
05299 
05300          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05301 
05302          if (!strcasecmp(cfg_group, group)) {
05303             port_up = misdn_lib_port_up(port, 1);
05304 
05305             if (!port_up) {
05306                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05307                misdn_lib_get_port_up(port);
05308                dowait = 1;
05309             }
05310          }
05311       }
05312 
05313    } else {
05314       port = atoi(port_str);
05315       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05316       port_up = misdn_lib_port_up(port, 1);
05317       if (!port_up) {
05318          misdn_lib_get_port_up(port);
05319          dowait = 1;
05320       }
05321    }
05322 
05323    if (dowait) {
05324       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05325       sleep(timeout);
05326    }
05327 
05328    return 0;
05329 }

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

Definition at line 2328 of file chan_misdn.c.

02329 {
02330    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02331    return 0;
02332 }

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

Definition at line 2334 of file chan_misdn.c.

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

02335 {
02336    struct chan_list *p;
02337    struct misdn_bchannel *bc;
02338 
02339    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02340 
02341    bc = p->bc;
02342    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
02343    
02344    if (!bc) {
02345       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
02346       return -1;
02347    }
02348    
02349    switch (p->state ) {
02350    case MISDN_CALLING:
02351       {
02352          int l;      
02353          char buf[8];
02354          buf[0]=digit;
02355          buf[1]=0;
02356          
02357          l = sizeof(bc->infos_pending);
02358          strncat(bc->infos_pending, buf, l - strlen(bc->infos_pending) - 1);
02359       }
02360       break;
02361    case MISDN_CALLING_ACKNOWLEDGE:
02362       {
02363          bc->info_dad[0]=digit;
02364          bc->info_dad[1]=0;
02365          
02366          {
02367             int l = sizeof(bc->dad);
02368             strncat(bc->dad, bc->info_dad, l - strlen(bc->dad) - 1);
02369          }
02370          {
02371             int l = sizeof(p->ast->exten);
02372             strncpy(p->ast->exten, bc->dad, l);
02373             p->ast->exten[l-1] = 0;
02374          }
02375          
02376          misdn_lib_send_event( bc, EVENT_INFORMATION);
02377       }
02378       break;
02379    default: 
02380          /* Do not send Digits in CONNECTED State, when
02381           * the other side is too mISDN. */
02382          if (p->other_ch ) 
02383             return 0;
02384 
02385          if ( bc->send_dtmf ) 
02386             send_digit_to_chan(p,digit);
02387       break;
02388    }
02389 
02390    return 0;
02391 }

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

Definition at line 5212 of file chan_misdn.c.

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

Referenced by load_module().

05213 {
05214    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05215    char *tok, *tokb;
05216 
05217    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05218    
05219    if (strcasecmp(chan->tech->type, "mISDN")) {
05220       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05221       return -1;
05222    }
05223    
05224    if (ast_strlen_zero((char *)data)) {
05225       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05226       return -1;
05227    }
05228 
05229    tok = strtok_r((char*) data, "|", &tokb) ;
05230 
05231    if (!tok) {
05232       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05233       return -1;
05234    }
05235 
05236    if (!strcasecmp(tok, "calldeflect")) {
05237       tok = strtok_r(NULL, "|", &tokb) ;
05238       
05239       if (!tok) {
05240          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05241       }
05242 
05243       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05244          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05245          return 0; 
05246       }
05247       ch->bc->fac_out.Function = Fac_CD;
05248       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05249       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05250    } else {
05251       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05252    }
05253 
05254    return 0;
05255 }

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

Definition at line 2394 of file chan_misdn.c.

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

02395 {
02396    struct chan_list *p;
02397 
02398    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02399 
02400    chan_misdn_log(1, p->bc ? p->bc->port : 0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
02401 
02402    p->ast = ast;
02403 
02404    return 0;
02405 }

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

Definition at line 1206 of file chan_misdn.c.

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

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

01207 {
01208    int i;
01209    static char state[8];
01210    
01211    if( !p) return NULL;
01212   
01213    for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
01214       if (state_array[i].state == p->state)
01215          return state_array[i].txt; 
01216    }
01217 
01218    snprintf(state, sizeof(state), "%d", p->state) ;
01219 
01220    return state;
01221 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2530 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, chan_list::bc, misdn_bchannel::cause, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, cl_dequeue_chan(), cl_te, ast_channel::context, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, ast_channel::exten, free, ast_channel::hangupcause, hanguptone_indicate(), INFO_PI_INBAND_AVAILABLE, chan_list::l3id, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_BUSY, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, misdn_get_ch_state(), MISDN_HOLD_DISCONNECT, MISDN_HOLDED, MISDN_INCOMING_SETUP, misdn_lib_release(), misdn_lib_send_event(), MISDN_NOTHING, MISDN_PRECONNECTED, MISDN_PROCEEDING, MISDN_PROGRESS, MISDN_RELEASED, ast_channel::name, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, misdn_bchannel::need_release_complete, misdn_bchannel::nt, ORG_AST, chan_list::originator, misdn_bchannel::out_cause, pbx_builtin_getvar_helper(), misdn_bchannel::pid, chan_list::pipe, misdn_bchannel::port, release_chan(), release_lock, start_bc_tones(), chan_list::state, stop_bc_tones(), misdn_bchannel::uu, and misdn_bchannel::uulen.

02531 {
02532    struct chan_list *p;
02533    struct misdn_bchannel *bc = NULL;
02534    const char *varcause = NULL;
02535 
02536    ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
02537 
02538    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
02539 
02540    if (!p) {
02541       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
02542       return 0 ;
02543    }
02544 
02545    bc = p->bc;
02546 
02547    if (bc) {
02548       const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
02549       if (tmp) {
02550          ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
02551          strcpy(bc->uu, tmp);
02552          bc->uulen=strlen(bc->uu);
02553       }
02554    }
02555 
02556    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02557    p->ast = NULL;
02558 
02559    if (ast->_state == AST_STATE_RESERVED || 
02560       p->state == MISDN_NOTHING || 
02561       p->state == MISDN_HOLDED || 
02562       p->state == MISDN_HOLD_DISCONNECT ) {
02563 
02564       CLEAN_CH:
02565       /* between request and call */
02566       ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
02567       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02568    
02569       ast_mutex_lock(&release_lock);
02570       cl_dequeue_chan(&cl_te, p);
02571       close(p->pipe[0]);
02572       close(p->pipe[1]);
02573       free(p);
02574       ast_mutex_unlock(&release_lock);
02575       
02576       if (bc)
02577          misdn_lib_release(bc);
02578       
02579       return 0;
02580    }
02581 
02582    if (!bc) {
02583       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02584       goto CLEAN_CH;
02585    }
02586 
02587 
02588    p->need_hangup = 0;
02589    p->need_queue_hangup = 0;
02590    p->need_busy = 0;
02591 
02592 
02593    if (!p->bc->nt) 
02594       stop_bc_tones(p);
02595 
02596    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02597 
02598    if ((varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02599       (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02600       int tmpcause = atoi(varcause);
02601       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02602    }
02603 
02604    chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n", p->bc ? p->bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
02605    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02606    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02607    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02608    chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02609 
02610    switch (p->state) {
02611    case MISDN_INCOMING_SETUP:
02612       /* This is the only place in misdn_hangup, where we 
02613        * can call release_chan, else it might create lot's of trouble
02614        * */
02615       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02616       release_chan(bc);
02617 
02618       p->state = MISDN_CLEANING;
02619       if (bc->need_release_complete)
02620          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02621       break;
02622    case MISDN_HOLDED:
02623    case MISDN_DIALING:
02624       start_bc_tones(p);
02625       hanguptone_indicate(p);
02626 
02627       if (bc->need_disconnect)
02628          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02629       break;
02630    case MISDN_CALLING_ACKNOWLEDGE:
02631       start_bc_tones(p);
02632       hanguptone_indicate(p);
02633 
02634       if (bc->need_disconnect)
02635          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02636       break;
02637 
02638    case MISDN_CALLING:
02639    case MISDN_ALERTING:
02640    case MISDN_PROGRESS:
02641    case MISDN_PROCEEDING:
02642       if (p->originator != ORG_AST) 
02643          hanguptone_indicate(p);
02644 
02645       /*p->state=MISDN_CLEANING;*/
02646       if (bc->need_disconnect)
02647          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02648       break;
02649    case MISDN_CONNECTED:
02650    case MISDN_PRECONNECTED:
02651       /*  Alerting or Disconnect */
02652       if (p->bc->nt) {
02653          start_bc_tones(p);
02654          hanguptone_indicate(p);
02655          p->bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
02656       }
02657       if (bc->need_disconnect)
02658          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02659 
02660       /*p->state=MISDN_CLEANING;*/
02661       break;
02662    case MISDN_DISCONNECTED:
02663       if (bc->need_release)
02664          misdn_lib_send_event( bc, EVENT_RELEASE);
02665       p->state = MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
02666       break;
02667 
02668    case MISDN_RELEASED:
02669    case MISDN_CLEANING:
02670       p->state = MISDN_CLEANING;
02671       break;
02672 
02673    case MISDN_BUSY:
02674       break;
02675 
02676    case MISDN_HOLD_DISCONNECT:
02677       /* need to send release here */
02678       chan_misdn_log(1, bc->port, " --> cause %d\n", bc->cause);
02679       chan_misdn_log(1, bc->port, " --> out_cause %d\n", bc->out_cause);
02680 
02681       bc->out_cause = -1;
02682       if (bc->need_release)
02683          misdn_lib_send_event(bc, EVENT_RELEASE);
02684       p->state = MISDN_CLEANING;
02685       break;
02686    default:
02687       if (bc->nt) {
02688          bc->out_cause = -1;
02689          if (bc->need_release)
02690             misdn_lib_send_event(bc, EVENT_RELEASE);
02691          p->state = MISDN_CLEANING; 
02692       } else {
02693          if (bc->need_disconnect)
02694             misdn_lib_send_event(bc, EVENT_DISCONNECT);
02695       }
02696    }
02697 
02698    p->state = MISDN_CLEANING;
02699 
02700    chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
02701 
02702    return 0;
02703 }

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

Definition at line 2409 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_setstate(), AST_STATE_BUSY, AST_STATE_RING, chan_list::bc, chan_misdn_log(), EVENT_ALERTING, EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_PROGRESS, ast_channel::exten, hanguptone_indicate(), chan_list::incoming_early_audio, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_inband_avail(), misdn_lib_send_event(), misdn_bchannel::nt, ORG_MISDN, chan_list::originator, chan_list::other_ch, misdn_bchannel::out_cause, misdn_bchannel::pid, misdn_bchannel::port, start_bc_tones(), chan_list::state, and stop_indicate().

02410 {
02411    struct chan_list *p;
02412 
02413    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02414       ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
02415       return -1;
02416    }
02417    
02418    if (!p->bc ) {
02419       chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast->exten);
02420       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02421       return -1;
02422    }
02423    
02424    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n", cond, ast->exten);
02425    
02426    switch (cond) {
02427    case AST_CONTROL_BUSY:
02428       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
02429       ast_setstate(ast, AST_STATE_BUSY);
02430 
02431       p->bc->out_cause = AST_CAUSE_USER_BUSY;
02432       if (p->state != MISDN_CONNECTED) {
02433          start_bc_tones(p);
02434          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02435       }
02436       return -1;
02437    case AST_CONTROL_RING:
02438       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02439       return -1;
02440    case AST_CONTROL_RINGING:
02441       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02442       switch (p->state) {
02443       case MISDN_ALERTING:
02444          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc ? p->bc->pid : -1);
02445          break;
02446       case MISDN_CONNECTED:
02447          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc ? p->bc->pid : -1);
02448          return -1;
02449       default:
02450          p->state = MISDN_ALERTING;
02451          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02452          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02453 
02454          if (p->other_ch && p->other_ch->bc) {
02455             if (misdn_inband_avail(p->other_ch->bc)) {
02456                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02457                break;
02458             }
02459 
02460             if (!p->other_ch->bc->nt) {
02461                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02462                break;
02463             }
02464          }
02465 
02466          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02467          ast_setstate(ast, AST_STATE_RING);
02468 
02469          if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio)
02470             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02471          else 
02472             return -1;
02473       }
02474       break;
02475    case AST_CONTROL_ANSWER:
02476       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02477       start_bc_tones(p);
02478       break;
02479    case AST_CONTROL_TAKEOFFHOOK:
02480       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02481       return -1;
02482    case AST_CONTROL_OFFHOOK:
02483       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02484       return -1;
02485    case AST_CONTROL_FLASH:
02486       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02487       break;
02488    case AST_CONTROL_PROGRESS:
02489       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02490       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02491       break;
02492    case AST_CONTROL_PROCEEDING:
02493       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02494       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02495       break;
02496    case AST_CONTROL_CONGESTION:
02497       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02498 
02499       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02500       start_bc_tones(p);
02501       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02502 
02503       if (p->bc->nt) {
02504          hanguptone_indicate(p);
02505       }
02506       break;
02507    case -1 :
02508       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02509 
02510       stop_indicate(p);
02511 
02512       if (p->state == MISDN_CONNECTED) 
02513          start_bc_tones(p);
02514       break;
02515    case AST_CONTROL_HOLD:
02516       ast_moh_start(ast, data, p->mohinterpret); 
02517       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02518       break;
02519    case AST_CONTROL_UNHOLD:
02520       ast_moh_stop(ast);
02521       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02522       break;
02523    default:
02524       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02525    }
02526   
02527    return 0;
02528 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

Definition at line 5595 of file chan_misdn.c.

References ast_mutex_destroy, free, misdn_jb::mutexjb, misdn_jb::ok, and misdn_jb::samples.

Referenced by config_jitterbuffer(), and release_chan().

05596 {
05597    ast_mutex_destroy(&jb->mutexjb);
05598    
05599    free(jb->ok);
05600    free(jb->samples);
05601    free(jb);
05602 }

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

gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data.

Definition at line 5665 of file chan_misdn.c.

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

Referenced by chan_misdn_jb_empty().

05666 {
05667    int i, wp, rp, read = 0;
05668 
05669    ast_mutex_lock(&jb->mutexjb);
05670 
05671    rp = jb->rp;
05672    wp = jb->wp;
05673 
05674    if (jb->state_empty) {  
05675       for (i = 0; i < len; i++) {
05676          if (wp == rp) {
05677             jb->rp = rp;
05678             jb->state_empty = 0;
05679 
05680             ast_mutex_unlock(&jb->mutexjb);
05681 
05682             return read;
05683          } else {
05684             if (jb->ok[rp] == 1) {
05685                data[i] = jb->samples[rp];
05686                jb->ok[rp] = 0;
05687                rp = (rp != jb->size - 1) ? rp + 1 : 0;
05688                read += 1;
05689             }
05690          }
05691       }
05692 
05693       if (wp >= rp)
05694          jb->state_buffer = wp - rp;
05695       else
05696          jb->state_buffer = jb->size - rp + wp;
05697       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05698 
05699       jb->rp = rp;
05700    } else
05701       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05702 
05703    ast_mutex_unlock(&jb->mutexjb);
05704 
05705    return read;
05706 }

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

fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).

Definition at line 5606 of file chan_misdn.c.

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

05607 {
05608    int i, j, rp, wp;
05609 
05610    if (!jb || ! data)
05611       return 0;
05612 
05613    ast_mutex_lock(&jb->mutexjb);
05614    
05615    wp = jb->wp;
05616    rp = jb->rp;
05617    
05618    for (i = 0; i < len; i++) {
05619       jb->samples[wp] = data[i];
05620       jb->ok[wp] = 1;
05621       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05622 
05623       if (wp == jb->rp)
05624          jb->state_full = 1;
05625    }
05626 
05627    if (wp >= rp)
05628       jb->state_buffer = wp - rp;
05629    else
05630       jb->state_buffer = jb->size - rp + wp;
05631    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05632 
05633    if (jb->state_full) {
05634       jb->wp = wp;
05635 
05636       rp = wp;
05637       for (j = 0; j < jb->upper_threshold; j++)
05638          rp = (rp != 0) ? rp - 1 : jb->size - 1;
05639       jb->rp = rp;
05640       jb->state_full = 0;
05641       jb->state_empty = 1;
05642 
05643       ast_mutex_unlock(&jb->mutexjb);
05644 
05645       return -1;
05646    }
05647 
05648    if (!jb->state_empty) {
05649       jb->bytes_wrote += len;
05650       if (jb->bytes_wrote >= jb->upper_threshold) {
05651          jb->state_empty = 1;
05652          jb->bytes_wrote = 0;
05653       }
05654    }
05655    jb->wp = wp;
05656 
05657    ast_mutex_unlock(&jb->mutexjb);
05658    
05659    return 0;
05660 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

Definition at line 5554 of file chan_misdn.c.

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

Referenced by config_jitterbuffer().

05555 {
05556    int i;
05557    struct misdn_jb *jb;
05558 
05559    jb = malloc(sizeof(struct misdn_jb));
05560    if (!jb) {
05561        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05562        return NULL;
05563    }
05564    jb->size = size;
05565    jb->upper_threshold = upper_threshold;
05566    jb->wp = 0;
05567    jb->rp = 0;
05568    jb->state_full = 0;
05569    jb->state_empty = 0;
05570    jb->bytes_wrote = 0;
05571    jb->samples = malloc(size * sizeof(char));
05572    if (!jb->samples) {
05573       free(jb);
05574       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05575       return NULL;
05576    }
05577 
05578    jb->ok = malloc(size * sizeof(char));
05579    if (!jb->ok) {
05580       free(jb->samples);
05581       free(jb);
05582       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05583       return NULL;
05584    }
05585 
05586    for (i = 0; i < size; i++)
05587       jb->ok[i] = 0;
05588 
05589    ast_mutex_init(&jb->mutexjb);
05590 
05591    return jb;
05592 }

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

Definition at line 825 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

00826 {
00827    misdn_lib_isdn_l1watcher(*(int *)data);
00828    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00829    return 1;
00830 }

static struct ast_channel * misdn_new ( struct chan_list cl,
int  state,
char *  exten,
char *  callerid,
int  format,
int  port,
int  c 
) [static]

Definition at line 3448 of file chan_misdn.c.

References ast_callerid_parse(), ast_channel_alloc(), ast_copy_string(), ast_jb_configure(), AST_STATE_RING, ast_strdup, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_ani, cid_name, cid_num, ast_channel::exten, ast_channel::fds, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_GEN_BRIDGING, misdn_get_global_jbconf(), misdn_lib_port_is_pri(), misdn_tech, misdn_tech_wo_bridge, misdn_type, ast_channel::nativeformats, chan_list::pipe, prefformat, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by cb_events(), and misdn_request().

03449 {
03450    struct ast_channel *tmp;
03451    char *cid_name = 0, *cid_num = 0;
03452    int chan_offset = 0;
03453    int tmp_port = misdn_cfg_get_next_port(0);
03454    int bridging;
03455 
03456    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03457       if (tmp_port == port)
03458          break;
03459       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03460    }
03461    if (c < 0)
03462       c = 0;
03463 
03464    if (callerid) {
03465       ast_callerid_parse(callerid, &cid_name, &cid_num);
03466    }
03467 
03468    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03469    if (tmp) {
03470       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03471 
03472       tmp->nativeformats = prefformat;
03473 
03474       tmp->readformat = format;
03475       tmp->rawreadformat = format;
03476       tmp->writeformat = format;
03477       tmp->rawwriteformat = format;
03478     
03479       tmp->tech_pvt = chlist;
03480 
03481       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03482 
03483       if (bridging)
03484          tmp->tech = &misdn_tech;
03485       else
03486          tmp->tech = &misdn_tech_wo_bridge;
03487 
03488       tmp->writeformat = format;
03489       tmp->readformat = format;
03490       tmp->priority=1;
03491 
03492       if (exten) 
03493          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03494       else
03495          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03496 
03497       if (callerid)
03498          /* Don't use ast_set_callerid() here because it will
03499           * generate a needless NewCallerID event */
03500          tmp->cid.cid_ani = ast_strdup(cid_num);
03501 
03502       if (pipe(chlist->pipe) < 0)
03503          perror("Pipe failed\n");
03504       tmp->fds[0] = chlist->pipe[0];
03505 
03506       if (state == AST_STATE_RING)
03507          tmp->rings = 1;
03508       else
03509          tmp->rings = 0;
03510 
03511            ast_jb_configure(tmp, misdn_get_global_jbconf());      
03512    } else {
03513       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03514    }
03515    
03516    return tmp;
03517 }

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

Definition at line 832 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_UNALLOCATED, ast_exists_extension(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), chan_list::bc, chan_misdn_log(), chan_list::context, misdn_bchannel::dad, EVENT_DISCONNECT, ast_channel::exten, hanguptone_indicate(), MISDN_CLEANING, MISDN_DIALING, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::oad, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_start_chan(), misdn_bchannel::port, chan_list::state, and stop_indicate().

Referenced by cb_events().

00833 {
00834    struct timeval tv_end, tv_now;
00835    int diff;
00836    struct chan_list *ch = (struct chan_list *)data;
00837 
00838    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
00839 
00840    if (ch->state != MISDN_WAITING4DIGS) {
00841       ch->overlap_dial_task = -1;
00842       return 0;
00843    }
00844    
00845    ast_mutex_lock(&ch->overlap_tv_lock);
00846    tv_end = ch->overlap_tv;
00847    ast_mutex_unlock(&ch->overlap_tv_lock);
00848    
00849    tv_end.tv_sec += ch->overlap_dial;
00850    tv_now = ast_tvnow();
00851 
00852    diff = ast_tvdiff_ms(tv_end, tv_now);
00853 
00854    if (diff <= 100) {
00855       char *dad=ch->bc->dad, sexten[]="s";
00856       /* if we are 100ms near the timeout, we are satisfied.. */
00857       stop_indicate(ch);
00858       
00859       if (ast_strlen_zero(ch->bc->dad)) {
00860          dad=sexten;
00861          strcpy(ch->ast->exten, sexten);
00862       }
00863 
00864       if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
00865          ch->state=MISDN_DIALING;
00866          if (pbx_start_chan(ch) < 0) {
00867             chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
00868             goto misdn_overlap_dial_task_disconnect;
00869          }
00870       } else {
00871 misdn_overlap_dial_task_disconnect:
00872          hanguptone_indicate(ch);
00873          ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
00874          ch->state=MISDN_CLEANING;
00875          misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
00876       }
00877       ch->overlap_dial_task = -1;
00878       return 0;
00879    } else
00880       return diff;
00881 }

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

Definition at line 989 of file chan_misdn.c.

References misdn_lib_port_block(), and RESULT_SHOWUSAGE.

00990 {
00991    int port;
00992 
00993    if (argc != 4)
00994       return RESULT_SHOWUSAGE;
00995   
00996    port = atoi(argv[3]);
00997 
00998    misdn_lib_port_block(port);
00999 
01000    return 0;
01001 }

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

Definition at line 1060 of file chan_misdn.c.

References misdn_lib_get_port_down(), and RESULT_SHOWUSAGE.

01061 {
01062    int port;
01063 
01064    if (argc != 4)
01065       return RESULT_SHOWUSAGE;
01066    
01067    port = atoi(argv[3]);
01068    
01069    misdn_lib_get_port_down(port);
01070   
01071    return 0;
01072 }

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

Definition at line 1003 of file chan_misdn.c.

References misdn_lib_port_unblock(), and RESULT_SHOWUSAGE.

01004 {
01005    int port;
01006   
01007    if (argc != 4)
01008       return RESULT_SHOWUSAGE;
01009   
01010    port = atoi(argv[3]);
01011 
01012    misdn_lib_port_unblock(port);
01013 
01014    return 0;
01015 }

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

Definition at line 1046 of file chan_misdn.c.

References misdn_lib_get_port_up(), and RESULT_SHOWUSAGE.

01047 {
01048    int port;
01049    
01050    if (argc != 4)
01051       return RESULT_SHOWUSAGE;
01052    
01053    port = atoi(argv[3]);
01054    
01055    misdn_lib_get_port_up(port);
01056   
01057    return 0;
01058 }

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

Definition at line 2777 of file chan_misdn.c.

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

02778 {
02779    struct chan_list *tmp;
02780    fd_set rrfs;
02781    struct timeval tv;
02782    int len, t;
02783 
02784    if (!ast) {
02785       chan_misdn_log(1, 0, "misdn_read called without ast\n");
02786       return NULL;
02787    }
02788    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
02789       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
02790       return NULL;
02791    }
02792 
02793    if (!tmp->bc && !(tmp->state == MISDN_HOLDED)) {
02794       chan_misdn_log(1, 0, "misdn_read called without bc\n");
02795       return NULL;
02796    }
02797 
02798    tv.tv_sec=0;
02799    tv.tv_usec=20000;
02800 
02801    FD_ZERO(&rrfs);
02802    FD_SET(tmp->pipe[0],&rrfs);
02803 
02804    t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
02805 
02806    if (!t) {
02807       chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
02808       len=160;
02809    }
02810 
02811    if (t<0) {
02812       chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
02813       return NULL;
02814    }
02815 
02816    if (FD_ISSET(tmp->pipe[0],&rrfs)) {
02817       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
02818 
02819       if (len<=0) {
02820          /* we hangup here, since our pipe is closed */
02821          chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
02822          return NULL;
02823       }
02824 
02825    } else {
02826       return NULL;
02827    }
02828 
02829    tmp->frame.frametype = AST_FRAME_VOICE;
02830    tmp->frame.subclass = AST_FORMAT_ALAW;
02831    tmp->frame.datalen = len;
02832    tmp->frame.samples = len;
02833    tmp->frame.mallocd = 0;
02834    tmp->frame.offset = 0;
02835    tmp->frame.delivery = ast_tv(0,0);
02836    tmp->frame.src = NULL;
02837    tmp->frame.data = tmp->ast_rd_buf;
02838 
02839    if (tmp->faxdetect && !tmp->faxhandled) {
02840       if (tmp->faxdetect_timeout) {
02841          if (ast_tvzero(tmp->faxdetect_tv)) {
02842             tmp->faxdetect_tv = ast_tvnow();
02843             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
02844             return process_ast_dsp(tmp, &tmp->frame);
02845          } else {
02846             struct timeval tv_now = ast_tvnow();
02847             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
02848             if (diff <= (tmp->faxdetect_timeout * 1000)) {
02849                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
02850                return process_ast_dsp(tmp, &tmp->frame);
02851             } else {
02852                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
02853                tmp->faxdetect = 0;
02854                return &tmp->frame;
02855             }
02856          }
02857       } else {
02858          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
02859          return process_ast_dsp(tmp, &tmp->frame);
02860       }
02861    } else {
02862       if (tmp->ast_dsp)
02863          return process_ast_dsp(tmp, &tmp->frame);
02864       else
02865          return &tmp->frame;
02866    }
02867 }

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

Definition at line 1246 of file chan_misdn.c.

References ast_cli(), and reload_config().

01247 {
01248    ast_cli(fd, "Reloading mISDN configuration\n");
01249    reload_config();
01250    return 0;
01251 }

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

Definition at line 3175 of file chan_misdn.c.

References chan_list::ast, ast_copy_string(), ast_log(), AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, cl_queue_chan(), cl_te, misdn_bchannel::dec, ext, get_robin_position(), group, init_chan_list(), LOG_ERROR, LOG_WARNING, METHOD_ROUND_ROBIN, METHOD_STANDARD_DEC, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_next_port_spin(), MISDN_CFG_GROUPNAME, misdn_cfg_is_group_method(), MISDN_CFG_PMP_L1_CHECK, misdn_lib_get_free_bc(), misdn_lib_get_maxchans(), misdn_lib_port_up(), misdn_new(), misdn_type, chan_list::need_hangup, ORG_AST, misdn_bchannel::port, robin_list::port, and read_config().

03176 {
03177    struct ast_channel *tmp = NULL;
03178    char group[BUFFERSIZE + 1] = "";
03179    char dial_str[128];
03180    char *buf2 = ast_strdupa(data);
03181    char *ext;
03182    char *port_str;
03183    char *p = NULL;
03184    int channel = 0;
03185    int port = 0;
03186    struct misdn_bchannel *newbc = NULL;
03187    int dec = 0;
03188 
03189    struct chan_list *cl = init_chan_list(ORG_AST);
03190 
03191    snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
03192 
03193    /*
03194     * data is ---v
03195     * Dial(mISDN/g:group_name[/extension[/options]])
03196     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
03197     *
03198     * The dial extension could be empty if you are using MISDN_KEYPAD
03199     * to control ISDN provider features.
03200     */
03201    port_str = strsep(&buf2, "/");
03202    if (!ast_strlen_zero(port_str)) {
03203       if (port_str[0] == 'g' && port_str[1] == ':' ) {
03204          /* We make a group call lets checkout which ports are in my group */
03205          port_str += 2;
03206          ast_copy_string(group, port_str, sizeof(group));
03207          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03208       } else if ((p = strchr(port_str, ':'))) {
03209          /* we have a preselected channel */
03210          *p = 0;
03211          channel = atoi(++p);
03212          port = atoi(port_str);
03213          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03214       } else {
03215          port = atoi(port_str);
03216       }
03217    } else {
03218       ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
03219       return NULL;
03220    }
03221 
03222    ext = strsep(&buf2, "/");
03223    if (!ext) {
03224       ext = "";
03225    }
03226 
03227    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03228       chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
03229       dec = 1;
03230    }
03231 
03232    if (!ast_strlen_zero(group)) {
03233       char cfg_group[BUFFERSIZE + 1];
03234       struct robin_list *rr = NULL;
03235 
03236       /* Group dial */
03237 
03238       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03239          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03240          rr = get_robin_position(group);
03241       }
03242 
03243       if (rr) {
03244          int port_start = 0;
03245          int port_bak = rr->port;
03246          int chan_bak = rr->channel;
03247 
03248          if (!rr->port)
03249             rr->port = misdn_cfg_get_next_port_spin(rr->port);
03250          
03251          for (; rr->port > 0; rr->port = misdn_cfg_get_next_port_spin(rr->port)) {
03252             int port_up;
03253             int check;
03254             int max_chan;
03255             int last_chance = 0;
03256 
03257             misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03258             if (strcasecmp(cfg_group, group))
03259                continue;
03260 
03261             misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03262             port_up = misdn_lib_port_up(rr->port, check);
03263 
03264             if (check && !port_up) 
03265                chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
03266 
03267             if (check && port_up < 0)
03268                ast_log(LOG_WARNING,"This port (%d) is blocked\n", rr->port);
03269 
03270             if ((port_start == rr->port) && (port_up <= 0))
03271                break;
03272 
03273             if (!port_start)
03274                port_start = rr->port;
03275 
03276             if (port_up <= 0)
03277                continue;
03278 
03279             max_chan = misdn_lib_get_maxchans(rr->port);
03280 
03281             for (++rr->channel; !last_chance && rr->channel <= max_chan; ++rr->channel) {
03282                if (rr->port == port_bak && rr->channel == chan_bak)
03283                   last_chance = 1;
03284 
03285                chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr->port, rr->channel);
03286                newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0);
03287                if (newbc) {
03288                   chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03289                   if (port_up)
03290                      chan_misdn_log(4, rr->port, "portup:%d\n",  port_up);
03291                   port = rr->port;
03292                   break;
03293                }
03294             }
03295 
03296             if (newbc || last_chance)
03297                break;
03298 
03299             rr->channel = 0;
03300          }
03301          if (!newbc) {
03302             rr->port = port_bak;
03303             rr->channel = chan_bak;
03304          }
03305       } else {    
03306          for (port = misdn_cfg_get_next_port(0); port > 0;
03307              port = misdn_cfg_get_next_port(port)) {
03308 
03309             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03310 
03311             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03312             if (!strcasecmp(cfg_group, group)) {
03313                int port_up;
03314                int check;
03315                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03316                port_up = misdn_lib_port_up(port, check);
03317 
03318                chan_misdn_log(4, port, "portup:%d\n", port_up);
03319 
03320                if (port_up > 0) {
03321                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03322                   if (newbc)
03323                      break;
03324                }
03325             }
03326          }
03327       }
03328       
03329       /* Group dial failed ?*/
03330       if (!newbc) {
03331          ast_log(LOG_WARNING, 
03332                "Could not Dial out on group '%s'.\n"
03333                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03334                "\tOr there was no free channel on none of the ports\n\n"
03335                , group);
03336          return NULL;
03337       }
03338    } else {
03339       /* 'Normal' Port dial * Port dial */
03340       if (channel)
03341          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03342       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03343 
03344       if (!newbc) {
03345          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03346          return NULL;
03347       }
03348    }
03349    
03350 
03351    /* create ast_channel and link all the objects together */
03352    cl->bc = newbc;
03353    
03354    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03355    if (!tmp) {
03356       ast_log(LOG_ERROR,"Could not create Asterisk object\n");
03357       return NULL;
03358    }
03359 
03360    cl->ast=tmp;
03361    
03362    /* register chan in local list */
03363    cl_queue_chan(&cl_te, cl) ;
03364    
03365    /* fill in the config into the objects */
03366    read_config(cl, ORG_AST);
03367 
03368    /* important */
03369    cl->need_hangup = 0;
03370    
03371    return tmp;
03372 }

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

Definition at line 1032 of file chan_misdn.c.

References misdn_lib_pid_restart(), and RESULT_SHOWUSAGE.

01033 {
01034    int pid;
01035   
01036    if (argc != 4)
01037       return RESULT_SHOWUSAGE;
01038   
01039    pid = atoi(argv[3]);
01040 
01041    misdn_lib_pid_restart(pid);
01042 
01043    return 0;
01044 }

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

Definition at line 1018 of file chan_misdn.c.

References misdn_lib_port_restart(), and RESULT_SHOWUSAGE.

01019 {
01020    int port;
01021   
01022    if (argc != 4)
01023       return RESULT_SHOWUSAGE;
01024   
01025    port = atoi(argv[3]);
01026 
01027    misdn_lib_port_restart(port);
01028 
01029    return 0;
01030 }

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

Definition at line 1439 of file chan_misdn.c.

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

01440 {
01441    char *channame; 
01442    char *nr;
01443    struct chan_list *tmp;
01444 
01445    if (argc != 5)
01446       return RESULT_SHOWUSAGE;
01447  
01448    
01449    {
01450       channame = argv[3];
01451       nr = argv[4];
01452 
01453       ast_cli(fd, "Sending Calldeflection (%s) to %s\n", nr, channame);
01454       tmp = get_chan_by_ast_name(channame);
01455       if (!tmp) {
01456          ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
01457          return 0; 
01458       }
01459 
01460       if (strlen(nr) >= 15) {
01461          ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
01462          return 0; 
01463       }
01464       tmp->bc->fac_out.Function = Fac_CD;
01465       ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
01466       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
01467    }
01468 
01469    return 0;
01470 }

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

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

01493 {
01494    char *channame; 
01495    char *msg; 
01496    struct chan_list *tmp;
01497    int i, msglen;
01498 
01499    if (argc != 5)
01500       return RESULT_SHOWUSAGE;
01501 
01502    channame = argv[3];
01503    msg = argv[4];
01504    msglen = strlen(msg);
01505 
01506    ast_cli(fd, "Sending %s to %s\n", msg, channame);
01507 
01508    tmp = get_chan_by_ast_name(channame);
01509    if (!tmp) {
01510       ast_cli(fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
01511       return 0; 
01512    }
01513 #if 1
01514    for (i = 0; i < msglen; i++) {
01515       ast_cli(fd, "Sending: %c\n", msg[i]);
01516       send_digit_to_chan(tmp, msg[i]);
01517       /* res = ast_safe_sleep(tmp->ast, 250); */
01518       usleep(250000);
01519       /* res = ast_waitfor(tmp->ast,100); */
01520    }
01521 #else
01522    ast_dtmf_stream(tmp->ast, NULL, msg, 250);
01523 #endif
01524 
01525    return 0;
01526 }

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

Definition at line 1562 of file chan_misdn.c.

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

01563 {
01564    char *channame;
01565    char *msg;
01566    struct chan_list *tmp;
01567 
01568    if (argc != 5)
01569       return RESULT_SHOWUSAGE;
01570 
01571    channame = argv[3];
01572    msg = argv[4];
01573 
01574    ast_cli(fd, "Sending %s to %s\n", msg, channame);
01575    tmp = get_chan_by_ast_name(channame);
01576     
01577    if (tmp && tmp->bc) {
01578       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01579       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01580    } else {
01581       ast_cli(fd, "No such channel %s\n", channame);
01582       return RESULT_FAILURE;
01583    }
01584 
01585    return RESULT_SUCCESS;
01586 }

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

Definition at line 1472 of file chan_misdn.c.

References misdn_lib_send_restart(), and RESULT_SHOWUSAGE.

01473 {
01474    int port;
01475    int channel;
01476 
01477    if (argc < 4 || argc > 5)
01478       return RESULT_SHOWUSAGE;
01479 
01480    port = atoi(argv[3]);
01481 
01482    if (argc == 5) {
01483       channel = atoi(argv[4]);
01484       misdn_lib_send_restart(port, channel);
01485    } else {
01486       misdn_lib_send_restart(port, -1);
01487    }
01488 
01489    return 0;
01490 }

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

Definition at line 3375 of file chan_misdn.c.

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

03376 {
03377    struct chan_list *tmp = chan->tech_pvt;
03378    
03379    if (tmp && tmp->bc) {
03380       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03381       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03382    } else {
03383       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03384       return -1;
03385    }
03386    
03387    return 0;
03388 }

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

Definition at line 982 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

00983 {
00984    if (argc != 5) return RESULT_SHOWUSAGE; 
00985 
00986    return 0;
00987 }

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

Definition at line 919 of file chan_misdn.c.

References ast_cli(), and RESULT_SHOWUSAGE.

00920 {
00921    int level;
00922 
00923    if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
00924       return RESULT_SHOWUSAGE; 
00925 
00926    level = atoi(argv[3]);
00927 
00928    switch (argc) {
00929    case 4:
00930    case 5:
00931       {
00932          int i;
00933          int only = 0;
00934          if (argc == 5) {
00935             if (strncasecmp(argv[4], "only", strlen(argv[4])))
00936                return RESULT_SHOWUSAGE;
00937             else
00938                only = 1;
00939          }
00940    
00941          for (i = 0; i <= max_ports; i++) {
00942             misdn_debug[i] = level;
00943             misdn_debug_only[i] = only;
00944          }
00945          ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00946       }
00947       break;
00948    case 6:
00949    case 7:
00950       {
00951          int port;
00952          if (strncasecmp(argv[4], "port", strlen(argv[4])))
00953             return RESULT_SHOWUSAGE;
00954          port = atoi(argv[5]);
00955          if (port <= 0 || port > max_ports) {
00956             switch (max_ports) {
00957             case 0:
00958                ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00959                break;
00960             case 1:
00961                ast_cli(fd, "port number not valid! only port 1 is available.\n");
00962                break;
00963             default:
00964                ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00965             }
00966             return 0;
00967          }
00968          if (argc == 7) {
00969             if (strncasecmp(argv[6], "only", strlen(argv[6])))
00970                return RESULT_SHOWUSAGE;
00971             else
00972                misdn_debug_only[port] = 1;
00973          } else
00974             misdn_debug_only[port] = 0;
00975          misdn_debug[port] = level;
00976          ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
00977       }
00978    }
00979    return 0;
00980 }

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

Definition at line 5331 of file chan_misdn.c.

References ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, keys, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_GEN_CRYPT_KEYS, misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_bchannel::orig, chan_list::originator, misdn_bchannel::port, misdn_bchannel::pres, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, ast_channel::tech, misdn_bchannel::txgain, and ast_channel_tech::type.

Referenced by load_module(), and misdn_call().

05332 {
05333    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05334    char *tok, *tokb;
05335    int  keyidx = 0;
05336    int rxgain = 0;
05337    int txgain = 0;
05338    int change_jitter = 0;
05339 
05340    if (strcasecmp(chan->tech->type, "mISDN")) {
05341       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05342       return -1;
05343    }
05344    
05345    if (ast_strlen_zero((char *)data)) {
05346       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05347       return -1;
05348    }
05349 
05350    for (tok = strtok_r((char*) data, ":", &tokb);
05351         tok;
05352         tok = strtok_r(NULL, ":", &tokb) ) {
05353       int neglect = 0;
05354 
05355       if (tok[0] == '!' ) {
05356          neglect = 1;
05357          tok++;
05358       }
05359       
05360       switch(tok[0]) {
05361          
05362       case 'd' :
05363          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05364          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05365          break;
05366          
05367       case 'n':
05368          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05369          ch->bc->nodsp = 1;
05370          break;
05371 
05372       case 'j':
05373          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05374          tok++;
05375          change_jitter = 1;
05376 
05377          switch ( tok[0] ) {
05378          case 'b':
05379             ch->jb_len = atoi(++tok);
05380             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05381             break;
05382          case 't' :
05383             ch->jb_upper_threshold = atoi(++tok);
05384             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05385             break;
05386          case 'n':
05387             ch->bc->nojitter = 1;
05388             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05389             break;
05390          default:
05391             ch->jb_len = 4000;
05392             ch->jb_upper_threshold = 0;
05393             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05394             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05395          }
05396          break;
05397       case 'v':
05398          tok++;
05399 
05400          switch (tok[0]) {
05401          case 'r' :
05402             rxgain = atoi(++tok);
05403             if (rxgain < -8)
05404                rxgain = -8;
05405             if (rxgain > 8)
05406                rxgain = 8;
05407             ch->bc->rxgain = rxgain;
05408             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05409             break;
05410          case 't':
05411             txgain = atoi(++tok);
05412             if (txgain < -8)
05413                txgain = -8;
05414             if (txgain > 8)
05415                txgain = 8;
05416             ch->bc->txgain = txgain;
05417             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05418             break;
05419          }
05420          break;
05421       
05422       case 'c':
05423          keyidx = atoi(++tok);
05424          {
05425             char keys[4096];
05426             char *key = NULL, *tmp = keys;
05427             int i;
05428             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05429 
05430             for (i = 0; i < keyidx; i++) {
05431                key = strsep(&tmp, ",");
05432             }
05433 
05434             if (key) {
05435                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05436             }
05437 
05438             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05439             break;
05440          }
05441       case 'e':
05442          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05443          
05444          if (neglect) {
05445             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05446 #ifdef MISDN_1_2
05447             *ch->bc->pipeline = 0;
05448 #else
05449             ch->bc->ec_enable = 0;
05450 #endif
05451          } else {
05452 #ifdef MISDN_1_2
05453             update_pipeline_config(ch->bc);
05454 #else
05455             ch->bc->ec_enable = 1;
05456             ch->bc->orig = ch->originator;
05457             tok++;
05458             if (*tok) {
05459                ch->bc->ec_deftaps = atoi(tok);
05460             }
05461 #endif
05462          }
05463          
05464          break;
05465       case 'h':
05466          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05467          
05468          if (strlen(tok) > 1 && tok[1] == '1') {
05469             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05470             if (!ch->bc->hdlc) {
05471                ch->bc->hdlc = 1;
05472             }
05473          }
05474          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05475          break;
05476             
05477       case 's':
05478          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05479          ch->bc->send_dtmf = 1;
05480          break;
05481          
05482       case 'f':
05483          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05484          ch->faxdetect = 1;
05485          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05486          break;
05487 
05488       case 'a':
05489          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05490          ch->ast_dsp = 1;
05491          break;
05492 
05493       case 'p':
05494          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05495          /* CRICH: callingpres!!! */
05496          if (strstr(tok,"allowed")) {
05497             ch->bc->pres = 0;
05498          } else if (strstr(tok, "restricted")) {
05499             ch->bc->pres = 1;
05500          } else if (strstr(tok, "not_screened")) {
05501             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05502             ch->bc->pres = 1;
05503          }
05504          break;
05505       case 'i' :
05506          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05507          ch->ignore_dtmf=1;
05508          break;
05509       default:
05510          break;
05511       }
05512    }
05513 
05514    if (change_jitter)
05515       config_jitterbuffer(ch);
05516 
05517    if (ch->faxdetect || ch->ast_dsp) {
05518       if (!ch->dsp)
05519          ch->dsp = ast_dsp_new();
05520       if (ch->dsp)
05521          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
05522       if (!ch->trans)
05523          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05524    }
05525 
05526    if (ch->ast_dsp) {
05527       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05528       ch->bc->nodsp = 1;
05529    }
05530    
05531    return 0;
05532 }

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

Definition at line 1383 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

01384 {
01385    if (argc != 4)
01386       return RESULT_SHOWUSAGE;
01387 
01388    MAXTICS = atoi(argv[3]);
01389 
01390    return 0;
01391 }

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

Definition at line 1356 of file chan_misdn.c.

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

01357 {
01358    struct chan_list *help;
01359 
01360    if (argc != 4)
01361       return RESULT_SHOWUSAGE;
01362 
01363    help = cl_te;
01364 
01365    for (; help; help = help->next) {
01366       struct misdn_bchannel *bc = help->bc;   
01367       struct ast_channel *ast = help->ast;
01368     
01369       if (bc && ast) {
01370          if (!strcasecmp(ast->name,argv[3])) {
01371             print_bc_info(fd, help, bc);
01372             break; 
01373          }
01374       } 
01375    }
01376 
01377    return 0;
01378 }

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

Definition at line 1308 of file chan_misdn.c.

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

01309 {
01310    struct chan_list *help;
01311 
01312    help = cl_te;
01313   
01314    ast_cli(fd, "Channel List: %p\n", cl_te);
01315 
01316    for (; help; help = help->next) {
01317       struct misdn_bchannel *bc = help->bc;   
01318       struct ast_channel *ast = help->ast;
01319       if (!ast) {
01320          if (!bc) {
01321             ast_cli(fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
01322             continue;
01323          }
01324          ast_cli(fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
01325          continue;
01326       }
01327 
01328       if (misdn_debug[0] > 2)
01329          ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
01330       if (bc) {
01331          print_bc_info(fd, help, bc);
01332       } else {
01333          if (help->state == MISDN_HOLDED) {
01334             ast_cli(fd, "ITS A HOLDED BC:\n");
01335             ast_cli(fd, " --> l3_id: %x\n"
01336                   " --> dad:%s oad:%s\n"
01337                   " --> hold_port: %d\n"
01338                   " --> hold_channel: %d\n",
01339                   help->l3id,
01340                   ast->exten,
01341                   ast->cid.cid_num,
01342                   help->hold_info.port,
01343                   help->hold_info.channel
01344                   );
01345          } else {
01346             ast_cli(fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
01347          }
01348       }
01349    }
01350 
01351    misdn_dump_chanlist();
01352 
01353    return 0;
01354 }

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

Definition at line 1097 of file chan_misdn.c.

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

01098 {
01099    char buffer[BUFFERSIZE];
01100    enum misdn_cfg_elements elem;
01101    int linebreak;
01102    int onlyport = -1;
01103    int ok = 0;
01104 
01105    if (argc >= 4) {
01106       if (!strcmp(argv[3], "description")) {
01107          if (argc == 5) {
01108             enum misdn_cfg_elements elem = misdn_cfg_get_elem(argv[4]);
01109             if (elem == MISDN_CFG_FIRST)
01110                ast_cli(fd, "Unknown element: %s\n", argv[4]);
01111             else
01112                show_config_description(fd, elem);
01113             return 0;
01114          }
01115          return RESULT_SHOWUSAGE;
01116       }
01117       if (!strcmp(argv[3], "descriptions")) {
01118          if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
01119             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01120                show_config_description(fd, elem);
01121                ast_cli(fd, "\n");
01122             }
01123             ok = 1;
01124          }
01125          if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
01126             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
01127                show_config_description(fd, elem);
01128                ast_cli(fd, "\n");
01129             }
01130             ok = 1;
01131          }
01132          return ok ? 0 : RESULT_SHOWUSAGE;
01133       }
01134       if (!sscanf(argv[3], "%30d", &onlyport) || onlyport < 0) {
01135          ast_cli(fd, "Unknown option: %s\n", argv[3]);
01136          return RESULT_SHOWUSAGE;
01137       }
01138    }
01139    
01140    if (argc == 3 || onlyport == 0) {
01141       ast_cli(fd, "Misdn General-Config:\n");
01142       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
01143          misdn_cfg_get_config_string(0, elem, buffer, BUFFERSIZE);
01144          ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01145       }
01146       ast_cli(fd, "\n");
01147    }
01148 
01149    if (onlyport < 0) {
01150       int port = misdn_cfg_get_next_port(0);
01151       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
01152          ast_cli(fd, "\n[PORT %d]\n", port);
01153          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01154             misdn_cfg_get_config_string(port, elem, buffer, BUFFERSIZE);
01155             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01156          }  
01157          ast_cli(fd, "\n");
01158       }
01159    }
01160    
01161    if (onlyport > 0) {
01162       if (misdn_cfg_is_port_valid(onlyport)) {
01163          ast_cli(fd, "[PORT %d]\n", onlyport);
01164          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01165             misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
01166             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01167          }  
01168          ast_cli(fd, "\n");
01169       } else {
01170          ast_cli(fd, "Port %d is not active!\n", onlyport);
01171       }
01172    }
01173 
01174    return 0;
01175 }

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

Definition at line 1422 of file chan_misdn.c.

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

01423 {
01424    int port;
01425    char buf[128];
01426 
01427    if (argc != 4)
01428       return RESULT_SHOWUSAGE;
01429 
01430    port = atoi(argv[3]);
01431   
01432    ast_cli(fd, "BEGIN STACK_LIST:\n");
01433    get_show_stack_details(port, buf);
01434    ast_cli(fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01435 
01436    return 0;
01437 }

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

Definition at line 1408 of file chan_misdn.c.

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

01409 {
01410    int port;
01411 
01412    ast_cli(fd, "Port\tin_calls\tout_calls\n");
01413    for (port = misdn_cfg_get_next_port(0); port > 0;
01414         port = misdn_cfg_get_next_port(port)) {
01415       ast_cli(fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
01416    }
01417    ast_cli(fd, "\n");
01418 
01419    return 0;
01420 }

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

Definition at line 1393 of file chan_misdn.c.

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

01394 {
01395    int port;
01396 
01397    ast_cli(fd, "BEGIN STACK_LIST:\n");
01398    for (port = misdn_cfg_get_next_port(0); port > 0;
01399         port = misdn_cfg_get_next_port(port)) {
01400       char buf[128];
01401       get_show_stack_details(port, buf);
01402       ast_cli(fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01403    }
01404 
01405    return 0;
01406 }

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

Definition at line 810 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

00811 {
00812    return _misdn_tasks_add_variable(timeout, callback, data, 0);
00813 }

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

Definition at line 815 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

00816 {
00817    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00818 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 780 of file chan_misdn.c.

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

Referenced by unload_module().

00781 {
00782    if (misdn_tasks) {
00783       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
00784       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
00785          cb_log(4, 0, "Joining misdn_tasks thread\n");
00786          pthread_join(misdn_tasks_thread, NULL);
00787       }
00788       sched_context_destroy(misdn_tasks);
00789    }
00790 }

static void misdn_tasks_init ( void   )  [static]

Definition at line 761 of file chan_misdn.c.

References chan_misdn_log(), misdn_tasks, misdn_tasks_thread_func(), pthread_create, and sched_context_create().

Referenced by _misdn_tasks_add_variable().

00762 {
00763    sem_t blocker;
00764    int i = 5;
00765 
00766    if (sem_init(&blocker, 0, 0)) {
00767       perror("chan_misdn: Failed to initialize semaphore!");
00768       exit(1);
00769    }
00770 
00771    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
00772    
00773    misdn_tasks = sched_context_create();
00774    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
00775 
00776    while (sem_wait(&blocker) && --i);
00777    sem_destroy(&blocker);
00778 }

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 820 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by release_chan().

00821 {
00822    AST_SCHED_DEL(misdn_tasks, task_id);
00823 }

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

Definition at line 737 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

00738 {
00739    int wait;
00740    struct sigaction sa;
00741 
00742    sa.sa_handler = sighandler;
00743    sa.sa_flags = SA_NODEFER;
00744    sigemptyset(&sa.sa_mask);
00745    sigaddset(&sa.sa_mask, SIGUSR1);
00746    sigaction(SIGUSR1, &sa, NULL);
00747    
00748    sem_post((sem_t *)data);
00749 
00750    while (1) {
00751       wait = ast_sched_wait(misdn_tasks);
00752       if (wait < 0)
00753          wait = 8000;
00754       if (poll(NULL, 0, wait) < 0)
00755          chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
00756       ast_sched_runq(misdn_tasks);
00757    }
00758    return NULL;
00759 }

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 792 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

00793 {
00794    pthread_kill(misdn_tasks_thread, SIGUSR1);
00795 }

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

Definition at line 1528 of file chan_misdn.c.

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

01529 {
01530    char *channame;
01531    struct chan_list *tmp;
01532 
01533    if (argc != 4)
01534       return RESULT_SHOWUSAGE;
01535 
01536    channame = argv[3];
01537   
01538    ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
01539   
01540    tmp = get_chan_by_ast_name(channame);
01541    if (!tmp) {
01542       ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
01543       return 0;
01544    }
01545 
01546    tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
01547 
01548    if (tmp->toggle_ec) {
01549 #ifdef MISDN_1_2
01550       update_pipeline_config(tmp->bc);
01551 #else
01552       update_ec_config(tmp->bc);
01553 #endif
01554       manager_ec_enable(tmp->bc);
01555    } else {
01556       manager_ec_disable(tmp->bc);
01557    }
01558 
01559    return 0;
01560 }

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

Definition at line 3744 of file chan_misdn.c.

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

Referenced by cb_events().

03745 {
03746    chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
03747 
03748    tmp_ch->state = MISDN_HOLD_DISCONNECT;
03749 
03750    ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03751 
03752    holded_chan->state=MISDN_CONNECTED;
03753    /* misdn_lib_transfer(holded_chan->bc); */
03754    ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03755 }

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

Definition at line 2870 of file chan_misdn.c.

References misdn_bchannel::addr, chan_list::ast, ast_log(), chan_list::bc, misdn_bchannel::bc_state, BCHAN_ACTIVATED, BCHAN_BRIDGED, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_frame::data, chan_list::dropped_frame_cnt, ast_channel::exten, chan_list::frame, misdn_bchannel::l3_id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_get_ch_state(), MISDN_HOLDED, misdn_lib_tone_generator_start(), chan_list::notxtone, misdn_bchannel::port, prefformat, ast_frame::samples, ast_frame::src, chan_list::state, ast_frame::subclass, and chan_list::ts.

02871 {
02872    struct chan_list *ch;
02873    int i  = 0;
02874    
02875    if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02876 
02877    if (ch->state == MISDN_HOLDED) {
02878       chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
02879       return 0;
02880    }
02881    
02882    if (!ch->bc ) {
02883       ast_log(LOG_WARNING, "private but no bc\n");
02884       return -1;
02885    }
02886    
02887    if (ch->notxtone) {
02888       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
02889       return 0;
02890    }
02891 
02892 
02893    if (!frame->subclass) {
02894       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
02895       return 0;
02896    }
02897    
02898    if (!(frame->subclass & prefformat)) {
02899       
02900       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
02901       return 0;
02902    }
02903    
02904 
02905    if (!frame->samples ) {
02906       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
02907       
02908       if (!strcmp(frame->src,"ast_prod")) {
02909          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
02910 
02911          if (ch->ts) {
02912             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
02913             misdn_lib_tone_generator_start(ch->bc);
02914          }
02915          return 0;
02916       }
02917 
02918       return -1;
02919    }
02920 
02921    if ( ! ch->bc->addr ) {
02922       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
02923       return 0;
02924    }
02925    
02926 #ifdef MISDN_DEBUG
02927    {
02928       int i, max = 5 > frame->samples ? frame->samples : 5;
02929 
02930       printf("write2mISDN %p %d bytes: ", p, frame->samples);
02931 
02932       for (i = 0; i < max; i++)
02933          printf("%2.2x ", ((char*) frame->data)[i]);
02934       printf ("\n");
02935    }
02936 #endif
02937 
02938    switch (ch->bc->bc_state) {
02939    case BCHAN_ACTIVATED:
02940    case BCHAN_BRIDGED:
02941       break;
02942    default:
02943       if (!ch->dropped_frame_cnt)
02944          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n", frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
02945       
02946       ch->dropped_frame_cnt++;
02947       if (ch->dropped_frame_cnt > 100) {
02948          ch->dropped_frame_cnt = 0;
02949          chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x  dropped > 100 frames!\n", frame->samples, ch->bc->addr);
02950       }
02951 
02952       return 0;
02953    }
02954 
02955    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
02956    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
02957       /* Buffered Transmit (triggered by read from isdn side)*/
02958       if (misdn_jb_fill(ch->jb, frame->data, frame->samples) < 0) {
02959          if (ch->bc->active)
02960             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
02961       }
02962       
02963    } else {
02964       /*transmit without jitterbuffer*/
02965       i = misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
02966    }
02967 
02968    return 0;
02969 }

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

Definition at line 3627 of file chan_misdn.c.

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

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

03628 {
03629    int ret = ast_pbx_start(ch->ast);   
03630 
03631    if (ret >= 0) 
03632       ch->need_hangup = 0;
03633    else
03634       ch->need_hangup = 1;
03635 
03636    return ret;
03637 }

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

Definition at line 1253 of file chan_misdn.c.

References misdn_bchannel::active, misdn_bchannel::addr, chan_list::addr, chan_list::ast, ast_cli(), misdn_bchannel::bc_state, bc_state2str(), bearer2str(), misdn_bchannel::capability, misdn_bchannel::channel, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, misdn_bchannel::display, misdn_bchannel::ec_enable, ast_channel::exten, misdn_bchannel::holded, misdn_bchannel::l3_id, chan_list::l3id, misdn_get_ch_state(), ast_channel::name, chan_list::norxtone, chan_list::notxtone, misdn_bchannel::nt, ORG_AST, chan_list::originator, misdn_bchannel::pid, misdn_bchannel::port, and misdn_bchannel::rad.

Referenced by misdn_show_cl(), and misdn_show_cls().

01254 {
01255    struct ast_channel *ast = help->ast;
01256    ast_cli(fd,
01257       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
01258 
01259       bc->pid, bc->port, bc->channel,
01260       bc->nt ? "NT" : "TE",
01261       help->originator == ORG_AST ? "*" : "I",
01262       ast ? ast->exten : NULL,
01263       ast ? ast->cid.cid_num : NULL,
01264       bc->rad,
01265       ast ? ast->context : NULL,
01266       misdn_get_ch_state(help)
01267       );
01268    if (misdn_debug[bc->port] > 0)
01269       ast_cli(fd,
01270          "  --> astname: %s\n"
01271          "  --> ch_l3id: %x\n"
01272          "  --> ch_addr: %x\n"
01273          "  --> bc_addr: %x\n"
01274          "  --> bc_l3id: %x\n"
01275          "  --> display: %s\n"
01276          "  --> activated: %d\n"
01277          "  --> state: %s\n"
01278          "  --> capability: %s\n"
01279 #ifdef MISDN_1_2
01280          "  --> pipeline: %s\n"
01281 #else
01282          "  --> echo_cancel: %d\n"
01283 #endif
01284          "  --> notone : rx %d tx:%d\n"
01285          "  --> bc_hold: %d\n",
01286          help->ast->name,
01287          help->l3id,
01288          help->addr,
01289          bc->addr,
01290          bc ? bc->l3_id : -1,
01291          bc->display,
01292          
01293          bc->active,
01294          bc_state2str(bc->bc_state),
01295          bearer2str(bc->capability),
01296 #ifdef MISDN_1_2
01297          bc->pipeline,
01298 #else
01299          bc->ec_enable,
01300 #endif
01301 
01302          help->norxtone, help->notxtone,
01303          bc->holded
01304          );
01305 
01306 }

static void print_bearer ( struct misdn_bchannel bc  )  [static]

Definition at line 662 of file chan_misdn.c.

References bearer2str(), misdn_bchannel::capability, chan_misdn_log(), INFO_CODEC_ALAW, INFO_CODEC_ULAW, misdn_bchannel::law, and misdn_bchannel::port.

Referenced by cb_events().

00663 {
00664    
00665    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00666    
00667    switch(bc->law) {
00668    case INFO_CODEC_ALAW:
00669       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00670       break;
00671    case INFO_CODEC_ULAW:
00672       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00673       break;
00674    }
00675 }

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

Definition at line 623 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by cb_events().

00624 {
00625    switch (fac->Function) {
00626    case Fac_CD:
00627       chan_misdn_log(1,bc->port," --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
00628          fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
00629       break;
00630    case Fac_AOCDCurrency:
00631       if (fac->u.AOCDcur.chargeNotAvailable)
00632          chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
00633       else if (fac->u.AOCDcur.freeOfCharge)
00634          chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
00635       else if (fac->u.AOCDchu.billingId >= 0)
00636          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
00637             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00638             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
00639       else
00640          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
00641             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00642             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
00643       break;
00644    case Fac_AOCDChargingUnit:
00645       if (fac->u.AOCDchu.chargeNotAvailable)
00646          chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
00647       else if (fac->u.AOCDchu.freeOfCharge)
00648          chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
00649       else if (fac->u.AOCDchu.billingId >= 0)
00650          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
00651             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
00652       else
00653          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
00654             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
00655       break;
00656    default:
00657       chan_misdn_log(1,bc->port," --> unknown facility\n");
00658       break;
00659    }
00660 }

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

Definition at line 2706 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_log(), ast_strlen_zero(), ast_translate(), ast_verbose(), chan_list::bc, BUFFERSIZE, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, chan_list::dsp, misdn_bchannel::ec_enable, ast_channel::exten, f, chan_list::faxdetect, chan_list::faxhandled, isdn_lib_stop_dtmf(), isdn_lib_update_ec(), isdn_lib_update_rxgain(), isdn_lib_update_txgain(), LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), ast_channel::name, option_verbose, pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, chan_list::trans, misdn_bchannel::txgain, and VERBOSE_PREFIX_3.

Referenced by misdn_read().

02707 {
02708    struct ast_frame *f,*f2;
02709  
02710    if (tmp->trans) {
02711       f2 = ast_translate(tmp->trans, frame, 0);
02712       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02713    } else {
02714       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02715       return NULL;
02716    }
02717 
02718    if (!f || (f->frametype != AST_FRAME_DTMF))
02719       return frame;
02720  
02721    ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
02722  
02723    if (tmp->faxdetect && (f->subclass == 'f')) {
02724       /* Fax tone -- Handle and return NULL */
02725       if (!tmp->faxhandled) {
02726          struct ast_channel *ast = tmp->ast;
02727          tmp->faxhandled++;
02728          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02729          tmp->bc->rxgain = 0;
02730          isdn_lib_update_rxgain(tmp->bc);
02731          tmp->bc->txgain = 0;
02732          isdn_lib_update_txgain(tmp->bc);
02733 #ifdef MISDN_1_2
02734          *tmp->bc->pipeline = 0;
02735 #else
02736          tmp->bc->ec_enable = 0;
02737 #endif
02738          isdn_lib_update_ec(tmp->bc);
02739          isdn_lib_stop_dtmf(tmp->bc);
02740          switch (tmp->faxdetect) {
02741          case 1:
02742             if (strcmp(ast->exten, "fax")) {
02743                char *context;
02744                char context_tmp[BUFFERSIZE];
02745                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02746                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02747                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02748                   if (option_verbose > 2)
02749                      ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02750                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02751                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02752                   if (ast_async_goto(ast, context, "fax", 1))
02753                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02754                } else
02755                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02756             } else {
02757                ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02758             }
02759             break;
02760          case 2:
02761             ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02762             break;
02763          }
02764       } else {
02765          ast_log(LOG_DEBUG, "Fax already handled\n");
02766       }
02767    }
02768    
02769    if (tmp->ast_dsp && (f->subclass != 'f')) {
02770       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02771    }
02772 
02773    return f;
02774 }

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

Definition at line 1915 of file chan_misdn.c.

References chan_list::allowed_bearers, misdn_bchannel::AOCDtype, chan_list::ast, ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_mutex_init, ast_print_group(), ast_set_callerid(), ast_string_field_set, ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, BUFFERSIZE, ast_channel::callgroup, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_rdnis, config_jitterbuffer(), ast_channel::context, chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::dad, debug_numplan(), misdn_bchannel::dnumplan, chan_list::dsp, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::early_bconnect, ast_channel::exten, chan_list::far_alerting, chan_list::faxdetect, chan_list::faxdetect_timeout, free, misdn_bchannel::hdlc, chan_list::ignore_dtmf, chan_list::incoming_early_audio, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, misdn_bchannel::keypad, language, LOG_WARNING, MISDN_CFG_ALLOWED_BEARERS, MISDN_CFG_ASTDTMF, MISDN_CFG_CALLERID, MISDN_CFG_CALLGROUP, MISDN_CFG_CONTEXT, MISDN_CFG_CPNDIALPLAN, MISDN_CFG_DIALPLAN, MISDN_CFG_EARLY_BCONNECT, MISDN_CFG_FAR_ALERTING, MISDN_CFG_FAXDETECT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CFG_INTERNATPREFIX, MISDN_CFG_JITTERBUFFER, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CFG_LANGUAGE, MISDN_CFG_LOCALDIALPLAN, MISDN_CFG_MUSICCLASS, MISDN_CFG_NATPREFIX, MISDN_CFG_NEED_MORE_INFOS, MISDN_CFG_NOAUTORESPOND_ON_SETUP, MISDN_CFG_NTTIMEOUT, MISDN_CFG_OVERLAP_DIAL, MISDN_CFG_PICKUPGROUP, MISDN_CFG_RXGAIN, MISDN_CFG_SENDDTMF, MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CFG_TXGAIN, chan_list::mohinterpret, misdn_bchannel::need_more_infos, chan_list::noautorespond_on_setup, chan_list::nttimeout, NUMPLAN_INTERNATIONAL, NUMPLAN_NATIONAL, misdn_bchannel::oad, misdn_bchannel::onumplan, ORG_AST, misdn_bchannel::orig_dad, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, ast_channel::pickupgroup, misdn_bchannel::port, prefix, misdn_bchannel::rad, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, strdup, misdn_bchannel::te_choose_channel, chan_list::trans, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

01916 {
01917    struct ast_channel *ast;
01918    struct misdn_bchannel *bc;
01919    int port;
01920    int hdlc = 0;
01921    char lang[BUFFERSIZE + 1];
01922    char faxdetect[BUFFERSIZE + 1];
01923    char buf[256];
01924    char buf2[256];
01925    ast_group_t pg;
01926    ast_group_t cg;
01927 
01928    if (!ch) {
01929       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01930       return -1;
01931    }
01932 
01933    ast = ch->ast;
01934    bc = ch->bc;
01935    if (! ast || ! bc) {
01936       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01937       return -1;
01938    }
01939    
01940    port = bc->port;
01941    chan_misdn_log(1, port, "read_config: Getting Config\n");
01942 
01943    misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
01944    ast_string_field_set(ast, language, lang);
01945 
01946    misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
01947 
01948    misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
01949    misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
01950 
01951    misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
01952 
01953    misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
01954    
01955    misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
01956 
01957    if (ch->ast_dsp) {
01958       ch->ignore_dtmf = 1;
01959    }
01960 
01961    misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
01962    misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
01963 
01964    misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
01965 
01966    misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
01967 
01968    misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
01969 
01970    misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
01971 
01972    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01973 
01974    if (hdlc) {
01975       switch (bc->capability) {
01976       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01977       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01978          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
01979          bc->hdlc = 1;
01980          break;
01981       }
01982       
01983    }
01984    /*Initialize new Jitterbuffer*/
01985    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
01986    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
01987 
01988    config_jitterbuffer(ch);
01989 
01990    misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
01991 
01992    ast_copy_string(ast->context, ch->context, sizeof(ast->context));
01993 
01994 #ifdef MISDN_1_2
01995    update_pipeline_config(bc);
01996 #else
01997    update_ec_config(bc);
01998 #endif
01999 
02000    {
02001       int eb3;
02002       
02003       misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
02004       bc->early_bconnect=eb3;
02005    }
02006 
02007    misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02008    misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02009 
02010    chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
02011    ast->pickupgroup = pg;
02012    ast->callgroup = cg;
02013    
02014    if (orig == ORG_AST) {
02015       char callerid[BUFFERSIZE + 1];
02016 
02017       /* ORIGINATOR Asterisk (outgoing call) */
02018 
02019       misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
02020 
02021       if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
02022          if (strstr(faxdetect, "nojump"))
02023             ch->faxdetect = 2;
02024          else
02025             ch->faxdetect = 1;
02026       }
02027 
02028       misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
02029       if ( ! ast_strlen_zero(callerid) ) {
02030          chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
02031          ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
02032       }
02033 
02034       misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
02035       misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
02036       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
02037       debug_numplan(port, bc->dnumplan, "TON");
02038       debug_numplan(port, bc->onumplan, "LTON");
02039       debug_numplan(port, bc->cpnnumplan, "CTON");
02040 
02041       ch->overlap_dial = 0;
02042    } else {
02043       /* ORIGINATOR MISDN (incoming call) */
02044       char prefix[BUFFERSIZE + 1] = "";
02045 
02046       if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
02047          if (strstr(faxdetect, "nojump"))
02048             ch->faxdetect = 2;
02049          else
02050             ch->faxdetect = 1;
02051       }
02052 
02053       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
02054       debug_numplan(port, bc->cpnnumplan, "CTON");
02055 
02056       switch (bc->onumplan) {
02057       case NUMPLAN_INTERNATIONAL:
02058          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02059          break;
02060 
02061       case NUMPLAN_NATIONAL:
02062          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02063          break;
02064       default:
02065          break;
02066       }
02067 
02068       ast_copy_string(buf, bc->oad, sizeof(buf));
02069       snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
02070 
02071       if (!ast_strlen_zero(bc->dad)) {
02072          ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
02073       }
02074 
02075       if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02076          ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
02077       }
02078 
02079       prefix[0] = 0;
02080 
02081       switch (bc->dnumplan) {
02082       case NUMPLAN_INTERNATIONAL:
02083          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02084          break;
02085       case NUMPLAN_NATIONAL:
02086          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02087          break;
02088       default:
02089          break;
02090       }
02091 
02092       ast_copy_string(buf, bc->dad, sizeof(buf));
02093       snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
02094 
02095       if (strcmp(bc->dad, ast->exten)) {
02096          ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
02097       }
02098 
02099       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
02100 
02101       if ( !ast_strlen_zero(bc->rad) ) {
02102          if (ast->cid.cid_rdnis)
02103             free(ast->cid.cid_rdnis);
02104          ast->cid.cid_rdnis = strdup(bc->rad);
02105       }
02106    
02107       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
02108       ast_mutex_init(&ch->overlap_tv_lock);
02109    } /* ORIG MISDN END */
02110 
02111    ch->overlap_dial_task = -1;
02112    
02113    if (ch->faxdetect  || ch->ast_dsp) {
02114       misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
02115       if (!ch->dsp)
02116          ch->dsp = ast_dsp_new();
02117       if (ch->dsp) {
02118          if (ch->faxdetect) 
02119             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
02120          else 
02121             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT );
02122       }
02123       if (!ch->trans)
02124          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
02125    }
02126 
02127    /* AOCD initialization */
02128    bc->AOCDtype = Fac_None;
02129 
02130    return 0;
02131 }

static void release_chan ( struct misdn_bchannel bc  )  [static]

Isdn asks us to release channel, pendant to misdn_hangup

Definition at line 3676 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_list::bc, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, cl_dequeue_chan(), cl_te, ast_channel::context, ast_channel::exten, find_chan_by_bc(), free, chan_list::jb, misdn_bchannel::l3_id, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, misdn_get_ch_state(), misdn_in_calls, misdn_jb_destroy(), misdn_out_calls, misdn_tasks_remove(), misdn_bchannel::nojitter, ORG_AST, chan_list::originator, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, misdn_bchannel::pid, chan_list::pipe, misdn_bchannel::port, release_lock, and chan_list::state.

Referenced by cb_events(), and misdn_hangup().

03676                                                     {
03677    struct ast_channel *ast = NULL;
03678 
03679    ast_mutex_lock(&release_lock);
03680    {
03681       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03682       if (!ch)  {
03683          chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03684          ast_mutex_unlock(&release_lock);
03685          return;
03686       }
03687 
03688       if (ch->ast) {
03689          ast = ch->ast;
03690       } 
03691 
03692       chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
03693 
03694       /*releasing jitterbuffer*/
03695       if (ch->jb ) {
03696          misdn_jb_destroy(ch->jb);
03697          ch->jb = NULL;
03698       } else {
03699          if (!bc->nojitter)
03700             chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03701       }
03702 
03703       if (ch->overlap_dial) {
03704          if (ch->overlap_dial_task != -1) {
03705             misdn_tasks_remove(ch->overlap_dial_task);
03706             ch->overlap_dial_task = -1;
03707          }
03708          ast_mutex_destroy(&ch->overlap_tv_lock);
03709       }
03710 
03711       if (ch->originator == ORG_AST) {
03712          misdn_out_calls[bc->port]--;
03713       } else {
03714          misdn_in_calls[bc->port]--;
03715       }
03716 
03717       if (ch) {
03718          close(ch->pipe[0]);
03719          close(ch->pipe[1]);
03720 
03721          if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03722             chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n", bc ? bc->pid : -1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch));
03723             chan_misdn_log(3, bc->port, " --> * State Down\n");
03724             MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03725 
03726             if (ast->_state != AST_STATE_RESERVED) {
03727                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03728                ast_setstate(ast, AST_STATE_DOWN);
03729             }
03730          }
03731 
03732          ch->state = MISDN_CLEANING;
03733          cl_dequeue_chan(&cl_te, ch);
03734 
03735          free(ch);
03736       } else {
03737          /* chan is already cleaned, so exiting  */
03738       }
03739    }
03740    ast_mutex_unlock(&release_lock);
03741 /*** release end **/
03742 }

static int reload ( void   )  [static]

Definition at line 5203 of file chan_misdn.c.

References reload_config().

05204 {
05205    reload_config();
05206 
05207    return 0;
05208 }

static void reload_config ( void   )  [static]

Definition at line 1225 of file chan_misdn.c.

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

01226 {
01227    int i, cfg_debug;
01228 
01229    if (!g_config_initialized) {
01230       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
01231       return ;
01232    }
01233    
01234    free_robin_list();
01235    misdn_cfg_reload();
01236    misdn_cfg_update_ptp();
01237    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
01238    misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
01239 
01240    for (i = 0;  i <= max_ports; i++) {
01241       misdn_debug[i] = cfg_debug;
01242       misdn_debug_only[i] = 0;
01243    }
01244 }

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

Definition at line 3822 of file chan_misdn.c.

References AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NO_ROUTE_DESTINATION, AST_CAUSE_NO_ROUTE_TRANSIT_NET, AST_CAUSE_NUMBER_CHANGED, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, ast_queue_control(), misdn_bchannel::cause, chan_misdn_log(), ast_channel::hangupcause, MISDN_BUSY, chan_list::need_busy, misdn_bchannel::pid, misdn_bchannel::port, and chan_list::state.

Referenced by hangup_chan().

03822                                                                                                      {
03823    if (!ast) {
03824       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
03825       return;
03826    }
03827    if (!bc) {
03828       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
03829       return;
03830    }
03831    if (!ch) {
03832       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
03833       return;
03834    }
03835 
03836    ast->hangupcause = bc->cause;
03837 
03838    switch (bc->cause) {
03839 
03840    case AST_CAUSE_UNALLOCATED:
03841    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
03842    case AST_CAUSE_NO_ROUTE_DESTINATION:
03843    case 4:  /* Send special information tone */
03844    case AST_CAUSE_NUMBER_CHANGED:
03845    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03846       /* Congestion Cases */
03847       /*
03848        * Not Queueing the Congestion anymore, since we want to hear
03849        * the inband message
03850        *
03851       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
03852       ch->state = MISDN_BUSY;
03853       
03854       ast_queue_control(ast, AST_CONTROL_CONGESTION);
03855       */
03856       break;
03857 
03858    case AST_CAUSE_CALL_REJECTED:
03859    case AST_CAUSE_USER_BUSY:
03860       ch->state = MISDN_BUSY;
03861 
03862       if (!ch->need_busy) {
03863          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
03864          break;
03865       }
03866 
03867       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
03868       
03869       ast_queue_control(ast, AST_CONTROL_BUSY);
03870       
03871       ch->need_busy = 0;
03872       
03873       break;
03874    }
03875 }

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

Definition at line 883 of file chan_misdn.c.

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

Referenced by misdn_digit_end(), and misdn_send_digit().

00884 {
00885    static const char* dtmf_tones[] = {
00886       "!941+1336/100,!0/100", /* 0 */
00887       "!697+1209/100,!0/100", /* 1 */
00888       "!697+1336/100,!0/100", /* 2 */
00889       "!697+1477/100,!0/100", /* 3 */
00890       "!770+1209/100,!0/100", /* 4 */
00891       "!770+1336/100,!0/100", /* 5 */
00892       "!770+1477/100,!0/100", /* 6 */
00893       "!852+1209/100,!0/100", /* 7 */
00894       "!852+1336/100,!0/100", /* 8 */
00895       "!852+1477/100,!0/100", /* 9 */
00896       "!697+1633/100,!0/100", /* A */
00897       "!770+1633/100,!0/100", /* B */
00898       "!852+1633/100,!0/100", /* C */
00899       "!941+1633/100,!0/100", /* D */
00900       "!941+1209/100,!0/100", /* * */
00901       "!941+1477/100,!0/100" };  /* # */
00902    struct ast_channel *chan=cl->ast; 
00903   
00904    if (digit >= '0' && digit <='9')
00905       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00906    else if (digit >= 'A' && digit <= 'D')
00907       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00908    else if (digit == '*')
00909       ast_playtones_start(chan,0,dtmf_tones[14], 0);
00910    else if (digit == '#')
00911       ast_playtones_start(chan,0,dtmf_tones[15], 0);
00912    else {
00913       /* not handled */
00914       ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00915    }
00916 }

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

Definition at line 1074 of file chan_misdn.c.

References ast_cli(), BUFFERSIZE, COLOR_BRWHITE, COLOR_YELLOW, desc, misdn_cfg_get_desc(), misdn_cfg_get_name(), MISDN_CFG_LAST, name, and term_color().

Referenced by misdn_show_config().

01075 {
01076    char section[BUFFERSIZE];
01077    char name[BUFFERSIZE];
01078    char desc[BUFFERSIZE];
01079    char def[BUFFERSIZE];
01080    char tmp[BUFFERSIZE];
01081 
01082    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
01083    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
01084    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
01085 
01086    if (elem < MISDN_CFG_LAST)
01087       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
01088    else
01089       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
01090 
01091    if (*def)
01092       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
01093    else
01094       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
01095 }

static void sighandler ( int  sig  )  [static]

Definition at line 734 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00735 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3137 of file chan_misdn.c.

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

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

03138 {
03139    misdn_lib_tone_generator_stop(cl->bc);
03140    cl->notxtone = 0;
03141    cl->norxtone = 0;
03142    return 0;
03143 }

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

Definition at line 3970 of file chan_misdn.c.

References chan_misdn_log(), EVENT_RELEASE, EVENT_RELEASE_COMPLETE, hangup_chan(), hanguptone_indicate(), misdn_lib_send_event(), misdn_bchannel::nt, pbx_start_chan(), and misdn_bchannel::port.

Referenced by cb_events().

03970                                                                                                  {
03971    if (pbx_start_chan(ch) < 0) {
03972       hangup_chan(ch);
03973       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03974       if (bc->nt) {
03975          hanguptone_indicate(ch);
03976          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
03977       } else
03978          misdn_lib_send_event(bc, EVENT_RELEASE);
03979    }
03980 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3145 of file chan_misdn.c.

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

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

03146 {
03147    if (!cl) return -1;
03148 
03149    cl->notxtone = 1;
03150    cl->norxtone = 1;
03151    
03152    return 0;
03153 }

static int stop_indicate ( struct chan_list cl  )  [static]

Definition at line 3117 of file chan_misdn.c.

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

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

03118 {
03119    struct ast_channel *ast = cl->ast;
03120 
03121    if (!ast) {
03122       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03123       return -1;
03124    }
03125 
03126    chan_misdn_log(3, cl->bc->port, " --> None\n");
03127    misdn_lib_tone_generator_stop(cl->bc);
03128    ast_playtones_stop(ast);
03129 
03130    cl->ts = NULL;
03131    /*ast_deactivate_generator(ast);*/
03132 
03133    return 0;
03134 }

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 5012 of file chan_misdn.c.

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

05013 {
05014    /* First, take us out of the channel loop */
05015    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05016 
05017    misdn_tasks_destroy();
05018    
05019    if (!g_config_initialized)
05020       return 0;
05021    
05022    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05023    
05024    /* ast_unregister_application("misdn_crypt"); */
05025    ast_unregister_application("misdn_set_opt");
05026    ast_unregister_application("misdn_facility");
05027    ast_unregister_application("misdn_check_l2l1");
05028   
05029    ast_channel_unregister(&misdn_tech);
05030 
05031    free_robin_list();
05032    misdn_cfg_destroy();
05033    misdn_lib_destroy();
05034   
05035    if (misdn_debug)
05036       free(misdn_debug);
05037    if (misdn_debug_only)
05038       free(misdn_debug_only);
05039    free(misdn_ports);
05040    
05041    return 0;
05042 }

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

Updates caller ID information from config.

Definition at line 1734 of file chan_misdn.c.

References chan_list::ast, ast_log(), AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_pres, misdn_bchannel::hdlc, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, LOG_WARNING, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_PRES, MISDN_CFG_SCREEN, misdn_bchannel::port, misdn_bchannel::pres, and misdn_bchannel::screen.

Referenced by misdn_call().

01735 {
01736    struct ast_channel *ast;
01737    struct misdn_bchannel *bc;
01738    int port, hdlc = 0;
01739    int pres, screen;
01740 
01741    if (!ch) {
01742       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01743       return -1;
01744    }
01745 
01746    ast = ch->ast;
01747    bc = ch->bc;
01748    if (! ast || ! bc) {
01749       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01750       return -1;
01751    }
01752 
01753    port = bc->port;
01754 
01755    chan_misdn_log(7, port, "update_config: Getting Config\n");
01756 
01757    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01758    
01759    if (hdlc) {
01760       switch (bc->capability) {
01761       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01762       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01763          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
01764          bc->hdlc = 1;
01765          break;
01766       }
01767    }
01768 
01769 
01770    misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
01771    misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
01772    chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
01773       
01774    if (pres < 0 || screen < 0) {
01775       chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
01776          
01777       switch (ast->cid.cid_pres & 0x60) {
01778       case AST_PRES_RESTRICTED:
01779          bc->pres = 1;
01780          chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
01781          break;
01782       case AST_PRES_UNAVAILABLE:
01783          bc->pres = 2;
01784          chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
01785          break;
01786       default:
01787          bc->pres = 0;
01788          chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
01789          break;
01790       }
01791 
01792       switch (ast->cid.cid_pres & 0x3) {
01793       default:
01794       case AST_PRES_USER_NUMBER_UNSCREENED:
01795          bc->screen = 0;
01796          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
01797          break;
01798       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
01799          bc->screen = 1;
01800          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
01801          break;
01802       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
01803          bc->screen = 2;
01804          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
01805          break;
01806       case AST_PRES_NETWORK_NUMBER:
01807          bc->screen = 3;
01808          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
01809          break;
01810       }
01811    } else {
01812       bc->screen = screen;
01813       bc->pres = pres;
01814    }
01815 
01816    return 0;
01817 }

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

Definition at line 1896 of file chan_misdn.c.

References misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, MISDN_CFG_ECHOCANCEL, misdn_cfg_get(), and misdn_bchannel::port.

Referenced by misdn_toggle_echocancel(), and read_config().

01897 {
01898    int ec;
01899    int port = bc->port;
01900 
01901    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
01902 
01903    if (ec == 1) {
01904       bc->ec_enable = 1;
01905    } else if (ec > 1) {
01906       bc->ec_enable = 1;
01907       bc->ec_deftaps = ec;
01908    }
01909 
01910    return 0;
01911 }

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

Definition at line 3430 of file chan_misdn.c.

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

Referenced by cb_events().

03431 {
03432    int chan_offset = 0;
03433    int tmp_port = misdn_cfg_get_next_port(0);
03434    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03435       if (tmp_port == port)
03436          break;
03437       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03438    }
03439    if (c < 0)
03440       c = 0;
03441 
03442    ast_string_field_build(tmp, name, "%s/%d-u%d",
03443       misdn_type, chan_offset + c, glob_channel++);
03444 
03445    chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03446 }

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

Definition at line 3982 of file chan_misdn.c.

References misdn_bchannel::dad, dialtone_indicate(), EVENT_SETUP_ACKNOWLEDGE, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::nt, and chan_list::state.

Referenced by cb_events().

03982                                                                                                        {
03983    ch->state=MISDN_WAITING4DIGS;
03984    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03985    if (bc->nt && !bc->dad[0])
03986       dialtone_indicate(ch);
03987 }


Variable Documentation

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

Definition at line 5781 of file chan_misdn.c.

struct allowed_bearers allowed_bearers_array[] [static]

Definition at line 598 of file chan_misdn.c.

Referenced by bearer2str(), and cb_events().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 5781 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1682 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

struct chan_list* cl_te = NULL

Global channel call record list head.

Definition at line 519 of file chan_misdn.c.

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

ast_mutex_t cl_te_lock

Definition at line 520 of file chan_misdn.c.

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

struct chan_list dummy_cl

Definition at line 514 of file chan_misdn.c.

int g_config_initialized = 0 [static]

Definition at line 86 of file chan_misdn.c.

int glob_channel = 0 [static]

Definition at line 3428 of file chan_misdn.c.

char global_tracefile[BUFFERSIZE+1]

Definition at line 84 of file chan_misdn.c.

ast_mutex_t lock

Definition at line 1380 of file chan_misdn.c.

Referenced by dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_show_locks(), load_config(), load_module(), load_rpt_vars(), rpt_master(), smdi_message_wait(), and unload_module().

int max_ports [static]

Definition at line 508 of file chan_misdn.c.

Referenced by _build_port_config(), chan_misdn_log(), load_module(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), misdn_cfg_is_group_method(), misdn_cfg_is_port_valid(), and misdn_cfg_update_ptp().

int MAXTICS = 8

Definition at line 1381 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 506 of file chan_misdn.c.

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

int* misdn_debug_only [static]

Definition at line 507 of file chan_misdn.c.

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

int* misdn_in_calls [static]

Definition at line 510 of file chan_misdn.c.

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

int* misdn_out_calls [static]

Definition at line 511 of file chan_misdn.c.

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

int* misdn_ports [static]

Definition at line 481 of file chan_misdn.c.

struct sched_context* misdn_tasks = NULL [static]

the main schedule context for stuff like l1 watcher, overlap dial, ...

Definition at line 478 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable(), misdn_tasks_destroy(), misdn_tasks_init(), misdn_tasks_remove(), and misdn_tasks_thread_func().

pthread_t misdn_tasks_thread [static]

Definition at line 479 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

Definition at line 3390 of file chan_misdn.c.

Referenced by load_module(), misdn_new(), and unload_module().

struct ast_channel_tech misdn_tech_wo_bridge [static]

Definition at line 3409 of file chan_misdn.c.

Referenced by misdn_new().

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

Definition at line 499 of file chan_misdn.c.

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

int prefformat = AST_FORMAT_ALAW [static]

Only alaw and mulaw is allowed for now.

Definition at line 504 of file chan_misdn.c.

Referenced by misdn_new(), and misdn_write().

ast_mutex_t release_lock

Definition at line 120 of file chan_misdn.c.

Referenced by load_module(), misdn_hangup(), and release_chan().

struct robin_list* robin = NULL [static]

Definition at line 431 of file chan_misdn.c.

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 1182 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 501 of file chan_misdn.c.

Referenced by load_module().


Generated on Thu Oct 8 00:59:28 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7