Sat Aug 6 00:39:46 2011

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 490 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 489 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 3556 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 5914 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

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

int add_in_calls ( int  port  ) 

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

04046 {
04047    int max_in_calls;
04048    
04049    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04050    misdn_in_calls[port]++;
04051 
04052    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04053       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04054       return misdn_in_calls[port] - max_in_calls;
04055    }
04056    
04057    return 0;
04058 }

int add_out_calls ( int  port  ) 

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

04061 {
04062    int max_out_calls;
04063    
04064    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04065 
04066    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04067       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04068       return (misdn_out_calls[port] + 1) - max_out_calls;
04069    }
04070 
04071    misdn_out_calls[port]++;
04072    
04073    return 0;
04074 }

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

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

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

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

Definition at line 4100 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_poll, 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().

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

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

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

05669 {
05670    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05671    
05672    if (ch && ch->jb) {
05673       return misdn_jb_empty(ch->jb, buf, len);
05674    }
05675    
05676    return -1;
05677 }

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

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

05852 {
05853    va_list ap;
05854    char buf[1024];
05855    char port_buf[8];
05856 
05857    if (! ((0 <= port) && (port <= max_ports))) {
05858       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05859       port = 0;
05860       level = -1;
05861    }
05862 
05863    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05864 
05865    va_start(ap, tmpl);
05866    vsnprintf(buf, sizeof(buf), tmpl, ap);
05867    va_end(ap);
05868 
05869    if (level == -1)
05870       ast_log(LOG_WARNING, "%s", buf);
05871 
05872    else if (misdn_debug_only[port] ? 
05873          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
05874        : level <= misdn_debug[port]) {
05875       
05876       ast_console_puts(port_buf);
05877       ast_console_puts(buf);
05878    }
05879    
05880    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05881       time_t tm = time(NULL);
05882       char *tmp = ctime(&tm), *p;
05883 
05884       FILE *fp = fopen(global_tracefile, "a+");
05885 
05886       p = strchr(tmp, '\n');
05887       if (p)
05888          *p = ':';
05889       
05890       if (!fp) {
05891          ast_console_puts("Error opening Tracefile: [ ");
05892          ast_console_puts(global_tracefile);
05893          ast_console_puts(" ] ");
05894          
05895          ast_console_puts(strerror(errno));
05896          ast_console_puts("\n");
05897          return ;
05898       }
05899       
05900       fputs(tmp, fp);
05901       fputs(" ", fp);
05902       fputs(port_buf, fp);
05903       fputs(" ", fp);
05904       fputs(buf, fp);
05905 
05906       fclose(fp);
05907    }
05908 }

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

Definition at line 3608 of file chan_misdn.c.

References ast_dsp_free(), ast_mutex_lock(), ast_mutex_unlock(), cl_te_lock, chan_list::dsp, and chan_list::next.

Referenced by release_chan(), and release_chan_early().

03609 {
03610    struct chan_list *help;
03611 
03612    if (chan->dsp) 
03613       ast_dsp_free(chan->dsp);
03614 
03615    ast_mutex_lock(&cl_te_lock);
03616    if (!*list) {
03617       ast_mutex_unlock(&cl_te_lock);
03618       return;
03619    }
03620   
03621    if (*list == chan) {
03622       *list = (*list)->next;
03623       ast_mutex_unlock(&cl_te_lock);
03624       return;
03625    }
03626   
03627    for (help = *list; help->next; help = help->next) {
03628       if (help->next == chan) {
03629          help->next = help->next->next;
03630          ast_mutex_unlock(&cl_te_lock);
03631          return;
03632       }
03633    }
03634    
03635    ast_mutex_unlock(&cl_te_lock);
03636 }

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

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

03593 {
03594    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03595   
03596    ast_mutex_lock(&cl_te_lock);
03597    if (!*list) {
03598       *list = chan;
03599    } else {
03600       struct chan_list *help = *list;
03601       for (; help->next; help = help->next); 
03602       help->next = chan;
03603    }
03604    chan->next = NULL;
03605    ast_mutex_unlock(&cl_te_lock);
03606 }

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

Definition at line 1603 of file chan_misdn.c.

References complete_ch_helper().

01604 {
01605    return complete_ch_helper(line, word, pos, state, 3);
01606 }

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

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

01580 {
01581    struct ast_channel *c;
01582    int which=0;
01583    char *ret;
01584    if (pos != rpos)
01585       return NULL;
01586    c = ast_channel_walk_locked(NULL);
01587    while(c) {
01588       if (!strncasecmp(word, c->name, strlen(word))) {
01589          if (++which > state)
01590             break;
01591       }
01592       ast_mutex_unlock(&c->lock);
01593       c = ast_channel_walk_locked(c);
01594    }
01595    if (c) {
01596       ret = strdup(c->name);
01597       ast_mutex_unlock(&c->lock);
01598    } else
01599       ret = NULL;
01600    return ret;
01601 }

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

Definition at line 1608 of file chan_misdn.c.

References strdup.

01609 {
01610    if (state)
01611       return NULL;
01612 
01613    switch (pos) {
01614    case 4:
01615       if (*word == 'p')
01616          return strdup("port");
01617       else if (*word == 'o')
01618          return strdup("only");
01619       break;
01620    case 6:
01621       if (*word == 'o')
01622          return strdup("only");
01623       break;
01624    }
01625    return NULL;
01626 }

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

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

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

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

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

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

Definition at line 1845 of file chan_misdn.c.

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

Referenced by read_config().

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

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

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

03059 {
03060    const struct tone_zone_sound *ts = NULL;
03061    struct ast_channel *ast = cl->ast;
03062    int nd = 0;
03063 
03064    if (!ast) {
03065       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03066       return -1;
03067    }
03068 
03069    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03070 
03071    if (nd) {
03072       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03073       return 0;
03074    }
03075    
03076    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03077    ts = ast_get_indication_tone(ast->zone, "dial");
03078    cl->ts = ts;   
03079    
03080    if (ts) {
03081       cl->notxtone = 0;
03082       cl->norxtone = 0;
03083       /* This prods us in misdn_write */
03084       ast_playtones_start(ast, 0, ts->data, 0);
03085    }
03086 
03087    return 0;
03088 }

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

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

03865 {
03866    char predial[256]="";
03867    char *p = predial;
03868   
03869    struct ast_frame fr;
03870 
03871    strncpy(predial, ast->exten, sizeof(predial) -1 );
03872 
03873    ch->state = MISDN_DIALING;
03874 
03875    if (!ch->noautorespond_on_setup) {
03876       if (bc->nt) {
03877          int ret; 
03878          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03879       } else {
03880          int ret;
03881          if ( misdn_lib_is_ptp(bc->port)) {
03882             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03883          } else {
03884             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03885          }
03886       }
03887    } else {
03888       ch->state = MISDN_INCOMING_SETUP;
03889    }
03890 
03891    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);
03892   
03893    strcpy(ast->exten, "s");
03894  
03895    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03896       ast = NULL;
03897       bc->out_cause = AST_CAUSE_UNALLOCATED;
03898       hangup_chan(ch, bc);
03899       hanguptone_indicate(ch);
03900 
03901       if (bc->nt)
03902          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03903       else
03904          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03905    }
03906   
03907   
03908    while (!ast_strlen_zero(p) ) {
03909       fr.frametype = AST_FRAME_DTMF;
03910       fr.subclass = *p;
03911       fr.src = NULL;
03912       fr.data = NULL;
03913       fr.datalen = 0;
03914       fr.samples = 0;
03915       fr.mallocd = 0;
03916       fr.offset = 0;
03917       fr.delivery = ast_tv(0,0);
03918 
03919       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03920          ast_queue_frame(ch->ast, &fr);
03921       }
03922       p++;
03923    }
03924 }

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

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

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

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

04020 {
04021    char tmp[32];
04022    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04023    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04024    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04025 
04026    if (bc->sending_complete) {
04027       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04028       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04029    }
04030 
04031    if (bc->urate) {
04032       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04033       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04034    }
04035 
04036    if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
04037       bc->uu[bc->uulen] = 0;
04038       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04039    }
04040 
04041    if (!ast_strlen_zero(bc->keypad)) 
04042       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04043 }

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

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

03503 {
03504    struct chan_list *help = list;
03505    for (; help; help = help->next) {
03506       if (help->bc == bc) return help;
03507    }
03508 
03509    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03510 
03511    return NULL;
03512 }

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

Definition at line 3514 of file chan_misdn.c.

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

Referenced by import_ch().

03515 {
03516    struct chan_list *help = list;
03517    for (; help; help = help->next) {
03518       if ( help->bc && (help->bc->pid == pid) ) return help;
03519    }
03520 
03521    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03522 
03523    return NULL;
03524 }

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

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

03573 {
03574    for (; list; list = list->next) {
03575       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
03576          && list->ast) {
03577          switch (list->state) {
03578          case MISDN_PROCEEDING:
03579          case MISDN_PROGRESS:
03580          case MISDN_ALERTING:
03581          case MISDN_CONNECTED:
03582             return list;
03583          default:
03584             break;
03585          }
03586       }
03587    }
03588    return NULL;
03589 }

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

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

03527 {
03528    struct chan_list *help = list;
03529 
03530    if (bc->pri) return NULL;
03531 
03532    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03533    for (;help; help = help->next) {
03534       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
03535       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port)
03536          return help;
03537    }
03538    chan_misdn_log(6, bc->port, "$$$ find_hold_call: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03539 
03540    return NULL;
03541 }

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

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

03545 {
03546    struct chan_list *help = list;
03547 
03548    for (; help; help = help->next) {
03549       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id)
03550          return help;
03551    }
03552 
03553    return NULL;
03554 }

static void free_robin_list ( void   )  [static]

Definition at line 434 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

00435 {
00436    struct robin_list *r;
00437    struct robin_list *next;
00438 
00439    for (r = robin, robin = NULL; r; r = next) {
00440       next = r->next;
00441       free(r->group);
00442       free(r);
00443    }
00444 }

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

Definition at line 564 of file chan_misdn.c.

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

Referenced by misdn_bridge().

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

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

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

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

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

Definition at line 446 of file chan_misdn.c.

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

Referenced by misdn_request().

00447 {
00448    struct robin_list *new;
00449    struct robin_list *iter = robin;
00450    for (; iter; iter = iter->next) {
00451       if (!strcasecmp(iter->group, group)) {
00452          return iter;
00453       }
00454    }
00455    new = calloc(1, sizeof(*new));
00456    if (!new) {
00457       return NULL;
00458    }
00459    new->group = strdup(group);
00460    if (!new->group) {
00461       free(new);
00462       return NULL;
00463    }
00464    new->port = 0;
00465    new->channel = 0;
00466    if (robin) {
00467       new->next = robin;
00468       robin->prev = new;
00469    }
00470    robin = new;
00471    return robin;
00472 }

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

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

03654 {
03655    int port;
03656 
03657    if (!ch) {
03658       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03659       return;
03660    }
03661 
03662    port = bc->port;
03663    cb_log(5, port, "hangup_chan called\n");
03664 
03665    if (ch->need_hangup) {
03666       cb_log(2, port, " --> hangup\n");
03667       ch->need_hangup = 0;
03668       ch->need_queue_hangup = 0;
03669       if (ch->ast) {
03670          send_cause2ast(ch->ast, bc, ch);
03671          ast_hangup(ch->ast);
03672       }
03673       return;
03674    }
03675 
03676    if (!ch->need_queue_hangup) {
03677       cb_log(2, port, " --> No need to queue hangup\n");
03678    }
03679 
03680    ch->need_queue_hangup = 0;
03681    if (ch->ast) {
03682       send_cause2ast(ch->ast, bc, ch);
03683       ast_queue_hangup(ch->ast);
03684       cb_log(2, port, " --> queue_hangup\n");
03685    } else {
03686       cb_log(1, port, "Cannot hangup chan, no ast\n");
03687    }
03688 }

static void hanguptone_indicate ( struct chan_list cl  )  [static]

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

03091 {
03092    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03093 }

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

03986 {
03987    const char *tmp;
03988 
03989    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
03990    if (tmp) {
03991       ch->other_pid = atoi(tmp);
03992       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
03993       if (ch->other_pid > 0) {
03994          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
03995          if (ch->other_ch)
03996             ch->other_ch->other_ch = ch;
03997       }
03998    }
03999 
04000    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04001    if (tmp && (atoi(tmp) == 1)) {
04002       bc->sending_complete = 1;
04003    }
04004 
04005    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04006    if (tmp) {
04007       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04008       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04009       bc->uulen = strlen(bc->uu);
04010    }
04011 
04012    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04013    if (tmp) {
04014       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04015    }
04016 }

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

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

03135 {
03136    struct chan_list *cl;
03137 
03138    cl = calloc(1, sizeof(struct chan_list));
03139    if (!cl) {
03140       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03141       return NULL;
03142    }
03143    
03144    cl->originator = orig;
03145    cl->need_queue_hangup = 1;
03146    cl->need_hangup = 1;
03147    cl->need_busy = 1;
03148    cl->overlap_dial_task = -1;
03149 
03150    return cl;
03151 }

static int load_module ( void   )  [static]

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

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

static int misdn_answer ( struct ast_channel ast  )  [static]

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

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

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

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

03830 {
03831    int retval;
03832    struct ast_channel *bridged;
03833 
03834    switch (active_ch->state) {
03835    case MISDN_PROCEEDING:
03836    case MISDN_PROGRESS:
03837    case MISDN_ALERTING:
03838    case MISDN_CONNECTED:
03839       break;
03840    default:
03841       return -1;
03842    }
03843 
03844    bridged = ast_bridged_channel(held_ch->ast);
03845    if (bridged) {
03846       ast_queue_control(held_ch->ast, AST_CONTROL_UNHOLD);
03847       held_ch->hold.state = MISDN_HOLD_TRANSFER;
03848 
03849       chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
03850          held_ch->ast->name, active_ch->ast->name);
03851       retval = ast_channel_masquerade(active_ch->ast, bridged);
03852    } else {
03853       /*
03854        * Could not transfer.  Held channel is not bridged anymore.
03855        * Held party probably got tired of waiting and hung up.
03856        */
03857       retval = -1;
03858    }
03859 
03860    return retval;
03861 }

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

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

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

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

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

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

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

05393 {
05394    char group[BUFFERSIZE + 1];
05395    char *port_str;
05396    int port = 0;
05397    int timeout;
05398    int dowait = 0;
05399    int port_up;
05400 
05401    AST_DECLARE_APP_ARGS(args,
05402          AST_APP_ARG(grouppar);
05403          AST_APP_ARG(timeout);
05404    );
05405 
05406    if (ast_strlen_zero((char *)data)) {
05407       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05408       return -1;
05409    }
05410 
05411    AST_STANDARD_APP_ARGS(args, data);
05412 
05413    if (args.argc != 2) {
05414       ast_log(LOG_WARNING, "Wrong argument count\n");
05415       return 0;
05416    }
05417 
05418    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05419    timeout = atoi(args.timeout);
05420    port_str = args.grouppar;
05421 
05422    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05423       /* We make a group call lets checkout which ports are in my group */
05424       port_str += 2;
05425       ast_copy_string(group, port_str, sizeof(group));
05426       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05427 
05428       for ( port = misdn_cfg_get_next_port(port); 
05429          port > 0;
05430          port = misdn_cfg_get_next_port(port)) {
05431          char cfg_group[BUFFERSIZE + 1];
05432 
05433          chan_misdn_log(2, 0, "trying port %d\n", port);
05434 
05435          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05436 
05437          if (!strcasecmp(cfg_group, group)) {
05438             port_up = misdn_lib_port_up(port, 1);
05439 
05440             if (!port_up) {
05441                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05442                misdn_lib_get_port_up(port);
05443                dowait = 1;
05444             }
05445          }
05446       }
05447 
05448    } else {
05449       port = atoi(port_str);
05450       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05451       port_up = misdn_lib_port_up(port, 1);
05452       if (!port_up) {
05453          misdn_lib_get_port_up(port);
05454          dowait = 1;
05455       }
05456    }
05457 
05458    if (dowait) {
05459       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05460       sleep(timeout);
05461    }
05462 
05463    return 0;
05464 }

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

Definition at line 2317 of file chan_misdn.c.

02318 {
02319    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02320    return 0;
02321 }

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

Definition at line 2323 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(), misdn_bchannel::port, send_digit_to_chan(), misdn_bchannel::send_dtmf, and chan_list::state.

02324 {
02325    struct chan_list *p;
02326    struct misdn_bchannel *bc;
02327 
02328    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02329 
02330    bc = p->bc;
02331    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
02332    
02333    if (!bc) {
02334       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
02335       return -1;
02336    }
02337    
02338    switch (p->state ) {
02339    case MISDN_CALLING:
02340       {
02341          int l;      
02342          char buf[8];
02343          buf[0]=digit;
02344          buf[1]=0;
02345          
02346          l = sizeof(bc->infos_pending);
02347          strncat(bc->infos_pending, buf, l - strlen(bc->infos_pending) - 1);
02348       }
02349       break;
02350    case MISDN_CALLING_ACKNOWLEDGE:
02351       {
02352          bc->info_dad[0]=digit;
02353          bc->info_dad[1]=0;
02354          
02355          {
02356             int l = sizeof(bc->dad);
02357             strncat(bc->dad, bc->info_dad, l - strlen(bc->dad) - 1);
02358          }
02359          {
02360             int l = sizeof(p->ast->exten);
02361             strncpy(p->ast->exten, bc->dad, l);
02362             p->ast->exten[l-1] = 0;
02363          }
02364          
02365          misdn_lib_send_event( bc, EVENT_INFORMATION);
02366       }
02367       break;
02368    default: 
02369          if ( bc->send_dtmf ) 
02370             send_digit_to_chan(p,digit);
02371       break;
02372    }
02373 
02374    return 0;
02375 }

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

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

05348 {
05349    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05350    char *tok, *tokb;
05351 
05352    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05353    
05354    if (strcasecmp(chan->tech->type, "mISDN")) {
05355       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05356       return -1;
05357    }
05358    
05359    if (ast_strlen_zero((char *)data)) {
05360       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05361       return -1;
05362    }
05363 
05364    tok = strtok_r((char*) data, "|", &tokb) ;
05365 
05366    if (!tok) {
05367       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05368       return -1;
05369    }
05370 
05371    if (!strcasecmp(tok, "calldeflect")) {
05372       tok = strtok_r(NULL, "|", &tokb) ;
05373       
05374       if (!tok) {
05375          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05376       }
05377 
05378       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05379          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05380          return 0; 
05381       }
05382       ch->bc->fac_out.Function = Fac_CD;
05383       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05384       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05385    } else {
05386       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05387    }
05388 
05389    return 0;
05390 }

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

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

02379 {
02380    struct chan_list *p;
02381 
02382    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02383 
02384    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);
02385 
02386    p->ast = ast;
02387 
02388    return 0;
02389 }

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

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

01198 {
01199    int i;
01200    static char state[8];
01201    
01202    if( !p) return NULL;
01203   
01204    for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
01205       if (state_array[i].state == p->state)
01206          return state_array[i].txt; 
01207    }
01208 
01209    snprintf(state, sizeof(state), "%d", p->state) ;
01210 
01211    return state;
01212 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

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

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

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

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

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

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

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

05729 {
05730    ast_mutex_destroy(&jb->mutexjb);
05731    
05732    free(jb->ok);
05733    free(jb->samples);
05734    free(jb);
05735 }

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

05799 {
05800    int i, wp, rp, read = 0;
05801 
05802    ast_mutex_lock(&jb->mutexjb);
05803 
05804    rp = jb->rp;
05805    wp = jb->wp;
05806 
05807    if (jb->state_empty) {  
05808       for (i = 0; i < len; i++) {
05809          if (wp == rp) {
05810             jb->rp = rp;
05811             jb->state_empty = 0;
05812 
05813             ast_mutex_unlock(&jb->mutexjb);
05814 
05815             return read;
05816          } else {
05817             if (jb->ok[rp] == 1) {
05818                data[i] = jb->samples[rp];
05819                jb->ok[rp] = 0;
05820                rp = (rp != jb->size - 1) ? rp + 1 : 0;
05821                read += 1;
05822             }
05823          }
05824       }
05825 
05826       if (wp >= rp)
05827          jb->state_buffer = wp - rp;
05828       else
05829          jb->state_buffer = jb->size - rp + wp;
05830       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05831 
05832       jb->rp = rp;
05833    } else
05834       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05835 
05836    ast_mutex_unlock(&jb->mutexjb);
05837 
05838    return read;
05839 }

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

05740 {
05741    int i, j, rp, wp;
05742 
05743    if (!jb || ! data)
05744       return 0;
05745 
05746    ast_mutex_lock(&jb->mutexjb);
05747    
05748    wp = jb->wp;
05749    rp = jb->rp;
05750    
05751    for (i = 0; i < len; i++) {
05752       jb->samples[wp] = data[i];
05753       jb->ok[wp] = 1;
05754       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05755 
05756       if (wp == jb->rp)
05757          jb->state_full = 1;
05758    }
05759 
05760    if (wp >= rp)
05761       jb->state_buffer = wp - rp;
05762    else
05763       jb->state_buffer = jb->size - rp + wp;
05764    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05765 
05766    if (jb->state_full) {
05767       jb->wp = wp;
05768 
05769       rp = wp;
05770       for (j = 0; j < jb->upper_threshold; j++)
05771          rp = (rp != 0) ? rp - 1 : jb->size - 1;
05772       jb->rp = rp;
05773       jb->state_full = 0;
05774       jb->state_empty = 1;
05775 
05776       ast_mutex_unlock(&jb->mutexjb);
05777 
05778       return -1;
05779    }
05780 
05781    if (!jb->state_empty) {
05782       jb->bytes_wrote += len;
05783       if (jb->bytes_wrote >= jb->upper_threshold) {
05784          jb->state_empty = 1;
05785          jb->bytes_wrote = 0;
05786       }
05787    }
05788    jb->wp = wp;
05789 
05790    ast_mutex_unlock(&jb->mutexjb);
05791    
05792    return 0;
05793 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

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

05688 {
05689    int i;
05690    struct misdn_jb *jb;
05691 
05692    jb = malloc(sizeof(struct misdn_jb));
05693    if (!jb) {
05694        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05695        return NULL;
05696    }
05697    jb->size = size;
05698    jb->upper_threshold = upper_threshold;
05699    jb->wp = 0;
05700    jb->rp = 0;
05701    jb->state_full = 0;
05702    jb->state_empty = 0;
05703    jb->bytes_wrote = 0;
05704    jb->samples = malloc(size * sizeof(char));
05705    if (!jb->samples) {
05706       free(jb);
05707       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05708       return NULL;
05709    }
05710 
05711    jb->ok = malloc(size * sizeof(char));
05712    if (!jb->ok) {
05713       free(jb->samples);
05714       free(jb);
05715       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05716       return NULL;
05717    }
05718 
05719    for (i = 0; i < size; i++)
05720       jb->ok[i] = 0;
05721 
05722    ast_mutex_init(&jb->mutexjb);
05723 
05724    return jb;
05725 }

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

Definition at line 823 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

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

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

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

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

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

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

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

Definition at line 987 of file chan_misdn.c.

References misdn_lib_port_block(), and RESULT_SHOWUSAGE.

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

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

Definition at line 1058 of file chan_misdn.c.

References misdn_lib_get_port_down(), and RESULT_SHOWUSAGE.

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

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

Definition at line 1001 of file chan_misdn.c.

References misdn_lib_port_unblock(), and RESULT_SHOWUSAGE.

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

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

Definition at line 1044 of file chan_misdn.c.

References misdn_lib_get_port_up(), and RESULT_SHOWUSAGE.

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

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

Definition at line 2764 of file chan_misdn.c.

References chan_list::ast_dsp, AST_FORMAT_ALAW, AST_FRAME_VOICE, ast_poll, 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.

02765 {
02766    struct chan_list *tmp;
02767    int len, t;
02768    struct pollfd pfd = { .fd = -1, .events = POLLIN };
02769 
02770    if (!ast) {
02771       chan_misdn_log(1, 0, "misdn_read called without ast\n");
02772       return NULL;
02773    }
02774    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
02775       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
02776       return NULL;
02777    }
02778 
02779    if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
02780       chan_misdn_log(1, 0, "misdn_read called without bc\n");
02781       return NULL;
02782    }
02783 
02784    pfd.fd = tmp->pipe[0];
02785    t = ast_poll(&pfd, 1, 20);
02786 
02787    if (t < 0) {
02788       chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
02789       return NULL;
02790    }
02791 
02792    if (!t) {
02793       chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
02794       len = 160;
02795    } else if (pfd.revents & POLLIN) {
02796       len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
02797 
02798       if (len <= 0) {
02799          /* we hangup here, since our pipe is closed */
02800          chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
02801          return NULL;
02802       }
02803 
02804    } else {
02805       return NULL;
02806    }
02807 
02808    tmp->frame.frametype = AST_FRAME_VOICE;
02809    tmp->frame.subclass = AST_FORMAT_ALAW;
02810    tmp->frame.datalen = len;
02811    tmp->frame.samples = len;
02812    tmp->frame.mallocd = 0;
02813    tmp->frame.offset = 0;
02814    tmp->frame.delivery = ast_tv(0,0);
02815    tmp->frame.src = NULL;
02816    tmp->frame.data = tmp->ast_rd_buf;
02817 
02818    if (tmp->faxdetect && !tmp->faxhandled) {
02819       if (tmp->faxdetect_timeout) {
02820          if (ast_tvzero(tmp->faxdetect_tv)) {
02821             tmp->faxdetect_tv = ast_tvnow();
02822             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
02823             return process_ast_dsp(tmp, &tmp->frame);
02824          } else {
02825             struct timeval tv_now = ast_tvnow();
02826             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
02827             if (diff <= (tmp->faxdetect_timeout * 1000)) {
02828                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
02829                return process_ast_dsp(tmp, &tmp->frame);
02830             } else {
02831                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
02832                tmp->faxdetect = 0;
02833                return &tmp->frame;
02834             }
02835          }
02836       } else {
02837          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
02838          return process_ast_dsp(tmp, &tmp->frame);
02839       }
02840    } else {
02841       if (tmp->ast_dsp)
02842          return process_ast_dsp(tmp, &tmp->frame);
02843       else
02844          return &tmp->frame;
02845    }
02846 }

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

Definition at line 1237 of file chan_misdn.c.

References ast_cli(), and reload_config().

01238 {
01239    ast_cli(fd, "Reloading mISDN configuration\n");
01240    reload_config();
01241    return 0;
01242 }

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

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

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

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

Definition at line 1030 of file chan_misdn.c.

References misdn_lib_pid_restart(), and RESULT_SHOWUSAGE.

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

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

Definition at line 1016 of file chan_misdn.c.

References misdn_lib_port_restart(), and RESULT_SHOWUSAGE.

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

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

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

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

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

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

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

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

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

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

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

Definition at line 1463 of file chan_misdn.c.

References misdn_lib_send_restart(), and RESULT_SHOWUSAGE.

01464 {
01465    int port;
01466    int channel;
01467 
01468    if (argc < 4 || argc > 5)
01469       return RESULT_SHOWUSAGE;
01470 
01471    port = atoi(argv[3]);
01472 
01473    if (argc == 5) {
01474       channel = atoi(argv[4]);
01475       misdn_lib_send_restart(port, channel);
01476    } else {
01477       misdn_lib_send_restart(port, -1);
01478    }
01479 
01480    return 0;
01481 }

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

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

03359 {
03360    struct chan_list *tmp = chan->tech_pvt;
03361    
03362    if (tmp && tmp->bc) {
03363       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03364       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03365    } else {
03366       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03367       return -1;
03368    }
03369    
03370    return 0;
03371 }

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

Definition at line 980 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

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

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

Definition at line 917 of file chan_misdn.c.

References ast_cli(), and RESULT_SHOWUSAGE.

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

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

Definition at line 5466 of file chan_misdn.c.

References ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), ast_log(), ast_strlen_zero(), 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().

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

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

Definition at line 1374 of file chan_misdn.c.

References RESULT_SHOWUSAGE.

01375 {
01376    if (argc != 4)
01377       return RESULT_SHOWUSAGE;
01378 
01379    MAXTICS = atoi(argv[3]);
01380 
01381    return 0;
01382 }

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

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

01348 {
01349    struct chan_list *help;
01350 
01351    if (argc != 4)
01352       return RESULT_SHOWUSAGE;
01353 
01354    help = cl_te;
01355 
01356    for (; help; help = help->next) {
01357       struct misdn_bchannel *bc = help->bc;   
01358       struct ast_channel *ast = help->ast;
01359     
01360       if (bc && ast) {
01361          if (!strcasecmp(ast->name,argv[3])) {
01362             print_bc_info(fd, help, bc);
01363             break; 
01364          }
01365       } 
01366    }
01367 
01368    return 0;
01369 }

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

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

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

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

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

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

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

Definition at line 1413 of file chan_misdn.c.

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

01414 {
01415    int port;
01416    char buf[128];
01417 
01418    if (argc != 4)
01419       return RESULT_SHOWUSAGE;
01420 
01421    port = atoi(argv[3]);
01422   
01423    ast_cli(fd, "BEGIN STACK_LIST:\n");
01424    get_show_stack_details(port, buf);
01425    ast_cli(fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01426 
01427    return 0;
01428 }

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

Definition at line 1399 of file chan_misdn.c.

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

01400 {
01401    int port;
01402 
01403    ast_cli(fd, "Port\tin_calls\tout_calls\n");
01404    for (port = misdn_cfg_get_next_port(0); port > 0;
01405         port = misdn_cfg_get_next_port(port)) {
01406       ast_cli(fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
01407    }
01408    ast_cli(fd, "\n");
01409 
01410    return 0;
01411 }

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

Definition at line 1384 of file chan_misdn.c.

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

01385 {
01386    int port;
01387 
01388    ast_cli(fd, "BEGIN STACK_LIST:\n");
01389    for (port = misdn_cfg_get_next_port(0); port > 0;
01390         port = misdn_cfg_get_next_port(port)) {
01391       char buf[128];
01392       get_show_stack_details(port, buf);
01393       ast_cli(fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01394    }
01395 
01396    return 0;
01397 }

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

Definition at line 808 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

00809 {
00810    return _misdn_tasks_add_variable(timeout, callback, data, 0);
00811 }

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

Definition at line 813 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

00814 {
00815    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00816 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 778 of file chan_misdn.c.

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

Referenced by unload_module().

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

static void misdn_tasks_init ( void   )  [static]

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

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

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 818 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by release_chan(), and release_chan_early().

00819 {
00820    AST_SCHED_DEL(misdn_tasks, task_id);
00821 }

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

Definition at line 735 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 790 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

00791 {
00792    pthread_kill(misdn_tasks_thread, SIGUSR1);
00793 }

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

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

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

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

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

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

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

03642 {
03643    int ret = ast_pbx_start(ch->ast);   
03644 
03645    if (ret >= 0) 
03646       ch->need_hangup = 0;
03647    else
03648       ch->need_hangup = 1;
03649 
03650    return ret;
03651 }

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

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

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

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

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

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

Definition at line 621 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by cb_events().

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

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

Definition at line 2693 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_log(), ast_strlen_zero(), ast_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, misdn_bchannel::txgain, and VERBOSE_PREFIX_3.

Referenced by misdn_read().

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

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

Definition at line 1906 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_log(), ast_mutex_init(), ast_print_group(), ast_set_callerid(), ast_string_field_set, ast_strlen_zero(), 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, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

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

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

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

03702 {
03703    struct ast_channel *ast;
03704 
03705    ch->state = MISDN_CLEANING;
03706 
03707    ast_mutex_lock(&release_lock);
03708 
03709    cl_dequeue_chan(&cl_te, ch);
03710 
03711    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
03712 
03713    /* releasing jitterbuffer */
03714    if (ch->jb) {
03715       misdn_jb_destroy(ch->jb);
03716       ch->jb = NULL;
03717    } else {
03718       if (!bc->nojitter) {
03719          chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03720       }
03721    }
03722 
03723    if (ch->overlap_dial) {
03724       if (ch->overlap_dial_task != -1) {
03725          misdn_tasks_remove(ch->overlap_dial_task);
03726          ch->overlap_dial_task = -1;
03727       }
03728       ast_mutex_destroy(&ch->overlap_tv_lock);
03729    }
03730 
03731    if (ch->originator == ORG_AST) {
03732       --misdn_out_calls[bc->port];
03733    } else {
03734       --misdn_in_calls[bc->port];
03735    }
03736 
03737    close(ch->pipe[0]);
03738    close(ch->pipe[1]);
03739 
03740    ast = ch->ast;
03741    if (ast) {
03742       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03743       chan_misdn_log(1, bc->port,
03744          "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s\n",
03745          bc->pid,
03746          ast->context,
03747          ast->exten,
03748          ast->cid.cid_num);
03749 
03750       if (ast->_state != AST_STATE_RESERVED) {
03751          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03752          ast_setstate(ast, AST_STATE_DOWN);
03753       }
03754    }
03755 
03756    free(ch);
03757 
03758    ast_mutex_unlock(&release_lock);
03759 }

static void release_chan_early ( struct chan_list ch  )  [static]

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

03772 {
03773    struct ast_channel *ast;
03774 
03775    ch->state = MISDN_CLEANING;
03776 
03777    ast_mutex_lock(&release_lock);
03778 
03779    cl_dequeue_chan(&cl_te, ch);
03780 
03781    /* releasing jitterbuffer */
03782    if (ch->jb) {
03783       misdn_jb_destroy(ch->jb);
03784       ch->jb = NULL;
03785    }
03786 
03787    if (ch->overlap_dial) {
03788       if (ch->overlap_dial_task != -1) {
03789          misdn_tasks_remove(ch->overlap_dial_task);
03790          ch->overlap_dial_task = -1;
03791       }
03792       ast_mutex_destroy(&ch->overlap_tv_lock);
03793    }
03794 
03795    if (ch->hold.state != MISDN_HOLD_IDLE) {
03796       if (ch->originator == ORG_AST) {
03797          --misdn_out_calls[ch->hold.port];
03798       } else {
03799          --misdn_in_calls[ch->hold.port];
03800       }
03801    }
03802 
03803    close(ch->pipe[0]);
03804    close(ch->pipe[1]);
03805 
03806    ast = ch->ast;
03807    if (ast) {
03808       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03809       if (ast->_state != AST_STATE_RESERVED) {
03810          ast_setstate(ast, AST_STATE_DOWN);
03811       }
03812    }
03813 
03814    free(ch);
03815 
03816    ast_mutex_unlock(&release_lock);
03817 }

static int reload ( void   )  [static]

Definition at line 5338 of file chan_misdn.c.

References reload_config().

05339 {
05340    reload_config();
05341 
05342    return 0;
05343 }

static void reload_config ( void   )  [static]

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

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

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

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

03928                                                                                                      {
03929    if (!ast) {
03930       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
03931       return;
03932    }
03933    if (!bc) {
03934       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
03935       return;
03936    }
03937    if (!ch) {
03938       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
03939       return;
03940    }
03941 
03942    ast->hangupcause = bc->cause;
03943 
03944    switch (bc->cause) {
03945 
03946    case AST_CAUSE_UNALLOCATED:
03947    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
03948    case AST_CAUSE_NO_ROUTE_DESTINATION:
03949    case 4:  /* Send special information tone */
03950    case AST_CAUSE_NUMBER_CHANGED:
03951    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03952       /* Congestion Cases */
03953       /*
03954        * Not Queueing the Congestion anymore, since we want to hear
03955        * the inband message
03956        *
03957       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
03958       ch->state = MISDN_BUSY;
03959       
03960       ast_queue_control(ast, AST_CONTROL_CONGESTION);
03961       */
03962       break;
03963 
03964    case AST_CAUSE_CALL_REJECTED:
03965    case AST_CAUSE_USER_BUSY:
03966       ch->state = MISDN_BUSY;
03967 
03968       if (!ch->need_busy) {
03969          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
03970          break;
03971       }
03972 
03973       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
03974       
03975       ast_queue_control(ast, AST_CONTROL_BUSY);
03976       
03977       ch->need_busy = 0;
03978       
03979       break;
03980    }
03981 }

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

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

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

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

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

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

static void sighandler ( int  sig  )  [static]

Definition at line 732 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00733 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

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

03116 {
03117    misdn_lib_tone_generator_stop(cl->bc);
03118    cl->notxtone = 0;
03119    cl->norxtone = 0;
03120    return 0;
03121 }

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

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

04076                                                                                                  {
04077    if (pbx_start_chan(ch) < 0) {
04078       hangup_chan(ch, bc);
04079       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04080       if (bc->nt) {
04081          hanguptone_indicate(ch);
04082          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04083       } else
04084          misdn_lib_send_event(bc, EVENT_RELEASE);
04085    }
04086 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3123 of file chan_misdn.c.

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

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

03124 {
03125    if (!cl) return -1;
03126 
03127    cl->notxtone = 1;
03128    cl->norxtone = 1;
03129    
03130    return 0;
03131 }

static int stop_indicate ( struct chan_list cl  )  [static]

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

03096 {
03097    struct ast_channel *ast = cl->ast;
03098 
03099    if (!ast) {
03100       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03101       return -1;
03102    }
03103 
03104    chan_misdn_log(3, cl->bc->port, " --> None\n");
03105    misdn_lib_tone_generator_stop(cl->bc);
03106    ast_playtones_stop(ast);
03107 
03108    cl->ts = NULL;
03109    /*ast_deactivate_generator(ast);*/
03110 
03111    return 0;
03112 }

static int unload_module ( void   )  [static]

TE STUFF END

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

05126 {
05127    /* First, take us out of the channel loop */
05128    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05129 
05130    misdn_tasks_destroy();
05131    
05132    if (!g_config_initialized)
05133       return 0;
05134    
05135    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05136    
05137    /* ast_unregister_application("misdn_crypt"); */
05138    ast_unregister_application("misdn_set_opt");
05139    ast_unregister_application("misdn_facility");
05140    ast_unregister_application("misdn_check_l2l1");
05141   
05142    ast_channel_unregister(&misdn_tech);
05143 
05144    free_robin_list();
05145    misdn_cfg_destroy();
05146    misdn_lib_destroy();
05147   
05148    free(misdn_out_calls);
05149    free(misdn_in_calls);
05150    free(misdn_debug_only);
05151    free(misdn_ports);
05152    free(misdn_debug);
05153    
05154    return 0;
05155 }

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

Updates caller ID information from config.

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

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

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

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

01888 {
01889    int ec;
01890    int port = bc->port;
01891 
01892    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
01893 
01894    if (ec == 1) {
01895       bc->ec_enable = 1;
01896    } else if (ec > 1) {
01897       bc->ec_enable = 1;
01898       bc->ec_deftaps = ec;
01899    }
01900 
01901    return 0;
01902 }

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

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

03414 {
03415    int chan_offset = 0;
03416    int tmp_port = misdn_cfg_get_next_port(0);
03417    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03418       if (tmp_port == port)
03419          break;
03420       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03421    }
03422    if (c < 0)
03423       c = 0;
03424 
03425    ast_string_field_build(tmp, name, "%s/%d-u%d",
03426       misdn_type, chan_offset + c, glob_channel++);
03427 
03428    chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03429 }

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

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

04088                                                                                                        {
04089    ch->state=MISDN_WAITING4DIGS;
04090    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04091    if (bc->nt && !bc->dad[0])
04092       dialtone_indicate(ch);
04093 }


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

struct allowed_bearers allowed_bearers_array[] [static]

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

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1673 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 516 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 517 of file chan_misdn.c.

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

struct chan_list dummy_cl

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

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

int max_ports [static]

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

int* misdn_debug [static]

Definition at line 503 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 504 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 507 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 508 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 479 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 476 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 477 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

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

Referenced by misdn_new().

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

Definition at line 496 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 501 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 426 of file chan_misdn.c.

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 1180 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 498 of file chan_misdn.c.

Referenced by load_module().


Generated on Sat Aug 6 00:39:47 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7