Wed Mar 3 22:48:59 2010

Asterisk developer's documentation


chan_misdn.c File Reference

the chan_misdn channel driver for Asterisk More...

#include "asterisk.h"
#include <pthread.h>
#include <sys/socket.h>
#include <sys/time.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/module.h"
#include "asterisk/pbx.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/abstract_jb.h"
#include "asterisk/causes.h"
#include "chan_misdn_config.h"
#include "isdn_lib.h"
#include "asterisk/strings.h"
Include dependency graph for chan_misdn.c:

Go to the source code of this file.

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 (struct ast_cli_args *a)
static char * complete_debug_port (struct ast_cli_args *a)
static char * complete_show_config (struct ast_cli_args *a)
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 char * handle_cli_misdn_port_block (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_down (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_unblock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_up (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_restart_pid (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_restart_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_digit (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_display (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_facility (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_restart (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_crypt_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_tics (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_config (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_ports_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_stacks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_toggle_echocancel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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).
struct 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 struct ast_framemisdn_read (struct ast_channel *ast)
static struct ast_channelmisdn_request (const char *type, int format, void *data, int *cause)
static int misdn_send_text (struct ast_channel *chan, const char *text)
static int misdn_set_opt_exec (struct ast_channel *chan, void *data)
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_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 , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct allowed_bearers allowed_bearers_array []
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry chan_misdn_clis []
struct chan_listcl_te = NULL
 Global channel call record list head.
ast_mutex_t cl_te_lock
struct 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
#define ORG_AST   1
#define ORG_MISDN   2

Definition at line 134 of file chan_misdn.c.

Referenced by cb_events(), and misdn_indication().

#define TRANSFER_ON_HELD_CALL_HANGUP   1

Definition at line 3767 of file chan_misdn.c.


Enumeration Type Documentation

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

00116                       {
00117    MISDN_NOTHING=0,  /*!< at beginning */
00118    MISDN_WAITING4DIGS, /*!<  when waiting for infos */
00119    MISDN_EXTCANTMATCH, /*!<  when asterisk couldn't match our ext */
00120    MISDN_INCOMING_SETUP, /*!<  for incoming setups*/
00121    MISDN_DIALING, /*!<  when pbx_start */
00122    MISDN_PROGRESS, /*!<  we got a progress */
00123    MISDN_PROCEEDING, /*!<  we got a progress */
00124    MISDN_CALLING, /*!<  when misdn_call is called */
00125    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
00126    MISDN_ALERTING, /*!<  when Alerting */
00127    MISDN_BUSY, /*!<  when BUSY */
00128    MISDN_CONNECTED, /*!<  when connected */
00129    MISDN_DISCONNECTED, /*!<  when connected */
00130    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00131 };

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

00136                       {
00137    MISDN_HOLD_IDLE,     /*!< HOLD not active */
00138    MISDN_HOLD_ACTIVE,      /*!< Call is held */
00139    MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
00140    MISDN_HOLD_DISCONNECT,  /*!< Held call is being disconnected */
00141 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 6133 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by misdn_tasks_add(), and misdn_tasks_add_variable().

00810 {
00811    int task_id;
00812 
00813    if (!misdn_tasks) {
00814       misdn_tasks_init();
00815    }
00816    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
00817    misdn_tasks_wakeup();
00818 
00819    return task_id;
00820 }

int add_in_calls ( int  port  ) 

Definition at line 4254 of file chan_misdn.c.

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

Referenced by cb_events().

04255 {
04256    int max_in_calls;
04257    
04258    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04259    misdn_in_calls[port]++;
04260 
04261    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04262       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04263       return misdn_in_calls[port] - max_in_calls;
04264    }
04265    
04266    return 0;
04267 }

int add_out_calls ( int  port  ) 

Definition at line 4269 of file chan_misdn.c.

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

Referenced by misdn_call().

04270 {
04271    int max_out_calls;
04272    
04273    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04274 
04275    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04276       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04277       return (misdn_out_calls[port] + 1) - max_out_calls;
04278    }
04279 
04280    misdn_out_calls[port]++;
04281    
04282    return 0;
04283 }

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

Definition at line 607 of file chan_misdn.c.

References ARRAY_LEN, and allowed_bearers::display.

Referenced by cb_events(), 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    }
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]

queue new chan

Sending SETUP_ACK

Supplementary Services

Definition at line 4309 of file chan_misdn.c.

References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, 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_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pickup_call(), ast_pickup_ext(), AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_queue_frame(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_transfercapability2str(), ast_tv(), ast_tvnow(), chan_list::bc, misdn_bchannel::bc_state, bc_state2str(), bearer2str(), misdn_bchannel::bframe, misdn_bchannel::bframe_len, misdn_bchannel::cad, misdn_bchannel::capability, misdn_bchannel::cause, cb_log, chan, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, misdn_bchannel::chargingUnit, ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::currency, misdn_bchannel::cw, misdn_bchannel::dad, ast_frame::data, ast_frame::datalen, ast_frame::delivery, do_immediate_setup(), misdn_bchannel::dtmf, misdn_bchannel::dummy, errno, EVENT_ALERTING, EVENT_BCHAN_ACTIVATED, EVENT_BCHAN_DATA, EVENT_BCHAN_ERROR, EVENT_CLEANUP, EVENT_CONNECT, EVENT_CONNECT_ACKNOWLEDGE, EVENT_DISCONNECT, EVENT_DTMF_TONE, EVENT_FACILITY, EVENT_HOLD, EVENT_HOLD_ACKNOWLEDGE, EVENT_HOLD_REJECT, EVENT_INFORMATION, EVENT_NEW_BC, EVENT_NEW_CHANNEL, EVENT_NEW_L3ID, EVENT_PORT_ALARM, EVENT_PROCEEDING, EVENT_PROGRESS, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, EVENT_RESTART, EVENT_RETRIEVE, EVENT_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_REJECT, EVENT_SETUP, EVENT_SETUP_ACKNOWLEDGE, EVENT_STATUS, EVENT_TIMEOUT, EVENT_TONE_GENERATE, export_aoc_vars(), export_ch(), ast_channel::exten, misdn_bchannel::fac_in, chan_list::far_alerting, find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), ast_frame::frametype, 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, ast_frame::mallocd, 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, ast_frame::offset, ORG_AST, ORG_MISDN, chan_list::originator, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_builtin_setvar_helper(), pbx_start_chan(), misdn_bchannel::pid, chan_list::pipe, hold_info::port, misdn_bchannel::port, misdn_bchannel::pres, print_bearer(), print_facility(), misdn_bchannel::progress_indicator, ast_frame::ptr, read_config(), release_chan(), RESPONSE_IGNORE_SETUP, RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE, RESPONSE_OK, RESPONSE_RELEASE_SETUP, ast_channel::rings, ast_frame::samples, misdn_bchannel::screen, misdn_bchannel::sending_complete, ast_frame::src, start_bc_tones(), start_pbx(), hold_info::state, chan_list::state, stop_bc_tones(), stop_indicate(), ast_frame::subclass, ast_channel::tech, misdn_bchannel::tone_cnt, ast_channel::transfercapability, ast_channel_tech::type, update_name(), and wait_for_digits().

Referenced by load_module().

04310 {
04311    int msn_valid;
04312    struct chan_list *held_ch;
04313    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04314    
04315    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
04316       int debuglevel = 1;
04317       if ( event == EVENT_CLEANUP && !user_data)
04318          debuglevel = 5;
04319 
04320       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");
04321       if (debuglevel == 1) {
04322          misdn_lib_log_ies(bc);
04323          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04324       }
04325    }
04326    
04327    if (!ch) {
04328       switch(event) {
04329       case EVENT_SETUP:
04330       case EVENT_DISCONNECT:
04331       case EVENT_RELEASE:
04332       case EVENT_RELEASE_COMPLETE:
04333       case EVENT_PORT_ALARM:
04334       case EVENT_RETRIEVE:
04335       case EVENT_NEW_BC:
04336       case EVENT_FACILITY:
04337          break;
04338       case EVENT_CLEANUP:
04339       case EVENT_TONE_GENERATE:
04340       case EVENT_BCHAN_DATA:
04341          return -1;
04342       default:
04343          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);
04344          return -1;
04345       }
04346    }
04347    
04348    if (ch) {
04349       switch (event) {
04350       case EVENT_TONE_GENERATE:
04351          break;
04352       case EVENT_DISCONNECT:
04353       case EVENT_RELEASE:
04354       case EVENT_RELEASE_COMPLETE:
04355       case EVENT_CLEANUP:
04356       case EVENT_TIMEOUT:
04357          if (!ch->ast)
04358             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));
04359          break;
04360       default:
04361          if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04362             if (event != EVENT_BCHAN_DATA)
04363                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04364             return -1;
04365          }
04366       }
04367    }
04368    
04369    
04370    switch (event) {
04371    case EVENT_PORT_ALARM:
04372       {
04373          int boa = 0;
04374          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
04375          if (boa) {
04376             cb_log(1, bc->port, " --> blocking\n");
04377             misdn_lib_port_block(bc->port); 
04378          }
04379       }
04380       break;
04381    case EVENT_BCHAN_ACTIVATED:
04382       break;
04383       
04384    case EVENT_NEW_CHANNEL:
04385       update_name(ch->ast,bc->port,bc->channel);
04386       break;
04387       
04388    case EVENT_NEW_L3ID:
04389       ch->l3id=bc->l3_id;
04390       ch->addr=bc->addr;
04391       break;
04392 
04393    case EVENT_NEW_BC:
04394       if (!ch) {
04395          ch = find_hold_call(cl_te,bc);
04396       }
04397       
04398       if (!ch) {
04399          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04400          break;
04401       }
04402 
04403       if (bc)
04404          ch->bc = (struct misdn_bchannel *)user_data;
04405       break;
04406       
04407    case EVENT_DTMF_TONE:
04408    {
04409       /*  sending INFOS as DTMF-Frames :) */
04410       struct ast_frame fr;
04411 
04412       memset(&fr, 0, sizeof(fr));
04413       fr.frametype = AST_FRAME_DTMF;
04414       fr.subclass = bc->dtmf ;
04415       fr.src = NULL;
04416       fr.data.ptr = NULL;
04417       fr.datalen = 0;
04418       fr.samples = 0;
04419       fr.mallocd = 0;
04420       fr.offset = 0;
04421       fr.delivery = ast_tv(0,0);
04422       
04423       if (!ch->ignore_dtmf) {
04424          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04425          ast_queue_frame(ch->ast, &fr);
04426       } else {
04427          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04428       }
04429    }
04430       break;
04431    case EVENT_STATUS:
04432       break;
04433     
04434    case EVENT_INFORMATION:
04435    {
04436       if ( ch->state != MISDN_CONNECTED ) 
04437          stop_indicate(ch);
04438    
04439       if (!ch->ast)
04440          break;
04441 
04442       if (ch->state == MISDN_WAITING4DIGS ) {
04443          /*  Ok, incomplete Setup, waiting till extension exists */
04444          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04445             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04446             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04447          }
04448 
04449          strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04450          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04451 
04452          /* Check for Pickup Request first */
04453          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04454             if (ast_pickup_call(ch->ast)) {
04455                hangup_chan(ch, bc);
04456             } else {
04457                struct ast_channel *chan = ch->ast;
04458                ch->state = MISDN_CALLING_ACKNOWLEDGE;
04459                ast_setstate(chan, AST_STATE_DOWN);
04460                hangup_chan(ch, bc);
04461                ch->ast = NULL;
04462                break;
04463             }
04464          }
04465          
04466          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04467             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04468                ast_log(LOG_WARNING,
04469                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04470                   bc->dad, ch->context, bc->port);
04471                strcpy(ch->ast->exten, "i");
04472 
04473                ch->state = MISDN_DIALING;
04474                start_pbx(ch, bc, ch->ast);
04475                break;
04476             }
04477 
04478             ast_log(LOG_WARNING,
04479                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04480                "\tMaybe you want to add an 'i' extension to catch this case.\n",
04481                bc->dad, ch->context, bc->port);
04482 
04483             if (bc->nt)
04484                hanguptone_indicate(ch);
04485             ch->state = MISDN_EXTCANTMATCH;
04486             bc->out_cause = AST_CAUSE_UNALLOCATED;
04487 
04488             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04489             break;
04490          }
04491 
04492          if (ch->overlap_dial) {
04493             ast_mutex_lock(&ch->overlap_tv_lock);
04494             ch->overlap_tv = ast_tvnow();
04495             ast_mutex_unlock(&ch->overlap_tv_lock);
04496             if (ch->overlap_dial_task == -1) {
04497                ch->overlap_dial_task = 
04498                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04499             }
04500             break;
04501          }
04502 
04503          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04504             
04505             ch->state = MISDN_DIALING;
04506             start_pbx(ch, bc, ch->ast);
04507          }
04508       } else {
04509          /*  sending INFOS as DTMF-Frames :) */
04510          struct ast_frame fr;
04511          int digits;
04512 
04513          memset(&fr, 0, sizeof(fr));
04514          fr.frametype = AST_FRAME_DTMF;
04515          fr.subclass = bc->info_dad[0] ;
04516          fr.src = NULL;
04517          fr.data.ptr = NULL;
04518          fr.datalen = 0;
04519          fr.samples = 0;
04520          fr.mallocd = 0;
04521          fr.offset = 0;
04522          fr.delivery = ast_tv(0,0);
04523 
04524          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
04525          if (ch->state != MISDN_CONNECTED ) {
04526             if (digits) {
04527                strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04528                ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04529                ast_cdr_update(ch->ast);
04530             }
04531             
04532             ast_queue_frame(ch->ast, &fr);
04533          }
04534       }
04535    }
04536       break;
04537    case EVENT_SETUP:
04538    {
04539       struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04540       struct ast_channel *chan;
04541       int exceed;
04542       int pres, screen;
04543       int ai;
04544       int im;
04545 
04546       if (ch) {
04547          switch (ch->state) {
04548          case MISDN_NOTHING:
04549             ch = NULL;
04550             break;
04551          default:
04552             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04553             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
04554          }
04555       }
04556 
04557       msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04558       if (!bc->nt && ! msn_valid) {
04559          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04560          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04561       }
04562 
04563       if (bc->cw) {
04564          int cause;
04565          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04566          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04567          bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
04568          return RESPONSE_RELEASE_SETUP;
04569       }
04570 
04571       print_bearer(bc);
04572 
04573       ch = init_chan_list(ORG_MISDN);
04574 
04575       if (!ch) {
04576          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
04577          return 0;
04578       }
04579 
04580       ch->bc = bc;
04581       ch->l3id = bc->l3_id;
04582       ch->addr = bc->addr;
04583       ch->originator = ORG_MISDN;
04584 
04585       chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04586       if (!chan) {
04587          ast_free(ch);
04588          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04589          ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); 
04590          return 0;
04591       }
04592 
04593       ch->ast = chan;
04594 
04595       if ((exceed = add_in_calls(bc->port))) {
04596          char tmp[16];
04597          snprintf(tmp, sizeof(tmp), "%d", exceed);
04598          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
04599       }
04600 
04601       read_config(ch, ORG_MISDN);
04602 
04603       export_ch(chan, bc, ch);
04604 
04605       ch->ast->rings = 1;
04606       ast_setstate(ch->ast, AST_STATE_RINGING);
04607 
04608       switch (bc->pres) {
04609       case 1:
04610          pres = AST_PRES_RESTRICTED;
04611          chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
04612          break;
04613       case 2:
04614          pres = AST_PRES_UNAVAILABLE;
04615          chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
04616          break;
04617       default:
04618          pres = AST_PRES_ALLOWED;
04619          chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
04620          break;
04621       }
04622 
04623       switch (bc->screen) {
04624       default:
04625       case 0:
04626          screen = AST_PRES_USER_NUMBER_UNSCREENED;
04627          chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
04628          break;
04629       case 1:
04630          screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
04631          chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
04632          break;
04633       case 2:
04634          screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
04635          chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
04636          break;
04637       case 3:
04638          screen = AST_PRES_NETWORK_NUMBER;
04639          chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
04640          break;
04641       }
04642 
04643       chan->cid.cid_pres = pres | screen;
04644 
04645       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04646       chan->transfercapability = bc->capability;
04647 
04648       switch (bc->capability) {
04649       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04650          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
04651          break;
04652       default:
04653          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
04654       }
04655 
04656       /** queue new chan **/
04657       cl_queue_chan(&cl_te, ch);
04658 
04659       if (!strstr(ch->allowed_bearers, "all")) {
04660          int i;
04661 
04662          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
04663             if (allowed_bearers_array[i].cap == bc->capability) {
04664                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
04665                   /* The bearer capability is allowed */
04666                   if (allowed_bearers_array[i].deprecated) {
04667                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
04668                         allowed_bearers_array[i].name);
04669                   }
04670                   break;
04671                }
04672             }
04673          }  /* end for */
04674          if (i == ARRAY_LEN(allowed_bearers_array)) {
04675             /* We did not find the bearer capability */
04676             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
04677                bearer2str(bc->capability), bc->capability);
04678             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
04679 
04680             ch->state = MISDN_EXTCANTMATCH;
04681             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04682             return RESPONSE_OK;
04683          }
04684       }
04685 
04686       /* Check for Pickup Request first */
04687       if (!strcmp(chan->exten, ast_pickup_ext())) {
04688          if (!ch->noautorespond_on_setup) {
04689             int ret;/** Sending SETUP_ACK**/
04690             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04691          } else {
04692             ch->state = MISDN_INCOMING_SETUP;
04693          }
04694          if (ast_pickup_call(chan)) {
04695             hangup_chan(ch, bc);
04696          } else {
04697             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04698             ast_setstate(chan, AST_STATE_DOWN);
04699             hangup_chan(ch, bc);
04700             ch->ast = NULL;
04701             break;
04702          }
04703       }
04704 
04705       /*
04706        * added support for s extension hope it will help those poor cretains
04707        * which haven't overlap dial.
04708        */
04709       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04710       if (ai) {
04711          do_immediate_setup(bc, ch, chan);
04712          break;
04713       }
04714 
04715       /* check if we should jump into s when we have no dad */
04716       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04717       if (im && ast_strlen_zero(bc->dad)) {
04718          do_immediate_setup(bc, ch, chan);
04719          break;
04720       }
04721 
04722       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
04723       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04724          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04725             ast_log(LOG_WARNING,
04726                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04727                bc->dad, ch->context, bc->port);
04728             strcpy(ch->ast->exten, "i");
04729             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04730             ch->state = MISDN_DIALING;
04731             start_pbx(ch, bc, chan);
04732             break;
04733          }
04734 
04735          ast_log(LOG_WARNING,
04736             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04737             "\tMaybe you want to add an 'i' extension to catch this case.\n",
04738             bc->dad, ch->context, bc->port);
04739          if (bc->nt)
04740             hanguptone_indicate(ch);
04741 
04742          ch->state = MISDN_EXTCANTMATCH;
04743          bc->out_cause = AST_CAUSE_UNALLOCATED;
04744 
04745          if (bc->nt)
04746             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04747          else
04748             misdn_lib_send_event(bc, EVENT_RELEASE );
04749 
04750          break;
04751       }
04752 
04753       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
04754        * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
04755        * will be used by Asterisk automatically. */
04756       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04757          if (!ch->noautorespond_on_setup) {
04758             ch->state=MISDN_DIALING;
04759             misdn_lib_send_event(bc, EVENT_PROCEEDING );
04760          } else {
04761             ch->state = MISDN_INCOMING_SETUP;
04762          }
04763          start_pbx(ch, bc, chan);
04764          break;
04765       }
04766 
04767 
04768       /*
04769        * When we are NT and overlapdial is set and if 
04770        * the number is empty, we wait for the ISDN timeout
04771        * instead of our own timer.
04772        */
04773       if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04774          wait_for_digits(ch, bc, chan);
04775          break;
04776       }
04777 
04778       /* 
04779        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
04780        * Infos with a Interdigit Timeout.
04781        * */
04782       if (ch->overlap_dial) {
04783          ast_mutex_lock(&ch->overlap_tv_lock);
04784          ch->overlap_tv = ast_tvnow();
04785          ast_mutex_unlock(&ch->overlap_tv_lock);
04786 
04787          wait_for_digits(ch, bc, chan);
04788          if (ch->overlap_dial_task == -1) 
04789             ch->overlap_dial_task = 
04790                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04791 
04792          break;
04793       }
04794 
04795       /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
04796        * without interdigit timeout.
04797        * */
04798       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04799          wait_for_digits(ch, bc, chan);
04800          break;
04801       }
04802 
04803       /*
04804        * If the extension exists let's just jump into it.
04805        * */
04806       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04807          if (bc->need_more_infos)
04808             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04809          else
04810             misdn_lib_send_event(bc, EVENT_PROCEEDING);
04811 
04812          ch->state = MISDN_DIALING;
04813          start_pbx(ch, bc, chan);
04814          break;
04815       }
04816    }
04817    break;
04818 
04819    case EVENT_SETUP_ACKNOWLEDGE:
04820    {
04821       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04822 
04823       if (bc->channel) 
04824          update_name(ch->ast,bc->port,bc->channel);
04825       
04826       if (!ast_strlen_zero(bc->infos_pending)) {
04827          /* TX Pending Infos */
04828          strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04829 
04830          if (!ch->ast)
04831             break;
04832          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04833          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04834          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04835 
04836          misdn_lib_send_event(bc, EVENT_INFORMATION);
04837       }
04838    }
04839    break;
04840    case EVENT_PROCEEDING:
04841    {
04842       if (misdn_cap_is_speech(bc->capability) &&
04843            misdn_inband_avail(bc) ) {
04844          start_bc_tones(ch);
04845       }
04846 
04847       ch->state = MISDN_PROCEEDING;
04848       
04849       if (!ch->ast)
04850          break;
04851 
04852       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04853    }
04854    break;
04855    case EVENT_PROGRESS:
04856 
04857       if (bc->channel) 
04858          update_name(ch->ast, bc->port, bc->channel);
04859 
04860       if (!bc->nt ) {
04861          if ( misdn_cap_is_speech(bc->capability) &&
04862               misdn_inband_avail(bc)
04863             ) {
04864             start_bc_tones(ch);
04865          }
04866          
04867          ch->state = MISDN_PROGRESS;
04868 
04869          if (!ch->ast)
04870             break;
04871          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04872       }
04873       break;
04874       
04875       
04876    case EVENT_ALERTING:
04877    {
04878       ch->state = MISDN_ALERTING;
04879       
04880       if (!ch->ast)
04881          break;
04882 
04883       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04884       ast_setstate(ch->ast, AST_STATE_RINGING);
04885       
04886       cb_log(7, bc->port, " --> Set State Ringing\n");
04887       
04888       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04889          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04890          start_bc_tones(ch);
04891       } else {
04892          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04893          if (ch->far_alerting) {
04894             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04895             start_bc_tones(ch);
04896             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04897          }
04898       }
04899    }
04900    break;
04901    case EVENT_CONNECT:
04902    {
04903       struct ast_channel *bridged;
04904 
04905       /*we answer when we've got our very new L3 ID from the NT stack */
04906       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04907 
04908       if (!ch->ast)
04909          break;
04910 
04911       bridged = ast_bridged_channel(ch->ast);
04912       stop_indicate(ch);
04913 
04914       if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04915          struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04916 
04917          chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04918          if (bridged_ch) {
04919             bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04920             ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04921          }
04922       }
04923    }
04924    ch->l3id=bc->l3_id;
04925    ch->addr=bc->addr;
04926 
04927    start_bc_tones(ch);
04928    
04929    ch->state = MISDN_CONNECTED;
04930    
04931    ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04932    break;
04933    case EVENT_CONNECT_ACKNOWLEDGE:
04934    {
04935       ch->l3id = bc->l3_id;
04936       ch->addr = bc->addr;
04937 
04938       start_bc_tones(ch);
04939 
04940       ch->state = MISDN_CONNECTED;
04941    }
04942    break;
04943    case EVENT_DISCONNECT:
04944       /*we might not have an ch->ast ptr here anymore*/
04945       if (ch) {
04946          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);
04947          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04948             /* If there's inband information available (e.g. a
04949                recorded message saying what was wrong with the
04950                dialled number, or perhaps even giving an
04951                alternative number, then play it instead of
04952                immediately releasing the call */
04953             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04954       
04955             ch->state = MISDN_DISCONNECTED;
04956             start_bc_tones(ch);
04957 
04958             if (ch->ast) {
04959                ch->ast->hangupcause = bc->cause;
04960                if (bc->cause == AST_CAUSE_USER_BUSY)
04961                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04962             }
04963             ch->need_busy = 0;
04964             break;
04965          }
04966 
04967          bc->need_disconnect = 0;
04968          stop_bc_tones(ch);
04969 
04970          /* Check for held channel, to implement transfer */
04971          held_ch = find_hold_call(cl_te, bc);
04972          if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
04973             hangup_chan(ch, bc);
04974          }
04975       } else {
04976          held_ch = find_hold_call_l3(cl_te, bc->l3_id);
04977          if (held_ch && held_ch->hold.state == MISDN_HOLD_ACTIVE) {
04978             bc->need_disconnect = 0;
04979 
04980 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
04981             /*
04982              * Some phones disconnect the held call and the active call at the
04983              * same time to do the transfer.  Unfortunately, either call could
04984              * be disconnected first.
04985              */
04986             ch = find_hold_active_call(cl_te, bc);
04987             if (!ch || misdn_attempt_transfer(ch, held_ch)) {
04988                held_ch->hold.state = MISDN_HOLD_DISCONNECT;
04989                hangup_chan(held_ch, bc);
04990             }
04991 #else
04992             hangup_chan(held_ch, bc);
04993 #endif   /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
04994          }
04995       }
04996       bc->out_cause = -1;
04997       if (bc->need_release)
04998          misdn_lib_send_event(bc, EVENT_RELEASE);
04999       break;
05000    
05001    case EVENT_RELEASE:
05002       if (!ch) {
05003          ch = find_hold_call_l3(cl_te, bc->l3_id);
05004          if (!ch) {
05005             chan_misdn_log(1, bc->port,
05006                " --> no Ch, so we've already released. (%s)\n",
05007                manager_isdn_get_info(event));
05008             return -1;
05009          }
05010       }
05011 
05012       bc->need_disconnect = 0;
05013       bc->need_release = 0;
05014 
05015       hangup_chan(ch, bc);
05016       release_chan(ch, bc);
05017       break;
05018    case EVENT_RELEASE_COMPLETE:
05019       if (!ch) {
05020          ch = find_hold_call_l3(cl_te, bc->l3_id);
05021          if (!ch) {
05022             chan_misdn_log(1, bc->port,
05023                " --> no Ch, so we've already released. (%s)\n",
05024                manager_isdn_get_info(event));
05025             break;
05026          }
05027       }
05028 
05029       bc->need_disconnect = 0;
05030       bc->need_release = 0;
05031       bc->need_release_complete = 0;
05032 
05033       stop_bc_tones(ch);
05034       hangup_chan(ch, bc);
05035       release_chan(ch, bc);
05036       break;
05037    case EVENT_BCHAN_ERROR:
05038    case EVENT_CLEANUP:
05039    {
05040       stop_bc_tones(ch);
05041       
05042       switch (ch->state) {
05043       case MISDN_CALLING:
05044          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
05045          break;
05046       default:
05047          break;
05048       }
05049       
05050       hangup_chan(ch, bc);
05051       release_chan(ch, bc);
05052    }
05053    break;
05054 
05055    case EVENT_TONE_GENERATE:
05056    {
05057       int tone_len = bc->tone_cnt;
05058       struct ast_channel *ast = ch->ast;
05059       void *tmp;
05060       int res;
05061       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
05062 
05063       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
05064 
05065       if (!ast)
05066          break;
05067 
05068       if (!ast->generator)
05069          break;
05070 
05071       tmp = ast->generatordata;
05072       ast->generatordata = NULL;
05073       generate = ast->generator->generate;
05074 
05075       if (tone_len < 0 || tone_len > 512 ) {
05076          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
05077          tone_len = 128;
05078       }
05079 
05080       res = generate(ast, tmp, tone_len, tone_len);
05081       ast->generatordata = tmp;
05082       
05083       if (res) {
05084          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
05085          ast_deactivate_generator(ast);
05086       } else {
05087          bc->tone_cnt = 0;
05088       }
05089    }
05090    break;
05091 
05092    case EVENT_BCHAN_DATA:
05093    {
05094       if (ch->bc->AOCD_need_export)
05095          export_aoc_vars(ch->originator, ch->ast, ch->bc);
05096       if (!misdn_cap_is_speech(ch->bc->capability)) {
05097          struct ast_frame frame;
05098          /*In Data Modes we queue frames*/
05099          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
05100          frame.subclass = AST_FORMAT_ALAW;
05101          frame.datalen = bc->bframe_len;
05102          frame.samples = bc->bframe_len;
05103          frame.mallocd = 0;
05104          frame.offset = 0;
05105          frame.delivery = ast_tv(0,0);
05106          frame.src = NULL;
05107          frame.data.ptr = bc->bframe;
05108 
05109          if (ch->ast) 
05110             ast_queue_frame(ch->ast, &frame);
05111       } else {
05112          fd_set wrfs;
05113          struct timeval tv = { 0, 0 };
05114          int t;
05115 
05116          FD_ZERO(&wrfs);
05117          FD_SET(ch->pipe[1], &wrfs);
05118 
05119          t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
05120 
05121          if (!t) {
05122             chan_misdn_log(9, bc->port, "Select Timed out\n");
05123             break;
05124          }
05125          
05126          if (t < 0) {
05127             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
05128             break;
05129          }
05130          
05131          if (FD_ISSET(ch->pipe[1], &wrfs)) {
05132             chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
05133             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
05134                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
05135 
05136                stop_bc_tones(ch);
05137                hangup_chan(ch, bc);
05138                release_chan(ch, bc);
05139             }
05140          } else {
05141             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
05142          }
05143       }
05144    }
05145    break;
05146    case EVENT_TIMEOUT:
05147    {
05148       if (ch && bc)
05149          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
05150 
05151       switch (ch->state) {
05152       case MISDN_DIALING:
05153       case MISDN_PROGRESS:
05154          if (bc->nt && !ch->nttimeout)
05155             break;
05156          
05157       case MISDN_CALLING:
05158       case MISDN_ALERTING:
05159       case MISDN_PROCEEDING:
05160       case MISDN_CALLING_ACKNOWLEDGE:
05161          if (bc->nt) {
05162             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
05163             hanguptone_indicate(ch);
05164          }
05165             
05166          bc->out_cause = AST_CAUSE_UNALLOCATED;
05167          misdn_lib_send_event(bc, EVENT_DISCONNECT);
05168          break;
05169 
05170       case MISDN_WAITING4DIGS:
05171          if (bc->nt) {
05172             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
05173             bc->out_cause = AST_CAUSE_UNALLOCATED;
05174             hanguptone_indicate(ch);
05175             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05176          } else {
05177             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
05178             misdn_lib_send_event(bc, EVENT_RELEASE);
05179          }
05180             
05181          break;
05182 
05183       case MISDN_CLEANING: 
05184          chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
05185          break;
05186 
05187       default:
05188          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
05189       }
05190    }
05191    break;
05192 
05193     
05194    /****************************/
05195    /** Supplementary Services **/
05196    /****************************/
05197    case EVENT_RETRIEVE:
05198       if (!ch) {
05199          chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
05200          ch = find_hold_call_l3(cl_te, bc->l3_id);
05201          if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
05202             ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
05203             misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05204             break;
05205          }
05206       }
05207 
05208       /* remember the channel again */
05209       ch->bc = bc;
05210 
05211       ch->hold.state = MISDN_HOLD_IDLE;
05212       ch->hold.port = 0;
05213       ch->hold.channel = 0;
05214 
05215       ast_queue_control(ch->ast, AST_CONTROL_UNHOLD);
05216    
05217       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
05218          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
05219          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05220       }
05221       break;
05222     
05223    case EVENT_HOLD:
05224    {
05225       int hold_allowed;
05226       struct ast_channel *bridged;
05227 
05228       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
05229       if (!hold_allowed) {
05230          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
05231          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05232          break;
05233       }
05234 
05235       bridged = ast_bridged_channel(ch->ast);
05236       if (bridged) {
05237          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
05238          ch->l3id = bc->l3_id;
05239 
05240          /* forget the channel now */
05241          ch->bc = NULL;
05242          ch->hold.state = MISDN_HOLD_ACTIVE;
05243          ch->hold.port = bc->port;
05244          ch->hold.channel = bc->channel;
05245 
05246          ast_queue_control(ch->ast, AST_CONTROL_HOLD);
05247          
05248          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
05249       } else {
05250          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05251          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
05252       }
05253    } 
05254    break;
05255    
05256    case EVENT_FACILITY:
05257       print_facility(&(bc->fac_in), bc);
05258       
05259       switch (bc->fac_in.Function) {
05260 #ifdef HAVE_MISDN_FAC_RESULT
05261       case Fac_RESULT:
05262       break;
05263 #endif
05264       case Fac_CD:
05265          if (ch) {
05266             struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05267             struct chan_list *ch_br;
05268             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
05269                ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
05270                /*ch->state = MISDN_FACILITY_DEFLECTED;*/
05271                if (ch_br->bc) {
05272                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
05273                      ch_br->state = MISDN_DIALING;
05274                      if (pbx_start_chan(ch_br) < 0) {
05275                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
05276                      }
05277                   }
05278                }
05279             }
05280             misdn_lib_send_event(bc, EVENT_DISCONNECT);
05281          } 
05282          break;
05283       case Fac_AOCDCurrency:
05284          if (ch) {
05285             bc->AOCDtype = Fac_AOCDCurrency;
05286             memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
05287             bc->AOCD_need_export = 1;
05288             export_aoc_vars(ch->originator, ch->ast, bc);
05289          }
05290          break;
05291       case Fac_AOCDChargingUnit:
05292          if (ch) {
05293             bc->AOCDtype = Fac_AOCDChargingUnit;
05294             memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
05295             bc->AOCD_need_export = 1;
05296             export_aoc_vars(ch->originator, ch->ast, bc);
05297          }
05298          break;
05299       case Fac_None:
05300 #ifdef HAVE_MISDN_FAC_ERROR
05301       case Fac_ERROR:
05302 #endif
05303       break;
05304       default:
05305          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
05306       }
05307       
05308       break;
05309 
05310    case EVENT_RESTART:
05311 
05312       if (!bc->dummy) {
05313          stop_bc_tones(ch);
05314          release_chan(ch, bc);
05315       }
05316       break;
05317 
05318    default:
05319       chan_misdn_log(1, 0, "Got Unknown Event\n");
05320       break;
05321    }
05322    
05323    return RESPONSE_OK;
05324 }

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

Definition at line 5886 of file chan_misdn.c.

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

Referenced by load_module().

05887 {
05888    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05889    
05890    if (ch && ch->jb) {
05891       return misdn_jb_empty(ch->jb, buf, len);
05892    }
05893    
05894    return -1;
05895 }

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

Definition at line 6069 of file chan_misdn.c.

References ast_console_puts(), ast_log(), ast_strlen_zero(), buf, errno, and LOG_WARNING.

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

06070 {
06071    va_list ap;
06072    char buf[1024];
06073    char port_buf[8];
06074 
06075    if (! ((0 <= port) && (port <= max_ports))) {
06076       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
06077       port = 0;
06078       level = -1;
06079    }
06080 
06081    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
06082 
06083    va_start(ap, tmpl);
06084    vsnprintf(buf, sizeof(buf), tmpl, ap);
06085    va_end(ap);
06086 
06087    if (level == -1)
06088       ast_log(LOG_WARNING, "%s", buf);
06089 
06090    else if (misdn_debug_only[port] ? 
06091          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
06092        : level <= misdn_debug[port]) {
06093       
06094       ast_console_puts(port_buf);
06095       ast_console_puts(buf);
06096    }
06097    
06098    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
06099       char ctimebuf[30];
06100       time_t tm = time(NULL);
06101       char *tmp = ctime_r(&tm, ctimebuf), *p;
06102 
06103       FILE *fp = fopen(global_tracefile, "a+");
06104 
06105       p = strchr(tmp, '\n');
06106       if (p)
06107          *p = ':';
06108       
06109       if (!fp) {
06110          ast_console_puts("Error opening Tracefile: [ ");
06111          ast_console_puts(global_tracefile);
06112          ast_console_puts(" ] ");
06113          
06114          ast_console_puts(strerror(errno));
06115          ast_console_puts("\n");
06116          return ;
06117       }
06118       
06119       fputs(tmp, fp);
06120       fputs(" ", fp);
06121       fputs(port_buf, fp);
06122       fputs(" ", fp);
06123       fputs(buf, fp);
06124 
06125       fclose(fp);
06126    }
06127 }

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

Definition at line 3819 of file chan_misdn.c.

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

Referenced by release_chan(), and release_chan_early().

03820 {
03821    struct chan_list *help;
03822 
03823    if (chan->dsp) 
03824       ast_dsp_free(chan->dsp);
03825    if (chan->trans)
03826       ast_translator_free_path(chan->trans);
03827 
03828    ast_mutex_lock(&cl_te_lock);
03829    if (!*list) {
03830       ast_mutex_unlock(&cl_te_lock);
03831       return;
03832    }
03833   
03834    if (*list == chan) {
03835       *list = (*list)->next;
03836       ast_mutex_unlock(&cl_te_lock);
03837       return;
03838    }
03839   
03840    for (help = *list; help->next; help = help->next) {
03841       if (help->next == chan) {
03842          help->next = help->next->next;
03843          ast_mutex_unlock(&cl_te_lock);
03844          return;
03845       }
03846    }
03847    
03848    ast_mutex_unlock(&cl_te_lock);
03849 }

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

Definition at line 3803 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_request().

03804 {
03805    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03806   
03807    ast_mutex_lock(&cl_te_lock);
03808    if (!*list) {
03809       *list = chan;
03810    } else {
03811       struct chan_list *help = *list;
03812       for (; help->next; help = help->next); 
03813       help->next = chan;
03814    }
03815    chan->next = NULL;
03816    ast_mutex_unlock(&cl_te_lock);
03817 }

static char * complete_ch ( struct ast_cli_args a  )  [static]
static char * complete_debug_port ( struct ast_cli_args a  )  [static]

Definition at line 1864 of file chan_misdn.c.

References ast_strdup, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.

Referenced by handle_cli_misdn_set_debug().

01865 {
01866    if (a->n)
01867       return NULL;
01868 
01869    switch (a->pos) {
01870    case 4:
01871       if (a->word[0] == 'p')
01872          return ast_strdup("port");
01873       else if (a->word[0] == 'o')
01874          return ast_strdup("only");
01875       break;
01876    case 6:
01877       if (a->word[0] == 'o')
01878          return ast_strdup("only");
01879       break;
01880    }
01881    return NULL;
01882 }

static char * complete_show_config ( struct ast_cli_args a  )  [static]

Definition at line 1884 of file chan_misdn.c.

References ast_strdup, BUFFERSIZE, ast_cli_args::line, MISDN_CFG_FIRST, misdn_cfg_get_name(), misdn_cfg_get_next_port(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.

Referenced by handle_cli_misdn_show_config().

01885 {
01886    char buffer[BUFFERSIZE];
01887    enum misdn_cfg_elements elem;
01888    int wordlen = strlen(a->word);
01889    int which = 0;
01890    int port = 0;
01891 
01892    switch (a->pos) {
01893    case 3:
01894       if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n))
01895          return ast_strdup("description");
01896       if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n))
01897          return ast_strdup("descriptions");
01898       if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n))
01899          return ast_strdup("0");
01900       while ((port = misdn_cfg_get_next_port(port)) != -1) {
01901          snprintf(buffer, sizeof(buffer), "%d", port);
01902          if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
01903             return ast_strdup(buffer);
01904          }
01905       }
01906       break;
01907    case 4:
01908       if (strstr(a->line, "description ")) {
01909          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01910             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
01911                continue;
01912             misdn_cfg_get_name(elem, buffer, sizeof(buffer));
01913             if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
01914                if (++which > a->n)
01915                   return ast_strdup(buffer);
01916             }
01917          }
01918       } else if (strstr(a->line, "descriptions ")) {
01919          if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n))
01920             return ast_strdup("general");
01921          if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n))
01922             return ast_strdup("ports");
01923       }
01924       break;
01925    }
01926    return NULL;
01927 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

02040 {
02041    struct misdn_bchannel *bc = ch->bc;
02042    int len = ch->jb_len, threshold = ch->jb_upper_threshold;
02043    
02044    chan_misdn_log(5, bc->port, "config_jb: Called\n");
02045    
02046    if (! len) {
02047       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
02048       bc->nojitter=1;
02049    } else {
02050       if (len <= 100 || len > 8000) {
02051          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
02052          len = 1000;
02053       }
02054 
02055       if ( threshold > len ) {
02056          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
02057       }
02058 
02059       if ( ch->jb) {
02060          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
02061          misdn_jb_destroy(ch->jb);
02062          ch->jb = NULL;
02063       }
02064 
02065       ch->jb=misdn_jb_init(len, threshold);
02066 
02067       if (!ch->jb ) 
02068          bc->nojitter = 1;
02069    }
02070 }

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

Definition at line 2073 of file chan_misdn.c.

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

Referenced by read_config().

02074 {
02075    switch (numplan) {
02076    case NUMPLAN_INTERNATIONAL:
02077       chan_misdn_log(2, port, " --> %s: International\n", type);
02078       break;
02079    case NUMPLAN_NATIONAL:
02080       chan_misdn_log(2, port, " --> %s: National\n", type);
02081       break;
02082    case NUMPLAN_SUBSCRIBER:
02083       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
02084       break;
02085    case NUMPLAN_UNKNOWN:
02086       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
02087       break;
02088       /* Maybe we should cut off the prefix if present ? */
02089    default:
02090       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
02091       break;
02092    }
02093 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

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

03275 {
03276    const struct tone_zone_sound *ts = NULL;
03277    struct ast_channel *ast = cl->ast;
03278    int nd = 0;
03279 
03280    if (!ast) {
03281       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03282       return -1;
03283    }
03284 
03285    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03286 
03287    if (nd) {
03288       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03289       return 0;
03290    }
03291    
03292    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03293    ts = ast_get_indication_tone(ast->zone, "dial");
03294    cl->ts = ts;   
03295    
03296    if (ts) {
03297       cl->notxtone = 0;
03298       cl->norxtone = 0;
03299       /* This prods us in misdn_write */
03300       ast_playtones_start(ast, 0, ts->data, 0);
03301    }
03302 
03303    return 0;
03304 }

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

Definition at line 4077 of file chan_misdn.c.

References chan_list::ast, ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_FRAME_DTMF, ast_queue_frame(), ast_strdupa, 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::ptr, ast_frame::samples, ast_frame::src, chan_list::state, and ast_frame::subclass.

Referenced by cb_events().

04078 {
04079    char *predial;
04080    struct ast_frame fr;
04081 
04082    predial = ast_strdupa(ast->exten);
04083 
04084    ch->state = MISDN_DIALING;
04085 
04086    if (!ch->noautorespond_on_setup) {
04087       if (bc->nt) {
04088          int ret; 
04089          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04090       } else {
04091          int ret;
04092          if ( misdn_lib_is_ptp(bc->port)) {
04093             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04094          } else {
04095             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
04096          }
04097       }
04098    } else {
04099       ch->state = MISDN_INCOMING_SETUP;
04100    }
04101 
04102    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);
04103   
04104    strcpy(ast->exten, "s");
04105   
04106    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
04107       ast = NULL;
04108       bc->out_cause = AST_CAUSE_UNALLOCATED;
04109       hangup_chan(ch, bc);
04110       hanguptone_indicate(ch);
04111 
04112       if (bc->nt)
04113          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04114       else
04115          misdn_lib_send_event(bc, EVENT_DISCONNECT );
04116    }
04117   
04118   
04119    while (!ast_strlen_zero(predial) ) {
04120       fr.frametype = AST_FRAME_DTMF;
04121       fr.subclass = *predial;
04122       fr.src = NULL;
04123       fr.data.ptr = NULL;
04124       fr.datalen = 0;
04125       fr.samples = 0;
04126       fr.mallocd = 0;
04127       fr.offset = 0;
04128       fr.delivery = ast_tv(0,0);
04129 
04130       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04131          ast_queue_frame(ch->ast, &fr);
04132       }
04133       predial++;
04134    }
04135 }

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

Definition at line 687 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

04231 {
04232    char tmp[32];
04233    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04234    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04235    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04236 
04237    if (bc->sending_complete) {
04238       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04239       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04240    }
04241 
04242    if (bc->urate) {
04243       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04244       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04245    }
04246 
04247    if (bc->uulen)
04248       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04249 
04250    if (!ast_strlen_zero(bc->keypad)) 
04251       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04252 }

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

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

03714 {
03715    struct chan_list *help = list;
03716    for (; help; help = help->next) {
03717       if (help->bc == bc) return help;
03718    }
03719 
03720    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03721 
03722    return NULL;
03723 }

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

Definition at line 3725 of file chan_misdn.c.

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

Referenced by import_ch().

03726 {
03727    struct chan_list *help = list;
03728    for (; help; help = help->next) {
03729       if ( help->bc && (help->bc->pid == pid) ) return help;
03730    }
03731 
03732    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03733 
03734    return NULL;
03735 }

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

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

03784 {
03785    for (; list; list = list->next) {
03786       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
03787          && list->ast) {
03788          switch (list->state) {
03789          case MISDN_PROCEEDING:
03790          case MISDN_PROGRESS:
03791          case MISDN_ALERTING:
03792          case MISDN_CONNECTED:
03793             return list;
03794          default:
03795             break;
03796          }
03797       }
03798    }
03799    return NULL;
03800 }

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

Definition at line 3737 of file chan_misdn.c.

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

03738 {
03739    struct chan_list *help = list;
03740 
03741    if (bc->pri) return NULL;
03742 
03743    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03744    for (;help; help = help->next) {
03745       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
03746       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port)
03747          return help;
03748    }
03749    chan_misdn_log(6, bc->port, "$$$ find_hold_call: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03750 
03751    return NULL;
03752 }

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

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

03756 {
03757    struct chan_list *help = list;
03758 
03759    for (; help; help = help->next) {
03760       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id)
03761          return help;
03762    }
03763 
03764    return NULL;
03765 }

static void free_robin_list ( void   )  [static]

Definition at line 435 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

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

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

Definition at line 564 of file chan_misdn.c.

References chan_list::ast, 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, read]

Definition at line 575 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_send_digit(), handle_cli_misdn_send_display(), handle_cli_misdn_send_facility(), and handle_cli_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, read]

Definition at line 447 of file chan_misdn.c.

References ast_calloc, ast_free, ast_strdup, robin_list::group, robin_list::next, and robin_list::prev.

Referenced by misdn_request().

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

static char* handle_cli_misdn_port_block ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1028 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_block(), and ast_cli_entry::usage.

01029 {
01030    switch (cmd) {
01031    case CLI_INIT:
01032       e->command = "misdn port block";
01033       e->usage =
01034          "Usage: misdn port block <port>\n"
01035          "       Block the specified port by <port>.\n";
01036       return NULL;
01037    case CLI_GENERATE:
01038       return NULL;
01039    }
01040 
01041    if (a->argc != 4)
01042       return CLI_SHOWUSAGE;
01043 
01044    misdn_lib_port_block(atoi(a->argv[3]));
01045 
01046    return CLI_SUCCESS;
01047 }

static char* handle_cli_misdn_port_down ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1133 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_get_port_down(), and ast_cli_entry::usage.

01134 {
01135    switch (cmd) {
01136    case CLI_INIT:
01137       e->command = "misdn port down";
01138       e->usage =
01139          "Usage: misdn port down <port>\n"
01140          "       Try to deactivate the L1 on the given port.\n";
01141       return NULL;
01142    case CLI_GENERATE:
01143       return NULL;
01144    }
01145 
01146    if (a->argc != 4)
01147       return CLI_SHOWUSAGE;
01148 
01149    misdn_lib_get_port_down(atoi(a->argv[3]));
01150 
01151    return CLI_SUCCESS;
01152 }

static char* handle_cli_misdn_port_unblock ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1049 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_unblock(), and ast_cli_entry::usage.

01050 {
01051    switch (cmd) {
01052    case CLI_INIT:
01053       e->command = "misdn port unblock";
01054       e->usage =
01055          "Usage: misdn port unblock <port>\n"
01056          "       Unblock the port specified by <port>.\n";
01057       return NULL;
01058    case CLI_GENERATE:
01059       return NULL;
01060    }
01061 
01062    if (a->argc != 4)
01063       return CLI_SHOWUSAGE;
01064 
01065    misdn_lib_port_unblock(atoi(a->argv[3]));
01066 
01067    return CLI_SUCCESS;
01068 }

static char* handle_cli_misdn_port_up ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1112 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_get_port_up(), and ast_cli_entry::usage.

01113 {
01114    switch (cmd) {
01115    case CLI_INIT:
01116       e->command = "misdn port up";
01117       e->usage =
01118          "Usage: misdn port up <port>\n"
01119          "       Try to establish L1 on the given port.\n";
01120       return NULL;
01121    case CLI_GENERATE:
01122       return NULL;
01123    }
01124 
01125    if (a->argc != 4)
01126       return CLI_SHOWUSAGE;
01127 
01128    misdn_lib_get_port_up(atoi(a->argv[3]));
01129 
01130    return CLI_SUCCESS;
01131 }

static char* handle_cli_misdn_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1326 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, reload_config(), and ast_cli_entry::usage.

01327 {
01328    switch (cmd) {
01329    case CLI_INIT:
01330       e->command = "misdn reload";
01331       e->usage =
01332          "Usage: misdn reload\n"
01333          "       Reload internal mISDN config, read from the config\n"
01334          "       file.\n";
01335       return NULL;
01336    case CLI_GENERATE:
01337       return NULL;
01338    }
01339 
01340    if (a->argc != 2)
01341       return CLI_SHOWUSAGE;
01342 
01343    ast_cli(a->fd, "Reloading mISDN configuration\n");
01344    reload_config();
01345    return CLI_SUCCESS;
01346 }

static char* handle_cli_misdn_restart_pid ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1091 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_pid_restart(), and ast_cli_entry::usage.

01092 {
01093    switch (cmd) {
01094    case CLI_INIT:
01095       e->command = "misdn restart pid";
01096       e->usage =
01097          "Usage: misdn restart pid <pid>\n"
01098          "       Restart the given pid\n";
01099       return NULL;
01100    case CLI_GENERATE:
01101       return NULL;
01102    }
01103 
01104    if (a->argc != 4)
01105       return CLI_SHOWUSAGE;
01106 
01107    misdn_lib_pid_restart(atoi(a->argv[3]));
01108 
01109    return CLI_SUCCESS;
01110 }

static char* handle_cli_misdn_restart_port ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1070 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_port_restart(), and ast_cli_entry::usage.

01071 {
01072    switch (cmd) {
01073    case CLI_INIT:
01074       e->command = "misdn restart port";
01075       e->usage =
01076          "Usage: misdn restart port <port>\n"
01077          "       Restart the given port.\n";
01078       return NULL;
01079    case CLI_GENERATE:
01080       return NULL;
01081    }
01082 
01083    if (a->argc != 4)
01084       return CLI_SHOWUSAGE;
01085 
01086    misdn_lib_port_restart(atoi(a->argv[3]));
01087 
01088    return CLI_SUCCESS;
01089 }

static char* handle_cli_misdn_send_digit ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1728 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, chan_list::ast, ast_cli(), ast_dtmf_stream(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, get_chan_by_ast_name(), msg, msglen, send_digit_to_chan(), and ast_cli_entry::usage.

01729 {
01730    char *channame; 
01731    char *msg; 
01732    struct chan_list *tmp;
01733    int i, msglen;
01734 
01735    switch (cmd) {
01736    case CLI_INIT:
01737       e->command = "misdn send digit";
01738       e->usage =
01739          "Usage: misdn send digit <channel> \"<msg>\" \n"
01740          "       Send <digit> to <channel> as DTMF Tone\n"
01741          "       when channel is a mISDN channel\n";
01742       return NULL;
01743    case CLI_GENERATE:
01744       return complete_ch(a);
01745    }
01746 
01747    if (a->argc != 5)
01748       return CLI_SHOWUSAGE;
01749 
01750    channame = a->argv[3];
01751    msg = a->argv[4];
01752    msglen = strlen(msg);
01753 
01754    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01755 
01756    tmp = get_chan_by_ast_name(channame);
01757    if (!tmp) {
01758       ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
01759       return CLI_SUCCESS; 
01760    }
01761 #if 1
01762    for (i = 0; i < msglen; i++) {
01763       ast_cli(a->fd, "Sending: %c\n", msg[i]);
01764       send_digit_to_chan(tmp, msg[i]);
01765       /* res = ast_safe_sleep(tmp->ast, 250); */
01766       usleep(250000);
01767       /* res = ast_waitfor(tmp->ast,100); */
01768    }
01769 #else
01770    ast_dtmf_stream(tmp->ast, NULL, msg, 250);
01771 #endif
01772 
01773    return CLI_SUCCESS;
01774 }

static char* handle_cli_misdn_send_display ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1821 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), chan_list::bc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), misdn_bchannel::display, EVENT_INFORMATION, ast_cli_args::fd, get_chan_by_ast_name(), misdn_lib_send_event(), msg, and ast_cli_entry::usage.

01822 {
01823    char *channame;
01824    char *msg;
01825    struct chan_list *tmp;
01826 
01827    switch (cmd) {
01828    case CLI_INIT:
01829       e->command = "misdn send display";
01830       e->usage =
01831          "Usage: misdn send display <channel> \"<msg>\" \n"
01832          "       Send <msg> to <channel> as Display Message\n"
01833          "       when channel is a mISDN channel\n";
01834       return NULL;
01835    case CLI_GENERATE:
01836       return complete_ch(a);
01837    }
01838 
01839    if (a->argc != 5)
01840       return CLI_SHOWUSAGE;
01841 
01842    channame = a->argv[3];
01843    msg = a->argv[4];
01844 
01845    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01846    tmp = get_chan_by_ast_name(channame);
01847     
01848    if (tmp && tmp->bc) {
01849       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01850       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01851    } else {
01852       ast_cli(a->fd, "No such channel %s\n", channame);
01853       return CLI_SUCCESS;
01854    }
01855 
01856    return CLI_SUCCESS;
01857 }

static char* handle_cli_misdn_send_facility ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1608 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_copy_string(), ast_verbose, chan_list::bc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), EVENT_FACILITY, misdn_bchannel::fac_out, get_chan_by_ast_name(), misdn_lib_port_is_nt(), misdn_lib_send_event(), misdn_make_dummy(), and ast_cli_entry::usage.

01609 {
01610    char *channame; 
01611    char *nr;
01612    struct chan_list *tmp;
01613    int port; 
01614    char *served_nr;
01615    struct misdn_bchannel dummy, *bc=&dummy;
01616  
01617    switch (cmd) {
01618    case CLI_INIT:
01619       e->command = "misdn send facility";
01620       e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
01621       "\t type is one of:\n"
01622       "\t - calldeflect\n"
01623       "\t - CFActivate\n"
01624       "\t - CFDeactivate\n";
01625 
01626       return NULL;
01627    case CLI_GENERATE:
01628       return complete_ch(a);
01629    }
01630 
01631    if (a->argc < 5)
01632       return CLI_SHOWUSAGE;
01633  
01634    if (strstr(a->argv[3], "calldeflect")) {
01635       if (a->argc < 6) {
01636          ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
01637          return 0;
01638       }
01639       channame = a->argv[4];
01640       nr = a->argv[5];
01641 
01642       ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
01643       tmp = get_chan_by_ast_name(channame);
01644       if (!tmp) {
01645          ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
01646          return 0; 
01647       }
01648 
01649       if (strlen(nr) >= 15) {
01650          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
01651          return 0; 
01652       }
01653       tmp->bc->fac_out.Function = Fac_CD;
01654       ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
01655       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
01656    } else if (strstr(a->argv[3],"CFActivate")) {
01657       if (a->argc < 7) {
01658          ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
01659          return 0;
01660       }
01661       port = atoi(a->argv[4]);
01662       served_nr = a->argv[5];
01663       nr = a->argv[6];
01664 
01665       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01666 
01667       ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
01668 
01669       bc->fac_out.Function = Fac_CFActivate;
01670       bc->fac_out.u.CFActivate.BasicService = 0; //All Services
01671       bc->fac_out.u.CFActivate.Procedure = 0; //Unconditional
01672       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01673       ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
01674 
01675       misdn_lib_send_event(bc, EVENT_FACILITY);
01676    } else if (strstr(a->argv[3],"CFDeactivate")) {
01677       if (a->argc < 6) {
01678          ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
01679          return 0;
01680       }
01681       port = atoi(a->argv[4]);
01682       served_nr = a->argv[5];
01683       
01684       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01685       ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
01686 
01687       bc->fac_out.Function = Fac_CFDeactivate;
01688       bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
01689       bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
01690       
01691       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01692       misdn_lib_send_event(bc, EVENT_FACILITY);
01693    }
01694 
01695    return CLI_SUCCESS;
01696 }

static char* handle_cli_misdn_send_restart ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1698 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, misdn_bchannel::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, misdn_lib_send_restart(), and ast_cli_entry::usage.

01699 {
01700    int port;
01701    int channel;
01702 
01703    switch (cmd) {
01704    case CLI_INIT:
01705       e->command = "misdn send restart";
01706       e->usage =
01707          "Usage: misdn send restart [port [channel]]\n"
01708          "       Send a restart for every bchannel on the given port.\n";
01709       return NULL;
01710    case CLI_GENERATE:
01711       return NULL;
01712    }
01713 
01714    if (a->argc < 4 || a->argc > 5)
01715       return CLI_SHOWUSAGE;
01716 
01717    port = atoi(a->argv[3]);
01718    if (a->argc == 5) {
01719       channel = atoi(a->argv[4]);
01720       misdn_lib_send_restart(port, channel);
01721    } else {
01722       misdn_lib_send_restart(port, -1);
01723    }
01724 
01725    return CLI_SUCCESS;
01726 }

static char* handle_cli_misdn_set_crypt_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1006 of file chan_misdn.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

01007 {
01008    switch (cmd) {
01009    case CLI_INIT:
01010       e->command = "misdn set crypt debug";
01011       e->usage =
01012          "Usage: misdn set crypt debug <level>\n"
01013          "       Set the crypt debug level of the mISDN channel. Level\n"
01014          "       must be 1 or 2.\n";
01015       return NULL;
01016    case CLI_GENERATE:
01017       return NULL;
01018    }
01019 
01020    if (a->argc != 5)
01021       return CLI_SHOWUSAGE;
01022 
01023    /* Is this supposed to not do anything? */
01024 
01025    return CLI_SUCCESS;
01026 }

static char* handle_cli_misdn_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 931 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_debug_port(), ast_cli_args::fd, and ast_cli_entry::usage.

00932 {
00933    int level;
00934 
00935    switch (cmd) {
00936    case CLI_INIT:
00937       e->command = "misdn set debug";
00938       e->usage =
00939          "Usage: misdn set debug <level> [only] | [port <port> [only]]\n"
00940          "       Set the debug level of the mISDN channel.\n";
00941       return NULL;
00942    case CLI_GENERATE:
00943       return complete_debug_port(a);
00944    }
00945 
00946    if (a->argc < 4 || a->argc > 7)
00947       return CLI_SHOWUSAGE;
00948 
00949    level = atoi(a->argv[3]);
00950 
00951    switch (a->argc) {
00952    case 4:
00953    case 5:
00954       {
00955          int i;
00956          int only = 0;
00957          if (a->argc == 5) {
00958             if (strncasecmp(a->argv[4], "only", strlen(a->argv[4])))
00959                return CLI_SHOWUSAGE;
00960             else
00961                only = 1;
00962          }
00963    
00964          for (i = 0; i <= max_ports; i++) {
00965             misdn_debug[i] = level;
00966             misdn_debug_only[i] = only;
00967          }
00968          ast_cli(a->fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00969       }
00970       break;
00971    case 6:
00972    case 7:
00973       {
00974          int port;
00975          if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
00976             return CLI_SHOWUSAGE;
00977          port = atoi(a->argv[5]);
00978          if (port <= 0 || port > max_ports) {
00979             switch (max_ports) {
00980             case 0:
00981                ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00982                break;
00983             case 1:
00984                ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
00985                break;
00986             default:
00987                ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00988             }
00989             return 0;
00990          }
00991          if (a->argc == 7) {
00992             if (strncasecmp(a->argv[6], "only", strlen(a->argv[6])))
00993                return CLI_SHOWUSAGE;
00994             else
00995                misdn_debug_only[port] = 1;
00996          } else
00997             misdn_debug_only[port] = 0;
00998          misdn_debug[port] = level;
00999          ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
01000       }
01001    }
01002 
01003    return CLI_SUCCESS;
01004 }

static char* handle_cli_misdn_set_tics ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1503 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

01504 {
01505    switch (cmd) {
01506    case CLI_INIT:
01507       e->command = "misdn set tics";
01508       e->usage =
01509          "Usage: misdn set tics <value>\n";
01510       return NULL;
01511    case CLI_GENERATE:
01512       return NULL;
01513    }
01514 
01515    if (a->argc != 4)
01516       return CLI_SHOWUSAGE;
01517 
01518    MAXTICS = atoi(a->argv[3]);
01519 
01520    return CLI_SUCCESS;
01521 }

static char* handle_cli_misdn_show_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1465 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, chan_list::ast, chan_list::bc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, chan_list::next, print_bc_info(), and ast_cli_entry::usage.

01466 {
01467    struct chan_list *help;
01468 
01469    switch (cmd) {
01470    case CLI_INIT:
01471       e->command = "misdn show channel";
01472       e->usage =
01473          "Usage: misdn show channel <channel>\n"
01474          "       Show an internal mISDN channel\n.";
01475       return NULL;
01476    case CLI_GENERATE:
01477       return complete_ch(a);
01478    }
01479 
01480    if (a->argc != 4)
01481       return CLI_SHOWUSAGE;
01482 
01483    help = cl_te;
01484 
01485    for (; help; help = help->next) {
01486       struct misdn_bchannel *bc = help->bc;   
01487       struct ast_channel *ast = help->ast;
01488     
01489       if (bc && ast) {
01490          if (!strcasecmp(ast->name, a->argv[3])) {
01491             print_bc_info(a->fd, help, bc);
01492             break; 
01493          }
01494       } 
01495    }
01496 
01497    return CLI_SUCCESS;
01498 }

static char* handle_cli_misdn_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1403 of file chan_misdn.c.

References ast_cli_args::argc, chan_list::ast, ast_cli(), chan_list::bc, hold_info::channel, ast_channel::cid, ast_callerid::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel::exten, ast_cli_args::fd, chan_list::hold, chan_list::l3id, misdn_dump_chanlist(), MISDN_HOLD_IDLE, chan_list::next, misdn_bchannel::pid, hold_info::port, print_bc_info(), hold_info::state, and ast_cli_entry::usage.

01404 {
01405    struct chan_list *help;
01406 
01407    switch (cmd) {
01408    case CLI_INIT:
01409       e->command = "misdn show channels";
01410       e->usage =
01411          "Usage: misdn show channels\n"
01412          "       Show the internal mISDN channel list\n";
01413       return NULL;
01414    case CLI_GENERATE:
01415       return NULL;
01416    }
01417 
01418    if (a->argc != 3)
01419       return CLI_SHOWUSAGE;
01420 
01421    help = cl_te;
01422   
01423    ast_cli(a->fd, "Channel List: %p\n", cl_te);
01424 
01425    for (; help; help = help->next) {
01426       struct misdn_bchannel *bc = help->bc;   
01427       struct ast_channel *ast = help->ast;
01428       if (!ast) {
01429          if (!bc) {
01430             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
01431             continue;
01432          }
01433          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
01434          continue;
01435       }
01436 
01437       if (misdn_debug[0] > 2)
01438          ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
01439       if (bc) {
01440          print_bc_info(a->fd, help, bc);
01441       } else {
01442          if (help->hold.state != MISDN_HOLD_IDLE) {
01443             ast_cli(a->fd, "ITS A HELD CALL BC:\n");
01444             ast_cli(a->fd, " --> l3_id: %x\n"
01445                   " --> dad:%s oad:%s\n"
01446                   " --> hold_port: %d\n"
01447                   " --> hold_channel: %d\n",
01448                   help->l3id,
01449                   ast->exten,
01450                   ast->cid.cid_num,
01451                   help->hold.port,
01452                   help->hold.channel
01453                   );
01454          } else {
01455             ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
01456          }
01457       }
01458    }
01459 
01460    misdn_dump_chanlist();
01461 
01462    return CLI_SUCCESS;
01463 }

static char* handle_cli_misdn_show_config ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1177 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), BUFFERSIZE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_config(), ast_cli_args::fd, 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, show_config_description(), and ast_cli_entry::usage.

01178 {
01179    char buffer[BUFFERSIZE];
01180    enum misdn_cfg_elements elem;
01181    int linebreak;
01182    int onlyport = -1;
01183    int ok = 0;
01184 
01185    switch (cmd) {
01186    case CLI_INIT:
01187       e->command = "misdn show config";
01188       e->usage =
01189          "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
01190          "       Use 0 for <port> to only print the general config.\n";
01191       return NULL;
01192    case CLI_GENERATE:
01193       return complete_show_config(a);
01194    }
01195 
01196    if (a->argc >= 4) {
01197       if (!strcmp(a->argv[3], "description")) {
01198          if (a->argc == 5) {
01199             enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
01200             if (elem == MISDN_CFG_FIRST)
01201                ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
01202             else
01203                show_config_description(a->fd, elem);
01204             return CLI_SUCCESS;
01205          }
01206          return CLI_SHOWUSAGE;
01207       } else if (!strcmp(a->argv[3], "descriptions")) {
01208          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
01209             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01210                show_config_description(a->fd, elem);
01211                ast_cli(a->fd, "\n");
01212             }
01213             ok = 1;
01214          }
01215          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
01216             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
01217                show_config_description(a->fd, elem);
01218                ast_cli(a->fd, "\n");
01219             }
01220             ok = 1;
01221          }
01222          return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
01223       } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
01224          ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
01225          return CLI_SHOWUSAGE;
01226       }
01227    } else if (a->argc == 3 || onlyport == 0) {
01228       ast_cli(a->fd, "mISDN General-Config:\n");
01229       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
01230          misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
01231          ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01232       }
01233       ast_cli(a->fd, "\n");
01234    }
01235 
01236    if (onlyport < 0) {
01237       int port = misdn_cfg_get_next_port(0);
01238       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
01239          ast_cli(a->fd, "\n[PORT %d]\n", port);
01240          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01241             misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
01242             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01243          }  
01244          ast_cli(a->fd, "\n");
01245       }
01246    }
01247    
01248    if (onlyport > 0) {
01249       if (misdn_cfg_is_port_valid(onlyport)) {
01250          ast_cli(a->fd, "[PORT %d]\n", onlyport);
01251          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01252             misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
01253             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01254          }  
01255          ast_cli(a->fd, "\n");
01256       } else {
01257          ast_cli(a->fd, "Port %d is not active!\n", onlyport);
01258       }
01259    }
01260 
01261    return CLI_SUCCESS;
01262 }

static char* handle_cli_misdn_show_port ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1580 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_show_stack_details(), and ast_cli_entry::usage.

01581 {
01582    int port;
01583    char buf[128];
01584 
01585    switch (cmd) {
01586    case CLI_INIT:
01587       e->command = "misdn show port";
01588       e->usage =
01589          "Usage: misdn show port <port>\n"
01590          "       Show detailed information for given port.\n";
01591       return NULL;
01592    case CLI_GENERATE:
01593       return NULL;
01594    }
01595 
01596    if (a->argc != 4)
01597       return CLI_SHOWUSAGE;
01598 
01599    port = atoi(a->argv[3]);
01600 
01601    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01602    get_show_stack_details(port, buf);
01603    ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01604 
01605    return CLI_SUCCESS;
01606 }

static char* handle_cli_misdn_show_ports_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1552 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, misdn_cfg_get_next_port(), and ast_cli_entry::usage.

01553 {
01554    int port;
01555 
01556    switch (cmd) {
01557    case CLI_INIT:
01558       e->command = "misdn show ports stats";
01559       e->usage =
01560          "Usage: misdn show ports stats\n"
01561          "       Show mISDNs channel's call statistics per port.\n";
01562       return NULL;
01563    case CLI_GENERATE:
01564       return NULL;
01565    }
01566 
01567    if (a->argc != 4)
01568       return CLI_SHOWUSAGE;
01569 
01570    ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
01571    for (port = misdn_cfg_get_next_port(0); port > 0;
01572         port = misdn_cfg_get_next_port(port)) {
01573       ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
01574    }
01575    ast_cli(a->fd, "\n");
01576 
01577    return CLI_SUCCESS;
01578 }

static char* handle_cli_misdn_show_stacks ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1523 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli(), buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_show_stack_details(), misdn_cfg_get_next_port(), and ast_cli_entry::usage.

01524 {
01525    int port;
01526 
01527    switch (cmd) {
01528    case CLI_INIT:
01529       e->command = "misdn show stacks";
01530       e->usage =
01531          "Usage: misdn show stacks\n"
01532          "       Show internal mISDN stack_list.\n";
01533       return NULL;
01534    case CLI_GENERATE:
01535       return NULL;
01536    }
01537 
01538    if (a->argc != 3)
01539       return CLI_SHOWUSAGE;
01540 
01541    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01542    for (port = misdn_cfg_get_next_port(0); port > 0;
01543         port = misdn_cfg_get_next_port(port)) {
01544       char buf[128];
01545       get_show_stack_details(port, buf);
01546       ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01547    }
01548 
01549    return CLI_SUCCESS;
01550 }

static char* handle_cli_misdn_toggle_echocancel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1776 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), chan_list::bc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, get_chan_by_ast_name(), manager_ec_disable(), manager_ec_enable(), chan_list::toggle_ec, update_ec_config(), and ast_cli_entry::usage.

01777 {
01778    char *channame;
01779    struct chan_list *tmp;
01780 
01781    switch (cmd) {
01782    case CLI_INIT:
01783       e->command = "misdn toggle echocancel";
01784       e->usage =
01785          "Usage: misdn toggle echocancel <channel>\n"
01786          "       Toggle EchoCancel on mISDN Channel.\n";
01787       return NULL;
01788    case CLI_GENERATE:
01789       return complete_ch(a);
01790    }
01791 
01792    if (a->argc != 4)
01793       return CLI_SHOWUSAGE;
01794 
01795    channame = a->argv[3];
01796   
01797    ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
01798   
01799    tmp = get_chan_by_ast_name(channame);
01800    if (!tmp) {
01801       ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
01802       return CLI_SUCCESS;
01803    }
01804 
01805    tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
01806 
01807    if (tmp->toggle_ec) {
01808 #ifdef MISDN_1_2
01809       update_pipeline_config(tmp->bc);
01810 #else
01811       update_ec_config(tmp->bc);
01812 #endif
01813       manager_ec_enable(tmp->bc);
01814    } else {
01815       manager_ec_disable(tmp->bc);
01816    }
01817 
01818    return CLI_SUCCESS;
01819 }

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

Definition at line 3866 of file chan_misdn.c.

References chan_list::ast, ast_hangup(), ast_queue_hangup_with_cause(), misdn_bchannel::cause, 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().

03867 {
03868    int port;
03869 
03870    if (!ch) {
03871       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03872       return;
03873    }
03874 
03875    port = bc->port;
03876    cb_log(5, port, "hangup_chan called\n");
03877 
03878    if (ch->need_hangup) {
03879       cb_log(2, port, " --> hangup\n");
03880       ch->need_hangup = 0;
03881       ch->need_queue_hangup = 0;
03882       if (ch->ast) {
03883          send_cause2ast(ch->ast, bc, ch);
03884          ast_hangup(ch->ast);
03885       }
03886       return;
03887    }
03888 
03889    if (!ch->need_queue_hangup) {
03890       cb_log(2, port, " --> No need to queue hangup\n");
03891    }
03892 
03893    ch->need_queue_hangup = 0;
03894    if (ch->ast) {
03895       send_cause2ast(ch->ast, bc, ch);
03896       ast_queue_hangup_with_cause(ch->ast, bc->cause);
03897       cb_log(2, port, " --> queue_hangup\n");
03898    } else {
03899       cb_log(1, port, "Cannot hangup chan, no ast\n");
03900    }
03901 }

static void hanguptone_indicate ( struct chan_list cl  )  [static]
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 4196 of file chan_misdn.c.

References ast_copy_string(), ast_log(), chan_misdn_log(), 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().

04197 {
04198    const char *tmp;
04199 
04200    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04201    if (tmp) {
04202       ch->other_pid = atoi(tmp);
04203       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04204       if (ch->other_pid > 0) {
04205          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04206          if (ch->other_ch)
04207             ch->other_ch->other_ch = ch;
04208       }
04209    }
04210 
04211    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04212    if (tmp && (atoi(tmp) == 1)) {
04213       bc->sending_complete = 1;
04214    }
04215 
04216    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04217    if (tmp) {
04218       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04219       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04220       bc->uulen = strlen(bc->uu);
04221    }
04222 
04223    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04224    if (tmp) {
04225       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04226    }
04227 }

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

Definition at line 3350 of file chan_misdn.c.

References ast_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().

03351 {
03352    struct chan_list *cl;
03353 
03354    cl = ast_calloc(1, sizeof(*cl));
03355    if (!cl) {
03356       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03357       return NULL;
03358    }
03359    
03360    cl->originator = orig;
03361    cl->need_queue_hangup = 1;
03362    cl->need_hangup = 1;
03363    cl->need_busy = 1;
03364    cl->overlap_dial_task = -1;
03365 
03366    return cl;
03367 }

static int load_module ( void   )  [static]

Definition at line 5369 of file chan_misdn.c.

References ast_calloc, ast_channel_register(), ast_cli_register_multiple(), ast_free, ast_log(), ast_malloc, AST_MODULE_LOAD_DECLINE, ast_mutex_init(), ast_register_application, ast_strlen_zero(), BUFFERSIZE, misdn_lib_iface::cb_event, cb_events(), chan_misdn_jb_empty(), chan_misdn_log(), LOG_ERROR, 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_facility_exec(), MISDN_GEN_DEBUG, MISDN_GEN_NTDEBUGFILE, MISDN_GEN_NTDEBUGFLAGS, MISDN_GEN_NTKEEPCALLS, MISDN_GEN_TRACEFILE, misdn_l1_task(), misdn_lib_init(), misdn_lib_maxports_get(), misdn_lib_nt_debug_init(), misdn_lib_nt_keepcalls(), misdn_set_opt_exec(), misdn_tasks_add(), and unload_module().

05370 {
05371    int i, port;
05372    int ntflags = 0, ntkc = 0;
05373    char ports[256] = "";
05374    char tempbuf[BUFFERSIZE + 1];
05375    char ntfile[BUFFERSIZE + 1];
05376    struct misdn_lib_iface iface = {
05377       .cb_event = cb_events,
05378       .cb_log = chan_misdn_log,
05379       .cb_jb_empty = chan_misdn_jb_empty,
05380    };
05381 
05382    max_ports = misdn_lib_maxports_get();
05383    
05384    if (max_ports <= 0) {
05385       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05386       return AST_MODULE_LOAD_DECLINE;
05387    }
05388    
05389    if (misdn_cfg_init(max_ports, 0)) {
05390       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05391       return AST_MODULE_LOAD_DECLINE;
05392    }
05393    g_config_initialized = 1;
05394    
05395    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
05396    if (!misdn_debug) {
05397       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05398       return AST_MODULE_LOAD_DECLINE;
05399    }
05400    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
05401    if (!misdn_ports) {
05402       ast_free(misdn_debug);
05403       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05404       return AST_MODULE_LOAD_DECLINE;
05405    }
05406    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
05407    for (i = 1; i <= max_ports; i++) {
05408       misdn_debug[i] = misdn_debug[0];
05409       misdn_ports[i] = i;
05410    }
05411    *misdn_ports = 0;
05412    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
05413    if (!misdn_debug_only) {
05414       ast_free(misdn_ports);
05415       ast_free(misdn_debug);
05416       ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
05417       return AST_MODULE_LOAD_DECLINE;
05418    }
05419 
05420    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
05421    if (!ast_strlen_zero(tempbuf))
05422       tracing = 1;
05423 
05424    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05425    if (!misdn_in_calls) {
05426       ast_free(misdn_debug_only);
05427       ast_free(misdn_ports);
05428       ast_free(misdn_debug);
05429       ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
05430       return AST_MODULE_LOAD_DECLINE;
05431    }
05432    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05433    if (!misdn_out_calls) {
05434       ast_free(misdn_in_calls);
05435       ast_free(misdn_debug_only);
05436       ast_free(misdn_ports);
05437       ast_free(misdn_debug);
05438       ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
05439       return AST_MODULE_LOAD_DECLINE;
05440    }
05441 
05442    for (i = 1; i <= max_ports; i++) {
05443       misdn_in_calls[i] = 0;
05444       misdn_out_calls[i] = 0;
05445    }
05446 
05447    ast_mutex_init(&cl_te_lock);
05448    ast_mutex_init(&release_lock);
05449 
05450    misdn_cfg_update_ptp();
05451    misdn_cfg_get_ports_string(ports);
05452 
05453    if (!ast_strlen_zero(ports))
05454       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05455    if (misdn_lib_init(ports, &iface, NULL))
05456       chan_misdn_log(0, 0, "No te ports initialized\n");
05457 
05458    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
05459    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
05460    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
05461 
05462    misdn_lib_nt_keepcalls(ntkc);
05463    misdn_lib_nt_debug_init(ntflags, ntfile);
05464 
05465    if (ast_channel_register(&misdn_tech)) {
05466       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05467       unload_module();
05468       return AST_MODULE_LOAD_DECLINE;
05469    }
05470   
05471    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05472 
05473    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05474       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05475       "Sets mISDN opts. and optargs\n"
05476       "\n"
05477       "The available options are:\n"
05478       "    a - Have Asterisk detect DTMF tones on called channel\n"
05479       "    c - Make crypted outgoing call, optarg is keyindex\n"
05480       "    d - Send display text to called phone, text is the optarg\n"
05481       "    e - Perform echo cancelation on this channel,\n"
05482       "        takes taps as optarg (32,64,128,256)\n"
05483       "   e! - Disable echo cancelation on this channel\n"
05484       "    f - Enable fax detection\n"
05485       "    h - Make digital outgoing call\n"
05486       "   h1 - Make HDLC mode digital outgoing call\n"
05487       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05488       "        they will be transported inband.\n"
05489       "   jb - Set jitter buffer length, optarg is length\n"
05490       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05491       "   jn - Disable jitter buffer\n"
05492       "    n - Disable mISDN DSP on channel.\n"
05493       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05494       "    p - Caller ID presentation,\n"
05495       "        optarg is either 'allowed' or 'restricted'\n"
05496       "    s - Send Non-inband DTMF as inband\n"
05497       "   vr - Rx gain control, optarg is gain\n"
05498       "   vt - Tx gain control, optarg is gain\n"
05499       );
05500 
05501    
05502    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05503              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05504              "Sends the Facility Message FACILITY_TYPE with \n"
05505              "the given Arguments to the current ISDN Channel\n"
05506              "Supported Facilities are:\n"
05507              "\n"
05508              "type=calldeflect args=Nr where to deflect\n"
05509       );
05510 
05511 
05512    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05513              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05514              "Checks if the L2 and L1 are up on either the given <port> or\n"
05515              "on the ports in the group with <groupname>\n"
05516              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05517              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05518              "\n"
05519              "This application, ensures the L1/L2 state of the Ports in a group\n"
05520              "it is intended to make the pmp_l1_check option redundant and to\n"
05521              "fix a buggy switch config from your provider\n"
05522              "\n"
05523              "a sample dialplan would look like:\n\n"
05524              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05525              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05526              "\n"
05527       );
05528 
05529 
05530    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
05531 
05532    /* start the l1 watchers */
05533    
05534    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05535       int l1timeout;
05536       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05537       if (l1timeout) {
05538          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05539          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05540       }
05541    }
05542 
05543    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05544 
05545    return 0;
05546 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2492 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_PROTOCOL_ERROR, ast_copy_string(), ast_log(), ast_queue_hangup_with_cause(), 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().

02493 {
02494    struct chan_list *p;
02495    const char *tmp;
02496 
02497    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02498    
02499    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
02500    
02501    if (!p) {
02502       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02503       ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
02504    }
02505 
02506    if (!p->bc) {
02507       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
02508 
02509       ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
02510    }
02511 
02512    tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
02513    if (!ast_strlen_zero(tmp)) {
02514       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02515       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
02516    } else {
02517       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02518    }
02519 
02520    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02521    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
02522       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02523       p->bc->nodsp = 1;
02524       p->bc->hdlc = 0;
02525       p->bc->nojitter = 1;
02526    }
02527 
02528    p->state = MISDN_CONNECTED;
02529    stop_indicate(p);
02530 
02531    if ( ast_strlen_zero(p->bc->cad) ) {
02532       chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
02533       ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
02534    }
02535 
02536    misdn_lib_send_event( p->bc, EVENT_CONNECT);
02537    start_bc_tones(p);
02538 
02539    return 0;
02540 }

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

Definition at line 4042 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, hold_info::port, hold_info::state, and chan_list::state.

Referenced by cb_events().

04043 {
04044    int retval;
04045    struct ast_channel *bridged;
04046 
04047    switch (active_ch->state) {
04048    case MISDN_PROCEEDING:
04049    case MISDN_PROGRESS:
04050    case MISDN_ALERTING:
04051    case MISDN_CONNECTED:
04052       break;
04053    default:
04054       return -1;
04055    }
04056 
04057    bridged = ast_bridged_channel(held_ch->ast);
04058    if (bridged) {
04059       ast_queue_control(held_ch->ast, AST_CONTROL_UNHOLD);
04060       held_ch->hold.state = MISDN_HOLD_TRANSFER;
04061 
04062       chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
04063          held_ch->ast->name, active_ch->ast->name);
04064       retval = ast_channel_masquerade(active_ch->ast, bridged);
04065    } else {
04066       /*
04067        * Could not transfer.  Held channel is not bridged anymore.
04068        * Held party probably got tired of waiting and hung up.
04069        */
04070       retval = -1;
04071    }
04072 
04073    return retval;
04074 }

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 3170 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_verb, ast_waitfor_n(), ast_write(), chan_list::bc, chan_misdn_log(), ast_channel::exten, f, ast_frame::frametype, 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(), misdn_bchannel::oad, misdn_bchannel::pid, misdn_bchannel::port, and ast_frame::subclass.

03176 {
03177    struct chan_list *ch1, *ch2;
03178    struct ast_channel *carr[2], *who;
03179    int to = -1;
03180    struct ast_frame *f;
03181    int p1_b, p2_b;
03182    int bridging;
03183   
03184    ch1 = get_chan_by_ast(c0);
03185    ch2 = get_chan_by_ast(c1);
03186 
03187    carr[0] = c0;
03188    carr[1] = c1;
03189   
03190    if (!(ch1 && ch2))
03191       return -1;
03192 
03193    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
03194    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
03195 
03196    if (! p1_b || ! p2_b) {
03197       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03198       return AST_BRIDGE_FAILED;
03199    }
03200 
03201    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03202    if (bridging) {
03203       /* trying to make a mISDN_dsp conference */
03204       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03205       misdn_lib_bridge(ch1->bc, ch2->bc);
03206    }
03207 
03208    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03209 
03210    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03211  
03212    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
03213       ch1->ignore_dtmf = 1;
03214 
03215    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
03216       ch2->ignore_dtmf = 1;
03217 
03218    for (;/*ever*/;) {
03219       to = -1;
03220       who = ast_waitfor_n(carr, 2, &to);
03221 
03222       if (!who) {
03223          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03224          break;
03225       }
03226       f = ast_read(who);
03227 
03228       if (!f || f->frametype == AST_FRAME_CONTROL) {
03229          /* got hangup .. */
03230 
03231          if (!f) 
03232             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03233          else
03234             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03235 
03236          *fo = f;
03237          *rc = who;
03238          break;
03239       }
03240       
03241       if ( f->frametype == AST_FRAME_DTMF ) {
03242          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03243 
03244          *fo = f;
03245          *rc = who;
03246          break;
03247       }
03248    
03249 #if 0
03250       if (f->frametype == AST_FRAME_VOICE) {
03251          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03252    
03253          continue;
03254       }
03255 #endif
03256 
03257       if (who == c0) {
03258          ast_write(c1, f);
03259       }
03260       else {
03261          ast_write(c0, f);
03262       }
03263    }
03264 
03265    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03266 
03267    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03268 
03269    return AST_BRIDGE_COMPLETE;
03270 }

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

we should have l3id after sending setup

Definition at line 2352 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(), 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(), strsep(), ast_channel::transfercapability, and update_config().

02353 {
02354    int port = 0;
02355    int r;
02356    int exceed;
02357    int bridging;
02358    struct chan_list *ch;
02359    struct misdn_bchannel *newbc;
02360    char *opts, *ext;
02361    char *dest_cp;
02362 
02363    if (!ast) {
02364       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
02365       return -1;
02366    }
02367 
02368    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
02369       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02370       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02371       ast_setstate(ast, AST_STATE_DOWN);
02372       return -1;
02373    }
02374 
02375    ch = MISDN_ASTERISK_TECH_PVT(ast);
02376    if (!ch) {
02377       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02378       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02379       ast_setstate(ast, AST_STATE_DOWN);
02380       return -1;
02381    }
02382    
02383    newbc = ch->bc;
02384    if (!newbc) {
02385       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02386       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02387       ast_setstate(ast, AST_STATE_DOWN);
02388       return -1;
02389    }
02390    
02391    /*
02392     * dest is ---v
02393     * Dial(mISDN/g:group_name[/extension[/options]])
02394     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
02395     *
02396     * The dial extension could be empty if you are using MISDN_KEYPAD
02397     * to control ISDN provider features.
02398     */
02399    dest_cp = ast_strdupa(dest);
02400    strsep(&dest_cp, "/");/* Discard port/group token */
02401    ext = strsep(&dest_cp, "/");
02402    if (!ext) {
02403       ext = "";
02404    }
02405    opts = dest_cp;
02406    
02407    port = newbc->port;
02408 
02409    if ((exceed = add_out_calls(port))) {
02410       char tmp[16];
02411       snprintf(tmp, sizeof(tmp), "%d", exceed);
02412       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
02413       return -1;
02414    }
02415    
02416    chan_misdn_log(1, port, "* CALL: %s\n", dest);
02417    
02418    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
02419    
02420    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
02421    if (ast->exten) {
02422       ast_copy_string(ast->exten, ext, sizeof(ast->exten));
02423       ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
02424    }
02425 
02426    ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
02427 
02428    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
02429    if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
02430       ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
02431    }
02432 
02433    newbc->capability = ast->transfercapability;
02434    pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
02435    if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
02436       chan_misdn_log(2, port, " --> * Call with flag Digital\n");
02437    }
02438 
02439    /* update screening and presentation */ 
02440    update_config(ch, ORG_AST);
02441       
02442    /* fill in some ies from channel vary*/
02443    import_ch(ast, newbc, ch);
02444 
02445    /* Finally The Options Override Everything */
02446    if (opts)
02447       misdn_set_opt_exec(ast, opts);
02448    else
02449       chan_misdn_log(2, port, "NO OPTS GIVEN\n");
02450 
02451    /*check for bridging*/
02452    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
02453    if (bridging && ch->other_ch) {
02454 #ifdef MISDN_1_2
02455       chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
02456       *ch->bc->pipeline = 0;
02457       *ch->other_ch->bc->pipeline = 0;
02458 #else
02459       chan_misdn_log(1, port, "Disabling EC on both Sides\n");
02460       ch->bc->ec_enable = 0;
02461       ch->other_ch->bc->ec_enable = 0;
02462 #endif
02463    }
02464 
02465    r = misdn_lib_send_event( newbc, EVENT_SETUP );
02466 
02467    /** we should have l3id after sending setup **/
02468    ch->l3id = newbc->l3_id;
02469 
02470    if ( r == -ENOCHAN  ) {
02471       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
02472       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
02473       ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
02474       ast_setstate(ast, AST_STATE_DOWN);
02475       return -1;
02476    }
02477    
02478    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
02479 
02480    ast_setstate(ast, AST_STATE_DIALING);
02481    ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
02482    
02483    if (newbc->nt)
02484       stop_bc_tones(ch);
02485 
02486    ch->state = MISDN_CALLING;
02487    
02488    return 0; 
02489 }

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

Definition at line 5605 of file chan_misdn.c.

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

Referenced by load_module().

05606 {
05607    char *parse;
05608    char group[BUFFERSIZE + 1];
05609    char *port_str;
05610    int port = 0;
05611    int timeout;
05612    int dowait = 0;
05613    int port_up;
05614 
05615    AST_DECLARE_APP_ARGS(args,
05616          AST_APP_ARG(grouppar);
05617          AST_APP_ARG(timeout);
05618    );
05619 
05620    if (ast_strlen_zero((char *)data)) {
05621       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05622       return -1;
05623    }
05624 
05625    parse = ast_strdupa(data);
05626    AST_STANDARD_APP_ARGS(args, parse);
05627 
05628    if (args.argc != 2) {
05629       ast_log(LOG_WARNING, "Wrong argument count\n");
05630       return 0;
05631    }
05632 
05633    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05634    timeout = atoi(args.timeout);
05635    port_str = args.grouppar;
05636 
05637    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05638       /* We make a group call lets checkout which ports are in my group */
05639       port_str += 2;
05640       ast_copy_string(group, port_str, sizeof(group));
05641       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05642 
05643       for ( port = misdn_cfg_get_next_port(port); 
05644          port > 0;
05645          port = misdn_cfg_get_next_port(port)) {
05646          char cfg_group[BUFFERSIZE + 1];
05647 
05648          chan_misdn_log(2, 0, "trying port %d\n", port);
05649 
05650          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
05651 
05652          if (!strcasecmp(cfg_group, group)) {
05653             port_up = misdn_lib_port_up(port, 1);
05654 
05655             if (!port_up) {
05656                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05657                misdn_lib_get_port_up(port);
05658                dowait = 1;
05659             }
05660          }
05661       }
05662 
05663    } else {
05664       port = atoi(port_str);
05665       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05666       port_up = misdn_lib_port_up(port, 1);
05667       if (!port_up) {
05668          misdn_lib_get_port_up(port);
05669          dowait = 1;
05670       }
05671    }
05672 
05673    if (dowait) {
05674       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05675       ast_safe_sleep(chan, timeout * 1000);
05676    }
05677 
05678    return 0;
05679 }

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

Definition at line 2542 of file chan_misdn.c.

02543 {
02544    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02545    return 0;
02546 }

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

Definition at line 2548 of file chan_misdn.c.

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

02549 {
02550    struct chan_list *p;
02551    struct misdn_bchannel *bc;
02552    char buf[2] = { digit, 0 };
02553    
02554    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
02555 
02556    bc = p->bc;
02557    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
02558    
02559    if (!bc) {
02560       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
02561       return -1;
02562    }
02563    
02564    switch (p->state ) {
02565    case MISDN_CALLING:
02566       if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1)
02567          strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
02568       break;
02569    case MISDN_CALLING_ACKNOWLEDGE:
02570       ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
02571       if (strlen(bc->dad) < sizeof(bc->dad) - 1)
02572          strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
02573       ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
02574       misdn_lib_send_event( bc, EVENT_INFORMATION);
02575       break;
02576    default: 
02577          /* Do not send Digits in CONNECTED State, when
02578           * the other side is too mISDN. */
02579          if (p->other_ch ) 
02580             return 0;
02581 
02582          if ( bc->send_dtmf ) 
02583             send_digit_to_chan(p,digit);
02584       break;
02585    }
02586 
02587    return 0;
02588 }

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

Definition at line 5559 of file chan_misdn.c.

References ast_copy_string(), ast_log(), ast_strdupa, 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(), parse(), misdn_bchannel::port, ast_channel::tech, and ast_channel_tech::type.

Referenced by load_module().

05560 {
05561    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05562    char *parse, *tok, *tokb;
05563 
05564    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05565    
05566    if (strcasecmp(chan->tech->type, "mISDN")) {
05567       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05568       return -1;
05569    }
05570    
05571    if (ast_strlen_zero((char *)data)) {
05572       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05573       return -1;
05574    }
05575 
05576    parse = ast_strdupa(data);
05577    tok = strtok_r(parse, "|", &tokb) ;
05578 
05579    if (!tok) {
05580       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05581       return -1;
05582    }
05583 
05584    if (!strcasecmp(tok, "calldeflect")) {
05585       tok = strtok_r(NULL, "|", &tokb) ;
05586       
05587       if (!tok) {
05588          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05589       }
05590 
05591       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05592          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05593          return 0; 
05594       }
05595       ch->bc->fac_out.Function = Fac_CD;
05596       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05597       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05598    } else {
05599       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05600    }
05601 
05602    return 0;
05603 }

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

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

02592 {
02593    struct chan_list *p;
02594 
02595    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02596 
02597    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);
02598 
02599    p->ast = ast;
02600 
02601    return 0;
02602 }

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

Definition at line 1286 of file chan_misdn.c.

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

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

01287 {
01288    int i;
01289    static char state[8];
01290    
01291    if( !p) return NULL;
01292   
01293    for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
01294       if (state_array[i].state == p->state)
01295          return state_array[i].txt; 
01296    }
01297 
01298    snprintf(state, sizeof(state), "%d", p->state) ;
01299 
01300    return state;
01301 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2734 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_copy_string(), ast_debug, 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_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, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, 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.

02735 {
02736    struct chan_list *p;
02737    struct misdn_bchannel *bc;
02738    const char *var;
02739 
02740    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
02741       return -1;
02742    }
02743    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02744 
02745    ast_debug(1, "misdn_hangup(%s)\n", ast->name);
02746 
02747    if (p->hold.state == MISDN_HOLD_IDLE) {
02748       bc = p->bc;
02749    } else {
02750       p->hold.state = MISDN_HOLD_DISCONNECT;
02751       bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
02752       if (!bc) {
02753          chan_misdn_log(4, p->hold.port,
02754             "misdn_hangup: Could not find held bc for (%s)\n", ast->name);
02755          release_chan_early(p);
02756          return 0;
02757       }
02758    }
02759 
02760    if (ast->_state == AST_STATE_RESERVED || p->state == MISDN_NOTHING) {
02761       /* between request and call */
02762       ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
02763       release_chan_early(p);
02764       if (bc) {
02765          misdn_lib_release(bc);
02766       }
02767       return 0;
02768    }
02769    if (!bc) {
02770       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
02771          misdn_get_ch_state(p), p->l3id);
02772       release_chan_early(p);
02773       return 0;
02774    }
02775 
02776    p->ast = NULL;
02777    p->need_hangup = 0;
02778    p->need_queue_hangup = 0;
02779    p->need_busy = 0;
02780 
02781    if (!bc->nt) {
02782       stop_bc_tones(p);
02783    }
02784 
02785    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02786 
02787    var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
02788    if (!var) {
02789       var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
02790    }
02791    if (var) {
02792       int tmpcause;
02793 
02794       tmpcause = atoi(var);
02795       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02796    }
02797 
02798    var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
02799    if (var) {
02800       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
02801       ast_copy_string(bc->uu, var, sizeof(bc->uu));
02802       bc->uulen = strlen(bc->uu);
02803    }
02804 
02805    chan_misdn_log(1, bc->port,
02806       "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",
02807       bc->pid,
02808       ast->context,
02809       ast->exten,
02810       ast->cid.cid_num,
02811       misdn_get_ch_state(p));
02812    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02813    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02814    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02815 
02816    switch (p->state) {
02817    case MISDN_INCOMING_SETUP:
02818       /*
02819        * This is the only place in misdn_hangup, where we
02820        * can call release_chan, else it might create a lot of trouble.
02821        */
02822       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02823       release_chan(p, bc);
02824       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
02825       return 0;
02826    case MISDN_DIALING:
02827       if (p->hold.state == MISDN_HOLD_IDLE) {
02828          start_bc_tones(p);
02829          hanguptone_indicate(p);
02830       }
02831 
02832       p->state = MISDN_CLEANING;
02833       if (bc->need_disconnect) {
02834          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02835       }
02836       break;
02837    case MISDN_CALLING_ACKNOWLEDGE:
02838       if (p->hold.state == MISDN_HOLD_IDLE) {
02839          start_bc_tones(p);
02840          hanguptone_indicate(p);
02841       }
02842 
02843       if (bc->need_disconnect) {
02844          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02845       }
02846       break;
02847 
02848    case MISDN_CALLING:
02849    case MISDN_ALERTING:
02850    case MISDN_PROGRESS:
02851    case MISDN_PROCEEDING:
02852       if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
02853          hanguptone_indicate(p);
02854       }
02855 
02856       if (bc->need_disconnect) {
02857          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02858       }
02859       break;
02860    case MISDN_CONNECTED:
02861       /*  Alerting or Disconnect */
02862       if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
02863          start_bc_tones(p);
02864          hanguptone_indicate(p);
02865          bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
02866       }
02867       if (bc->need_disconnect) {
02868          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02869       }
02870       break;
02871    case MISDN_DISCONNECTED:
02872       if (bc->need_release) {
02873          misdn_lib_send_event(bc, EVENT_RELEASE);
02874       }
02875       break;
02876 
02877    case MISDN_CLEANING:
02878       return 0;
02879 
02880    case MISDN_BUSY:
02881       break;
02882    default:
02883       if (bc->nt) {
02884          bc->out_cause = -1;
02885          if (bc->need_release) {
02886             misdn_lib_send_event(bc, EVENT_RELEASE);
02887          }
02888       } else {
02889          if (bc->need_disconnect) {
02890             misdn_lib_send_event(bc, EVENT_DISCONNECT);
02891          }
02892       }
02893       break;
02894    }
02895 
02896    p->state = MISDN_CLEANING;
02897    chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast->name,
02898       misdn_get_ch_state(p));
02899 
02900    return 0;
02901 }

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

Definition at line 2606 of file chan_misdn.c.

References 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(), chan_list::mohinterpret, 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().

02607 {
02608    struct chan_list *p;
02609 
02610    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02611       ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
02612       return -1;
02613    }
02614    
02615    if (!p->bc) {
02616       if (p->hold.state == MISDN_HOLD_IDLE) {
02617          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
02618             ast->name);
02619          ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02620       } else {
02621          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
02622             cond, ast->name);
02623       }
02624       return -1;
02625    }
02626    
02627    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n\n", cond, ast->name);
02628    
02629    switch (cond) {
02630    case AST_CONTROL_BUSY:
02631       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
02632       ast_setstate(ast, AST_STATE_BUSY);
02633 
02634       p->bc->out_cause = AST_CAUSE_USER_BUSY;
02635       if (p->state != MISDN_CONNECTED) {
02636          start_bc_tones(p);
02637          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02638       }
02639       return -1;
02640    case AST_CONTROL_RING:
02641       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02642       return -1;
02643    case AST_CONTROL_RINGING:
02644       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02645       switch (p->state) {
02646       case MISDN_ALERTING:
02647          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);
02648          break;
02649       case MISDN_CONNECTED:
02650          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);
02651          return -1;
02652       default:
02653          p->state = MISDN_ALERTING;
02654          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02655          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02656 
02657          if (p->other_ch && p->other_ch->bc) {
02658             if (misdn_inband_avail(p->other_ch->bc)) {
02659                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02660                break;
02661             }
02662 
02663             if (!p->other_ch->bc->nt) {
02664                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02665                break;
02666             }
02667          }
02668 
02669          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02670          ast_setstate(ast, AST_STATE_RING);
02671 
02672          if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio)
02673             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02674          else 
02675             return -1;
02676       }
02677       break;
02678    case AST_CONTROL_ANSWER:
02679       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02680       start_bc_tones(p);
02681       break;
02682    case AST_CONTROL_TAKEOFFHOOK:
02683       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02684       return -1;
02685    case AST_CONTROL_OFFHOOK:
02686       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02687       return -1;
02688    case AST_CONTROL_FLASH:
02689       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02690       break;
02691    case AST_CONTROL_PROGRESS:
02692       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02693       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02694       break;
02695    case AST_CONTROL_PROCEEDING:
02696       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02697       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02698       break;
02699    case AST_CONTROL_CONGESTION:
02700       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02701 
02702       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02703       start_bc_tones(p);
02704       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02705 
02706       if (p->bc->nt) {
02707          hanguptone_indicate(p);
02708       }
02709       break;
02710    case -1 :
02711       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02712 
02713       stop_indicate(p);
02714 
02715       if (p->state == MISDN_CONNECTED) 
02716          start_bc_tones(p);
02717       break;
02718    case AST_CONTROL_HOLD:
02719       ast_moh_start(ast, data, p->mohinterpret); 
02720       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02721       break;
02722    case AST_CONTROL_UNHOLD:
02723       ast_moh_stop(ast);
02724       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02725       break;
02726    default:
02727       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02728       return -1;
02729    }
02730   
02731    return 0;
02732 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

Definition at line 5946 of file chan_misdn.c.

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

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

05947 {
05948    ast_mutex_destroy(&jb->mutexjb);
05949    
05950    ast_free(jb->ok);
05951    ast_free(jb->samples);
05952    ast_free(jb);
05953 }

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

06017 {
06018    int i, wp, rp, read = 0;
06019 
06020    ast_mutex_lock(&jb->mutexjb);
06021 
06022    rp = jb->rp;
06023    wp = jb->wp;
06024 
06025    if (jb->state_empty) {  
06026       for (i = 0; i < len; i++) {
06027          if (wp == rp) {
06028             jb->rp = rp;
06029             jb->state_empty = 0;
06030 
06031             ast_mutex_unlock(&jb->mutexjb);
06032 
06033             return read;
06034          } else {
06035             if (jb->ok[rp] == 1) {
06036                data[i] = jb->samples[rp];
06037                jb->ok[rp] = 0;
06038                rp = (rp != jb->size - 1) ? rp + 1 : 0;
06039                read += 1;
06040             }
06041          }
06042       }
06043 
06044       if (wp >= rp)
06045          jb->state_buffer = wp - rp;
06046       else
06047          jb->state_buffer = jb->size - rp + wp;
06048       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
06049 
06050       jb->rp = rp;
06051    } else
06052       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
06053 
06054    ast_mutex_unlock(&jb->mutexjb);
06055 
06056    return read;
06057 }

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

References ast_mutex_lock(), ast_mutex_unlock(), misdn_jb::bytes_wrote, 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.

Referenced by misdn_write().

05958 {
05959    int i, j, rp, wp;
05960 
05961    if (!jb || ! data)
05962       return 0;
05963 
05964    ast_mutex_lock(&jb->mutexjb);
05965    
05966    wp = jb->wp;
05967    rp = jb->rp;
05968    
05969    for (i = 0; i < len; i++) {
05970       jb->samples[wp] = data[i];
05971       jb->ok[wp] = 1;
05972       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05973 
05974       if (wp == jb->rp)
05975          jb->state_full = 1;
05976    }
05977 
05978    if (wp >= rp)
05979       jb->state_buffer = wp - rp;
05980    else
05981       jb->state_buffer = jb->size - rp + wp;
05982    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05983 
05984    if (jb->state_full) {
05985       jb->wp = wp;
05986 
05987       rp = wp;
05988       for (j = 0; j < jb->upper_threshold; j++)
05989          rp = (rp != 0) ? rp - 1 : jb->size - 1;
05990       jb->rp = rp;
05991       jb->state_full = 0;
05992       jb->state_empty = 1;
05993 
05994       ast_mutex_unlock(&jb->mutexjb);
05995 
05996       return -1;
05997    }
05998 
05999    if (!jb->state_empty) {
06000       jb->bytes_wrote += len;
06001       if (jb->bytes_wrote >= jb->upper_threshold) {
06002          jb->state_empty = 1;
06003          jb->bytes_wrote = 0;
06004       }
06005    }
06006    jb->wp = wp;
06007 
06008    ast_mutex_unlock(&jb->mutexjb);
06009    
06010    return 0;
06011 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
) [read]

allocates the jb-structure and initialize the elements

Definition at line 5905 of file chan_misdn.c.

References ast_free, ast_malloc, ast_mutex_init(), misdn_jb::bytes_wrote, chan_misdn_log(), 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().

05906 {
05907    int i;
05908    struct misdn_jb *jb;
05909 
05910    jb = ast_malloc(sizeof(*jb));
05911    if (!jb) {
05912        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05913        return NULL;
05914    }
05915    jb->size = size;
05916    jb->upper_threshold = upper_threshold;
05917    jb->wp = 0;
05918    jb->rp = 0;
05919    jb->state_full = 0;
05920    jb->state_empty = 0;
05921    jb->bytes_wrote = 0;
05922    jb->samples = ast_malloc(size * sizeof(char));
05923    if (!jb->samples) {
05924       ast_free(jb);
05925       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05926       return NULL;
05927    }
05928 
05929    jb->ok = ast_malloc(size * sizeof(char));
05930    if (!jb->ok) {
05931       ast_free(jb->samples);
05932       ast_free(jb);
05933       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05934       return NULL;
05935    }
05936 
05937    for (i = 0; i < size; i++)
05938       jb->ok[i] = 0;
05939 
05940    ast_mutex_init(&jb->mutexjb);
05941 
05942    return jb;
05943 }

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

Definition at line 837 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

00838 {
00839    misdn_lib_isdn_l1watcher(*(int *)data);
00840    chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
00841    return 1;
00842 }

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

Definition at line 3642 of file chan_misdn.c.

References ast_callerid_parse(), ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_jb_configure(), ast_log(), AST_STATE_RING, ast_strdup, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_ani, cid_name, cid_num, ast_channel::exten, LOG_ERROR, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_GEN_BRIDGING, misdn_get_global_jbconf(), misdn_lib_port_is_pri(), ast_channel::nativeformats, chan_list::pipe, 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().

03643 {
03644    struct ast_channel *tmp;
03645    char *cid_name = 0, *cid_num = 0;
03646    int chan_offset = 0;
03647    int tmp_port = misdn_cfg_get_next_port(0);
03648    int bridging;
03649 
03650    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03651       if (tmp_port == port)
03652          break;
03653       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03654    }
03655    if (c < 0)
03656       c = 0;
03657 
03658    if (callerid) {
03659       ast_callerid_parse(callerid, &cid_name, &cid_num);
03660    }
03661 
03662    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
03663    if (tmp) {
03664       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03665 
03666       tmp->nativeformats = prefformat;
03667 
03668       tmp->readformat = format;
03669       tmp->rawreadformat = format;
03670       tmp->writeformat = format;
03671       tmp->rawwriteformat = format;
03672     
03673       tmp->tech_pvt = chlist;
03674 
03675       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03676 
03677       if (bridging)
03678          tmp->tech = &misdn_tech;
03679       else
03680          tmp->tech = &misdn_tech_wo_bridge;
03681 
03682       tmp->writeformat = format;
03683       tmp->readformat = format;
03684       tmp->priority=1;
03685 
03686       if (exten) 
03687          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03688       else
03689          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03690 
03691       if (callerid)
03692          /* Don't use ast_set_callerid() here because it will
03693           * generate a needless NewCallerID event */
03694          tmp->cid.cid_ani = ast_strdup(cid_num);
03695 
03696       if (pipe(chlist->pipe) < 0)
03697          ast_log(LOG_ERROR, "Pipe failed\n");
03698       ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
03699 
03700       if (state == AST_STATE_RING)
03701          tmp->rings = 1;
03702       else
03703          tmp->rings = 0;
03704       
03705       ast_jb_configure(tmp, misdn_get_global_jbconf());
03706    } else {
03707       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03708    }
03709    
03710    return tmp;
03711 }

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

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

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

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

Definition at line 2974 of file chan_misdn.c.

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

02975 {
02976    struct chan_list *tmp;
02977    fd_set rrfs;
02978    struct timeval tv;
02979    int len, t;
02980 
02981    if (!ast) {
02982       chan_misdn_log(1, 0, "misdn_read called without ast\n");
02983       return NULL;
02984    }
02985    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
02986       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
02987       return NULL;
02988    }
02989 
02990    if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
02991       chan_misdn_log(1, 0, "misdn_read called without bc\n");
02992       return NULL;
02993    }
02994 
02995    tv.tv_sec=0;
02996    tv.tv_usec=20000;
02997 
02998    FD_ZERO(&rrfs);
02999    FD_SET(tmp->pipe[0],&rrfs);
03000 
03001    t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
03002 
03003    if (!t) {
03004       chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
03005       len=160;
03006    }
03007 
03008    if (t<0) {
03009       chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
03010       return NULL;
03011    }
03012 
03013    if (FD_ISSET(tmp->pipe[0],&rrfs)) {
03014       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
03015 
03016       if (len<=0) {
03017          /* we hangup here, since our pipe is closed */
03018          chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
03019          return NULL;
03020       }
03021 
03022    } else {
03023       return NULL;
03024    }
03025 
03026    tmp->frame.frametype = AST_FRAME_VOICE;
03027    tmp->frame.subclass = AST_FORMAT_ALAW;
03028    tmp->frame.datalen = len;
03029    tmp->frame.samples = len;
03030    tmp->frame.mallocd = 0;
03031    tmp->frame.offset = 0;
03032    tmp->frame.delivery = ast_tv(0,0);
03033    tmp->frame.src = NULL;
03034    tmp->frame.data.ptr = tmp->ast_rd_buf;
03035 
03036    if (tmp->faxdetect && !tmp->faxhandled) {
03037       if (tmp->faxdetect_timeout) {
03038          if (ast_tvzero(tmp->faxdetect_tv)) {
03039             tmp->faxdetect_tv = ast_tvnow();
03040             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
03041             return process_ast_dsp(tmp, &tmp->frame);
03042          } else {
03043             struct timeval tv_now = ast_tvnow();
03044             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
03045             if (diff <= (tmp->faxdetect_timeout * 1000)) {
03046                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
03047                return process_ast_dsp(tmp, &tmp->frame);
03048             } else {
03049                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
03050                tmp->faxdetect = 0;
03051                return &tmp->frame;
03052             }
03053          }
03054       } else {
03055          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
03056          return process_ast_dsp(tmp, &tmp->frame);
03057       }
03058    } else {
03059       if (tmp->ast_dsp)
03060          return process_ast_dsp(tmp, &tmp->frame);
03061       else
03062          return &tmp->frame;
03063    }
03064 }

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

Definition at line 3369 of file chan_misdn.c.

References chan_list::ast, ast_copy_string(), ast_free, 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(), misdn_bchannel::dec, ext, get_robin_position(), 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(), chan_list::need_hangup, ORG_AST, misdn_bchannel::port, robin_list::port, read_config(), and strsep().

03370 {
03371    struct ast_channel *tmp = NULL;
03372    char group[BUFFERSIZE + 1] = "";
03373    char dial_str[128];
03374    char *buf2 = ast_strdupa(data);
03375    char *ext;
03376    char *port_str;
03377    char *p = NULL;
03378    int channel = 0;
03379    int port = 0;
03380    struct misdn_bchannel *newbc = NULL;
03381    int dec = 0;
03382    struct chan_list *cl;
03383 
03384    snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
03385 
03386    /*
03387     * data is ---v
03388     * Dial(mISDN/g:group_name[/extension[/options]])
03389     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
03390     *
03391     * The dial extension could be empty if you are using MISDN_KEYPAD
03392     * to control ISDN provider features.
03393     */
03394    port_str = strsep(&buf2, "/");
03395    if (!ast_strlen_zero(port_str)) {
03396       if (port_str[0] == 'g' && port_str[1] == ':' ) {
03397          /* We make a group call lets checkout which ports are in my group */
03398          port_str += 2;
03399          ast_copy_string(group, port_str, sizeof(group));
03400          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03401       } else if ((p = strchr(port_str, ':'))) {
03402          /* we have a preselected channel */
03403          *p = 0;
03404          channel = atoi(++p);
03405          port = atoi(port_str);
03406          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03407       } else {
03408          port = atoi(port_str);
03409       }
03410    } else {
03411       ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
03412       return NULL;
03413    }
03414 
03415    ext = strsep(&buf2, "/");
03416    if (!ext) {
03417       ext = "";
03418    }
03419 
03420    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03421       chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
03422       dec = 1;
03423    }
03424 
03425    if (!ast_strlen_zero(group)) {
03426       char cfg_group[BUFFERSIZE + 1];
03427       struct robin_list *rr = NULL;
03428 
03429       /* Group dial */
03430 
03431       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03432          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03433          rr = get_robin_position(group);
03434       }
03435 
03436       if (rr) {
03437          int robin_channel = rr->channel;
03438          int port_start;
03439          int next_chan = 1;
03440 
03441          do {
03442             port_start = 0;
03443             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
03444                 port = misdn_cfg_get_next_port_spin(port)) {
03445 
03446                if (!port_start)
03447                   port_start = port;
03448 
03449                if (port >= port_start)
03450                   next_chan = 1;
03451                
03452                if (port <= port_start && next_chan) {
03453                   int maxbchans=misdn_lib_get_maxchans(port);
03454                   if (++robin_channel >= maxbchans) {
03455                      robin_channel = 1;
03456                   }
03457                   next_chan = 0;
03458                }
03459 
03460                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03461 
03462                if (!strcasecmp(cfg_group, group)) {
03463                   int port_up;
03464                   int check;
03465                   misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03466                   port_up = misdn_lib_port_up(port, check);
03467 
03468                   if (check && !port_up) 
03469                      chan_misdn_log(1, port, "L1 is not Up on this Port\n");
03470                   
03471                   if (check && port_up < 0) {
03472                      ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
03473                   }
03474 
03475                   if (port_up > 0)  {
03476                      newbc = misdn_lib_get_free_bc(port, robin_channel, 0, 0);
03477                      if (newbc) {
03478                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03479                         if (port_up)
03480                            chan_misdn_log(4, port, "portup:%d\n",  port_up);
03481                         rr->port = newbc->port;
03482                         rr->channel = newbc->channel;
03483                         break;
03484                      }
03485                   }
03486                }
03487             }
03488          } while (!newbc && robin_channel != rr->channel);
03489          
03490       } else {    
03491          for (port = misdn_cfg_get_next_port(0); port > 0;
03492              port = misdn_cfg_get_next_port(port)) {
03493 
03494             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03495 
03496             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03497             if (!strcasecmp(cfg_group, group)) {
03498                int port_up;
03499                int check;
03500                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03501                port_up = misdn_lib_port_up(port, check);
03502 
03503                chan_misdn_log(4, port, "portup:%d\n", port_up);
03504 
03505                if (port_up > 0) {
03506                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03507                   if (newbc)
03508                      break;
03509                }
03510             }
03511          }
03512       }
03513       
03514       /* Group dial failed ?*/
03515       if (!newbc) {
03516          ast_log(LOG_WARNING, 
03517                "Could not Dial out on group '%s'.\n"
03518                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03519                "\tOr there was no free channel on none of the ports\n\n"
03520                , group);
03521          return NULL;
03522       }
03523    } else {
03524       /* 'Normal' Port dial * Port dial */
03525       if (channel)
03526          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03527       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03528 
03529       if (!newbc) {
03530          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03531          return NULL;
03532       }
03533    }
03534    
03535 
03536    /* create ast_channel and link all the objects together */
03537    cl = init_chan_list(ORG_AST);
03538    if (!cl) {
03539       ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
03540       return NULL;
03541    }
03542    cl->bc = newbc;
03543    
03544    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03545    if (!tmp) {
03546       ast_free(cl);
03547       ast_log(LOG_ERROR,"Could not create Asterisk object\n");
03548       return NULL;
03549    }
03550 
03551    cl->ast=tmp;
03552    
03553    /* register chan in local list */
03554    cl_queue_chan(&cl_te, cl) ;
03555    
03556    /* fill in the config into the objects */
03557    read_config(cl, ORG_AST);
03558 
03559    /* important */
03560    cl->need_hangup = 0;
03561    
03562    return tmp;
03563 }

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

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

03567 {
03568    struct chan_list *tmp = chan->tech_pvt;
03569    
03570    if (tmp && tmp->bc) {
03571       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03572       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03573    } else {
03574       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03575       return -1;
03576    }
03577    
03578    return 0;
03579 }

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

Definition at line 5681 of file chan_misdn.c.

References ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_strdupa, ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, chan_list::dsp, DSP_FEATURE_DIGIT_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, 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, parse(), misdn_bchannel::port, misdn_bchannel::pres, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, strsep(), ast_channel::tech, chan_list::trans, misdn_bchannel::txgain, and ast_channel_tech::type.

Referenced by load_module(), and misdn_call().

05682 {
05683    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05684    char *tok, *tokb, *parse;
05685    int  keyidx = 0;
05686    int rxgain = 0;
05687    int txgain = 0;
05688    int change_jitter = 0;
05689 
05690    if (strcasecmp(chan->tech->type, "mISDN")) {
05691       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05692       return -1;
05693    }
05694    
05695    if (ast_strlen_zero((char *)data)) {
05696       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05697       return -1;
05698    }
05699 
05700    parse = ast_strdupa(data);
05701    for (tok = strtok_r(parse, ":", &tokb);
05702         tok;
05703         tok = strtok_r(NULL, ":", &tokb) ) {
05704       int neglect = 0;
05705 
05706       if (tok[0] == '!' ) {
05707          neglect = 1;
05708          tok++;
05709       }
05710       
05711       switch(tok[0]) {
05712          
05713       case 'd' :
05714          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05715          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05716          break;
05717          
05718       case 'n':
05719          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05720          ch->bc->nodsp = 1;
05721          break;
05722 
05723       case 'j':
05724          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05725          tok++;
05726          change_jitter = 1;
05727 
05728          switch ( tok[0] ) {
05729          case 'b':
05730             ch->jb_len = atoi(++tok);
05731             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05732             break;
05733          case 't' :
05734             ch->jb_upper_threshold = atoi(++tok);
05735             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05736             break;
05737          case 'n':
05738             ch->bc->nojitter = 1;
05739             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05740             break;
05741          default:
05742             ch->jb_len = 4000;
05743             ch->jb_upper_threshold = 0;
05744             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05745             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05746          }
05747          break;
05748       case 'v':
05749          tok++;
05750 
05751          switch (tok[0]) {
05752          case 'r' :
05753             rxgain = atoi(++tok);
05754             if (rxgain < -8)
05755                rxgain = -8;
05756             if (rxgain > 8)
05757                rxgain = 8;
05758             ch->bc->rxgain = rxgain;
05759             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05760             break;
05761          case 't':
05762             txgain = atoi(++tok);
05763             if (txgain < -8)
05764                txgain = -8;
05765             if (txgain > 8)
05766                txgain = 8;
05767             ch->bc->txgain = txgain;
05768             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05769             break;
05770          }
05771          break;
05772       
05773       case 'c':
05774          keyidx = atoi(++tok);
05775          {
05776             char keys[4096];
05777             char *key = NULL, *tmp = keys;
05778             int i;
05779             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05780 
05781             for (i = 0; i < keyidx; i++) {
05782                key = strsep(&tmp, ",");
05783             }
05784 
05785             if (key) {
05786                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05787             }
05788 
05789             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05790             break;
05791          }
05792       case 'e':
05793          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05794          
05795          if (neglect) {
05796             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05797 #ifdef MISDN_1_2
05798             *ch->bc->pipeline = 0;
05799 #else
05800             ch->bc->ec_enable = 0;
05801 #endif
05802          } else {
05803 #ifdef MISDN_1_2
05804             update_pipeline_config(ch->bc);
05805 #else
05806             ch->bc->ec_enable = 1;
05807             ch->bc->orig = ch->originator;
05808             tok++;
05809             if (*tok) {
05810                ch->bc->ec_deftaps = atoi(tok);
05811             }
05812 #endif
05813          }
05814          
05815          break;
05816       case 'h':
05817          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05818          
05819          if (strlen(tok) > 1 && tok[1] == '1') {
05820             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05821             if (!ch->bc->hdlc) {
05822                ch->bc->hdlc = 1;
05823             }
05824          }
05825          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05826          break;
05827             
05828       case 's':
05829          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05830          ch->bc->send_dtmf = 1;
05831          break;
05832          
05833       case 'f':
05834          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05835          ch->faxdetect = 1;
05836          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05837          break;
05838 
05839       case 'a':
05840          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05841          ch->ast_dsp = 1;
05842          break;
05843 
05844       case 'p':
05845          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05846          /* CRICH: callingpres!!! */
05847          if (strstr(tok,"allowed")) {
05848             ch->bc->pres = 0;
05849          } else if (strstr(tok, "restricted")) {
05850             ch->bc->pres = 1;
05851          } else if (strstr(tok, "not_screened")) {
05852             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05853             ch->bc->pres = 1;
05854          }
05855          break;
05856       case 'i' :
05857          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05858          ch->ignore_dtmf=1;
05859          break;
05860       default:
05861          break;
05862       }
05863    }
05864 
05865    if (change_jitter)
05866       config_jitterbuffer(ch);
05867 
05868    if (ch->faxdetect || ch->ast_dsp) {
05869       if (!ch->dsp)
05870          ch->dsp = ast_dsp_new();
05871       if (ch->dsp)
05872          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
05873       if (!ch->trans)
05874          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05875    }
05876 
05877    if (ch->ast_dsp) {
05878       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05879       ch->bc->nodsp = 1;
05880    }
05881    
05882    return 0;
05883 }

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

Definition at line 822 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

00823 {
00824    return _misdn_tasks_add_variable(timeout, callback, data, 0);
00825 }

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

Definition at line 827 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

00828 {
00829    return _misdn_tasks_add_variable(timeout, callback, data, 1);
00830 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 792 of file chan_misdn.c.

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

Referenced by unload_module().

00793 {
00794    if (misdn_tasks) {
00795       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
00796       if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
00797          cb_log(4, 0, "Joining misdn_tasks thread\n");
00798          pthread_join(misdn_tasks_thread, NULL);
00799       }
00800       sched_context_destroy(misdn_tasks);
00801    }
00802 }

static void misdn_tasks_init ( void   )  [static]

Definition at line 773 of file chan_misdn.c.

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

Referenced by _misdn_tasks_add_variable().

00774 {
00775    sem_t blocker;
00776    int i = 5;
00777 
00778    if (sem_init(&blocker, 0, 0)) {
00779       perror("chan_misdn: Failed to initialize semaphore!");
00780       exit(1);
00781    }
00782 
00783    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
00784    
00785    misdn_tasks = sched_context_create();
00786    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
00787 
00788    while (sem_wait(&blocker) && --i);
00789    sem_destroy(&blocker);
00790 }

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 832 of file chan_misdn.c.

References AST_SCHED_DEL.

Referenced by release_chan(), and release_chan_early().

00833 {
00834    AST_SCHED_DEL(misdn_tasks, task_id);
00835 }

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

Definition at line 749 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 804 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

00805 {
00806    pthread_kill(misdn_tasks_thread, SIGUSR1);
00807 }

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

Definition at line 3067 of file chan_misdn.c.

References misdn_bchannel::active, misdn_bchannel::addr, ast_debug, ast_log(), chan_list::bc, misdn_bchannel::bc_state, BCHAN_ACTIVATED, BCHAN_BRIDGED, misdn_bchannel::capability, cb_log, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_frame::data, chan_list::dropped_frame_cnt, ast_channel::exten, chan_list::hold, chan_list::jb, misdn_bchannel::l3_id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_cap_is_speech(), misdn_get_ch_state(), MISDN_HOLD_IDLE, misdn_jb_fill(), misdn_lib_tone_generator_start(), misdn_lib_tx2misdn_frm(), misdn_bchannel::nojitter, chan_list::notxtone, misdn_bchannel::port, ast_frame::ptr, ast_frame::samples, ast_frame::src, hold_info::state, ast_frame::subclass, and chan_list::ts.

03068 {
03069    struct chan_list *ch;
03070    int i  = 0;
03071    
03072    if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
03073 
03074    if (ch->hold.state != MISDN_HOLD_IDLE) {
03075       chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
03076       return 0;
03077    }
03078    
03079    if (!ch->bc ) {
03080       ast_log(LOG_WARNING, "private but no bc\n");
03081       return -1;
03082    }
03083    
03084    if (ch->notxtone) {
03085       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
03086       return 0;
03087    }
03088 
03089 
03090    if (!frame->subclass) {
03091       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
03092       return 0;
03093    }
03094    
03095    if (!(frame->subclass & prefformat)) {
03096       
03097       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
03098       return 0;
03099    }
03100    
03101 
03102    if (!frame->samples ) {
03103       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
03104       
03105       if (!strcmp(frame->src,"ast_prod")) {
03106          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
03107 
03108          if (ch->ts) {
03109             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
03110             misdn_lib_tone_generator_start(ch->bc);
03111          }
03112          return 0;
03113       }
03114 
03115       return -1;
03116    }
03117 
03118    if ( ! ch->bc->addr ) {
03119       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
03120       return 0;
03121    }
03122    
03123 #ifdef MISDN_DEBUG
03124    {
03125       int i, max = 5 > frame->samples ? frame->samples : 5;
03126 
03127       ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
03128 
03129       for (i = 0; i < max ; i++)
03130          ast_debug(1, "%2.2x ", ((char*) frame->data.ptr)[i]);
03131    }
03132 #endif
03133 
03134    switch (ch->bc->bc_state) {
03135    case BCHAN_ACTIVATED:
03136    case BCHAN_BRIDGED:
03137       break;
03138    default:
03139       if (!ch->dropped_frame_cnt)
03140          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);
03141       
03142       ch->dropped_frame_cnt++;
03143       if (ch->dropped_frame_cnt > 100) {
03144          ch->dropped_frame_cnt = 0;
03145          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);
03146       }
03147 
03148       return 0;
03149    }
03150 
03151    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
03152    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
03153       /* Buffered Transmit (triggered by read from isdn side)*/
03154       if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
03155          if (ch->bc->active)
03156             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
03157       }
03158       
03159    } else {
03160       /*transmit without jitterbuffer*/
03161       i = misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
03162    }
03163 
03164    return 0;
03165 }

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

03855 {
03856    int ret = ast_pbx_start(ch->ast);   
03857 
03858    if (ret >= 0) 
03859       ch->need_hangup = 0;
03860    else
03861       ch->need_hangup = 1;
03862 
03863    return ret;
03864 }

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

Definition at line 1348 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(), 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 handle_cli_misdn_show_channel(), and handle_cli_misdn_show_channels().

01349 {
01350    struct ast_channel *ast = help->ast;
01351    ast_cli(fd,
01352       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
01353 
01354       bc->pid, bc->port, bc->channel,
01355       bc->nt ? "NT" : "TE",
01356       help->originator == ORG_AST ? "*" : "I",
01357       ast ? ast->exten : NULL,
01358       ast ? ast->cid.cid_num : NULL,
01359       bc->rad,
01360       ast ? ast->context : NULL,
01361       misdn_get_ch_state(help)
01362       );
01363    if (misdn_debug[bc->port] > 0)
01364       ast_cli(fd,
01365          "  --> astname: %s\n"
01366          "  --> ch_l3id: %x\n"
01367          "  --> ch_addr: %x\n"
01368          "  --> bc_addr: %x\n"
01369          "  --> bc_l3id: %x\n"
01370          "  --> display: %s\n"
01371          "  --> activated: %d\n"
01372          "  --> state: %s\n"
01373          "  --> capability: %s\n"
01374 #ifdef MISDN_1_2
01375          "  --> pipeline: %s\n"
01376 #else
01377          "  --> echo_cancel: %d\n"
01378 #endif
01379          "  --> notone : rx %d tx:%d\n"
01380          "  --> bc_hold: %d\n",
01381          help->ast->name,
01382          help->l3id,
01383          help->addr,
01384          bc->addr,
01385          bc ? bc->l3_id : -1,
01386          bc->display,
01387          
01388          bc->active,
01389          bc_state2str(bc->bc_state),
01390          bearer2str(bc->capability),
01391 #ifdef MISDN_1_2
01392          bc->pipeline,
01393 #else
01394          bc->ec_enable,
01395 #endif
01396 
01397          help->norxtone, help->notxtone,
01398          bc->holded
01399          );
01400 
01401 }

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

00673 {
00674    
00675    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00676    
00677    switch(bc->law) {
00678    case INFO_CODEC_ALAW:
00679       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00680       break;
00681    case INFO_CODEC_ULAW:
00682       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00683       break;
00684    }
00685 }

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 #ifdef HAVE_MISDN_FAC_RESULT
00625    case Fac_RESULT:
00626       chan_misdn_log(0, bc->port," --> Received RESULT Operation\n");
00627       break;
00628 #endif
00629 #ifdef HAVE_MISDN_FAC_ERROR
00630    case Fac_ERROR:
00631       chan_misdn_log(0, bc->port," --> Received Error Operation\n");
00632       chan_misdn_log(0, bc->port," --> Value:%d Error:%s\n",fac->u.ERROR.errorValue, fac->u.ERROR.error);
00633       break;
00634 #endif
00635    case Fac_CD:
00636       chan_misdn_log(1,bc->port," --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
00637          fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
00638       break;
00639    case Fac_AOCDCurrency:
00640       if (fac->u.AOCDcur.chargeNotAvailable)
00641          chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
00642       else if (fac->u.AOCDcur.freeOfCharge)
00643          chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
00644       else if (fac->u.AOCDchu.billingId >= 0)
00645          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
00646             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00647             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
00648       else
00649          chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
00650             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
00651             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
00652       break;
00653    case Fac_AOCDChargingUnit:
00654       if (fac->u.AOCDchu.chargeNotAvailable)
00655          chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
00656       else if (fac->u.AOCDchu.freeOfCharge)
00657          chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
00658       else if (fac->u.AOCDchu.billingId >= 0)
00659          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
00660             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
00661       else
00662          chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
00663             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
00664       break;
00665    case Fac_None:
00666    default:
00667       chan_misdn_log(1,bc->port," --> unknown facility\n");
00668       break;
00669    }
00670 }

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

Definition at line 2904 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), ast_debug, chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_log(), ast_strlen_zero(), ast_translate(), ast_verb, 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, ast_frame::frametype, isdn_lib_stop_dtmf(), isdn_lib_update_ec(), isdn_lib_update_rxgain(), isdn_lib_update_txgain(), LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, ast_frame::subclass, chan_list::trans, and misdn_bchannel::txgain.

Referenced by misdn_read().

02905 {
02906    struct ast_frame *f,*f2;
02907  
02908    if (tmp->trans) {
02909       f2 = ast_translate(tmp->trans, frame, 0);
02910       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02911    } else {
02912       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02913       return NULL;
02914    }
02915 
02916    if (!f || (f->frametype != AST_FRAME_DTMF))
02917       return frame;
02918  
02919    ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
02920  
02921    if (tmp->faxdetect && (f->subclass == 'f')) {
02922       /* Fax tone -- Handle and return NULL */
02923       if (!tmp->faxhandled) {
02924          struct ast_channel *ast = tmp->ast;
02925          tmp->faxhandled++;
02926          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02927          tmp->bc->rxgain = 0;
02928          isdn_lib_update_rxgain(tmp->bc);
02929          tmp->bc->txgain = 0;
02930          isdn_lib_update_txgain(tmp->bc);
02931 #ifdef MISDN_1_2
02932          *tmp->bc->pipeline = 0;
02933 #else
02934          tmp->bc->ec_enable = 0;
02935 #endif
02936          isdn_lib_update_ec(tmp->bc);
02937          isdn_lib_stop_dtmf(tmp->bc);
02938          switch (tmp->faxdetect) {
02939          case 1:
02940             if (strcmp(ast->exten, "fax")) {
02941                char *context;
02942                char context_tmp[BUFFERSIZE];
02943                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02944                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02945                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02946                   ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02947                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02948                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02949                   if (ast_async_goto(ast, context, "fax", 1))
02950                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02951                } else
02952                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02953             } else {
02954                ast_debug(1, "Already in a fax extension, not redirecting\n");
02955             }
02956             break;
02957          case 2:
02958             ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02959             break;
02960          }
02961       } else {
02962          ast_debug(1, "Fax already handled\n");
02963       }
02964    }
02965    
02966    if (tmp->ast_dsp && (f->subclass != 'f')) {
02967       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02968    }
02969 
02970    return f;
02971 }

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

Definition at line 2134 of file chan_misdn.c.

References chan_list::allowed_bearers, misdn_bchannel::AOCDtype, chan_list::ast, ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_mutex_init(), ast_print_group(), ast_set_callerid(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, buf, 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_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::early_bconnect, ast_channel::exten, chan_list::far_alerting, chan_list::faxdetect, chan_list::faxdetect_timeout, 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, misdn_bchannel::te_choose_channel, chan_list::trans, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

02135 {
02136    struct ast_channel *ast;
02137    struct misdn_bchannel *bc;
02138    int port;
02139    int hdlc = 0;
02140    char lang[BUFFERSIZE + 1];
02141    char faxdetect[BUFFERSIZE + 1];
02142    char buf[256];
02143    char buf2[256];
02144    ast_group_t pg;
02145    ast_group_t cg;
02146 
02147    if (!ch) {
02148       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
02149       return -1;
02150    }
02151 
02152    ast = ch->ast;
02153    bc = ch->bc;
02154    if (! ast || ! bc) {
02155       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
02156       return -1;
02157    }
02158    
02159    port = bc->port;
02160    chan_misdn_log(1, port, "read_config: Getting Config\n");
02161 
02162    misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
02163    ast_string_field_set(ast, language, lang);
02164 
02165    misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
02166 
02167    misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
02168    misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
02169 
02170    misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
02171 
02172    misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
02173 
02174    misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
02175 
02176    if (ch->ast_dsp) {
02177       ch->ignore_dtmf = 1;
02178    }
02179 
02180    misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
02181    misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
02182 
02183    misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
02184 
02185    misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
02186 
02187    misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
02188 
02189    misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
02190 
02191    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
02192 
02193    if (hdlc) {
02194       switch (bc->capability) {
02195       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02196       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
02197          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
02198          bc->hdlc = 1;
02199          break;
02200       }
02201       
02202    }
02203    /*Initialize new Jitterbuffer*/
02204    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
02205    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
02206 
02207    config_jitterbuffer(ch);
02208 
02209    misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
02210 
02211    ast_copy_string(ast->context, ch->context, sizeof(ast->context));
02212 
02213 #ifdef MISDN_1_2
02214    update_pipeline_config(bc);
02215 #else
02216    update_ec_config(bc);
02217 #endif
02218 
02219    misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
02220 
02221    misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02222    misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02223 
02224    chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
02225    ast->pickupgroup = pg;
02226    ast->callgroup = cg;
02227    
02228    if (orig == ORG_AST) {
02229       char callerid[BUFFERSIZE + 1];
02230 
02231       /* ORIGINATOR Asterisk (outgoing call) */
02232 
02233       misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
02234 
02235       if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
02236          if (strstr(faxdetect, "nojump"))
02237             ch->faxdetect = 2;
02238          else
02239             ch->faxdetect = 1;
02240       }
02241 
02242       misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
02243       if ( ! ast_strlen_zero(callerid) ) {
02244          chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
02245          ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
02246       }
02247 
02248       misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
02249       misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
02250       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02251       debug_numplan(port, bc->dnumplan, "TON");
02252       debug_numplan(port, bc->onumplan, "LTON");
02253       debug_numplan(port, bc->cpnnumplan, "CTON");
02254 
02255       ch->overlap_dial = 0;
02256    } else {
02257       /* ORIGINATOR MISDN (incoming call) */
02258       char prefix[BUFFERSIZE + 1] = "";
02259 
02260       if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
02261          if (strstr(faxdetect, "nojump"))
02262             ch->faxdetect = 2;
02263          else
02264             ch->faxdetect = 1;
02265       }
02266 
02267       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02268       debug_numplan(port, bc->cpnnumplan, "CTON");
02269 
02270       switch (bc->onumplan) {
02271       case NUMPLAN_INTERNATIONAL:
02272          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02273          break;
02274 
02275       case NUMPLAN_NATIONAL:
02276          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02277          break;
02278       default:
02279          break;
02280       }
02281 
02282       ast_copy_string(buf, bc->oad, sizeof(buf));
02283       snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
02284 
02285       if (!ast_strlen_zero(bc->dad)) {
02286          ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
02287       }
02288 
02289       if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02290          ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
02291       }
02292 
02293       prefix[0] = 0;
02294 
02295       switch (bc->dnumplan) {
02296       case NUMPLAN_INTERNATIONAL:
02297          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02298          break;
02299       case NUMPLAN_NATIONAL:
02300          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02301          break;
02302       default:
02303          break;
02304       }
02305 
02306       ast_copy_string(buf, bc->dad, sizeof(buf));
02307       snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
02308 
02309       if (strcmp(bc->dad, ast->exten)) {
02310          ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
02311       }
02312 
02313       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
02314 
02315       if ( !ast_strlen_zero(bc->rad) ) {
02316          if (ast->cid.cid_rdnis)
02317             ast_free(ast->cid.cid_rdnis);
02318          ast->cid.cid_rdnis = ast_strdup(bc->rad);
02319       }
02320    
02321       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
02322       ast_mutex_init(&ch->overlap_tv_lock);
02323    } /* ORIG MISDN END */
02324 
02325    ch->overlap_dial_task = -1;
02326    
02327    if (ch->faxdetect  || ch->ast_dsp) {
02328       misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
02329       if (!ch->dsp)
02330          ch->dsp = ast_dsp_new();
02331       if (ch->dsp) {
02332          if (ch->faxdetect) 
02333             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
02334          else 
02335             ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT );
02336       }
02337       if (!ch->trans)
02338          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
02339    }
02340 
02341    /* AOCD initialization */
02342    bc->AOCDtype = Fac_None;
02343 
02344    return 0;
02345 }

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

Definition at line 3914 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, ast_free, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, cl_dequeue_chan(), ast_channel::context, ast_channel::exten, chan_list::jb, misdn_bchannel::l3_id, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, misdn_jb_destroy(), 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().

03915 {
03916    struct ast_channel *ast;
03917 
03918    ch->state = MISDN_CLEANING;
03919 
03920    ast_mutex_lock(&release_lock);
03921 
03922    cl_dequeue_chan(&cl_te, ch);
03923 
03924    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
03925 
03926    /* releasing jitterbuffer */
03927    if (ch->jb) {
03928       misdn_jb_destroy(ch->jb);
03929       ch->jb = NULL;
03930    } else {
03931       if (!bc->nojitter) {
03932          chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03933       }
03934    }
03935 
03936    if (ch->overlap_dial) {
03937       if (ch->overlap_dial_task != -1) {
03938          misdn_tasks_remove(ch->overlap_dial_task);
03939          ch->overlap_dial_task = -1;
03940       }
03941       ast_mutex_destroy(&ch->overlap_tv_lock);
03942    }
03943 
03944    if (ch->originator == ORG_AST) {
03945       --misdn_out_calls[bc->port];
03946    } else {
03947       --misdn_in_calls[bc->port];
03948    }
03949 
03950    close(ch->pipe[0]);
03951    close(ch->pipe[1]);
03952 
03953    ast = ch->ast;
03954    if (ast) {
03955       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03956       chan_misdn_log(1, bc->port,
03957          "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s\n",
03958          bc->pid,
03959          ast->context,
03960          ast->exten,
03961          ast->cid.cid_num);
03962 
03963       if (ast->_state != AST_STATE_RESERVED) {
03964          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03965          ast_setstate(ast, AST_STATE_DOWN);
03966       }
03967    }
03968 
03969    ast_free(ch);
03970 
03971    ast_mutex_unlock(&release_lock);
03972 }

static void release_chan_early ( struct chan_list ch  )  [static]

Definition at line 3984 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, ast_free, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, cl_dequeue_chan(), chan_list::hold, chan_list::jb, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, MISDN_HOLD_IDLE, misdn_jb_destroy(), 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().

03985 {
03986    struct ast_channel *ast;
03987 
03988    ch->state = MISDN_CLEANING;
03989 
03990    ast_mutex_lock(&release_lock);
03991 
03992    cl_dequeue_chan(&cl_te, ch);
03993 
03994    /* releasing jitterbuffer */
03995    if (ch->jb) {
03996       misdn_jb_destroy(ch->jb);
03997       ch->jb = NULL;
03998    }
03999 
04000    if (ch->overlap_dial) {
04001       if (ch->overlap_dial_task != -1) {
04002          misdn_tasks_remove(ch->overlap_dial_task);
04003          ch->overlap_dial_task = -1;
04004       }
04005       ast_mutex_destroy(&ch->overlap_tv_lock);
04006    }
04007 
04008    if (ch->hold.state != MISDN_HOLD_IDLE) {
04009       if (ch->originator == ORG_AST) {
04010          --misdn_out_calls[ch->hold.port];
04011       } else {
04012          --misdn_in_calls[ch->hold.port];
04013       }
04014    }
04015 
04016    close(ch->pipe[0]);
04017    close(ch->pipe[1]);
04018 
04019    ast = ch->ast;
04020    if (ast) {
04021       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
04022       if (ast->_state != AST_STATE_RESERVED) {
04023          ast_setstate(ast, AST_STATE_DOWN);
04024       }
04025    }
04026 
04027    ast_free(ch);
04028 
04029    ast_mutex_unlock(&release_lock);
04030 }

static int reload ( void   )  [static]

Definition at line 5550 of file chan_misdn.c.

References reload_config().

05551 {
05552    reload_config();
05553 
05554    return 0;
05555 }

static void reload_config ( void   )  [static]

Definition at line 1305 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_reload(), and reload().

01306 {
01307    int i, cfg_debug;
01308 
01309    if (!g_config_initialized) {
01310       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
01311       return ;
01312    }
01313    
01314    free_robin_list();
01315    misdn_cfg_reload();
01316    misdn_cfg_update_ptp();
01317    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
01318    misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
01319 
01320    for (i = 0;  i <= max_ports; i++) {
01321       misdn_debug[i] = cfg_debug;
01322       misdn_debug_only[i] = 0;
01323    }
01324 }

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

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

04139                                                                                                      {
04140    if (!ast) {
04141       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
04142       return;
04143    }
04144    if (!bc) {
04145       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
04146       return;
04147    }
04148    if (!ch) {
04149       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
04150       return;
04151    }
04152 
04153    ast->hangupcause = bc->cause;
04154 
04155    switch (bc->cause) {
04156 
04157    case AST_CAUSE_UNALLOCATED:
04158    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
04159    case AST_CAUSE_NO_ROUTE_DESTINATION:
04160    case 4:  /* Send special information tone */
04161    case AST_CAUSE_NUMBER_CHANGED:
04162    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04163       /* Congestion Cases */
04164       /*
04165        * Not Queueing the Congestion anymore, since we want to hear
04166        * the inband message
04167        *
04168       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
04169       ch->state = MISDN_BUSY;
04170       
04171       ast_queue_control(ast, AST_CONTROL_CONGESTION);
04172       */
04173       break;
04174 
04175    case AST_CAUSE_CALL_REJECTED:
04176    case AST_CAUSE_USER_BUSY:
04177       ch->state = MISDN_BUSY;
04178 
04179       if (!ch->need_busy) {
04180          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
04181          break;
04182       }
04183 
04184       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04185       
04186       ast_queue_control(ast, AST_CONTROL_BUSY);
04187       
04188       ch->need_busy = 0;
04189       
04190       break;
04191    }
04192 }

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

Definition at line 895 of file chan_misdn.c.

References chan_list::ast, ast_debug, ast_playtones_start(), and chan.

Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().

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

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

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

01155 {
01156    char section[BUFFERSIZE];
01157    char name[BUFFERSIZE];
01158    char desc[BUFFERSIZE];
01159    char def[BUFFERSIZE];
01160    char tmp[BUFFERSIZE];
01161 
01162    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
01163    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
01164    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
01165 
01166    if (elem < MISDN_CFG_LAST)
01167       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
01168    else
01169       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
01170 
01171    if (*def)
01172       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
01173    else
01174       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
01175 }

static void sighandler ( int  sig  )  [static]

Definition at line 746 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00747 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

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

03332 {
03333    misdn_lib_tone_generator_stop(cl->bc);
03334    cl->notxtone = 0;
03335    cl->norxtone = 0;
03336    return 0;
03337 }

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

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

04285                                                                                                  {
04286    if (pbx_start_chan(ch) < 0) {
04287       hangup_chan(ch, bc);
04288       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04289       if (bc->nt) {
04290          hanguptone_indicate(ch);
04291          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04292       } else
04293          misdn_lib_send_event(bc, EVENT_RELEASE);
04294    }
04295 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3339 of file chan_misdn.c.

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

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

03340 {
03341    if (!cl) return -1;
03342 
03343    cl->notxtone = 1;
03344    cl->norxtone = 1;
03345    
03346    return 0;
03347 }

static int stop_indicate ( struct chan_list cl  )  [static]

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

03312 {
03313    struct ast_channel *ast = cl->ast;
03314 
03315    if (!ast) {
03316       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03317       return -1;
03318    }
03319 
03320    chan_misdn_log(3, cl->bc->port, " --> None\n");
03321    misdn_lib_tone_generator_stop(cl->bc);
03322    ast_playtones_stop(ast);
03323 
03324    cl->ts = NULL;
03325    /*ast_deactivate_generator(ast);*/
03326 
03327    return 0;
03328 }

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 5337 of file chan_misdn.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_free, ast_log(), ast_unregister_application(), free_robin_list(), LOG_VERBOSE, misdn_cfg_destroy(), misdn_lib_destroy(), and misdn_tasks_destroy().

Referenced by load_module().

05338 {
05339    /* First, take us out of the channel loop */
05340    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05341 
05342    misdn_tasks_destroy();
05343    
05344    if (!g_config_initialized)
05345       return 0;
05346    
05347    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05348    
05349    /* ast_unregister_application("misdn_crypt"); */
05350    ast_unregister_application("misdn_set_opt");
05351    ast_unregister_application("misdn_facility");
05352    ast_unregister_application("misdn_check_l2l1");
05353   
05354    ast_channel_unregister(&misdn_tech);
05355 
05356    free_robin_list();
05357    misdn_cfg_destroy();
05358    misdn_lib_destroy();
05359   
05360    ast_free(misdn_out_calls);
05361    ast_free(misdn_in_calls);
05362    ast_free(misdn_debug_only);
05363    ast_free(misdn_ports);
05364    ast_free(misdn_debug);
05365    
05366    return 0;
05367 }

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

Updates caller ID information from config.

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

01955 {
01956    struct ast_channel *ast;
01957    struct misdn_bchannel *bc;
01958    int port, hdlc = 0;
01959    int pres, screen;
01960 
01961    if (!ch) {
01962       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01963       return -1;
01964    }
01965 
01966    ast = ch->ast;
01967    bc = ch->bc;
01968    if (! ast || ! bc) {
01969       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01970       return -1;
01971    }
01972 
01973    port = bc->port;
01974 
01975    chan_misdn_log(7, port, "update_config: Getting Config\n");
01976 
01977    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01978    
01979    if (hdlc) {
01980       switch (bc->capability) {
01981       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01982       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01983          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
01984          bc->hdlc = 1;
01985          break;
01986       }
01987    }
01988 
01989    misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
01990    misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
01991    chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
01992       
01993    if (pres < 0 || screen < 0) {
01994       chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
01995          
01996       switch (ast->cid.cid_pres & 0x60) {
01997       case AST_PRES_RESTRICTED:
01998          bc->pres = 1;
01999          chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
02000          break;
02001       case AST_PRES_UNAVAILABLE:
02002          bc->pres = 2;
02003          chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
02004          break;
02005       default:
02006          bc->pres = 0;
02007          chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
02008          break;
02009       }
02010 
02011       switch (ast->cid.cid_pres & 0x3) {
02012       default:
02013       case AST_PRES_USER_NUMBER_UNSCREENED:
02014          bc->screen = 0;
02015          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
02016          break;
02017       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02018          bc->screen = 1;
02019          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
02020          break;
02021       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02022          bc->screen = 2;
02023          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
02024          break;
02025       case AST_PRES_NETWORK_NUMBER:
02026          bc->screen = 3;
02027          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
02028          break;
02029       }
02030    } else {
02031       bc->screen = screen;
02032       bc->pres = pres;
02033    }
02034 
02035    return 0;
02036 }

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

Definition at line 2115 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 handle_cli_misdn_toggle_echocancel(), and read_config().

02116 {
02117    int ec;
02118    int port = bc->port;
02119 
02120    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
02121 
02122    if (ec == 1) {
02123       bc->ec_enable = 1;
02124    } else if (ec > 1) {
02125       bc->ec_enable = 1;
02126       bc->ec_deftaps = ec;
02127    }
02128 
02129    return 0;
02130 }

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

Definition at line 3621 of file chan_misdn.c.

References ast_change_name(), chan_misdn_log(), misdn_cfg_get_next_port(), and misdn_lib_port_is_pri().

Referenced by cb_events().

03622 {
03623    int chan_offset = 0;
03624    int tmp_port = misdn_cfg_get_next_port(0);
03625    char newname[255];
03626    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03627       if (tmp_port == port)
03628          break;
03629       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03630    }
03631    if (c < 0)
03632       c = 0;
03633 
03634    snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
03635    if (strncmp(tmp->name, newname, strlen(newname))) {
03636       snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03637       ast_change_name(tmp, newname);
03638       chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03639    }
03640 }

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

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 6133 of file chan_misdn.c.

Definition at line 596 of file chan_misdn.c.

Definition at line 6133 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1929 of file chan_misdn.c.

struct chan_list* cl_te = NULL

Global channel call record list head.

Definition at line 516 of file chan_misdn.c.

Definition at line 517 of file chan_misdn.c.

Definition at line 511 of file chan_misdn.c.

int g_config_initialized = 0 [static]

Definition at line 77 of file chan_misdn.c.

int glob_channel = 0 [static]

Definition at line 3619 of file chan_misdn.c.

char global_tracefile[BUFFERSIZE+1]

Definition at line 75 of file chan_misdn.c.

Definition at line 1500 of file chan_misdn.c.

int max_ports [static]

Definition at line 505 of file chan_misdn.c.

int MAXTICS = 8

Definition at line 1501 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 503 of file chan_misdn.c.

int* misdn_debug_only [static]

Definition at line 504 of file chan_misdn.c.

int* misdn_in_calls [static]

Definition at line 507 of file chan_misdn.c.

int* misdn_out_calls [static]

Definition at line 508 of file chan_misdn.c.

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.

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

Definition at line 3600 of file chan_misdn.c.

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

Definition at line 496 of file chan_misdn.c.

int prefformat = AST_FORMAT_ALAW [static]

Only alaw and mulaw is allowed for now.

Definition at line 501 of file chan_misdn.c.

Definition at line 114 of file chan_misdn.c.

struct robin_list* robin = NULL [static]

Definition at line 427 of file chan_misdn.c.

struct state_struct state_array[] [static]

Definition at line 1269 of file chan_misdn.c.

int tracing = 0 [static]

Definition at line 498 of file chan_misdn.c.


Generated on 3 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1