Fri Jan 29 14:25:31 2010

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
#define TRANSFER_ON_HELD_CALL_HANGUP   1

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_DISCONNECTED, MISDN_CLEANING
}
enum  misdn_hold_state { MISDN_HOLD_IDLE, MISDN_HOLD_ACTIVE, MISDN_HOLD_TRANSFER, 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_hold_active_call (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_hold_call (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_hold_call_l3 (struct chan_list *list, unsigned long l3_id)
static void free_robin_list (void)
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, struct misdn_bchannel *bc)
static void 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 int misdn_attempt_transfer (struct chan_list *active_ch, struct chan_list *held_ch)
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 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 chan_list *ch, struct misdn_bchannel *bc)
static void release_chan_early (struct chan_list *ch)
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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 497 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 496 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(), release_chan(), and release_chan_early().

#define ORG_AST   1

Definition at line 139 of file chan_misdn.c.

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

#define ORG_MISDN   2

Definition at line 140 of file chan_misdn.c.

Referenced by cb_events(), and misdn_indication().

#define TRANSFER_ON_HELD_CALL_HANGUP   1

Definition at line 3582 of file chan_misdn.c.


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_DISCONNECTED  when connected
MISDN_CLEANING  when hangup from * but we were connected before

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_DISCONNECTED, /*!<  when connected */
00136    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00137 };

enum misdn_hold_state

Enumerator:
MISDN_HOLD_IDLE  HOLD not active
MISDN_HOLD_ACTIVE  Call is held
MISDN_HOLD_TRANSFER  Held call is being transferred
MISDN_HOLD_DISCONNECT  Held call is being disconnected

Definition at line 142 of file chan_misdn.c.

00142                       {
00143    MISDN_HOLD_IDLE,     /*!< HOLD not active */
00144    MISDN_HOLD_ACTIVE,      /*!< Call is held */
00145    MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
00146    MISDN_HOLD_DISCONNECT,  /*!< Held call is being disconnected */
00147 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 5948 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

00803 {
00804    int task_id;
00805 
00806    if (!misdn_tasks) {
00807       misdn_tasks_init();
00808    }
00809    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00810    misdn_tasks_wakeup();
00811 
00812    return task_id;
00813 }

int add_in_calls ( int  port  ) 

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

04074 {
04075    int max_in_calls;
04076    
04077    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04078    misdn_in_calls[port]++;
04079 
04080    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04081       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04082       return misdn_in_calls[port] - max_in_calls;
04083    }
04084    
04085    return 0;
04086 }

int add_out_calls ( int  port  ) 

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

04089 {
04090    int max_out_calls;
04091    
04092    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04093 
04094    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04095       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04096       return (misdn_out_calls[port] + 1) - max_out_calls;
04097    }
04098 
04099    misdn_out_calls[port]++;
04100    
04101    return 0;
04102 }

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

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

00615 {
00616    unsigned index;
00617 
00618    for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
00619       if (allowed_bearers_array[index].cap == cap) {
00620          return allowed_bearers_array[index].display;
00621       }
00622    }  /* end for */
00623 
00624    return "Unknown Bearer";
00625 }

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

Definition at line 4128 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_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_deactivate_generator(), ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pickup_call(), ast_pickup_ext(), AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_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, 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_hold_active_call(), find_hold_call(), find_hold_call_l3(), free, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, hangup_chan(), ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, 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, manager_isdn_get_info(), MISDN_ALERTING, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, misdn_attempt_transfer(), 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_HOLD_ACTIVE, MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, 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_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, 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, misdn_bchannel::screen, misdn_bchannel::sending_complete, start_bc_tones(), start_pbx(), hold_info::state, chan_list::state, stop_bc_tones(), stop_indicate(), 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().

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

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

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

05703 {
05704    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05705    
05706    if (ch && ch->jb) {
05707       return misdn_jb_empty(ch->jb, buf, len);
05708    }
05709    
05710    return -1;
05711 }

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

Definition at line 5885 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_hold_call(), import_ch(), init_chan_list(), load_module(), misdn_answer(), misdn_attempt_transfer(), 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_write(), print_bearer(), print_facility(), process_ast_dsp(), read_config(), release_chan(), send_cause2ast(), start_pbx(), stop_indicate(), update_config(), and update_name().

05886 {
05887    va_list ap;
05888    char buf[1024];
05889    char port_buf[8];
05890 
05891    if (! ((0 <= port) && (port <= max_ports))) {
05892       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05893       port = 0;
05894       level = -1;
05895    }
05896 
05897    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05898 
05899    va_start(ap, tmpl);
05900    vsnprintf(buf, sizeof(buf), tmpl, ap);
05901    va_end(ap);
05902 
05903    if (level == -1)
05904       ast_log(LOG_WARNING, "%s", buf);
05905 
05906    else if (misdn_debug_only[port] ? 
05907          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
05908        : level <= misdn_debug[port]) {
05909       
05910       ast_console_puts(port_buf);
05911       ast_console_puts(buf);
05912    }
05913    
05914    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05915       time_t tm = time(NULL);
05916       char *tmp = ctime(&tm), *p;
05917 
05918       FILE *fp = fopen(global_tracefile, "a+");
05919 
05920       p = strchr(tmp, '\n');
05921       if (p)
05922          *p = ':';
05923       
05924       if (!fp) {
05925          ast_console_puts("Error opening Tracefile: [ ");
05926          ast_console_puts(global_tracefile);
05927          ast_console_puts(" ] ");
05928          
05929          ast_console_puts(strerror(errno));
05930          ast_console_puts("\n");
05931          return ;
05932       }
05933       
05934       fputs(tmp, fp);
05935       fputs(" ", fp);
05936       fputs(port_buf, fp);
05937       fputs(" ", fp);
05938       fputs(buf, fp);
05939 
05940       fclose(fp);
05941    }
05942 }

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

Definition at line 3634 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 release_chan(), and release_chan_early().

03635 {
03636    struct chan_list *help;
03637 
03638    if (chan->dsp) 
03639       ast_dsp_free(chan->dsp);
03640    if (chan->trans)
03641       ast_translator_free_path(chan->trans);
03642 
03643    ast_mutex_lock(&cl_te_lock);
03644    if (!*list) {
03645       ast_mutex_unlock(&cl_te_lock);
03646       return;
03647    }
03648   
03649    if (*list == chan) {
03650       *list = (*list)->next;
03651       ast_mutex_unlock(&cl_te_lock);
03652       return;
03653    }
03654   
03655    for (help = *list; help->next; help = help->next) {
03656       if (help->next == chan) {
03657          help->next = help->next->next;
03658          ast_mutex_unlock(&cl_te_lock);
03659          return;
03660       }
03661    }
03662    
03663    ast_mutex_unlock(&cl_te_lock);
03664 }

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

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

03619 {
03620    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03621   
03622    ast_mutex_lock(&cl_te_lock);
03623    if (!*list) {
03624       *list = chan;
03625    } else {
03626       struct chan_list *help = *list;
03627       for (; help->next; help = help->next); 
03628       help->next = chan;
03629    }
03630    chan->next = NULL;
03631    ast_mutex_unlock(&cl_te_lock);
03632 }

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

Definition at line 1610 of file chan_misdn.c.

References complete_ch_helper().

01611 {
01612    return complete_ch_helper(line, word, pos, state, 3);
01613 }

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

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

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

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

Definition at line 1615 of file chan_misdn.c.

References strdup.

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

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

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

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

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

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

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

Definition at line 1852 of file chan_misdn.c.

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

Referenced by read_config().

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

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

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

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

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

Definition at line 3892 of file chan_misdn.c.

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

Referenced by cb_events().

03893 {
03894    char predial[256]="";
03895    char *p = predial;
03896   
03897    struct ast_frame fr;
03898 
03899    strncpy(predial, ast->exten, sizeof(predial) -1 );
03900 
03901    ch->state = MISDN_DIALING;
03902 
03903    if (!ch->noautorespond_on_setup) {
03904       if (bc->nt) {
03905          int ret; 
03906          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03907       } else {
03908          int ret;
03909          if ( misdn_lib_is_ptp(bc->port)) {
03910             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03911          } else {
03912             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03913          }
03914       }
03915    } else {
03916       ch->state = MISDN_INCOMING_SETUP;
03917    }
03918 
03919    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);
03920   
03921    strcpy(ast->exten, "s");
03922  
03923    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03924       ast = NULL;
03925       bc->out_cause = AST_CAUSE_UNALLOCATED;
03926       hangup_chan(ch, bc);
03927       hanguptone_indicate(ch);
03928 
03929       if (bc->nt)
03930          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03931       else
03932          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03933    }
03934   
03935   
03936    while (!ast_strlen_zero(p) ) {
03937       fr.frametype = AST_FRAME_DTMF;
03938       fr.subclass = *p;
03939       fr.src = NULL;
03940       fr.data = NULL;
03941       fr.datalen = 0;
03942       fr.samples = 0;
03943       fr.mallocd = 0;
03944       fr.offset = 0;
03945       fr.delivery = ast_tv(0,0);
03946 
03947       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03948          ast_queue_frame(ch->ast, &fr);
03949       }
03950       p++;
03951    }
03952 }

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

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

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

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

04048 {
04049    char tmp[32];
04050    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04051    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04052    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04053 
04054    if (bc->sending_complete) {
04055       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04056       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04057    }
04058 
04059    if (bc->urate) {
04060       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04061       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04062    }
04063 
04064    if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
04065       bc->uu[bc->uulen] = 0;
04066       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04067    }
04068 
04069    if (!ast_strlen_zero(bc->keypad)) 
04070       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04071 }

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

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

03529 {
03530    struct chan_list *help = list;
03531    for (; help; help = help->next) {
03532       if (help->bc == bc) return help;
03533    }
03534 
03535    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03536 
03537    return NULL;
03538 }

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

Definition at line 3540 of file chan_misdn.c.

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

Referenced by import_ch().

03541 {
03542    struct chan_list *help = list;
03543    for (; help; help = help->next) {
03544       if ( help->bc && (help->bc->pid == pid) ) return help;
03545    }
03546 
03547    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03548 
03549    return NULL;
03550 }

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

Definition at line 3598 of file chan_misdn.c.

References chan_list::ast, chan_list::bc, chan_list::hold, MISDN_ALERTING, MISDN_CONNECTED, MISDN_HOLD_IDLE, MISDN_PROCEEDING, MISDN_PROGRESS, chan_list::next, misdn_bchannel::port, chan_list::state, and hold_info::state.

Referenced by cb_events().

03599 {
03600    for (; list; list = list->next) {
03601       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
03602          && list->ast) {
03603          switch (list->state) {
03604          case MISDN_PROCEEDING:
03605          case MISDN_PROGRESS:
03606          case MISDN_ALERTING:
03607          case MISDN_CONNECTED:
03608             return list;
03609          default:
03610             break;
03611          }
03612       }
03613    }
03614    return NULL;
03615 }

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

Definition at line 3552 of file chan_misdn.c.

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

Referenced by cb_events().

03553 {
03554    struct chan_list *help = list;
03555 
03556    if (bc->pri) return NULL;
03557 
03558    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03559    for (;help; help = help->next) {
03560       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
03561       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port)
03562          return help;
03563    }
03564    chan_misdn_log(6, bc->port, "$$$ find_hold_call: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03565 
03566    return NULL;
03567 }

static struct chan_list* find_hold_call_l3 ( struct chan_list list,
unsigned long  l3_id 
) [static]

Definition at line 3570 of file chan_misdn.c.

References chan_list::hold, chan_list::l3id, MISDN_HOLD_IDLE, chan_list::next, and hold_info::state.

Referenced by cb_events().

03571 {
03572    struct chan_list *help = list;
03573 
03574    for (; help; help = help->next) {
03575       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id)
03576          return help;
03577    }
03578 
03579    return NULL;
03580 }

static void free_robin_list ( void   )  [static]

Definition at line 441 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

00442 {
00443    struct robin_list *r;
00444    struct robin_list *next;
00445 
00446    for (r = robin, robin = NULL; r; r = next) {
00447       next = r->next;
00448       free(r->group);
00449       free(r);
00450    }
00451 }

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

Definition at line 571 of file chan_misdn.c.

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

Referenced by misdn_bridge().

00572 {
00573    struct chan_list *tmp;
00574   
00575    for (tmp=cl_te; tmp; tmp = tmp->next) {
00576       if ( tmp->ast == ast ) return tmp;
00577    }
00578   
00579    return NULL;
00580 }

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

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

00583 {
00584    struct chan_list *tmp;
00585   
00586    for (tmp=cl_te; tmp; tmp = tmp->next) {
00587       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
00588    }
00589   
00590    return NULL;
00591 }

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

Definition at line 453 of file chan_misdn.c.

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

Referenced by misdn_request().

00454 {
00455    struct robin_list *new;
00456    struct robin_list *iter = robin;
00457    for (; iter; iter = iter->next) {
00458       if (!strcasecmp(iter->group, group)) {
00459          return iter;
00460       }
00461    }
00462    new = calloc(1, sizeof(*new));
00463    if (!new) {
00464       return NULL;
00465    }
00466    new->group = strdup(group);
00467    if (!new->group) {
00468       free(new);
00469       return NULL;
00470    }
00471    new->port = 0;
00472    new->channel = 0;
00473    if (robin) {
00474       new->next = robin;
00475       robin->prev = new;
00476    }
00477    robin = new;
00478    return robin;
00479 }

static void hangup_chan ( struct chan_list ch,
struct misdn_bchannel bc 
) [static]

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

03682 {
03683    int port;
03684 
03685    if (!ch) {
03686       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03687       return;
03688    }
03689 
03690    port = bc->port;
03691    cb_log(5, port, "hangup_chan called\n");
03692 
03693    if (ch->need_hangup) {
03694       cb_log(2, port, " --> hangup\n");
03695       ch->need_hangup = 0;
03696       ch->need_queue_hangup = 0;
03697       if (ch->ast) {
03698          send_cause2ast(ch->ast, bc, ch);
03699          ast_hangup(ch->ast);
03700       }
03701       return;
03702    }
03703 
03704    if (!ch->need_queue_hangup) {
03705       cb_log(2, port, " --> No need to queue hangup\n");
03706    }
03707 
03708    ch->need_queue_hangup = 0;
03709    if (ch->ast) {
03710       send_cause2ast(ch->ast, bc, ch);
03711       ast_queue_hangup(ch->ast);
03712       cb_log(2, port, " --> queue_hangup\n");
03713    } else {
03714       cb_log(1, port, "Cannot hangup chan, no ast\n");
03715    }
03716 }

static void hanguptone_indicate ( struct chan_list cl  )  [static]

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

03117 {
03118    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03119 }

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

04014 {
04015    const char *tmp;
04016 
04017    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04018    if (tmp) {
04019       ch->other_pid = atoi(tmp);
04020       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04021       if (ch->other_pid > 0) {
04022          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04023          if (ch->other_ch)
04024             ch->other_ch->other_ch = ch;
04025       }
04026    }
04027 
04028    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04029    if (tmp && (atoi(tmp) == 1)) {
04030       bc->sending_complete = 1;
04031    }
04032 
04033    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04034    if (tmp) {
04035       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04036       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04037       bc->uulen = strlen(bc->uu);
04038    }
04039 
04040    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04041    if (tmp) {
04042       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04043    }
04044 }

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

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

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

static int load_module ( void   )  [static]

Definition at line 5189 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, free, 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().

05190 {
05191    int i, port;
05192    int ntflags = 0, ntkc = 0;
05193    char ports[256] = "";
05194    char tempbuf[BUFFERSIZE + 1];
05195    char ntfile[BUFFERSIZE + 1];
05196    struct misdn_lib_iface iface = {
05197       .cb_event = cb_events,
05198       .cb_log = chan_misdn_log,
05199       .cb_jb_empty = chan_misdn_jb_empty,
05200    };
05201 
05202    max_ports = misdn_lib_maxports_get();
05203    
05204    if (max_ports <= 0) {
05205       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05206       return AST_MODULE_LOAD_DECLINE;
05207    }
05208    
05209    if (misdn_cfg_init(max_ports)) {
05210       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05211       return AST_MODULE_LOAD_DECLINE;
05212    }
05213    g_config_initialized = 1;
05214    
05215    misdn_debug = (int *) malloc(sizeof(int) * (max_ports + 1));
05216    if (!misdn_debug) {
05217       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05218       return AST_MODULE_LOAD_DECLINE;
05219    }
05220    misdn_ports = (int *) malloc(sizeof(int) * (max_ports + 1));
05221    if (!misdn_ports) {
05222       free(misdn_debug);
05223       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05224       return AST_MODULE_LOAD_DECLINE;
05225    }
05226    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
05227    for (i = 1; i <= max_ports; i++) {
05228       misdn_debug[i] = misdn_debug[0];
05229       misdn_ports[i] = i;
05230    }
05231    *misdn_ports = 0;
05232    misdn_debug_only = (int *) calloc(max_ports + 1, sizeof(int));
05233    if (!misdn_debug_only) {
05234       free(misdn_ports);
05235       free(misdn_debug);
05236       ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
05237       return AST_MODULE_LOAD_DECLINE;
05238    }
05239 
05240    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
05241    if (!ast_strlen_zero(tempbuf))
05242       tracing = 1;
05243 
05244    misdn_in_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05245    if (!misdn_in_calls) {
05246       free(misdn_debug_only);
05247       free(misdn_ports);
05248       free(misdn_debug);
05249       ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
05250       return AST_MODULE_LOAD_DECLINE;
05251    }
05252    misdn_out_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05253    if (!misdn_out_calls) {
05254       free(misdn_in_calls);
05255       free(misdn_debug_only);
05256       free(misdn_ports);
05257       free(misdn_debug);
05258       ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
05259       return AST_MODULE_LOAD_DECLINE;
05260    }
05261 
05262    for (i = 1; i <= max_ports; i++) {
05263       misdn_in_calls[i] = 0;
05264       misdn_out_calls[i] = 0;
05265    }
05266 
05267    ast_mutex_init(&cl_te_lock);
05268    ast_mutex_init(&release_lock);
05269 
05270    misdn_cfg_update_ptp();
05271    misdn_cfg_get_ports_string(ports);
05272 
05273    if (!ast_strlen_zero(ports))
05274       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05275    if (misdn_lib_init(ports, &iface, NULL))
05276       chan_misdn_log(0, 0, "No te ports initialized\n");
05277 
05278    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
05279    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
05280    misdn_lib_nt_debug_init(ntflags, ntfile);
05281 
05282    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(int));
05283    misdn_lib_nt_keepcalls(ntkc);
05284 
05285    if (ast_channel_register(&misdn_tech)) {
05286       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05287       unload_module();
05288       return -1;
05289    }
05290   
05291    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05292 
05293    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05294       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05295       "Sets mISDN opts. and optargs\n"
05296       "\n"
05297       "The available options are:\n"
05298       "    a - Have Asterisk detect DTMF tones on called channel\n"
05299       "    c - Make crypted outgoing call, optarg is keyindex\n"
05300       "    d - Send display text to called phone, text is the optarg\n"
05301       "    e - Perform echo cancelation on this channel,\n"
05302       "        takes taps as optarg (32,64,128,256)\n"
05303       "   e! - Disable echo cancelation on this channel\n"
05304       "    f - Enable fax detection\n"
05305       "    h - Make digital outgoing call\n"
05306       "   h1 - Make HDLC mode digital outgoing call\n"
05307       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05308       "        they will be transported inband.\n"
05309       "   jb - Set jitter buffer length, optarg is length\n"
05310       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05311       "   jn - Disable jitter buffer\n"
05312       "    n - Disable mISDN DSP on channel.\n"
05313       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05314       "    p - Caller ID presentation,\n"
05315       "        optarg is either 'allowed' or 'restricted'\n"
05316       "    s - Send Non-inband DTMF as inband\n"
05317       "   vr - Rx gain control, optarg is gain\n"
05318       "   vt - Tx gain control, optarg is gain\n"
05319       );
05320 
05321    
05322    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05323              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05324              "Sends the Facility Message FACILITY_TYPE with \n"
05325              "the given Arguments to the current ISDN Channel\n"
05326              "Supported Facilities are:\n"
05327              "\n"
05328              "type=calldeflect args=Nr where to deflect\n"
05329       );
05330 
05331 
05332    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05333              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05334              "Checks if the L2 and L1 are up on either the given <port> or\n"
05335              "on the ports in the group with <groupname>\n"
05336              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05337              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05338              "\n"
05339              "This application, ensures the L1/L2 state of the Ports in a group\n"
05340              "it is intended to make the pmp_l1_check option redundant and to\n"
05341              "fix a buggy switch config from your provider\n"
05342              "\n"
05343              "a sample dialplan would look like:\n\n"
05344              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05345              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05346              "\n"
05347       );
05348 
05349 
05350    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
05351 
05352    /* start the l1 watchers */
05353    
05354    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05355       int l1timeout;
05356       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05357       if (l1timeout) {
05358          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05359          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05360       }
05361    }
05362 
05363    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05364 
05365    return 0;
05366 }

static int misdn_answer ( struct ast_channel ast  )  [static]

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

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

static int misdn_attempt_transfer ( struct chan_list active_ch,
struct chan_list held_ch 
) [static]

Definition at line 3857 of file chan_misdn.c.

References chan_list::ast, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_UNHOLD, ast_queue_control(), chan_misdn_log(), chan_list::hold, MISDN_ALERTING, MISDN_CONNECTED, MISDN_HOLD_TRANSFER, MISDN_PROCEEDING, MISDN_PROGRESS, ast_channel::name, hold_info::port, hold_info::state, and chan_list::state.

Referenced by cb_events().

03858 {
03859    int retval;
03860    struct ast_channel *bridged;
03861 
03862    switch (active_ch->state) {
03863    case MISDN_PROCEEDING:
03864    case MISDN_PROGRESS:
03865    case MISDN_ALERTING:
03866    case MISDN_CONNECTED:
03867       break;
03868    default:
03869       return -1;
03870    }
03871 
03872    bridged = ast_bridged_channel(held_ch->ast);
03873    if (bridged) {
03874       ast_queue_control(held_ch->ast, AST_CONTROL_UNHOLD);
03875       held_ch->hold.state = MISDN_HOLD_TRANSFER;
03876 
03877       chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
03878          held_ch->ast->name, active_ch->ast->name);
03879       retval = ast_channel_masquerade(active_ch->ast, bridged);
03880    } else {
03881       /*
03882        * Could not transfer.  Held channel is not bridged anymore.
03883        * Held party probably got tired of waiting and hung up.
03884        */
03885       retval = -1;
03886    }
03887 
03888    return retval;
03889 }

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

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

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

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

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

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

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

05425 {
05426    char group[BUFFERSIZE + 1];
05427    char *port_str;
05428    int port = 0;
05429    int timeout;
05430    int dowait = 0;
05431    int port_up;
05432 
05433    AST_DECLARE_APP_ARGS(args,
05434          AST_APP_ARG(grouppar);
05435          AST_APP_ARG(timeout);
05436    );
05437 
05438    if (ast_strlen_zero((char *)data)) {
05439       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05440       return -1;
05441    }
05442 
05443    AST_STANDARD_APP_ARGS(args, data);
05444 
05445    if (args.argc != 2) {
05446       ast_log(LOG_WARNING, "Wrong argument count\n");
05447       return 0;
05448    }
05449 
05450    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05451    timeout = atoi(args.timeout);
05452    port_str = args.grouppar;
05453 
05454    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05455       /* We make a group call lets checkout which ports are in my group */
05456       port_str += 2;
05457       ast_copy_string(group, port_str, sizeof(group));
05458       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05459 
05460       for ( port = misdn_cfg_get_next_port(port); 
05461          port > 0;
05462          port = misdn_cfg_get_next_port(port)) {
05463          char cfg_group[BUFFERSIZE + 1];
05464 
05465          chan_misdn_log(2, 0, "trying port %d\n", port);
05466 
05467          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05468 
05469          if (!strcasecmp(cfg_group, group)) {
05470             port_up = misdn_lib_port_up(port, 1);
05471 
05472             if (!port_up) {
05473                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05474                misdn_lib_get_port_up(port);
05475                dowait = 1;
05476             }
05477          }
05478       }
05479 
05480    } else {
05481       port = atoi(port_str);
05482       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05483       port_up = misdn_lib_port_up(port, 1);
05484       if (!port_up) {
05485          misdn_lib_get_port_up(port);
05486          dowait = 1;
05487       }
05488    }
05489 
05490    if (dowait) {
05491       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05492       sleep(timeout);
05493    }
05494 
05495    return 0;
05496 }

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

Definition at line 2326 of file chan_misdn.c.

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

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

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

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

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

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

05380 {
05381    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05382    char *tok, *tokb;
05383 
05384    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05385    
05386    if (strcasecmp(chan->tech->type, "mISDN")) {
05387       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05388       return -1;
05389    }
05390    
05391    if (ast_strlen_zero((char *)data)) {
05392       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05393       return -1;
05394    }
05395 
05396    tok = strtok_r((char*) data, "|", &tokb) ;
05397 
05398    if (!tok) {
05399       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05400       return -1;
05401    }
05402 
05403    if (!strcasecmp(tok, "calldeflect")) {
05404       tok = strtok_r(NULL, "|", &tokb) ;
05405       
05406       if (!tok) {
05407          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05408       }
05409 
05410       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05411          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05412          return 0; 
05413       }
05414       ch->bc->fac_out.Function = Fac_CD;
05415       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05416       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05417    } else {
05418       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05419    }
05420 
05421    return 0;
05422 }

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

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

02393 {
02394    struct chan_list *p;
02395 
02396    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02397 
02398    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);
02399 
02400    p->ast = ast;
02401 
02402    return 0;
02403 }

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

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

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

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2535 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_copy_string(), ast_log(), AST_STATE_RESERVED, chan_list::bc, misdn_bchannel::cause, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, ast_channel::exten, ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, 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_HOLD_IDLE, MISDN_INCOMING_SETUP, misdn_lib_find_held_bc(), misdn_lib_release(), misdn_lib_send_event(), MISDN_NOTHING, MISDN_PROCEEDING, MISDN_PROGRESS, 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, misdn_bchannel::port, hold_info::port, misdn_bchannel::progress_indicator, release_chan(), release_chan_early(), start_bc_tones(), chan_list::state, hold_info::state, stop_bc_tones(), misdn_bchannel::uu, misdn_bchannel::uulen, and var.

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

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

Definition at line 2407 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, hanguptone_indicate(), chan_list::hold, chan_list::incoming_early_audio, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, MISDN_HOLD_IDLE, 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, hold_info::state, and stop_indicate().

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

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

Definition at line 5762 of file chan_misdn.c.

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

Referenced by config_jitterbuffer(), release_chan(), and release_chan_early().

05763 {
05764    ast_mutex_destroy(&jb->mutexjb);
05765    
05766    free(jb->ok);
05767    free(jb->samples);
05768    free(jb);
05769 }

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

05833 {
05834    int i, wp, rp, read = 0;
05835 
05836    ast_mutex_lock(&jb->mutexjb);
05837 
05838    rp = jb->rp;
05839    wp = jb->wp;
05840 
05841    if (jb->state_empty) {  
05842       for (i = 0; i < len; i++) {
05843          if (wp == rp) {
05844             jb->rp = rp;
05845             jb->state_empty = 0;
05846 
05847             ast_mutex_unlock(&jb->mutexjb);
05848 
05849             return read;
05850          } else {
05851             if (jb->ok[rp] == 1) {
05852                data[i] = jb->samples[rp];
05853                jb->ok[rp] = 0;
05854                rp = (rp != jb->size - 1) ? rp + 1 : 0;
05855                read += 1;
05856             }
05857          }
05858       }
05859 
05860       if (wp >= rp)
05861          jb->state_buffer = wp - rp;
05862       else
05863          jb->state_buffer = jb->size - rp + wp;
05864       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05865 
05866       jb->rp = rp;
05867    } else
05868       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05869 
05870    ast_mutex_unlock(&jb->mutexjb);
05871 
05872    return read;
05873 }

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

05774 {
05775    int i, j, rp, wp;
05776 
05777    if (!jb || ! data)
05778       return 0;
05779 
05780    ast_mutex_lock(&jb->mutexjb);
05781    
05782    wp = jb->wp;
05783    rp = jb->rp;
05784    
05785    for (i = 0; i < len; i++) {
05786       jb->samples[wp] = data[i];
05787       jb->ok[wp] = 1;
05788       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05789 
05790       if (wp == jb->rp)
05791          jb->state_full = 1;
05792    }
05793 
05794    if (wp >= rp)
05795       jb->state_buffer = wp - rp;
05796    else
05797       jb->state_buffer = jb->size - rp + wp;
05798    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05799 
05800    if (jb->state_full) {
05801       jb->wp = wp;
05802 
05803       rp = wp;
05804       for (j = 0; j < jb->upper_threshold; j++)
05805          rp = (rp != 0) ? rp - 1 : jb->size - 1;
05806       jb->rp = rp;
05807       jb->state_full = 0;
05808       jb->state_empty = 1;
05809 
05810       ast_mutex_unlock(&jb->mutexjb);
05811 
05812       return -1;
05813    }
05814 
05815    if (!jb->state_empty) {
05816       jb->bytes_wrote += len;
05817       if (jb->bytes_wrote >= jb->upper_threshold) {
05818          jb->state_empty = 1;
05819          jb->bytes_wrote = 0;
05820       }
05821    }
05822    jb->wp = wp;
05823 
05824    ast_mutex_unlock(&jb->mutexjb);
05825    
05826    return 0;
05827 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

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

05722 {
05723    int i;
05724    struct misdn_jb *jb;
05725 
05726    jb = malloc(sizeof(struct misdn_jb));
05727    if (!jb) {
05728        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05729        return NULL;
05730    }
05731    jb->size = size;
05732    jb->upper_threshold = upper_threshold;
05733    jb->wp = 0;
05734    jb->rp = 0;
05735    jb->state_full = 0;
05736    jb->state_empty = 0;
05737    jb->bytes_wrote = 0;
05738    jb->samples = malloc(size * sizeof(char));
05739    if (!jb->samples) {
05740       free(jb);
05741       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05742       return NULL;
05743    }
05744 
05745    jb->ok = malloc(size * sizeof(char));
05746    if (!jb->ok) {
05747       free(jb->samples);
05748       free(jb);
05749       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05750       return NULL;
05751    }
05752 
05753    for (i = 0; i < size; i++)
05754       jb->ok[i] = 0;
05755 
05756    ast_mutex_init(&jb->mutexjb);
05757 
05758    return jb;
05759 }

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

Definition at line 830 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

00831 {
00832    misdn_lib_isdn_l1watcher(*(int *)data);
00833    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00834    return 1;
00835 }

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

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

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

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

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

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

Definition at line 994 of file chan_misdn.c.

References misdn_lib_port_block(), and RESULT_SHOWUSAGE.

00995 {
00996    int port;
00997 
00998    if (argc != 4)
00999       return RESULT_SHOWUSAGE;
01000   
01001    port = atoi(argv[3]);
01002 
01003    misdn_lib_port_block(port);
01004 
01005    return 0;
01006 }

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

Definition at line 1065 of file chan_misdn.c.

References misdn_lib_get_port_down(), and RESULT_SHOWUSAGE.

01066 {
01067    int port;
01068 
01069    if (argc != 4)
01070       return RESULT_SHOWUSAGE;
01071    
01072    port = atoi(argv[3]);
01073    
01074    misdn_lib_get_port_down(port);
01075   
01076    return 0;
01077 }

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

Definition at line 1008 of file chan_misdn.c.

References misdn_lib_port_unblock(), and RESULT_SHOWUSAGE.

01009 {
01010    int port;
01011   
01012    if (argc != 4)
01013       return RESULT_SHOWUSAGE;
01014   
01015    port = atoi(argv[3]);
01016 
01017    misdn_lib_port_unblock(port);
01018 
01019    return 0;
01020 }

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

Definition at line 1051 of file chan_misdn.c.

References misdn_lib_get_port_up(), and RESULT_SHOWUSAGE.

01052 {
01053    int port;
01054    
01055    if (argc != 4)
01056       return RESULT_SHOWUSAGE;
01057    
01058    port = atoi(argv[3]);
01059    
01060    misdn_lib_get_port_up(port);
01061   
01062    return 0;
01063 }

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

Definition at line 2782 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, chan_list::hold, len(), ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, MISDN_HOLD_IDLE, ast_frame::offset, chan_list::pipe, misdn_bchannel::port, process_ast_dsp(), ast_frame::samples, ast_frame::src, hold_info::state, ast_frame::subclass, and t.

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

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

Definition at line 1244 of file chan_misdn.c.

References ast_cli(), and reload_config().

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

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

Definition at line 3179 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, free, 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().

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

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

Definition at line 1037 of file chan_misdn.c.

References misdn_lib_pid_restart(), and RESULT_SHOWUSAGE.

01038 {
01039    int pid;
01040   
01041    if (argc != 4)
01042       return RESULT_SHOWUSAGE;
01043   
01044    pid = atoi(argv[3]);
01045 
01046    misdn_lib_pid_restart(pid);
01047 
01048    return 0;
01049 }

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

Definition at line 1023 of file chan_misdn.c.

References misdn_lib_port_restart(), and RESULT_SHOWUSAGE.

01024 {
01025    int port;
01026   
01027    if (argc != 4)
01028       return RESULT_SHOWUSAGE;
01029   
01030    port = atoi(argv[3]);
01031 
01032    misdn_lib_port_restart(port);
01033 
01034    return 0;
01035 }

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

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

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

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

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

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

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

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

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

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

Definition at line 1470 of file chan_misdn.c.

References misdn_lib_send_restart(), and RESULT_SHOWUSAGE.

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

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

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

03385 {
03386    struct chan_list *tmp = chan->tech_pvt;
03387    
03388    if (tmp && tmp->bc) {
03389       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03390       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03391    } else {
03392       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03393       return -1;
03394    }
03395    
03396    return 0;
03397 }

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

Definition at line 987 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

00988 {
00989    if (argc != 5) return RESULT_SHOWUSAGE; 
00990 
00991    return 0;
00992 }

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

Definition at line 924 of file chan_misdn.c.

References ast_cli(), and RESULT_SHOWUSAGE.

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

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

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

05499 {
05500    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05501    char *tok, *tokb;
05502    int  keyidx = 0;
05503    int rxgain = 0;
05504    int txgain = 0;
05505    int change_jitter = 0;
05506 
05507    if (strcasecmp(chan->tech->type, "mISDN")) {
05508       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05509       return -1;
05510    }
05511    
05512    if (ast_strlen_zero((char *)data)) {
05513       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05514       return -1;
05515    }
05516 
05517    for (tok = strtok_r((char*) data, ":", &tokb);
05518         tok;
05519         tok = strtok_r(NULL, ":", &tokb) ) {
05520       int neglect = 0;
05521 
05522       if (tok[0] == '!' ) {
05523          neglect = 1;
05524          tok++;
05525       }
05526       
05527       switch(tok[0]) {
05528          
05529       case 'd' :
05530          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05531          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05532          break;
05533          
05534       case 'n':
05535          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05536          ch->bc->nodsp = 1;
05537          break;
05538 
05539       case 'j':
05540          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05541          tok++;
05542          change_jitter = 1;
05543 
05544          switch ( tok[0] ) {
05545          case 'b':
05546             ch->jb_len = atoi(++tok);
05547             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05548             break;
05549          case 't' :
05550             ch->jb_upper_threshold = atoi(++tok);
05551             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05552             break;
05553          case 'n':
05554             ch->bc->nojitter = 1;
05555             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05556             break;
05557          default:
05558             ch->jb_len = 4000;
05559             ch->jb_upper_threshold = 0;
05560             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05561             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05562          }
05563          break;
05564       case 'v':
05565          tok++;
05566 
05567          switch (tok[0]) {
05568          case 'r' :
05569             rxgain = atoi(++tok);
05570             if (rxgain < -8)
05571                rxgain = -8;
05572             if (rxgain > 8)
05573                rxgain = 8;
05574             ch->bc->rxgain = rxgain;
05575             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05576             break;
05577          case 't':
05578             txgain = atoi(++tok);
05579             if (txgain < -8)
05580                txgain = -8;
05581             if (txgain > 8)
05582                txgain = 8;
05583             ch->bc->txgain = txgain;
05584             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05585             break;
05586          }
05587          break;
05588       
05589       case 'c':
05590          keyidx = atoi(++tok);
05591          {
05592             char keys[4096];
05593             char *key = NULL, *tmp = keys;
05594             int i;
05595             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05596 
05597             for (i = 0; i < keyidx; i++) {
05598                key = strsep(&tmp, ",");
05599             }
05600 
05601             if (key) {
05602                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05603             }
05604 
05605             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05606             break;
05607          }
05608       case 'e':
05609          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05610          
05611          if (neglect) {
05612             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05613 #ifdef MISDN_1_2
05614             *ch->bc->pipeline = 0;
05615 #else
05616             ch->bc->ec_enable = 0;
05617 #endif
05618          } else {
05619 #ifdef MISDN_1_2
05620             update_pipeline_config(ch->bc);
05621 #else
05622             ch->bc->ec_enable = 1;
05623             ch->bc->orig = ch->originator;
05624             tok++;
05625             if (*tok) {
05626                ch->bc->ec_deftaps = atoi(tok);
05627             }
05628 #endif
05629          }
05630          
05631          break;
05632       case 'h':
05633          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05634          
05635          if (strlen(tok) > 1 && tok[1] == '1') {
05636             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05637             if (!ch->bc->hdlc) {
05638                ch->bc->hdlc = 1;
05639             }
05640          }
05641          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05642          break;
05643             
05644       case 's':
05645          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05646          ch->bc->send_dtmf = 1;
05647          break;
05648          
05649       case 'f':
05650          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05651          ch->faxdetect = 1;
05652          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05653          break;
05654 
05655       case 'a':
05656          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05657          ch->ast_dsp = 1;
05658          break;
05659 
05660       case 'p':
05661          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05662          /* CRICH: callingpres!!! */
05663          if (strstr(tok,"allowed")) {
05664             ch->bc->pres = 0;
05665          } else if (strstr(tok, "restricted")) {
05666             ch->bc->pres = 1;
05667          } else if (strstr(tok, "not_screened")) {
05668             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05669             ch->bc->pres = 1;
05670          }
05671          break;
05672       case 'i' :
05673          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05674          ch->ignore_dtmf=1;
05675          break;
05676       default:
05677          break;
05678       }
05679    }
05680 
05681    if (change_jitter)
05682       config_jitterbuffer(ch);
05683 
05684    if (ch->faxdetect || ch->ast_dsp) {
05685       if (!ch->dsp)
05686          ch->dsp = ast_dsp_new();
05687       if (ch->dsp)
05688          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
05689       if (!ch->trans)
05690          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05691    }
05692 
05693    if (ch->ast_dsp) {
05694       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05695       ch->bc->nodsp = 1;
05696    }
05697    
05698    return 0;
05699 }

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

Definition at line 1381 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

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

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

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

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

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

Definition at line 1306 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, chan_list::l3id, misdn_dump_chanlist(), MISDN_HOLD_IDLE, chan_list::next, misdn_bchannel::pid, hold_info::port, print_bc_info(), and hold_info::state.

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

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

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

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

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

Definition at line 1420 of file chan_misdn.c.

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

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

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

Definition at line 1406 of file chan_misdn.c.

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

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

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

Definition at line 1391 of file chan_misdn.c.

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

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

static int misdn_tasks_add ( 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 load_module().

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

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

Definition at line 820 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

00821 {
00822    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00823 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 785 of file chan_misdn.c.

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

Referenced by unload_module().

00786 {
00787    if (misdn_tasks) {
00788       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
00789       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
00790          cb_log(4, 0, "Joining misdn_tasks thread\n");
00791          pthread_join(misdn_tasks_thread, NULL);
00792       }
00793       sched_context_destroy(misdn_tasks);
00794    }
00795 }

static void misdn_tasks_init ( void   )  [static]

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

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

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 825 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by release_chan(), and release_chan_early().

00826 {
00827    AST_SCHED_DEL(misdn_tasks, task_id);
00828 }

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

Definition at line 742 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 797 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

00798 {
00799    pthread_kill(misdn_tasks_thread, SIGUSR1);
00800 }

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

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

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

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

Definition at line 2875 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, chan_list::hold, misdn_bchannel::l3_id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_get_ch_state(), MISDN_HOLD_IDLE, misdn_lib_tone_generator_start(), chan_list::notxtone, misdn_bchannel::port, prefformat, ast_frame::samples, ast_frame::src, hold_info::state, ast_frame::subclass, and chan_list::ts.

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

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

03670 {
03671    int ret = ast_pbx_start(ch->ast);   
03672 
03673    if (ret >= 0) 
03674       ch->need_hangup = 0;
03675    else
03676       ch->need_hangup = 1;
03677 
03678    return ret;
03679 }

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

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

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

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

00668 {
00669    
00670    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00671    
00672    switch(bc->law) {
00673    case INFO_CODEC_ALAW:
00674       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00675       break;
00676    case INFO_CODEC_ULAW:
00677       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00678       break;
00679    }
00680 }

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

Definition at line 628 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by cb_events().

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

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

Definition at line 2707 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_frfree, 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().

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

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

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

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

static void release_chan ( struct chan_list ch,
struct misdn_bchannel bc 
) [static]

Definition at line 3729 of file chan_misdn.c.

References chan_list::ast, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_misdn_log(), cl_dequeue_chan(), cl_te, free, chan_list::jb, misdn_bchannel::l3_id, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, 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().

03730 {
03731    struct ast_channel *ast;
03732 
03733    ch->state = MISDN_CLEANING;
03734 
03735    ast_mutex_lock(&release_lock);
03736 
03737    cl_dequeue_chan(&cl_te, ch);
03738 
03739    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
03740 
03741    /* releasing jitterbuffer */
03742    if (ch->jb) {
03743       misdn_jb_destroy(ch->jb);
03744       ch->jb = NULL;
03745    } else {
03746       if (!bc->nojitter) {
03747          chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03748       }
03749    }
03750 
03751    if (ch->overlap_dial) {
03752       if (ch->overlap_dial_task != -1) {
03753          misdn_tasks_remove(ch->overlap_dial_task);
03754          ch->overlap_dial_task = -1;
03755       }
03756       ast_mutex_destroy(&ch->overlap_tv_lock);
03757    }
03758 
03759    if (ch->originator == ORG_AST) {
03760       --misdn_out_calls[bc->port];
03761    } else {
03762       --misdn_in_calls[bc->port];
03763    }
03764 
03765    close(ch->pipe[0]);
03766    close(ch->pipe[1]);
03767 
03768    ast = ch->ast;
03769    if (ast) {
03770       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03771       chan_misdn_log(1, bc->port,
03772          "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s\n",
03773          bc->pid,
03774          ast->context,
03775          ast->exten,
03776          ast->cid.cid_num);
03777 
03778       if (ast->_state != AST_STATE_RESERVED) {
03779          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03780          ast_setstate(ast, AST_STATE_DOWN);
03781       }
03782    }
03783 
03784    free(ch);
03785 
03786    ast_mutex_unlock(&release_lock);
03787 }

static void release_chan_early ( struct chan_list ch  )  [static]

Definition at line 3799 of file chan_misdn.c.

References chan_list::ast, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, cl_dequeue_chan(), cl_te, free, chan_list::hold, chan_list::jb, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, MISDN_HOLD_IDLE, misdn_in_calls, misdn_jb_destroy(), misdn_out_calls, misdn_tasks_remove(), ORG_AST, chan_list::originator, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, chan_list::pipe, hold_info::port, hold_info::state, and chan_list::state.

Referenced by misdn_hangup().

03800 {
03801    struct ast_channel *ast;
03802 
03803    ch->state = MISDN_CLEANING;
03804 
03805    ast_mutex_lock(&release_lock);
03806 
03807    cl_dequeue_chan(&cl_te, ch);
03808 
03809    /* releasing jitterbuffer */
03810    if (ch->jb) {
03811       misdn_jb_destroy(ch->jb);
03812       ch->jb = NULL;
03813    }
03814 
03815    if (ch->overlap_dial) {
03816       if (ch->overlap_dial_task != -1) {
03817          misdn_tasks_remove(ch->overlap_dial_task);
03818          ch->overlap_dial_task = -1;
03819       }
03820       ast_mutex_destroy(&ch->overlap_tv_lock);
03821    }
03822 
03823    if (ch->hold.state != MISDN_HOLD_IDLE) {
03824       if (ch->originator == ORG_AST) {
03825          --misdn_out_calls[ch->hold.port];
03826       } else {
03827          --misdn_in_calls[ch->hold.port];
03828       }
03829    }
03830 
03831    close(ch->pipe[0]);
03832    close(ch->pipe[1]);
03833 
03834    ast = ch->ast;
03835    if (ast) {
03836       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03837       if (ast->_state != AST_STATE_RESERVED) {
03838          ast_setstate(ast, AST_STATE_DOWN);
03839       }
03840    }
03841 
03842    free(ch);
03843 
03844    ast_mutex_unlock(&release_lock);
03845 }

static int reload ( void   )  [static]

Definition at line 5370 of file chan_misdn.c.

References reload_config().

05371 {
05372    reload_config();
05373 
05374    return 0;
05375 }

static void reload_config ( void   )  [static]

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

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

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

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

03956                                                                                                      {
03957    if (!ast) {
03958       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
03959       return;
03960    }
03961    if (!bc) {
03962       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
03963       return;
03964    }
03965    if (!ch) {
03966       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
03967       return;
03968    }
03969 
03970    ast->hangupcause = bc->cause;
03971 
03972    switch (bc->cause) {
03973 
03974    case AST_CAUSE_UNALLOCATED:
03975    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
03976    case AST_CAUSE_NO_ROUTE_DESTINATION:
03977    case 4:  /* Send special information tone */
03978    case AST_CAUSE_NUMBER_CHANGED:
03979    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03980       /* Congestion Cases */
03981       /*
03982        * Not Queueing the Congestion anymore, since we want to hear
03983        * the inband message
03984        *
03985       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
03986       ch->state = MISDN_BUSY;
03987       
03988       ast_queue_control(ast, AST_CONTROL_CONGESTION);
03989       */
03990       break;
03991 
03992    case AST_CAUSE_CALL_REJECTED:
03993    case AST_CAUSE_USER_BUSY:
03994       ch->state = MISDN_BUSY;
03995 
03996       if (!ch->need_busy) {
03997          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
03998          break;
03999       }
04000 
04001       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04002       
04003       ast_queue_control(ast, AST_CONTROL_BUSY);
04004       
04005       ch->need_busy = 0;
04006       
04007       break;
04008    }
04009 }

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

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

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

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

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

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

static void sighandler ( int  sig  )  [static]

Definition at line 739 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00740 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

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

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

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

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

04104                                                                                                  {
04105    if (pbx_start_chan(ch) < 0) {
04106       hangup_chan(ch, bc);
04107       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04108       if (bc->nt) {
04109          hanguptone_indicate(ch);
04110          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04111       } else
04112          misdn_lib_send_event(bc, EVENT_RELEASE);
04113    }
04114 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3149 of file chan_misdn.c.

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

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

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

static int stop_indicate ( struct chan_list cl  )  [static]

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

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

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 5157 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_in_calls, misdn_lib_destroy(), misdn_out_calls, misdn_tasks_destroy(), and misdn_tech.

05158 {
05159    /* First, take us out of the channel loop */
05160    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05161 
05162    misdn_tasks_destroy();
05163    
05164    if (!g_config_initialized)
05165       return 0;
05166    
05167    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05168    
05169    /* ast_unregister_application("misdn_crypt"); */
05170    ast_unregister_application("misdn_set_opt");
05171    ast_unregister_application("misdn_facility");
05172    ast_unregister_application("misdn_check_l2l1");
05173   
05174    ast_channel_unregister(&misdn_tech);
05175 
05176    free_robin_list();
05177    misdn_cfg_destroy();
05178    misdn_lib_destroy();
05179   
05180    free(misdn_out_calls);
05181    free(misdn_in_calls);
05182    free(misdn_debug_only);
05183    free(misdn_ports);
05184    free(misdn_debug);
05185    
05186    return 0;
05187 }

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

Updates caller ID information from config.

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

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

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

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

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

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

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

03440 {
03441    int chan_offset = 0;
03442    int tmp_port = misdn_cfg_get_next_port(0);
03443    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03444       if (tmp_port == port)
03445          break;
03446       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03447    }
03448    if (c < 0)
03449       c = 0;
03450 
03451    ast_string_field_build(tmp, name, "%s/%d-u%d",
03452       misdn_type, chan_offset + c, glob_channel++);
03453 
03454    chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03455 }

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

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

04116                                                                                                        {
04117    ch->state=MISDN_WAITING4DIGS;
04118    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04119    if (bc->nt && !bc->dad[0])
04120       dialtone_indicate(ch);
04121 }


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

Definition at line 5948 of file chan_misdn.c.

struct allowed_bearers allowed_bearers_array[] [static]

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

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1680 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 523 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_request(), misdn_show_cl(), misdn_show_cls(), release_chan(), and release_chan_early().

ast_mutex_t cl_te_lock

Definition at line 524 of file chan_misdn.c.

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

struct chan_list dummy_cl

Definition at line 518 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 3437 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 1378 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 512 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 1379 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 510 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 511 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 514 of file chan_misdn.c.

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

int* misdn_out_calls [static]

Definition at line 515 of file chan_misdn.c.

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

int* misdn_ports [static]

Definition at line 486 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 483 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 484 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

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

Referenced by misdn_new().

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

Definition at line 503 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 508 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 433 of file chan_misdn.c.

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 1187 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 505 of file chan_misdn.c.

Referenced by load_module().


Generated on Fri Jan 29 14:25:31 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7