Tue Apr 28 22:50:26 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 = "f450f61f60e761b3aa089ebed76ca8a5" , .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 5777 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

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

int add_out_calls ( int  port  ) 

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

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

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

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

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

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

05532 {
05533    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05534    
05535    if (ch && ch->jb) {
05536       return misdn_jb_empty(ch->jb, buf, len);
05537    }
05538    
05539    return -1;
05540 }

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3760 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

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

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

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

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

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

Definition at line 3533 of file chan_misdn.c.

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

Referenced by import_ch().

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

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

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

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

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

Definition at line 3564 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

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

static int hanguptone_indicate ( struct chan_list cl  )  [static]

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

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

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

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

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

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

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

static int load_module ( void   )  [static]

Definition at line 5039 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, tracing, and unload_module().

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

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

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

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

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

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

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

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 2532 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(), start_bc_tones(), chan_list::state, stop_bc_tones(), misdn_bchannel::uu, and misdn_bchannel::uulen.

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

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(), ast_channel::name, misdn_bchannel::nt, ORG_MISDN, chan_list::originator, chan_list::other_ch, misdn_bchannel::out_cause, misdn_bchannel::pid, misdn_bchannel::port, start_bc_tones(), chan_list::state, and stop_indicate().

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       } else {
02436          chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
02437       }
02438       return -1;
02439    case AST_CONTROL_RING:
02440       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02441       return -1;
02442    case AST_CONTROL_RINGING:
02443       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02444       switch (p->state) {
02445       case MISDN_ALERTING:
02446          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);
02447          break;
02448       case MISDN_CONNECTED:
02449          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);
02450          return -1;
02451       default:
02452          p->state = MISDN_ALERTING;
02453          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02454          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02455 
02456          if (p->other_ch && p->other_ch->bc) {
02457             if (misdn_inband_avail(p->other_ch->bc)) {
02458                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02459                break;
02460             }
02461 
02462             if (!p->other_ch->bc->nt) {
02463                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02464                break;
02465             }
02466          }
02467 
02468          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02469          ast_setstate(ast, AST_STATE_RING);
02470 
02471          if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio)
02472             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02473          else 
02474             return -1;
02475       }
02476       break;
02477    case AST_CONTROL_ANSWER:
02478       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02479       start_bc_tones(p);
02480       break;
02481    case AST_CONTROL_TAKEOFFHOOK:
02482       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02483       return -1;
02484    case AST_CONTROL_OFFHOOK:
02485       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02486       return -1;
02487    case AST_CONTROL_FLASH:
02488       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02489       break;
02490    case AST_CONTROL_PROGRESS:
02491       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02492       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02493       break;
02494    case AST_CONTROL_PROCEEDING:
02495       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02496       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02497       break;
02498    case AST_CONTROL_CONGESTION:
02499       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02500 
02501       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02502       start_bc_tones(p);
02503       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02504 
02505       if (p->bc->nt) {
02506          hanguptone_indicate(p);
02507       }
02508       break;
02509    case -1 :
02510       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02511 
02512       stop_indicate(p);
02513 
02514       if (p->state == MISDN_CONNECTED) 
02515          start_bc_tones(p);
02516       break;
02517    case AST_CONTROL_HOLD:
02518       ast_moh_start(ast, data, p->mohinterpret); 
02519       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02520       break;
02521    case AST_CONTROL_UNHOLD:
02522       ast_moh_stop(ast);
02523       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02524       break;
02525    default:
02526       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02527    }
02528   
02529    return 0;
02530 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

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

05592 {
05593    ast_mutex_destroy(&jb->mutexjb);
05594    
05595    free(jb->ok);
05596    free(jb->samples);
05597    free(jb);
05598 }

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

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

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

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

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

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

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

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

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

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

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

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

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

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

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

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

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

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], "%d", &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, poll(), 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 3746 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().

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

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

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

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

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

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

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

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

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 3678 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, and chan_list::state.

Referenced by cb_events(), and misdn_hangup().

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

static int reload ( void   )  [static]

Definition at line 5198 of file chan_misdn.c.

References reload_config().

05199 {
05200    reload_config();
05201 
05202    return 0;
05203 }

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

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

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

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

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

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

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

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3147 of file chan_misdn.c.

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

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

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

static int stop_indicate ( struct chan_list cl  )  [static]

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

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

static int unload_module ( void   )  [static]

TE STUFF END

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

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

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

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

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

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

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


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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 5777 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 5777 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 3430 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(), 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 3392 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 3411 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.

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 Tue Apr 28 22:50:27 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7