Fri Nov 12 11:56:16 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 *vdata)
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 = "0901e4e500243c855563a2d78b0c03e4" , .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]
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
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 486 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 3837 of file chan_misdn.c.


Enumeration Type Documentation

Enumerator:
MISDN_NOTHING 

at beginning

MISDN_WAITING4DIGS 

when waiting for info

MISDN_EXTCANTMATCH 

when asterisk couldn't match our ext

MISDN_INCOMING_SETUP 

for incoming setup

MISDN_DIALING 

when pbx_start

MISDN_PROGRESS 

we have progress

MISDN_PROCEEDING 

we have 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 info */
00119    MISDN_EXTCANTMATCH,        /*!< when asterisk couldn't match our ext */
00120    MISDN_INCOMING_SETUP,      /*!< for incoming setup */
00121    MISDN_DIALING,             /*!< when pbx_start */
00122    MISDN_PROGRESS,            /*!< we have progress */
00123    MISDN_PROCEEDING,          /*!< we have 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 6203 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

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

int add_in_calls ( int  port  ) 

Definition at line 4322 of file chan_misdn.c.

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

Referenced by cb_events().

04323 {
04324    int max_in_calls;
04325    
04326    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04327    misdn_in_calls[port]++;
04328 
04329    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04330       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04331       return misdn_in_calls[port] - max_in_calls;
04332    }
04333    
04334    return 0;
04335 }

int add_out_calls ( int  port  ) 

Definition at line 4337 of file chan_misdn.c.

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

Referenced by misdn_call().

04338 {
04339    int max_out_calls;
04340    
04341    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04342 
04343    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04344       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04345       return (misdn_out_calls[port] + 1) - max_out_calls;
04346    }
04347 
04348    misdn_out_calls[port]++;
04349    
04350    return 0;
04351 }

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

Definition at line 602 of file chan_misdn.c.

References ARRAY_LEN, and allowed_bearers::display.

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

00603 {
00604    unsigned index;
00605 
00606    for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
00607       if (allowed_bearers_array[index].cap == cap) {
00608          return allowed_bearers_array[index].display;
00609       }
00610    }
00611 
00612    return "Unknown Bearer";
00613 }

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

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

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

Definition at line 5949 of file chan_misdn.c.

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

Referenced by load_module().

05950 {
05951    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05952    
05953    if (ch && ch->jb) {
05954       return misdn_jb_empty(ch->jb, buf, len);
05955    }
05956    
05957    return -1;
05958 }

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

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

06140 {
06141    va_list ap;
06142    char buf[1024];
06143    char port_buf[8];
06144 
06145    if (! ((0 <= port) && (port <= max_ports))) {
06146       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
06147       port = 0;
06148       level = -1;
06149    }
06150 
06151    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
06152 
06153    va_start(ap, tmpl);
06154    vsnprintf(buf, sizeof(buf), tmpl, ap);
06155    va_end(ap);
06156 
06157    if (level == -1) {
06158       ast_log(LOG_WARNING, "%s", buf);
06159 
06160    } else if (misdn_debug_only[port] ? 
06161          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
06162        : level <= misdn_debug[port]) {
06163       
06164       ast_console_puts(port_buf);
06165       ast_console_puts(buf);
06166    }
06167    
06168    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
06169       char ctimebuf[30];
06170       time_t tm = time(NULL);
06171       char *tmp = ctime_r(&tm, ctimebuf), *p;
06172 
06173       FILE *fp = fopen(global_tracefile, "a+");
06174 
06175       if ((p = strchr(tmp, '\n'))) {
06176          *p = ':';
06177       }
06178       
06179       if (!fp) {
06180          ast_console_puts("Error opening Tracefile: [ ");
06181          ast_console_puts(global_tracefile);
06182          ast_console_puts(" ] ");
06183          
06184          ast_console_puts(strerror(errno));
06185          ast_console_puts("\n");
06186          return ;
06187       }
06188       
06189       fputs(tmp, fp);
06190       fputs(" ", fp);
06191       fputs(port_buf, fp);
06192       fputs(" ", fp);
06193       fputs(buf, fp);
06194 
06195       fclose(fp);
06196    }
06197 }

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

Definition at line 3889 of file chan_misdn.c.

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

Referenced by release_chan(), and release_chan_early().

03890 {
03891    struct chan_list *help;
03892 
03893    if (chan->dsp) {
03894       ast_dsp_free(chan->dsp);
03895    }
03896 
03897    ast_mutex_lock(&cl_te_lock);
03898    if (!*list) {
03899       ast_mutex_unlock(&cl_te_lock);
03900       return;
03901    }
03902   
03903    if (*list == chan) {
03904       *list = (*list)->next;
03905       ast_mutex_unlock(&cl_te_lock);
03906       return;
03907    }
03908   
03909    for (help = *list; help->next; help = help->next) {
03910       if (help->next == chan) {
03911          help->next = help->next->next;
03912          ast_mutex_unlock(&cl_te_lock);
03913          return;
03914       }
03915    }
03916    
03917    ast_mutex_unlock(&cl_te_lock);
03918 }

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

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

03874 {
03875    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03876   
03877    ast_mutex_lock(&cl_te_lock);
03878    if (!*list) {
03879       *list = chan;
03880    } else {
03881       struct chan_list *help = *list;
03882       for (; help->next; help = help->next); 
03883       help->next = chan;
03884    }
03885    chan->next = NULL;
03886    ast_mutex_unlock(&cl_te_lock);
03887 }

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

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

01903 {
01904    if (a->n) {
01905       return NULL;
01906    }
01907 
01908    switch (a->pos) {
01909    case 4:
01910       if (a->word[0] == 'p') {
01911          return ast_strdup("port");
01912       } else if (a->word[0] == 'o') {
01913          return ast_strdup("only");
01914       }
01915       break;
01916    case 6:
01917       if (a->word[0] == 'o') {
01918          return ast_strdup("only");
01919       }
01920       break;
01921    }
01922    return NULL;
01923 }

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

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

01926 {
01927    char buffer[BUFFERSIZE];
01928    enum misdn_cfg_elements elem;
01929    int wordlen = strlen(a->word);
01930    int which = 0;
01931    int port = 0;
01932 
01933    switch (a->pos) {
01934    case 3:
01935       if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n)) {
01936          return ast_strdup("description");
01937       }
01938       if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n)) {
01939          return ast_strdup("descriptions");
01940       }
01941       if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n)) {
01942          return ast_strdup("0");
01943       }
01944       while ((port = misdn_cfg_get_next_port(port)) != -1) {
01945          snprintf(buffer, sizeof(buffer), "%d", port);
01946          if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
01947             return ast_strdup(buffer);
01948          }
01949       }
01950       break;
01951    case 4:
01952       if (strstr(a->line, "description ")) {
01953          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01954             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) {
01955                continue;
01956             }
01957             misdn_cfg_get_name(elem, buffer, sizeof(buffer));
01958             if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
01959                if (++which > a->n) {
01960                   return ast_strdup(buffer);
01961                }
01962             }
01963          }
01964       } else if (strstr(a->line, "descriptions ")) {
01965          if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n)) {
01966             return ast_strdup("general");
01967          }
01968          if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n)) {
01969             return ast_strdup("ports");
01970          }
01971       }
01972       break;
01973    }
01974    return NULL;
01975 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

02088 {
02089    struct misdn_bchannel *bc = ch->bc;
02090    int len = ch->jb_len, threshold = ch->jb_upper_threshold;
02091    
02092    chan_misdn_log(5, bc->port, "config_jb: Called\n");
02093    
02094    if (! len) {
02095       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
02096       bc->nojitter=1;
02097    } else {
02098       if (len <= 100 || len > 8000) {
02099          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
02100          len = 1000;
02101       }
02102 
02103       if (threshold > len) {
02104          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
02105       }
02106 
02107       if ( ch->jb) {
02108          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
02109          misdn_jb_destroy(ch->jb);
02110          ch->jb = NULL;
02111       }
02112 
02113       ch->jb = misdn_jb_init(len, threshold);
02114 
02115       if (!ch->jb) {
02116          bc->nojitter = 1;
02117       }
02118    }
02119 }

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

Definition at line 2122 of file chan_misdn.c.

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

Referenced by read_config().

02123 {
02124    switch (numplan) {
02125    case NUMPLAN_INTERNATIONAL:
02126       chan_misdn_log(2, port, " --> %s: International\n", type);
02127       break;
02128    case NUMPLAN_NATIONAL:
02129       chan_misdn_log(2, port, " --> %s: National\n", type);
02130       break;
02131    case NUMPLAN_SUBSCRIBER:
02132       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
02133       break;
02134    case NUMPLAN_UNKNOWN:
02135       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
02136       break;
02137       /* Maybe we should cut off the prefix if present ? */
02138    default:
02139       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
02140       break;
02141    }
02142 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

Definition at line 3330 of file chan_misdn.c.

References chan_list::ast, ast_get_indication_tone(), ast_playtones_start(), chan_list::bc, chan_misdn_log(), ast_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().

03331 {
03332    struct ast_channel *ast = cl->ast;
03333    int nd = 0;
03334 
03335    if (!ast) {
03336       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03337       return -1;
03338    }
03339 
03340    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03341 
03342    if (nd) {
03343       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03344       return 0;
03345    }
03346    
03347    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03348 
03349    cl->ts = ast_get_indication_tone(ast->zone, "dial");
03350    
03351    if (cl->ts) {
03352       cl->notxtone = 0;
03353       cl->norxtone = 0;
03354       /* This prods us in misdn_write */
03355       ast_playtones_start(ast, 0, cl->ts->data, 0);
03356    }
03357 
03358    return 0;
03359 }

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

Definition at line 4143 of file chan_misdn.c.

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

Referenced by cb_events().

04144 {
04145    char *predial;
04146    struct ast_frame fr;
04147 
04148    predial = ast_strdupa(ast->exten);
04149 
04150    ch->state = MISDN_DIALING;
04151 
04152    if (!ch->noautorespond_on_setup) {
04153       if (bc->nt) {
04154          int ret; 
04155          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04156       } else {
04157          int ret;
04158          if ( misdn_lib_is_ptp(bc->port)) {
04159             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04160          } else {
04161             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
04162          }
04163       }
04164    } else {
04165       ch->state = MISDN_INCOMING_SETUP;
04166    }
04167 
04168    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);
04169   
04170    strcpy(ast->exten, "s");
04171   
04172    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
04173       ast = NULL;
04174       bc->out_cause = AST_CAUSE_UNALLOCATED;
04175       hangup_chan(ch, bc);
04176       hanguptone_indicate(ch);
04177 
04178       misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
04179    }
04180   
04181   
04182    while (!ast_strlen_zero(predial) ) {
04183       fr.frametype = AST_FRAME_DTMF;
04184       fr.subclass = *predial;
04185       fr.src = NULL;
04186       fr.data.ptr = NULL;
04187       fr.datalen = 0;
04188       fr.samples = 0;
04189       fr.mallocd = 0;
04190       fr.offset = 0;
04191       fr.delivery = ast_tv(0,0);
04192 
04193       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04194          ast_queue_frame(ch->ast, &fr);
04195       }
04196       predial++;
04197    }
04198 }

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

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

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

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

04297 {
04298    char tmp[32];
04299    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04300    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04301    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04302 
04303    if (bc->sending_complete) {
04304       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04305       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04306    }
04307 
04308    if (bc->urate) {
04309       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04310       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04311    }
04312 
04313    if (bc->uulen) {
04314       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04315    }
04316 
04317    if (!ast_strlen_zero(bc->keypad)) {
04318       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04319    }
04320 }

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

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

03776 {
03777    struct chan_list *help = list;
03778    for (; help; help = help->next) {
03779       if (help->bc == bc) {
03780          return help;
03781       }
03782    }
03783 
03784    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03785 
03786    return NULL;
03787 }

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

Definition at line 3789 of file chan_misdn.c.

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

Referenced by import_ch().

03790 {
03791    struct chan_list *help = list;
03792    for (; help; help = help->next) {
03793       if (help->bc && (help->bc->pid == pid)) {
03794          return help;
03795       }
03796    }
03797 
03798    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03799 
03800    return NULL;
03801 }

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

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

03854 {
03855    for (; list; list = list->next) {
03856       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
03857          && list->ast) {
03858          switch (list->state) {
03859          case MISDN_PROCEEDING:
03860          case MISDN_PROGRESS:
03861          case MISDN_ALERTING:
03862          case MISDN_CONNECTED:
03863             return list;
03864          default:
03865             break;
03866          }
03867       }
03868    }
03869    return NULL;
03870 }

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

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

03804 {
03805    struct chan_list *help = list;
03806 
03807    if (bc->pri) {
03808       return NULL;
03809    }
03810 
03811    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03812    for (;help; help = help->next) {
03813       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
03814       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
03815          return help;
03816       }
03817    }
03818    chan_misdn_log(6, bc->port, "$$$ find_hold_call: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03819 
03820    return NULL;
03821 }

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

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

03825 {
03826    struct chan_list *help = list;
03827 
03828    for (; help; help = help->next) {
03829       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
03830          return help;
03831       }
03832    }
03833 
03834    return NULL;
03835 }

static void free_robin_list ( void   )  [static]

Definition at line 431 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

00432 {
00433    struct robin_list *r;
00434    struct robin_list *next;
00435 
00436    for (r = robin, robin = NULL; r; r = next) {
00437       next = r->next;
00438       ast_free(r->group);
00439       ast_free(r);
00440    }
00441 }

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

Definition at line 555 of file chan_misdn.c.

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

Referenced by misdn_bridge().

00556 {
00557    struct chan_list *tmp;
00558   
00559    for (tmp = cl_te; tmp; tmp = tmp->next) {
00560       if (tmp->ast == ast) {
00561          return tmp;
00562       }
00563    }
00564   
00565    return NULL;
00566 }

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

Definition at line 568 of file chan_misdn.c.

References chan_list::ast, ast_channel::name, 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().

00569 {
00570    struct chan_list *tmp;
00571   
00572    for (tmp = cl_te; tmp; tmp = tmp->next) {
00573       if (tmp->ast && strcmp(tmp->ast->name, name) == 0) {
00574          return tmp;
00575       }
00576    }
00577   
00578    return NULL;
00579 }

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

Definition at line 443 of file chan_misdn.c.

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

Referenced by misdn_request().

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

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

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

01044 {
01045    switch (cmd) {
01046    case CLI_INIT:
01047       e->command = "misdn port block";
01048       e->usage =
01049          "Usage: misdn port block <port>\n"
01050          "       Block the specified port by <port>.\n";
01051       return NULL;
01052    case CLI_GENERATE:
01053       return NULL;
01054    }
01055 
01056    if (a->argc != 4) {
01057       return CLI_SHOWUSAGE;
01058    }
01059 
01060    misdn_lib_port_block(atoi(a->argv[3]));
01061 
01062    return CLI_SUCCESS;
01063 }

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

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

01154 {
01155    switch (cmd) {
01156    case CLI_INIT:
01157       e->command = "misdn port down";
01158       e->usage =
01159          "Usage: misdn port down <port>\n"
01160          "       Try to deactivate the L1 on the given port.\n";
01161       return NULL;
01162    case CLI_GENERATE:
01163       return NULL;
01164    }
01165 
01166    if (a->argc != 4) {
01167       return CLI_SHOWUSAGE;
01168    }
01169 
01170    misdn_lib_get_port_down(atoi(a->argv[3]));
01171 
01172    return CLI_SUCCESS;
01173 }

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

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

01066 {
01067    switch (cmd) {
01068    case CLI_INIT:
01069       e->command = "misdn port unblock";
01070       e->usage =
01071          "Usage: misdn port unblock <port>\n"
01072          "       Unblock the port specified by <port>.\n";
01073       return NULL;
01074    case CLI_GENERATE:
01075       return NULL;
01076    }
01077 
01078    if (a->argc != 4) {
01079       return CLI_SHOWUSAGE;
01080    }
01081 
01082    misdn_lib_port_unblock(atoi(a->argv[3]));
01083 
01084    return CLI_SUCCESS;
01085 }

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

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

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

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

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

01353 {
01354    switch (cmd) {
01355    case CLI_INIT:
01356       e->command = "misdn reload";
01357       e->usage =
01358          "Usage: misdn reload\n"
01359          "       Reload internal mISDN config, read from the config\n"
01360          "       file.\n";
01361       return NULL;
01362    case CLI_GENERATE:
01363       return NULL;
01364    }
01365 
01366    if (a->argc != 2) {
01367       return CLI_SHOWUSAGE;
01368    }
01369 
01370    ast_cli(a->fd, "Reloading mISDN configuration\n");
01371    reload_config();
01372    return CLI_SUCCESS;
01373 }

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

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

01110 {
01111    switch (cmd) {
01112    case CLI_INIT:
01113       e->command = "misdn restart pid";
01114       e->usage =
01115          "Usage: misdn restart pid <pid>\n"
01116          "       Restart the given pid\n";
01117       return NULL;
01118    case CLI_GENERATE:
01119       return NULL;
01120    }
01121 
01122    if (a->argc != 4) {
01123       return CLI_SHOWUSAGE;
01124    }
01125 
01126    misdn_lib_pid_restart(atoi(a->argv[3]));
01127 
01128    return CLI_SUCCESS;
01129 }

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

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

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

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

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

01764 {
01765    char *channame; 
01766    char *msg; 
01767    struct chan_list *tmp;
01768    int i, msglen;
01769 
01770    switch (cmd) {
01771    case CLI_INIT:
01772       e->command = "misdn send digit";
01773       e->usage =
01774          "Usage: misdn send digit <channel> \"<msg>\" \n"
01775          "       Send <digit> to <channel> as DTMF Tone\n"
01776          "       when channel is a mISDN channel\n";
01777       return NULL;
01778    case CLI_GENERATE:
01779       return complete_ch(a);
01780    }
01781 
01782    if (a->argc != 5) {
01783       return CLI_SHOWUSAGE;
01784    }
01785 
01786    channame = a->argv[3];
01787    msg = a->argv[4];
01788    msglen = strlen(msg);
01789 
01790    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01791 
01792    tmp = get_chan_by_ast_name(channame);
01793    if (!tmp) {
01794       ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
01795       return CLI_SUCCESS; 
01796    }
01797 #if 1
01798    for (i = 0; i < msglen; i++) {
01799       ast_cli(a->fd, "Sending: %c\n", msg[i]);
01800       send_digit_to_chan(tmp, msg[i]);
01801       /* res = ast_safe_sleep(tmp->ast, 250); */
01802       usleep(250000);
01803       /* res = ast_waitfor(tmp->ast,100); */
01804    }
01805 #else
01806    ast_dtmf_stream(tmp->ast, NULL, msg, 250);
01807 #endif
01808 
01809    return CLI_SUCCESS;
01810 }

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

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

01859 {
01860    char *channame;
01861    char *msg;
01862    struct chan_list *tmp;
01863 
01864    switch (cmd) {
01865    case CLI_INIT:
01866       e->command = "misdn send display";
01867       e->usage =
01868          "Usage: misdn send display <channel> \"<msg>\" \n"
01869          "       Send <msg> to <channel> as Display Message\n"
01870          "       when channel is a mISDN channel\n";
01871       return NULL;
01872    case CLI_GENERATE:
01873       return complete_ch(a);
01874    }
01875 
01876    if (a->argc != 5) {
01877       return CLI_SHOWUSAGE;
01878    }
01879 
01880    channame = a->argv[3];
01881    msg = a->argv[4];
01882 
01883    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
01884    tmp = get_chan_by_ast_name(channame);
01885     
01886    if (tmp && tmp->bc) {
01887       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01888       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01889    } else {
01890       ast_cli(a->fd, "No such channel %s\n", channame);
01891       return CLI_SUCCESS;
01892    }
01893 
01894    return CLI_SUCCESS;
01895 }

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

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

01641 {
01642    char *channame; 
01643    char *nr;
01644    struct chan_list *tmp;
01645    int port; 
01646    char *served_nr;
01647    struct misdn_bchannel dummy, *bc=&dummy;
01648  
01649    switch (cmd) {
01650    case CLI_INIT:
01651       e->command = "misdn send facility";
01652       e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
01653       "\t type is one of:\n"
01654       "\t - calldeflect\n"
01655       "\t - CFActivate\n"
01656       "\t - CFDeactivate\n";
01657 
01658       return NULL;
01659    case CLI_GENERATE:
01660       return complete_ch(a);
01661    }
01662 
01663    if (a->argc < 5) {
01664       return CLI_SHOWUSAGE;
01665    }
01666  
01667    if (strstr(a->argv[3], "calldeflect")) {
01668       if (a->argc < 6) {
01669          ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
01670          return 0;
01671       }
01672       channame = a->argv[4];
01673       nr = a->argv[5];
01674 
01675       ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
01676       tmp = get_chan_by_ast_name(channame);
01677       if (!tmp) {
01678          ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
01679          return 0; 
01680       }
01681 
01682       if (strlen(nr) >= 15) {
01683          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n", nr, channame);
01684          return 0; 
01685       }
01686       tmp->bc->fac_out.Function = Fac_CD;
01687       ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
01688       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
01689    } else if (strstr(a->argv[3], "CFActivate")) {
01690       if (a->argc < 7) {
01691          ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
01692          return 0;
01693       }
01694       port = atoi(a->argv[4]);
01695       served_nr = a->argv[5];
01696       nr = a->argv[6];
01697 
01698       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01699 
01700       ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
01701 
01702       bc->fac_out.Function = Fac_CFActivate;
01703       bc->fac_out.u.CFActivate.BasicService = 0; /* All Services */
01704       bc->fac_out.u.CFActivate.Procedure = 0; /* Unconditional */
01705       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01706       ast_copy_string((char *)bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
01707 
01708       misdn_lib_send_event(bc, EVENT_FACILITY);
01709    } else if (strstr(a->argv[3], "CFDeactivate")) {
01710       if (a->argc < 6) {
01711          ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
01712          return 0;
01713       }
01714       port = atoi(a->argv[4]);
01715       served_nr = a->argv[5];
01716       
01717       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
01718       ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
01719 
01720       bc->fac_out.Function = Fac_CFDeactivate;
01721       bc->fac_out.u.CFDeactivate.BasicService = 0; //All Services
01722       bc->fac_out.u.CFDeactivate.Procedure = 0; //Unconditional
01723       
01724       ast_copy_string((char *)bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
01725       misdn_lib_send_event(bc, EVENT_FACILITY);
01726    }
01727 
01728    return CLI_SUCCESS;
01729 }

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

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

01732 {
01733    int port;
01734    int channel;
01735 
01736    switch (cmd) {
01737    case CLI_INIT:
01738       e->command = "misdn send restart";
01739       e->usage =
01740          "Usage: misdn send restart [port [channel]]\n"
01741          "       Send a restart for every bchannel on the given port.\n";
01742       return NULL;
01743    case CLI_GENERATE:
01744       return NULL;
01745    }
01746 
01747    if (a->argc < 4 || a->argc > 5) {
01748       return CLI_SHOWUSAGE;
01749    }
01750 
01751    port = atoi(a->argv[3]);
01752 
01753    if (a->argc == 5) {
01754       channel = atoi(a->argv[4]);
01755       misdn_lib_send_restart(port, channel);
01756    } else {
01757       misdn_lib_send_restart(port, -1);
01758    }
01759 
01760    return CLI_SUCCESS;
01761 }

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

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

01021 {
01022    switch (cmd) {
01023    case CLI_INIT:
01024       e->command = "misdn set crypt debug";
01025       e->usage =
01026          "Usage: misdn set crypt debug <level>\n"
01027          "       Set the crypt debug level of the mISDN channel. Level\n"
01028          "       must be 1 or 2.\n";
01029       return NULL;
01030    case CLI_GENERATE:
01031       return NULL;
01032    }
01033 
01034    if (a->argc != 5) {
01035       return CLI_SHOWUSAGE;
01036    }
01037 
01038    /* XXX Is this supposed to not do anything? XXX */
01039 
01040    return CLI_SUCCESS;
01041 }

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

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

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

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

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

01531 {
01532    switch (cmd) {
01533    case CLI_INIT:
01534       e->command = "misdn set tics";
01535       e->usage =
01536          "Usage: misdn set tics <value>\n";
01537       return NULL;
01538    case CLI_GENERATE:
01539       return NULL;
01540    }
01541 
01542    if (a->argc != 4) {
01543       return CLI_SHOWUSAGE;
01544    }
01545 
01546    /* XXX Wow, this does... a whole lot of nothing... XXX */
01547    MAXTICS = atoi(a->argv[3]);
01548 
01549    return CLI_SUCCESS;
01550 }

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

Definition at line 1494 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, ast_channel::name, chan_list::next, print_bc_info(), and ast_cli_entry::usage.

01495 {
01496    struct chan_list *help;
01497 
01498    switch (cmd) {
01499    case CLI_INIT:
01500       e->command = "misdn show channel";
01501       e->usage =
01502          "Usage: misdn show channel <channel>\n"
01503          "       Show an internal mISDN channel\n.";
01504       return NULL;
01505    case CLI_GENERATE:
01506       return complete_ch(a);
01507    }
01508 
01509    if (a->argc != 4) {
01510       return CLI_SHOWUSAGE;
01511    }
01512 
01513    help = cl_te;
01514 
01515    for (; help; help = help->next) {
01516       struct misdn_bchannel *bc = help->bc;   
01517       struct ast_channel *ast = help->ast;
01518     
01519       if (bc && ast) {
01520          if (!strcasecmp(ast->name, a->argv[3])) {
01521             print_bc_info(a->fd, help, bc);
01522             break; 
01523          }
01524       }
01525    }
01526 
01527    return CLI_SUCCESS;
01528 }

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

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

01431 {
01432    struct chan_list *help;
01433 
01434    switch (cmd) {
01435    case CLI_INIT:
01436       e->command = "misdn show channels";
01437       e->usage =
01438          "Usage: misdn show channels\n"
01439          "       Show the internal mISDN channel list\n";
01440       return NULL;
01441    case CLI_GENERATE:
01442       return NULL;
01443    }
01444 
01445    if (a->argc != 3) {
01446       return CLI_SHOWUSAGE;
01447    }
01448 
01449    help = cl_te;
01450   
01451    ast_cli(a->fd, "Channel List: %p\n", cl_te);
01452 
01453    for (; help; help = help->next) {
01454       struct misdn_bchannel *bc = help->bc;   
01455       struct ast_channel *ast = help->ast;
01456       if (!ast) {
01457          if (!bc) {
01458             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
01459             continue;
01460          }
01461          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
01462          continue;
01463       }
01464 
01465       if (misdn_debug[0] > 2) {
01466          ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
01467       }
01468       if (bc) {
01469          print_bc_info(a->fd, help, bc);
01470       } else {
01471          if (help->hold.state != MISDN_HOLD_IDLE) {
01472             ast_cli(a->fd, "ITS A HELD CALL BC:\n");
01473             ast_cli(a->fd, " --> l3_id: %x\n"
01474                   " --> dad:%s oad:%s\n"
01475                   " --> hold_port: %d\n"
01476                   " --> hold_channel: %d\n",
01477                   help->l3id,
01478                   ast->exten,
01479                   ast->cid.cid_num,
01480                   help->hold.port,
01481                   help->hold.channel
01482                   );
01483          } else {
01484             ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
01485          }
01486       }
01487    }
01488 
01489    misdn_dump_chanlist();
01490 
01491    return CLI_SUCCESS;
01492 }

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

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

01201 {
01202    char buffer[BUFFERSIZE];
01203    enum misdn_cfg_elements elem;
01204    int linebreak;
01205    int onlyport = -1;
01206    int ok = 0;
01207 
01208    switch (cmd) {
01209    case CLI_INIT:
01210       e->command = "misdn show config";
01211       e->usage =
01212          "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
01213          "       Use 0 for <port> to only print the general config.\n";
01214       return NULL;
01215    case CLI_GENERATE:
01216       return complete_show_config(a);
01217    }
01218 
01219    if (a->argc >= 4) {
01220       if (!strcmp(a->argv[3], "description")) {
01221          if (a->argc == 5) {
01222             enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
01223             if (elem == MISDN_CFG_FIRST) {
01224                ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
01225             } else {
01226                show_config_description(a->fd, elem);
01227             }
01228             return CLI_SUCCESS;
01229          }
01230          return CLI_SHOWUSAGE;
01231       } else if (!strcmp(a->argv[3], "descriptions")) {
01232          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
01233             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
01234                show_config_description(a->fd, elem);
01235                ast_cli(a->fd, "\n");
01236             }
01237             ok = 1;
01238          }
01239          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
01240             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
01241                show_config_description(a->fd, elem);
01242                ast_cli(a->fd, "\n");
01243             }
01244             ok = 1;
01245          }
01246          return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
01247       } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
01248          ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
01249          return CLI_SHOWUSAGE;
01250       }
01251    } else if (a->argc == 3 || onlyport == 0) {
01252       ast_cli(a->fd, "mISDN General-Config:\n");
01253       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
01254          misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
01255          ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01256       }
01257       ast_cli(a->fd, "\n");
01258    }
01259 
01260    if (onlyport < 0) {
01261       int port = misdn_cfg_get_next_port(0);
01262       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
01263          ast_cli(a->fd, "\n[PORT %d]\n", port);
01264          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01265             misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
01266             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01267          }  
01268          ast_cli(a->fd, "\n");
01269       }
01270    }
01271    
01272    if (onlyport > 0) {
01273       if (misdn_cfg_is_port_valid(onlyport)) {
01274          ast_cli(a->fd, "[PORT %d]\n", onlyport);
01275          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
01276             misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
01277             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
01278          }  
01279          ast_cli(a->fd, "\n");
01280       } else {
01281          ast_cli(a->fd, "Port %d is not active!\n", onlyport);
01282       }
01283    }
01284 
01285    return CLI_SUCCESS;
01286 }

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

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

01612 {
01613    int port;
01614    char buf[128];
01615 
01616    switch (cmd) {
01617    case CLI_INIT:
01618       e->command = "misdn show port";
01619       e->usage =
01620          "Usage: misdn show port <port>\n"
01621          "       Show detailed information for given port.\n";
01622       return NULL;
01623    case CLI_GENERATE:
01624       return NULL;
01625    }
01626 
01627    if (a->argc != 4) {
01628       return CLI_SHOWUSAGE;
01629    }
01630 
01631    port = atoi(a->argv[3]);
01632 
01633    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01634    get_show_stack_details(port, buf);
01635    ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01636 
01637    return CLI_SUCCESS;
01638 }

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

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

01583 {
01584    int port;
01585 
01586    switch (cmd) {
01587    case CLI_INIT:
01588       e->command = "misdn show ports stats";
01589       e->usage =
01590          "Usage: misdn show ports stats\n"
01591          "       Show mISDNs channel's call statistics per port.\n";
01592       return NULL;
01593    case CLI_GENERATE:
01594       return NULL;
01595    }
01596 
01597    if (a->argc != 4) {
01598       return CLI_SHOWUSAGE;
01599    }
01600 
01601    ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
01602    for (port = misdn_cfg_get_next_port(0); port > 0;
01603         port = misdn_cfg_get_next_port(port)) {
01604       ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
01605    }
01606    ast_cli(a->fd, "\n");
01607 
01608    return CLI_SUCCESS;
01609 }

static char* handle_cli_misdn_show_stacks ( 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(), 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.

01553 {
01554    int port;
01555 
01556    switch (cmd) {
01557    case CLI_INIT:
01558       e->command = "misdn show stacks";
01559       e->usage =
01560          "Usage: misdn show stacks\n"
01561          "       Show internal mISDN stack_list.\n";
01562       return NULL;
01563    case CLI_GENERATE:
01564       return NULL;
01565    }
01566 
01567    if (a->argc != 3) {
01568       return CLI_SHOWUSAGE;
01569    }
01570 
01571    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
01572    for (port = misdn_cfg_get_next_port(0); port > 0;
01573         port = misdn_cfg_get_next_port(port)) {
01574       char buf[128];
01575       get_show_stack_details(port, buf);
01576       ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
01577    }
01578 
01579    return CLI_SUCCESS;
01580 }

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

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

01813 {
01814    char *channame;
01815    struct chan_list *tmp;
01816 
01817    switch (cmd) {
01818    case CLI_INIT:
01819       e->command = "misdn toggle echocancel";
01820       e->usage =
01821          "Usage: misdn toggle echocancel <channel>\n"
01822          "       Toggle EchoCancel on mISDN Channel.\n";
01823       return NULL;
01824    case CLI_GENERATE:
01825       return complete_ch(a);
01826    }
01827 
01828    if (a->argc != 4) {
01829       return CLI_SHOWUSAGE;
01830    }
01831 
01832    channame = a->argv[3];
01833   
01834    ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
01835   
01836    tmp = get_chan_by_ast_name(channame);
01837    if (!tmp) {
01838       ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
01839       return CLI_SUCCESS;
01840    }
01841 
01842    tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
01843 
01844    if (tmp->toggle_ec) {
01845 #ifdef MISDN_1_2
01846       update_pipeline_config(tmp->bc);
01847 #else
01848       update_ec_config(tmp->bc);
01849 #endif
01850       manager_ec_enable(tmp->bc);
01851    } else {
01852       manager_ec_disable(tmp->bc);
01853    }
01854 
01855    return CLI_SUCCESS;
01856 }

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

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

03933 {
03934    int port;
03935 
03936    if (!ch) {
03937       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03938       return;
03939    }
03940 
03941    port = bc->port;
03942    cb_log(5, port, "hangup_chan called\n");
03943 
03944    if (ch->need_hangup) {
03945       cb_log(2, port, " --> hangup\n");
03946       ch->need_hangup = 0;
03947       ch->need_queue_hangup = 0;
03948       if (ch->ast) {
03949          send_cause2ast(ch->ast, bc, ch);
03950          ast_hangup(ch->ast);
03951       }
03952       return;
03953    }
03954 
03955    if (!ch->need_queue_hangup) {
03956       cb_log(2, port, " --> No need to queue hangup\n");
03957    }
03958 
03959    ch->need_queue_hangup = 0;
03960    if (ch->ast) {
03961       send_cause2ast(ch->ast, bc, ch);
03962       ast_queue_hangup_with_cause(ch->ast, bc->cause);
03963       cb_log(2, port, " --> queue_hangup\n");
03964    } else {
03965       cb_log(1, port, "Cannot hangup chan, no ast\n");
03966    }
03967 }

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

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

04260 {
04261    const char *tmp;
04262 
04263    ast_channel_lock(chan);
04264    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04265    if (tmp) {
04266       ch->other_pid = atoi(tmp);
04267       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04268       if (ch->other_pid > 0) {
04269          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04270          if (ch->other_ch) {
04271             ch->other_ch->other_ch = ch;
04272          }
04273       }
04274    }
04275 
04276    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04277    if (tmp && (atoi(tmp) == 1)) {
04278       bc->sending_complete = 1;
04279    }
04280 
04281    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04282    if (tmp) {
04283       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04284       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04285       bc->uulen = strlen(bc->uu);
04286    }
04287 
04288    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04289    if (tmp) {
04290       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04291    }
04292    ast_channel_unlock(chan);
04293 }

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

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

03409 {
03410    struct chan_list *cl;
03411 
03412    if (!(cl = ast_calloc(1, sizeof(*cl)))) {
03413       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03414       return NULL;
03415    }
03416    
03417    cl->originator = orig;
03418    cl->need_queue_hangup = 1;
03419    cl->need_hangup = 1;
03420    cl->need_busy = 1;
03421    cl->overlap_dial_task = -1;
03422 
03423    return cl;
03424 }

static int load_module ( void   )  [static]

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

05423 {
05424    int i, port;
05425    int ntflags = 0, ntkc = 0;
05426    char ports[256] = "";
05427    char tempbuf[BUFFERSIZE + 1];
05428    char ntfile[BUFFERSIZE + 1];
05429    struct misdn_lib_iface iface = {
05430       .cb_event = cb_events,
05431       .cb_log = chan_misdn_log,
05432       .cb_jb_empty = chan_misdn_jb_empty,
05433    };
05434 
05435    max_ports = misdn_lib_maxports_get();
05436    
05437    if (max_ports <= 0) {
05438       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05439       return AST_MODULE_LOAD_DECLINE;
05440    }
05441    
05442    if (misdn_cfg_init(max_ports, 0)) {
05443       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05444       return AST_MODULE_LOAD_DECLINE;
05445    }
05446    g_config_initialized = 1;
05447    
05448    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
05449    if (!misdn_debug) {
05450       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05451       return AST_MODULE_LOAD_DECLINE;
05452    }
05453    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
05454    if (!misdn_ports) {
05455       ast_free(misdn_debug);
05456       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05457       return AST_MODULE_LOAD_DECLINE;
05458    }
05459    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
05460    for (i = 1; i <= max_ports; i++) {
05461       misdn_debug[i] = misdn_debug[0];
05462       misdn_ports[i] = i;
05463    }
05464    *misdn_ports = 0;
05465    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
05466    if (!misdn_debug_only) {
05467       ast_free(misdn_ports);
05468       ast_free(misdn_debug);
05469       ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
05470       return AST_MODULE_LOAD_DECLINE;
05471    }
05472 
05473    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
05474    if (!ast_strlen_zero(tempbuf)) {
05475       tracing = 1;
05476    }
05477 
05478    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05479    if (!misdn_in_calls) {
05480       ast_free(misdn_debug_only);
05481       ast_free(misdn_ports);
05482       ast_free(misdn_debug);
05483       ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
05484       return AST_MODULE_LOAD_DECLINE;
05485    }
05486    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05487    if (!misdn_out_calls) {
05488       ast_free(misdn_in_calls);
05489       ast_free(misdn_debug_only);
05490       ast_free(misdn_ports);
05491       ast_free(misdn_debug);
05492       ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
05493       return AST_MODULE_LOAD_DECLINE;
05494    }
05495 
05496    for (i = 1; i <= max_ports; i++) {
05497       misdn_in_calls[i] = 0;
05498       misdn_out_calls[i] = 0;
05499    }
05500 
05501    ast_mutex_init(&cl_te_lock);
05502    ast_mutex_init(&release_lock);
05503 
05504    misdn_cfg_update_ptp();
05505    misdn_cfg_get_ports_string(ports);
05506 
05507    if (!ast_strlen_zero(ports)) {
05508       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05509    }
05510    if (misdn_lib_init(ports, &iface, NULL)) {
05511       chan_misdn_log(0, 0, "No te ports initialized\n");
05512    }
05513 
05514    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
05515    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
05516    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
05517 
05518    misdn_lib_nt_keepcalls(ntkc);
05519    misdn_lib_nt_debug_init(ntflags, ntfile);
05520 
05521    if (ast_channel_register(&misdn_tech)) {
05522       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05523       unload_module();
05524       return AST_MODULE_LOAD_DECLINE;
05525    }
05526   
05527    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05528 
05529    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05530       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05531       "Sets mISDN opts. and optargs\n"
05532       "\n"
05533       "The available options are:\n"
05534       "    a - Have Asterisk detect DTMF tones on called channel\n"
05535       "    c - Make crypted outgoing call, optarg is keyindex\n"
05536       "    d - Send display text to called phone, text is the optarg\n"
05537       "    e - Perform echo cancelation on this channel,\n"
05538       "        takes taps as optarg (32,64,128,256)\n"
05539       "   e! - Disable echo cancelation on this channel\n"
05540       "    f - Enable fax detection\n"
05541       "    h - Make digital outgoing call\n"
05542       "   h1 - Make HDLC mode digital outgoing call\n"
05543       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05544       "        they will be transported inband.\n"
05545       "   jb - Set jitter buffer length, optarg is length\n"
05546       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05547       "   jn - Disable jitter buffer\n"
05548       "    n - Disable mISDN DSP on channel.\n"
05549       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05550       "    p - Caller ID presentation,\n"
05551       "        optarg is either 'allowed' or 'restricted'\n"
05552       "    s - Send Non-inband DTMF as inband\n"
05553       "   vr - Rx gain control, optarg is gain\n"
05554       "   vt - Tx gain control, optarg is gain\n"
05555       );
05556 
05557    
05558    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05559              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05560              "Sends the Facility Message FACILITY_TYPE with \n"
05561              "the given Arguments to the current ISDN Channel\n"
05562              "Supported Facilities are:\n"
05563              "\n"
05564              "type=calldeflect args=Nr where to deflect\n"
05565       );
05566 
05567 
05568    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05569              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05570              "Checks if the L2 and L1 are up on either the given <port> or\n"
05571              "on the ports in the group with <groupname>\n"
05572              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05573              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05574              "\n"
05575              "This application, ensures the L1/L2 state of the Ports in a group\n"
05576              "it is intended to make the pmp_l1_check option redundant and to\n"
05577              "fix a buggy switch config from your provider\n"
05578              "\n"
05579              "a sample dialplan would look like:\n\n"
05580              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05581              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05582              "\n"
05583       );
05584 
05585 
05586    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
05587 
05588    /* start the l1 watchers */
05589    
05590    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05591       int l1timeout;
05592       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05593       if (l1timeout) {
05594          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05595          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05596       }
05597    }
05598 
05599    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05600 
05601    return 0;
05602 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2539 of file chan_misdn.c.

References AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_PROTOCOL_ERROR, ast_channel_lock, ast_channel_unlock, 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().

02540 {
02541    struct chan_list *p;
02542    const char *tmp;
02543 
02544    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
02545       return -1;
02546    }
02547    
02548    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
02549    
02550    if (!p) {
02551       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
02552       ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
02553    }
02554 
02555    if (!p->bc) {
02556       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
02557 
02558       ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
02559    }
02560 
02561    ast_channel_lock(ast);
02562    tmp = pbx_builtin_getvar_helper(ast, "CRYPT_KEY");
02563    if (!ast_strlen_zero(tmp)) {
02564       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
02565       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
02566    } else {
02567       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
02568    }
02569 
02570    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
02571    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
02572       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
02573       p->bc->nodsp = 1;
02574       p->bc->hdlc = 0;
02575       p->bc->nojitter = 1;
02576    }
02577    ast_channel_unlock(ast);
02578 
02579    p->state = MISDN_CONNECTED;
02580    stop_indicate(p);
02581 
02582    if ( ast_strlen_zero(p->bc->cad) ) {
02583       chan_misdn_log(2, p->bc->port, " --> empty cad using dad\n");
02584       ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
02585    }
02586 
02587    misdn_lib_send_event(p->bc, EVENT_CONNECT);
02588    start_bc_tones(p);
02589 
02590    return 0;
02591 }

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

Definition at line 4108 of file chan_misdn.c.

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

Referenced by cb_events().

04109 {
04110    int retval;
04111    struct ast_channel *bridged;
04112 
04113    switch (active_ch->state) {
04114    case MISDN_PROCEEDING:
04115    case MISDN_PROGRESS:
04116    case MISDN_ALERTING:
04117    case MISDN_CONNECTED:
04118       break;
04119    default:
04120       return -1;
04121    }
04122 
04123    bridged = ast_bridged_channel(held_ch->ast);
04124    if (bridged) {
04125       ast_queue_control(held_ch->ast, AST_CONTROL_UNHOLD);
04126       held_ch->hold.state = MISDN_HOLD_TRANSFER;
04127 
04128       chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
04129          held_ch->ast->name, active_ch->ast->name);
04130       retval = ast_channel_masquerade(active_ch->ast, bridged);
04131    } else {
04132       /*
04133        * Could not transfer.  Held channel is not bridged anymore.
04134        * Held party probably got tired of waiting and hung up.
04135        */
04136       retval = -1;
04137    }
04138 
04139    return retval;
04140 }

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 3228 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(), ast_channel::name, misdn_bchannel::oad, misdn_bchannel::pid, misdn_bchannel::port, and ast_frame::subclass.

03234 {
03235    struct chan_list *ch1, *ch2;
03236    struct ast_channel *carr[2], *who;
03237    int to = -1;
03238    struct ast_frame *f;
03239    int p1_b, p2_b;
03240    int bridging;
03241   
03242    ch1 = get_chan_by_ast(c0);
03243    ch2 = get_chan_by_ast(c1);
03244 
03245    carr[0] = c0;
03246    carr[1] = c1;
03247   
03248    if (!(ch1 && ch2)) {
03249       return -1;
03250    }
03251 
03252    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
03253    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
03254 
03255    if (! p1_b || ! p2_b) {
03256       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03257       return AST_BRIDGE_FAILED;
03258    }
03259 
03260    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03261    if (bridging) {
03262       /* trying to make a mISDN_dsp conference */
03263       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03264       misdn_lib_bridge(ch1->bc, ch2->bc);
03265    }
03266 
03267    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03268 
03269    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03270  
03271    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) ) {
03272       ch1->ignore_dtmf = 1;
03273    }
03274 
03275    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) ) {
03276       ch2->ignore_dtmf = 1;
03277    }
03278 
03279    for (;/*ever*/;) {
03280       to = -1;
03281       who = ast_waitfor_n(carr, 2, &to);
03282 
03283       if (!who) {
03284          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03285          break;
03286       }
03287       f = ast_read(who);
03288 
03289       if (!f || f->frametype == AST_FRAME_CONTROL) {
03290          /* got hangup .. */
03291 
03292          if (!f) 
03293             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03294          else
03295             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03296 
03297          *fo = f;
03298          *rc = who;
03299          break;
03300       }
03301       
03302       if ( f->frametype == AST_FRAME_DTMF ) {
03303          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03304 
03305          *fo = f;
03306          *rc = who;
03307          break;
03308       }
03309    
03310 #if 0
03311       if (f->frametype == AST_FRAME_VOICE) {
03312          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03313    
03314          continue;
03315       }
03316 #endif
03317 
03318       ast_write(who == c0 ? c1 : c0, f);
03319    }
03320 
03321    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03322 
03323    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03324 
03325    return AST_BRIDGE_COMPLETE;
03326 }

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

we should have l3id after sending setup

Definition at line 2394 of file chan_misdn.c.

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

02395 {
02396    int port = 0;
02397    int r;
02398    int exceed;
02399    int bridging;
02400    struct chan_list *ch;
02401    struct misdn_bchannel *newbc;
02402    char *dest_cp = ast_strdupa(dest);
02403    AST_DECLARE_APP_ARGS(args,
02404       AST_APP_ARG(type);
02405       AST_APP_ARG(ext);
02406       AST_APP_ARG(opts);
02407    );
02408 
02409    /*
02410     * dest is ---v
02411     * Dial(mISDN/g:group_name[/extension[/options]])
02412     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
02413     *
02414     * The dial extension could be empty if you are using MISDN_KEYPAD
02415     * to control ISDN provider features.
02416     */
02417    AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
02418 
02419    if (ast_strlen_zero(args.ext)) {
02420       chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
02421       return -1;
02422    }
02423 
02424    if (!ast) {
02425       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
02426       return -1;
02427    }
02428 
02429    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest) {
02430       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02431       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02432       ast_setstate(ast, AST_STATE_DOWN);
02433       return -1;
02434    }
02435 
02436    ch = MISDN_ASTERISK_TECH_PVT(ast);
02437    if (!ch) {
02438       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02439       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02440       ast_setstate(ast, AST_STATE_DOWN);
02441       return -1;
02442    }
02443    
02444    newbc = ch->bc;
02445    if (!newbc) {
02446       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
02447       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
02448       ast_setstate(ast, AST_STATE_DOWN);
02449       return -1;
02450    }
02451    
02452    port = newbc->port;
02453 
02454    if ((exceed = add_out_calls(port))) {
02455       char tmp[16];
02456       snprintf(tmp, sizeof(tmp), "%d", exceed);
02457       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
02458       return -1;
02459    }
02460    
02461    chan_misdn_log(1, port, "* CALL: %s\n", dest);
02462    
02463    chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
02464    
02465    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
02466    if (ast->exten) {
02467       ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
02468       ast_copy_string(newbc->dad, args.ext, sizeof(newbc->dad));
02469    }
02470 
02471    ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
02472 
02473    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
02474    if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
02475       ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
02476    }
02477 
02478    newbc->capability = ast->transfercapability;
02479    pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
02480    if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
02481       chan_misdn_log(2, port, " --> * Call with flag Digital\n");
02482    }
02483 
02484    /* update screening and presentation */ 
02485    update_config(ch, ORG_AST);
02486       
02487    /* fill in some ies from channel vary */
02488    import_ch(ast, newbc, ch);
02489 
02490    /* Finally The Options Override Everything */
02491    if (!ast_strlen_zero(args.opts)) {
02492       misdn_set_opt_exec(ast, args.opts);
02493    } else {
02494       chan_misdn_log(2, port, "NO OPTS GIVEN\n");
02495    }
02496 
02497    /*check for bridging*/
02498    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
02499    if (bridging && ch->other_ch) {
02500 #ifdef MISDN_1_2
02501       chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
02502       *ch->bc->pipeline = 0;
02503       *ch->other_ch->bc->pipeline = 0;
02504 #else
02505       chan_misdn_log(1, port, "Disabling EC on both Sides\n");
02506       ch->bc->ec_enable = 0;
02507       ch->other_ch->bc->ec_enable = 0;
02508 #endif
02509    }
02510 
02511    r = misdn_lib_send_event(newbc, EVENT_SETUP);
02512 
02513    /** we should have l3id after sending setup **/
02514    ch->l3id = newbc->l3_id;
02515 
02516    if (r == -ENOCHAN ) {
02517       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
02518       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
02519       ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
02520       ast_setstate(ast, AST_STATE_DOWN);
02521       return -1;
02522    }
02523 
02524    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
02525 
02526    ast_setstate(ast, AST_STATE_DIALING);
02527    ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
02528 
02529    if (newbc->nt) {
02530       stop_bc_tones(ch);
02531    }
02532 
02533    ch->state = MISDN_CALLING;
02534    
02535    return 0; 
02536 }

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

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

05664 {
05665    char *parse;
05666    char group[BUFFERSIZE + 1];
05667    char *port_str;
05668    int port = 0;
05669    int timeout;
05670    int dowait = 0;
05671    int port_up;
05672 
05673    AST_DECLARE_APP_ARGS(args,
05674          AST_APP_ARG(grouppar);
05675          AST_APP_ARG(timeout);
05676    );
05677 
05678    if (ast_strlen_zero((char *)data)) {
05679       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05680       return -1;
05681    }
05682 
05683    parse = ast_strdupa(data);
05684    AST_STANDARD_APP_ARGS(args, parse);
05685 
05686    if (args.argc != 2) {
05687       ast_log(LOG_WARNING, "Wrong argument count\n");
05688       return 0;
05689    }
05690 
05691    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05692    timeout = atoi(args.timeout);
05693    port_str = args.grouppar;
05694 
05695    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05696       /* We make a group call lets checkout which ports are in my group */
05697       port_str += 2;
05698       ast_copy_string(group, port_str, sizeof(group));
05699       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05700 
05701       for ( port = misdn_cfg_get_next_port(port); 
05702          port > 0;
05703          port = misdn_cfg_get_next_port(port)) {
05704          char cfg_group[BUFFERSIZE + 1];
05705 
05706          chan_misdn_log(2, 0, "trying port %d\n", port);
05707 
05708          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
05709 
05710          if (!strcasecmp(cfg_group, group)) {
05711             port_up = misdn_lib_port_up(port, 1);
05712 
05713             if (!port_up) {
05714                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05715                misdn_lib_get_port_up(port);
05716                dowait = 1;
05717             }
05718          }
05719       }
05720 
05721    } else {
05722       port = atoi(port_str);
05723       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05724       port_up = misdn_lib_port_up(port, 1);
05725       if (!port_up) {
05726          misdn_lib_get_port_up(port);
05727          dowait = 1;
05728       }
05729    }
05730 
05731    if (dowait) {
05732       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05733       ast_safe_sleep(chan, timeout * 1000);
05734    }
05735 
05736    return 0;
05737 }

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

Definition at line 2593 of file chan_misdn.c.

02594 {
02595    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
02596    return 0;
02597 }

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

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

02600 {
02601    struct chan_list *p;
02602    struct misdn_bchannel *bc;
02603    char buf[2] = { digit, 0 };
02604 
02605    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
02606       return -1;
02607    }
02608 
02609    bc = p->bc;
02610    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
02611    
02612    if (!bc) {
02613       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
02614       return -1;
02615    }
02616    
02617    switch (p->state ) {
02618    case MISDN_CALLING:
02619       if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
02620          strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
02621       }
02622       break;
02623    case MISDN_CALLING_ACKNOWLEDGE:
02624       ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
02625       if (strlen(bc->dad) < sizeof(bc->dad) - 1) {
02626          strncat(bc->dad, buf, sizeof(bc->dad) - strlen(bc->dad) - 1);
02627       }
02628       ast_copy_string(p->ast->exten, bc->dad, sizeof(p->ast->exten));
02629       misdn_lib_send_event(bc, EVENT_INFORMATION);
02630       break;
02631    default:
02632       if (bc->send_dtmf) {
02633          send_digit_to_chan(p, digit);
02634       }
02635       break;
02636    }
02637 
02638    return 0;
02639 }

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

Definition at line 5615 of file chan_misdn.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), 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().

05616 {
05617    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05618    char *parse;
05619    AST_DECLARE_APP_ARGS(args,
05620       AST_APP_ARG(facility_type);
05621       AST_APP_ARG(arg)[99];
05622    );
05623 
05624    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05625    
05626    if (strcasecmp(chan->tech->type, "mISDN")) {
05627       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05628       return -1;
05629    }
05630    
05631    if (ast_strlen_zero((char *)data)) {
05632       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
05633       return -1;
05634    }
05635 
05636    parse = ast_strdupa(data);
05637    AST_STANDARD_APP_ARGS(args, parse);
05638 
05639    if (ast_strlen_zero(args.facility_type)) {
05640       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
05641       return -1;
05642    }
05643 
05644    if (!strcasecmp(args.facility_type, "calldeflect")) {
05645       if (ast_strlen_zero(args.arg[0])) {
05646          ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
05647       }
05648 
05649       if (strlen(args.arg[0]) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05650          ast_log(LOG_WARNING, "Facility: Number argument too long (up to %d digits are allowed). Ignoring.\n", (int)sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05651          return 0;
05652       }
05653       ch->bc->fac_out.Function = Fac_CD;
05654       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0], sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05655       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05656    } else {
05657       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
05658    }
05659 
05660    return 0;
05661 }

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

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

02643 {
02644    struct chan_list *p;
02645 
02646    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
02647       return -1;
02648    }
02649 
02650    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);
02651 
02652    p->ast = ast;
02653 
02654    return 0;
02655 }

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

Definition at line 1310 of file chan_misdn.c.

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

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

01311 {
01312    int i;
01313    static char state[8];
01314    
01315    if (!p) {
01316       return NULL;
01317    }
01318   
01319    for (i = 0; i < ARRAY_LEN(state_array); i++) {
01320       if (state_array[i].state == p->state) {
01321          return state_array[i].txt;
01322       }
01323    }
01324 
01325    snprintf(state, sizeof(state), "%d", p->state) ;
01326 
01327    return state;
01328 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2789 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_channel_lock, ast_channel_unlock, 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, ast_channel::name, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, misdn_bchannel::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.

02790 {
02791    struct chan_list *p;
02792    struct misdn_bchannel *bc;
02793    const char *var;
02794 
02795    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
02796       return -1;
02797    }
02798    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02799 
02800    ast_debug(1, "misdn_hangup(%s)\n", ast->name);
02801 
02802    if (p->hold.state == MISDN_HOLD_IDLE) {
02803       bc = p->bc;
02804    } else {
02805       p->hold.state = MISDN_HOLD_DISCONNECT;
02806       bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
02807       if (!bc) {
02808          chan_misdn_log(4, p->hold.port,
02809             "misdn_hangup: Could not find held bc for (%s)\n", ast->name);
02810          release_chan_early(p);
02811          return 0;
02812       }
02813    }
02814 
02815    if (ast->_state == AST_STATE_RESERVED || p->state == MISDN_NOTHING) {
02816       /* between request and call */
02817       ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
02818       release_chan_early(p);
02819       if (bc) {
02820          misdn_lib_release(bc);
02821       }
02822       return 0;
02823    }
02824    if (!bc) {
02825       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
02826          misdn_get_ch_state(p), p->l3id);
02827       release_chan_early(p);
02828       return 0;
02829    }
02830 
02831    p->ast = NULL;
02832    p->need_hangup = 0;
02833    p->need_queue_hangup = 0;
02834    p->need_busy = 0;
02835 
02836    if (!bc->nt) {
02837       stop_bc_tones(p);
02838    }
02839 
02840    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02841 
02842    ast_channel_lock(ast);
02843    var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
02844    if (!var) {
02845       var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
02846    }
02847    if (var) {
02848       int tmpcause;
02849 
02850       tmpcause = atoi(var);
02851       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02852    }
02853 
02854    var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
02855    if (var) {
02856       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
02857       ast_copy_string(bc->uu, var, sizeof(bc->uu));
02858       bc->uulen = strlen(bc->uu);
02859    }
02860    ast_channel_unlock(ast);
02861 
02862    chan_misdn_log(1, bc->port,
02863       "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",
02864       bc->pid,
02865       ast->context,
02866       ast->exten,
02867       ast->cid.cid_num,
02868       misdn_get_ch_state(p));
02869    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02870    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02871    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02872 
02873    switch (p->state) {
02874    case MISDN_INCOMING_SETUP:
02875       /*
02876        * This is the only place in misdn_hangup, where we
02877        * can call release_chan, else it might create a lot of trouble.
02878        */
02879       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02880       release_chan(p, bc);
02881       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
02882       return 0;
02883    case MISDN_DIALING:
02884       if (p->hold.state == MISDN_HOLD_IDLE) {
02885          start_bc_tones(p);
02886          hanguptone_indicate(p);
02887       }
02888 
02889       p->state = MISDN_CLEANING;
02890       if (bc->need_disconnect) {
02891          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02892       }
02893       break;
02894    case MISDN_CALLING_ACKNOWLEDGE:
02895       if (p->hold.state == MISDN_HOLD_IDLE) {
02896          start_bc_tones(p);
02897          hanguptone_indicate(p);
02898       }
02899 
02900       if (bc->need_disconnect) {
02901          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02902       }
02903       break;
02904 
02905    case MISDN_CALLING:
02906    case MISDN_ALERTING:
02907    case MISDN_PROGRESS:
02908    case MISDN_PROCEEDING:
02909       if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
02910          hanguptone_indicate(p);
02911       }
02912 
02913       if (bc->need_disconnect) {
02914          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02915       }
02916       break;
02917    case MISDN_CONNECTED:
02918       /*  Alerting or Disconnect */
02919       if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
02920          start_bc_tones(p);
02921          hanguptone_indicate(p);
02922          bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
02923       }
02924       if (bc->need_disconnect) {
02925          misdn_lib_send_event(bc, EVENT_DISCONNECT);
02926       }
02927       break;
02928    case MISDN_DISCONNECTED:
02929       if (bc->need_release) {
02930          misdn_lib_send_event(bc, EVENT_RELEASE);
02931       }
02932       break;
02933 
02934    case MISDN_CLEANING:
02935       return 0;
02936 
02937    case MISDN_BUSY:
02938       break;
02939    default:
02940       if (bc->nt) {
02941          bc->out_cause = -1;
02942          if (bc->need_release) {
02943             misdn_lib_send_event(bc, EVENT_RELEASE);
02944          }
02945       } else {
02946          if (bc->need_disconnect) {
02947             misdn_lib_send_event(bc, EVENT_DISCONNECT);
02948          }
02949       }
02950       break;
02951    }
02952 
02953    p->state = MISDN_CLEANING;
02954    chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast->name,
02955       misdn_get_ch_state(p));
02956 
02957    return 0;
02958 }

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

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

02660 {
02661    struct chan_list *p;
02662 
02663    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
02664       ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
02665       return -1;
02666    }
02667    
02668    if (!p->bc) {
02669       if (p->hold.state == MISDN_HOLD_IDLE) {
02670          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
02671             ast->name);
02672          ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
02673       } else {
02674          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
02675             cond, ast->name);
02676       }
02677       return -1;
02678    }
02679    
02680    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n\n", cond, ast->name);
02681    
02682    switch (cond) {
02683    case AST_CONTROL_BUSY:
02684       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
02685       ast_setstate(ast, AST_STATE_BUSY);
02686 
02687       p->bc->out_cause = AST_CAUSE_USER_BUSY;
02688       if (p->state != MISDN_CONNECTED) {
02689          start_bc_tones(p);
02690          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02691       }
02692       return -1;
02693    case AST_CONTROL_RING:
02694       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02695       return -1;
02696    case AST_CONTROL_RINGING:
02697       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02698       switch (p->state) {
02699       case MISDN_ALERTING:
02700          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);
02701          break;
02702       case MISDN_CONNECTED:
02703          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);
02704          return -1;
02705       default:
02706          p->state = MISDN_ALERTING;
02707          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02708          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02709 
02710          if (p->other_ch && p->other_ch->bc) {
02711             if (misdn_inband_avail(p->other_ch->bc)) {
02712                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02713                break;
02714             }
02715 
02716             if (!p->other_ch->bc->nt) {
02717                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02718                break;
02719             }
02720          }
02721 
02722          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02723          ast_setstate(ast, AST_STATE_RING);
02724 
02725          if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
02726             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02727          } else {
02728             return -1;
02729          }
02730       }
02731       break;
02732    case AST_CONTROL_ANSWER:
02733       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02734       start_bc_tones(p);
02735       break;
02736    case AST_CONTROL_TAKEOFFHOOK:
02737       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02738       return -1;
02739    case AST_CONTROL_OFFHOOK:
02740       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02741       return -1;
02742    case AST_CONTROL_FLASH:
02743       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02744       break;
02745    case AST_CONTROL_PROGRESS:
02746       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02747       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02748       break;
02749    case AST_CONTROL_PROCEEDING:
02750       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02751       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02752       break;
02753    case AST_CONTROL_CONGESTION:
02754       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02755 
02756       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02757       start_bc_tones(p);
02758       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02759 
02760       if (p->bc->nt) {
02761          hanguptone_indicate(p);
02762       }
02763       break;
02764    case -1 :
02765       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02766 
02767       stop_indicate(p);
02768 
02769       if (p->state == MISDN_CONNECTED) {
02770          start_bc_tones(p);
02771       }
02772       break;
02773    case AST_CONTROL_HOLD:
02774       ast_moh_start(ast, data, p->mohinterpret); 
02775       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02776       break;
02777    case AST_CONTROL_UNHOLD:
02778       ast_moh_stop(ast);
02779       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02780       break;
02781    default:
02782       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02783       return -1;
02784    }
02785   
02786    return 0;
02787 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

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

06011 {
06012    ast_mutex_destroy(&jb->mutexjb);
06013    
06014    ast_free(jb->ok);
06015    ast_free(jb->samples);
06016    ast_free(jb);
06017 }

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

06085 {
06086    int i, wp, rp, read = 0;
06087 
06088    ast_mutex_lock(&jb->mutexjb);
06089 
06090    rp = jb->rp;
06091    wp = jb->wp;
06092 
06093    if (jb->state_empty) {  
06094       for (i = 0; i < len; i++) {
06095          if (wp == rp) {
06096             jb->rp = rp;
06097             jb->state_empty = 0;
06098 
06099             ast_mutex_unlock(&jb->mutexjb);
06100 
06101             return read;
06102          } else {
06103             if (jb->ok[rp] == 1) {
06104                data[i] = jb->samples[rp];
06105                jb->ok[rp] = 0;
06106                rp = (rp != jb->size - 1) ? rp + 1 : 0;
06107                read += 1;
06108             }
06109          }
06110       }
06111 
06112       if (wp >= rp) {
06113          jb->state_buffer = wp - rp;
06114       } else {
06115          jb->state_buffer = jb->size - rp + wp;
06116       }
06117       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
06118 
06119       jb->rp = rp;
06120    } else {
06121       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
06122    }
06123 
06124    ast_mutex_unlock(&jb->mutexjb);
06125 
06126    return read;
06127 }

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

06022 {
06023    int i, j, rp, wp;
06024 
06025    if (!jb || ! data) {
06026       return 0;
06027    }
06028 
06029    ast_mutex_lock(&jb->mutexjb);
06030    
06031    wp = jb->wp;
06032    rp = jb->rp;
06033    
06034    for (i = 0; i < len; i++) {
06035       jb->samples[wp] = data[i];
06036       jb->ok[wp] = 1;
06037       wp = (wp != jb->size - 1) ? wp + 1 : 0;
06038 
06039       if (wp == jb->rp) {
06040          jb->state_full = 1;
06041       }
06042    }
06043 
06044    if (wp >= rp) {
06045       jb->state_buffer = wp - rp;
06046    } else {
06047       jb->state_buffer = jb->size - rp + wp;
06048    }
06049    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
06050 
06051    if (jb->state_full) {
06052       jb->wp = wp;
06053 
06054       rp = wp;
06055       for (j = 0; j < jb->upper_threshold; j++) {
06056          rp = (rp != 0) ? rp - 1 : jb->size - 1;
06057       }
06058       jb->rp = rp;
06059       jb->state_full = 0;
06060       jb->state_empty = 1;
06061 
06062       ast_mutex_unlock(&jb->mutexjb);
06063 
06064       return -1;
06065    }
06066 
06067    if (!jb->state_empty) {
06068       jb->bytes_wrote += len;
06069       if (jb->bytes_wrote >= jb->upper_threshold) {
06070          jb->state_empty = 1;
06071          jb->bytes_wrote = 0;
06072       }
06073    }
06074    jb->wp = wp;
06075 
06076    ast_mutex_unlock(&jb->mutexjb);
06077    
06078    return 0;
06079 }

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

allocates the jb-structure and initialize the elements

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

05969 {
05970    int i;
05971    struct misdn_jb *jb;
05972 
05973    jb = ast_malloc(sizeof(*jb));
05974    if (!jb) {
05975        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05976        return NULL;
05977    }
05978    jb->size = size;
05979    jb->upper_threshold = upper_threshold;
05980    jb->wp = 0;
05981    jb->rp = 0;
05982    jb->state_full = 0;
05983    jb->state_empty = 0;
05984    jb->bytes_wrote = 0;
05985    jb->samples = ast_malloc(size * sizeof(char));
05986    if (!jb->samples) {
05987       ast_free(jb);
05988       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05989       return NULL;
05990    }
05991 
05992    jb->ok = ast_malloc(size * sizeof(char));
05993    if (!jb->ok) {
05994       ast_free(jb->samples);
05995       ast_free(jb);
05996       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05997       return NULL;
05998    }
05999 
06000    for (i = 0; i < size; i++) {
06001       jb->ok[i] = 0;
06002    }
06003 
06004    ast_mutex_init(&jb->mutexjb);
06005 
06006    return jb;
06007 }

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

Definition at line 838 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

00839 {
00840    const int *data = vdata;
00841    misdn_lib_isdn_l1watcher(*data);
00842    chan_misdn_log(5, *data, "L1watcher timeout\n");
00843    return 1;
00844 }

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

03706 {
03707    struct ast_channel *tmp;
03708    char *cid_name = 0, *cid_num = 0;
03709    int chan_offset = 0;
03710    int tmp_port = misdn_cfg_get_next_port(0);
03711    int bridging;
03712 
03713    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03714       if (tmp_port == port) {
03715          break;
03716       }
03717       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03718    }
03719    if (c < 0) {
03720       c = 0;
03721    }
03722 
03723    if (callerid) {
03724       ast_callerid_parse(callerid, &cid_name, &cid_num);
03725    }
03726 
03727    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++);
03728    if (tmp) {
03729       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03730 
03731       tmp->nativeformats = prefformat;
03732 
03733       tmp->readformat = format;
03734       tmp->rawreadformat = format;
03735       tmp->writeformat = format;
03736       tmp->rawwriteformat = format;
03737     
03738       tmp->tech_pvt = chlist;
03739 
03740       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03741 
03742       tmp->tech = bridging ? &misdn_tech : &misdn_tech_wo_bridge;
03743 
03744       tmp->writeformat = format;
03745       tmp->readformat = format;
03746       tmp->priority = 1;
03747 
03748       if (exten) {
03749          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03750       } else {
03751          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03752       }
03753 
03754       if (callerid) {
03755          /* Don't use ast_set_callerid() here because it will
03756           * generate a needless NewCallerID event */
03757          tmp->cid.cid_ani = ast_strdup(cid_num);
03758       }
03759 
03760       if (pipe(chlist->pipe) < 0) {
03761          ast_log(LOG_ERROR, "Pipe failed\n");
03762       }
03763       ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
03764 
03765       tmp->rings = (state == AST_STATE_RING) ? 1 : 0;
03766 
03767       ast_jb_configure(tmp, misdn_get_global_jbconf());
03768    } else {
03769       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03770    }
03771    
03772    return tmp;
03773 }

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

Definition at line 846 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_UNALLOCATED, ast_copy_string(), 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().

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

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

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

03034 {
03035    struct chan_list *tmp;
03036    fd_set rrfs;
03037    struct timeval tv = { 0, 20000 };
03038    int len, t;
03039 
03040    if (!ast) {
03041       chan_misdn_log(1, 0, "misdn_read called without ast\n");
03042       return NULL;
03043    }
03044    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
03045       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
03046       return NULL;
03047    }
03048 
03049    if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
03050       chan_misdn_log(1, 0, "misdn_read called without bc\n");
03051       return NULL;
03052    }
03053 
03054    FD_ZERO(&rrfs);
03055    FD_SET(tmp->pipe[0], &rrfs);
03056 
03057    if (!(t = select(FD_SETSIZE, &rrfs, NULL, NULL, &tv))) {
03058       chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
03059       len = 160;
03060    }
03061 
03062    if (t < 0) {
03063       chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n", strerror(errno));
03064       return NULL;
03065    }
03066 
03067    if (FD_ISSET(tmp->pipe[0], &rrfs)) {
03068       len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
03069 
03070       if (len <= 0) {
03071          /* we hangup here, since our pipe is closed */
03072          chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
03073          return NULL;
03074       }
03075 
03076    } else {
03077       return NULL;
03078    }
03079 
03080    tmp->frame.frametype = AST_FRAME_VOICE;
03081    tmp->frame.subclass = AST_FORMAT_ALAW;
03082    tmp->frame.datalen = len;
03083    tmp->frame.samples = len;
03084    tmp->frame.mallocd = 0;
03085    tmp->frame.offset = 0;
03086    tmp->frame.delivery = ast_tv(0, 0);
03087    tmp->frame.src = NULL;
03088    tmp->frame.data.ptr = tmp->ast_rd_buf;
03089 
03090    if (tmp->faxdetect && !tmp->faxhandled) {
03091       if (tmp->faxdetect_timeout) {
03092          if (ast_tvzero(tmp->faxdetect_tv)) {
03093             tmp->faxdetect_tv = ast_tvnow();
03094             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
03095             return process_ast_dsp(tmp, &tmp->frame);
03096          } else {
03097             struct timeval tv_now = ast_tvnow();
03098             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
03099             if (diff <= (tmp->faxdetect_timeout * 1000)) {
03100                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
03101                return process_ast_dsp(tmp, &tmp->frame);
03102             } else {
03103                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
03104                tmp->faxdetect = 0;
03105                return &tmp->frame;
03106             }
03107          }
03108       } else {
03109          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
03110          return process_ast_dsp(tmp, &tmp->frame);
03111       }
03112    } else {
03113       if (tmp->ast_dsp) {
03114          return process_ast_dsp(tmp, &tmp->frame);
03115       } else {
03116          return &tmp->frame;
03117       }
03118    }
03119 }

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

Definition at line 3426 of file chan_misdn.c.

References chan_list::ast, ast_copy_string(), ast_free, ast_log(), AST_STATE_RESERVED, ast_strlen_zero(), chan_list::bc, buf2, 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, and read_config().

03427 {
03428    struct ast_channel *tmp = NULL;
03429    char group[BUFFERSIZE + 1] = "";
03430    char dial_str[128];
03431    char *buf2 = ast_strdupa(data);
03432    char *ext;
03433    char *port_str;
03434    char *p = NULL;
03435    int channel = 0;
03436    int port = 0;
03437    struct misdn_bchannel *newbc = NULL;
03438    int dec = 0;
03439    struct chan_list *cl;
03440 
03441    snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
03442 
03443    /*
03444     * data is ---v
03445     * Dial(mISDN/g:group_name[/extension[/options]])
03446     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
03447     *
03448     * The dial extension could be empty if you are using MISDN_KEYPAD
03449     * to control ISDN provider features.
03450     */
03451    port_str = strsep(&buf2, "/");
03452    if (!ast_strlen_zero(port_str)) {
03453       if (port_str[0] == 'g' && port_str[1] == ':' ) {
03454          /* We make a group call lets checkout which ports are in my group */
03455          port_str += 2;
03456          ast_copy_string(group, port_str, sizeof(group));
03457          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03458       } else if ((p = strchr(port_str, ':'))) {
03459          /* we have a preselected channel */
03460          *p = 0;
03461          channel = atoi(++p);
03462          port = atoi(port_str);
03463          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03464       } else {
03465          port = atoi(port_str);
03466       }
03467    } else {
03468       ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
03469       return NULL;
03470    }
03471 
03472    ext = strsep(&buf2, "/");
03473    if (!ext) {
03474       ext = "";
03475    }
03476 
03477    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03478       chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
03479       dec = 1;
03480    }
03481 
03482    if (!ast_strlen_zero(group)) {
03483       char cfg_group[BUFFERSIZE + 1];
03484       struct robin_list *rr = NULL;
03485 
03486       /* Group dial */
03487 
03488       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03489          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03490          rr = get_robin_position(group);
03491       }
03492 
03493       if (rr) {
03494          int robin_channel = rr->channel;
03495          int port_start;
03496          int next_chan = 1;
03497 
03498          do {
03499             port_start = 0;
03500             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
03501                 port = misdn_cfg_get_next_port_spin(port)) {
03502 
03503                if (!port_start) {
03504                   port_start = port;
03505                }
03506 
03507                if (port >= port_start) {
03508                   next_chan = 1;
03509                }
03510                
03511                if (port <= port_start && next_chan) {
03512                   int maxbchans=misdn_lib_get_maxchans(port);
03513                   if (++robin_channel >= maxbchans) {
03514                      robin_channel = 1;
03515                   }
03516                   next_chan = 0;
03517                }
03518 
03519                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03520 
03521                if (!strcasecmp(cfg_group, group)) {
03522                   int port_up;
03523                   int check;
03524                   misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03525                   port_up = misdn_lib_port_up(port, check);
03526 
03527                   if (check && !port_up) {
03528                      chan_misdn_log(1, port, "L1 is not Up on this Port\n");
03529                   }
03530                   
03531                   if (check && port_up < 0) {
03532                      ast_log(LOG_WARNING, "This port (%d) is blocked\n", port);
03533                   }
03534 
03535                   if (port_up > 0)  {
03536                      newbc = misdn_lib_get_free_bc(port, robin_channel, 0, 0);
03537                      if (newbc) {
03538                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03539                         if (port_up) {
03540                            chan_misdn_log(4, port, "portup:%d\n",  port_up);
03541                         }
03542                         rr->port = newbc->port;
03543                         rr->channel = newbc->channel;
03544                         break;
03545                      }
03546                   }
03547                }
03548             }
03549          } while (!newbc && robin_channel != rr->channel);
03550       } else {    
03551          for (port = misdn_cfg_get_next_port(0); port > 0;
03552              port = misdn_cfg_get_next_port(port)) {
03553 
03554             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
03555 
03556             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03557             if (!strcasecmp(cfg_group, group)) {
03558                int port_up;
03559                int check;
03560                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
03561                port_up = misdn_lib_port_up(port, check);
03562 
03563                chan_misdn_log(4, port, "portup:%d\n", port_up);
03564 
03565                if (port_up > 0) {
03566                   if ((newbc = misdn_lib_get_free_bc(port, 0, 0, dec))) {
03567                      break;
03568                   }
03569                }
03570             }
03571          }
03572       }
03573       
03574       /* Group dial failed ?*/
03575       if (!newbc) {
03576          ast_log(LOG_WARNING, 
03577                "Could not Dial out on group '%s'.\n"
03578                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03579                "\tOr there was no free channel on none of the ports\n\n"
03580                , group);
03581          return NULL;
03582       }
03583    } else {
03584       /* 'Normal' Port dial * Port dial */
03585       if (channel) {
03586          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03587       }
03588       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03589 
03590       if (!newbc) {
03591          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03592          return NULL;
03593       }
03594    }
03595    
03596 
03597    /* create ast_channel and link all the objects together */
03598    cl = init_chan_list(ORG_AST);
03599    if (!cl) {
03600       ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
03601       return NULL;
03602    }
03603    cl->bc = newbc;
03604    
03605    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03606    if (!tmp) {
03607       ast_free(cl);
03608       ast_log(LOG_ERROR, "Could not create Asterisk object\n");
03609       return NULL;
03610    }
03611 
03612    cl->ast = tmp;
03613    
03614    /* register chan in local list */
03615    cl_queue_chan(&cl_te, cl);
03616    
03617    /* fill in the config into the objects */
03618    read_config(cl, ORG_AST);
03619 
03620    /* important */
03621    cl->need_hangup = 0;
03622    
03623    return tmp;
03624 }

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

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

03628 {
03629    struct chan_list *tmp = chan->tech_pvt;
03630    
03631    if (tmp && tmp->bc) {
03632       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03633       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03634    } else {
03635       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03636       return -1;
03637    }
03638    
03639    return 0;
03640 }

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

Definition at line 5739 of file chan_misdn.c.

References ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), ast_log(), ast_strlen_zero(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, 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, ast_channel::tech, misdn_bchannel::txgain, and ast_channel_tech::type.

Referenced by load_module(), and misdn_call().

05740 {
05741    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05742    char *tok, *tokb, *parse;
05743    int  keyidx = 0;
05744    int rxgain = 0;
05745    int txgain = 0;
05746    int change_jitter = 0;
05747 
05748    if (strcasecmp(chan->tech->type, "mISDN")) {
05749       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05750       return -1;
05751    }
05752    
05753    if (ast_strlen_zero((char *)data)) {
05754       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05755       return -1;
05756    }
05757 
05758    parse = ast_strdupa(data);
05759    for (tok = strtok_r(parse, ":", &tokb);
05760         tok;
05761         tok = strtok_r(NULL, ":", &tokb) ) {
05762       int neglect = 0;
05763 
05764       if (tok[0] == '!' ) {
05765          neglect = 1;
05766          tok++;
05767       }
05768       
05769       switch(tok[0]) {
05770          
05771       case 'd' :
05772          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05773          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05774          break;
05775          
05776       case 'n':
05777          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05778          ch->bc->nodsp = 1;
05779          break;
05780 
05781       case 'j':
05782          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05783          tok++;
05784          change_jitter = 1;
05785 
05786          switch ( tok[0] ) {
05787          case 'b':
05788             ch->jb_len = atoi(++tok);
05789             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05790             break;
05791          case 't' :
05792             ch->jb_upper_threshold = atoi(++tok);
05793             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05794             break;
05795          case 'n':
05796             ch->bc->nojitter = 1;
05797             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05798             break;
05799          default:
05800             ch->jb_len = 4000;
05801             ch->jb_upper_threshold = 0;
05802             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05803             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05804          }
05805          break;
05806       case 'v':
05807          tok++;
05808 
05809          switch (tok[0]) {
05810          case 'r' :
05811             rxgain = atoi(++tok);
05812             if (rxgain < -8) {
05813                rxgain = -8;
05814             }
05815             if (rxgain > 8) {
05816                rxgain = 8;
05817             }
05818             ch->bc->rxgain = rxgain;
05819             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05820             break;
05821          case 't':
05822             txgain = atoi(++tok);
05823             if (txgain < -8) {
05824                txgain = -8;
05825             }
05826             if (txgain > 8) {
05827                txgain = 8;
05828             }
05829             ch->bc->txgain = txgain;
05830             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05831             break;
05832          }
05833          break;
05834       
05835       case 'c':
05836          keyidx = atoi(++tok);
05837          {
05838             char keys[4096];
05839             char *key = NULL, *tmp = keys;
05840             int i;
05841             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05842 
05843             for (i = 0; i < keyidx; i++) {
05844                key = strsep(&tmp, ",");
05845             }
05846 
05847             if (key) {
05848                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05849             }
05850 
05851             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05852             break;
05853          }
05854       case 'e':
05855          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05856          
05857          if (neglect) {
05858             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05859 #ifdef MISDN_1_2
05860             *ch->bc->pipeline = 0;
05861 #else
05862             ch->bc->ec_enable = 0;
05863 #endif
05864          } else {
05865 #ifdef MISDN_1_2
05866             update_pipeline_config(ch->bc);
05867 #else
05868             ch->bc->ec_enable = 1;
05869             ch->bc->orig = ch->originator;
05870             tok++;
05871             if (*tok) {
05872                ch->bc->ec_deftaps = atoi(tok);
05873             }
05874 #endif
05875          }
05876          
05877          break;
05878       case 'h':
05879          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05880          
05881          if (strlen(tok) > 1 && tok[1] == '1') {
05882             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05883             if (!ch->bc->hdlc) {
05884                ch->bc->hdlc = 1;
05885             }
05886          }
05887          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05888          break;
05889             
05890       case 's':
05891          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05892          ch->bc->send_dtmf = 1;
05893          break;
05894          
05895       case 'f':
05896          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05897          ch->faxdetect = 1;
05898          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05899          break;
05900 
05901       case 'a':
05902          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05903          ch->ast_dsp = 1;
05904          break;
05905 
05906       case 'p':
05907          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05908          /* CRICH: callingpres!!! */
05909          if (strstr(tok, "allowed")) {
05910             ch->bc->pres = 0;
05911          } else if (strstr(tok, "restricted")) {
05912             ch->bc->pres = 1;
05913          } else if (strstr(tok, "not_screened")) {
05914             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05915             ch->bc->pres = 1;
05916          }
05917          break;
05918       case 'i' :
05919          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05920          ch->ignore_dtmf=1;
05921          break;
05922       default:
05923          break;
05924       }
05925    }
05926 
05927    if (change_jitter) {
05928       config_jitterbuffer(ch);
05929    }
05930 
05931    if (ch->faxdetect || ch->ast_dsp) {
05932       if (!ch->dsp) {
05933          ch->dsp = ast_dsp_new();
05934       }
05935       if (ch->dsp) {
05936          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
05937       }
05938    }
05939 
05940    if (ch->ast_dsp) {
05941       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05942       ch->bc->nodsp = 1;
05943    }
05944    
05945    return 0;
05946 }

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

Definition at line 823 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

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

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

Definition at line 828 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

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

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 793 of file chan_misdn.c.

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

Referenced by unload_module().

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

static void misdn_tasks_init ( void   )  [static]

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

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

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 833 of file chan_misdn.c.

References AST_SCHED_DEL.

Referenced by release_chan(), and release_chan_early().

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

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

Definition at line 748 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 805 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

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

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

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

03123 {
03124    struct chan_list *ch;
03125    int i  = 0;
03126    
03127    if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
03128       return -1;
03129    }
03130 
03131    if (ch->hold.state != MISDN_HOLD_IDLE) {
03132       chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
03133       return 0;
03134    }
03135    
03136    if (!ch->bc ) {
03137       ast_log(LOG_WARNING, "private but no bc\n");
03138       return -1;
03139    }
03140    
03141    if (ch->notxtone) {
03142       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
03143       return 0;
03144    }
03145 
03146 
03147    if (!frame->subclass) {
03148       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
03149       return 0;
03150    }
03151    
03152    if (!(frame->subclass & prefformat)) {
03153       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
03154       return 0;
03155    }
03156    
03157 
03158    if (!frame->samples ) {
03159       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
03160       
03161       if (!strcmp(frame->src,"ast_prod")) {
03162          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
03163 
03164          if (ch->ts) {
03165             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
03166             misdn_lib_tone_generator_start(ch->bc);
03167          }
03168          return 0;
03169       }
03170 
03171       return -1;
03172    }
03173 
03174    if (!ch->bc->addr) {
03175       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
03176       return 0;
03177    }
03178    
03179 #ifdef MISDN_DEBUG
03180    {
03181       int i, max = 5 > frame->samples ? frame->samples : 5;
03182 
03183       ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
03184 
03185       for (i = 0; i < max; i++) {
03186          ast_debug(1, "%2.2x ", ((char *) frame->data.ptr)[i]);
03187       }
03188    }
03189 #endif
03190 
03191    switch (ch->bc->bc_state) {
03192    case BCHAN_ACTIVATED:
03193    case BCHAN_BRIDGED:
03194       break;
03195    default:
03196       if (!ch->dropped_frame_cnt) {
03197          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);
03198       }
03199       
03200       if (++ch->dropped_frame_cnt > 100) {
03201          ch->dropped_frame_cnt = 0;
03202          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);
03203       }
03204 
03205       return 0;
03206    }
03207 
03208    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
03209    if (!ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability)) {
03210       /* Buffered Transmit (triggered by read from isdn side)*/
03211       if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
03212          if (ch->bc->active) {
03213             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
03214          }
03215       }
03216       
03217    } else {
03218       /*transmit without jitterbuffer*/
03219       i = misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
03220    }
03221 
03222    return 0;
03223 }

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

03924 {
03925    int ret = ast_pbx_start(ch->ast);   
03926 
03927    ch->need_hangup = (ret >= 0) ? 0 : 1;
03928 
03929    return ret;
03930 }

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

Definition at line 1375 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_show_channel(), and handle_cli_misdn_show_channels().

01376 {
01377    struct ast_channel *ast = help->ast;
01378    ast_cli(fd,
01379       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
01380 
01381       bc->pid, bc->port, bc->channel,
01382       bc->nt ? "NT" : "TE",
01383       help->originator == ORG_AST ? "*" : "I",
01384       ast ? ast->exten : NULL,
01385       ast ? ast->cid.cid_num : NULL,
01386       bc->rad,
01387       ast ? ast->context : NULL,
01388       misdn_get_ch_state(help)
01389       );
01390    if (misdn_debug[bc->port] > 0) {
01391       ast_cli(fd,
01392          "  --> astname: %s\n"
01393          "  --> ch_l3id: %x\n"
01394          "  --> ch_addr: %x\n"
01395          "  --> bc_addr: %x\n"
01396          "  --> bc_l3id: %x\n"
01397          "  --> display: %s\n"
01398          "  --> activated: %d\n"
01399          "  --> state: %s\n"
01400          "  --> capability: %s\n"
01401 #ifdef MISDN_1_2
01402          "  --> pipeline: %s\n"
01403 #else
01404          "  --> echo_cancel: %d\n"
01405 #endif
01406          "  --> notone : rx %d tx:%d\n"
01407          "  --> bc_hold: %d\n",
01408          help->ast->name,
01409          help->l3id,
01410          help->addr,
01411          bc->addr,
01412          bc ? bc->l3_id : -1,
01413          bc->display,
01414          
01415          bc->active,
01416          bc_state2str(bc->bc_state),
01417          bearer2str(bc->capability),
01418 #ifdef MISDN_1_2
01419          bc->pipeline,
01420 #else
01421          bc->ec_enable,
01422 #endif
01423 
01424          help->norxtone, help->notxtone,
01425          bc->holded
01426          );
01427    }
01428 }

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

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

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

Definition at line 616 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by cb_events().

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

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

Definition at line 2961 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_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(), ast_channel::name, pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, ast_frame::subclass, and misdn_bchannel::txgain.

Referenced by misdn_read().

02962 {
02963    struct ast_frame *f;
02964  
02965    if (tmp->dsp) {
02966       f = ast_dsp_process(tmp->ast, tmp->dsp, frame);
02967    } else {
02968       chan_misdn_log(0, tmp->bc->port, "No DSP-Path found\n");
02969       return NULL;
02970    }
02971 
02972    if (!f || (f->frametype != AST_FRAME_DTMF)) {
02973       return f;
02974    }
02975  
02976    ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass);
02977  
02978    if (tmp->faxdetect && (f->subclass == 'f')) {
02979       /* Fax tone -- Handle and return NULL */
02980       if (!tmp->faxhandled) {
02981          struct ast_channel *ast = tmp->ast;
02982          tmp->faxhandled++;
02983          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02984          tmp->bc->rxgain = 0;
02985          isdn_lib_update_rxgain(tmp->bc);
02986          tmp->bc->txgain = 0;
02987          isdn_lib_update_txgain(tmp->bc);
02988 #ifdef MISDN_1_2
02989          *tmp->bc->pipeline = 0;
02990 #else
02991          tmp->bc->ec_enable = 0;
02992 #endif
02993          isdn_lib_update_ec(tmp->bc);
02994          isdn_lib_stop_dtmf(tmp->bc);
02995          switch (tmp->faxdetect) {
02996          case 1:
02997             if (strcmp(ast->exten, "fax")) {
02998                char *context;
02999                char context_tmp[BUFFERSIZE];
03000                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
03001                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
03002                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
03003                   ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
03004                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
03005                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
03006                   if (ast_async_goto(ast, context, "fax", 1)) {
03007                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
03008                   }
03009                } else {
03010                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
03011                }
03012             } else {
03013                ast_debug(1, "Already in a fax extension, not redirecting\n");
03014             }
03015             break;
03016          case 2:
03017             ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
03018             break;
03019          }
03020       } else {
03021          ast_debug(1, "Fax already handled\n");
03022       }
03023    }
03024    
03025    if (tmp->ast_dsp && (f->subclass != 'f')) {
03026       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
03027    }
03028 
03029    return f;
03030 }

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

Definition at line 2185 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_free, ast_log(), ast_mutex_init(), ast_print_group(), ast_set_callerid(), ast_strdup, ast_string_field_set, ast_strlen_zero(), chan_list::bc, buf, buf2, 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, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

02186 {
02187    struct ast_channel *ast;
02188    struct misdn_bchannel *bc;
02189    int port;
02190    int hdlc = 0;
02191    char lang[BUFFERSIZE + 1];
02192    char faxdetect[BUFFERSIZE + 1];
02193    char buf[256];
02194    char buf2[256];
02195    ast_group_t pg;
02196    ast_group_t cg;
02197 
02198    if (!ch) {
02199       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
02200       return -1;
02201    }
02202 
02203    ast = ch->ast;
02204    bc = ch->bc;
02205    if (! ast || ! bc) {
02206       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
02207       return -1;
02208    }
02209    
02210    port = bc->port;
02211    chan_misdn_log(1, port, "read_config: Getting Config\n");
02212 
02213    misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
02214    ast_string_field_set(ast, language, lang);
02215 
02216    misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
02217 
02218    misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
02219    misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
02220 
02221    misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
02222 
02223    misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
02224 
02225    misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
02226 
02227    if (ch->ast_dsp) {
02228       ch->ignore_dtmf = 1;
02229    }
02230 
02231    misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
02232    misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
02233 
02234    misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
02235 
02236    misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
02237 
02238    misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
02239 
02240    misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
02241 
02242    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
02243 
02244    if (hdlc) {
02245       switch (bc->capability) {
02246       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02247       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
02248          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
02249          bc->hdlc = 1;
02250          break;
02251       }
02252       
02253    }
02254    /*Initialize new Jitterbuffer*/
02255    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
02256    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
02257 
02258    config_jitterbuffer(ch);
02259 
02260    misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
02261 
02262    ast_copy_string(ast->context, ch->context, sizeof(ast->context));
02263 
02264 #ifdef MISDN_1_2
02265    update_pipeline_config(bc);
02266 #else
02267    update_ec_config(bc);
02268 #endif
02269 
02270    misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
02271 
02272    misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02273    misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02274 
02275    chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
02276    ast->pickupgroup = pg;
02277    ast->callgroup = cg;
02278    
02279    if (orig == ORG_AST) {
02280       char callerid[BUFFERSIZE + 1];
02281 
02282       /* ORIGINATOR Asterisk (outgoing call) */
02283 
02284       misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
02285 
02286       if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
02287          ch->faxdetect = strstr(faxdetect, "nojump") ? 2 : 1;
02288       }
02289 
02290       misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
02291       if (!ast_strlen_zero(callerid)) {
02292          chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
02293          ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
02294       }
02295 
02296       misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(bc->dnumplan));
02297       misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(bc->onumplan));
02298       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02299       debug_numplan(port, bc->dnumplan, "TON");
02300       debug_numplan(port, bc->onumplan, "LTON");
02301       debug_numplan(port, bc->cpnnumplan, "CTON");
02302 
02303       ch->overlap_dial = 0;
02304    } else {
02305       /* ORIGINATOR MISDN (incoming call) */
02306       char prefix[BUFFERSIZE + 1] = "";
02307 
02308       if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
02309          ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
02310       }
02311 
02312       misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(bc->cpnnumplan));
02313       debug_numplan(port, bc->cpnnumplan, "CTON");
02314 
02315       switch (bc->onumplan) {
02316       case NUMPLAN_INTERNATIONAL:
02317          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02318          break;
02319 
02320       case NUMPLAN_NATIONAL:
02321          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02322          break;
02323       default:
02324          break;
02325       }
02326 
02327       ast_copy_string(buf, bc->oad, sizeof(buf));
02328       snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
02329 
02330       if (!ast_strlen_zero(bc->dad)) {
02331          ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
02332       }
02333 
02334       if (ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02335          ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
02336       }
02337 
02338       prefix[0] = 0;
02339 
02340       switch (bc->dnumplan) {
02341       case NUMPLAN_INTERNATIONAL:
02342          misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, sizeof(prefix));
02343          break;
02344       case NUMPLAN_NATIONAL:
02345          misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, sizeof(prefix));
02346          break;
02347       default:
02348          break;
02349       }
02350 
02351       ast_copy_string(buf, bc->dad, sizeof(buf));
02352       snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
02353 
02354       if (strcmp(bc->dad, ast->exten)) {
02355          ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
02356       }
02357 
02358       ast_set_callerid(ast, bc->oad, NULL, bc->oad);
02359 
02360       if ( !ast_strlen_zero(bc->rad) ) {
02361          if (ast->cid.cid_rdnis) {
02362             ast_free(ast->cid.cid_rdnis);
02363          }
02364          ast->cid.cid_rdnis = ast_strdup(bc->rad);
02365       }
02366    
02367       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
02368       ast_mutex_init(&ch->overlap_tv_lock);
02369    } /* ORIG MISDN END */
02370 
02371    ch->overlap_dial_task = -1;
02372    
02373    if (ch->faxdetect  || ch->ast_dsp) {
02374       misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
02375       if (!ch->dsp) {
02376          ch->dsp = ast_dsp_new();
02377       }
02378       if (ch->dsp) {
02379          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | (ch->faxdetect ? DSP_FEATURE_FAX_DETECT : 0));
02380       }
02381    }
02382 
02383    /* AOCD initialization */
02384    bc->AOCDtype = Fac_None;
02385 
02386    return 0;
02387 }

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

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

03981 {
03982    struct ast_channel *ast;
03983 
03984    ch->state = MISDN_CLEANING;
03985 
03986    ast_mutex_lock(&release_lock);
03987 
03988    cl_dequeue_chan(&cl_te, ch);
03989 
03990    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
03991 
03992    /* releasing jitterbuffer */
03993    if (ch->jb) {
03994       misdn_jb_destroy(ch->jb);
03995       ch->jb = NULL;
03996    } else {
03997       if (!bc->nojitter) {
03998          chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03999       }
04000    }
04001 
04002    if (ch->overlap_dial) {
04003       if (ch->overlap_dial_task != -1) {
04004          misdn_tasks_remove(ch->overlap_dial_task);
04005          ch->overlap_dial_task = -1;
04006       }
04007       ast_mutex_destroy(&ch->overlap_tv_lock);
04008    }
04009 
04010    if (ch->originator == ORG_AST) {
04011       --misdn_out_calls[bc->port];
04012    } else {
04013       --misdn_in_calls[bc->port];
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       chan_misdn_log(1, bc->port,
04023          "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s\n",
04024          bc->pid,
04025          ast->context,
04026          ast->exten,
04027          ast->cid.cid_num);
04028 
04029       if (ast->_state != AST_STATE_RESERVED) {
04030          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
04031          ast_setstate(ast, AST_STATE_DOWN);
04032       }
04033    }
04034 
04035    ast_free(ch);
04036 
04037    ast_mutex_unlock(&release_lock);
04038 }

static void release_chan_early ( struct chan_list ch  )  [static]

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

04051 {
04052    struct ast_channel *ast;
04053 
04054    ch->state = MISDN_CLEANING;
04055 
04056    ast_mutex_lock(&release_lock);
04057 
04058    cl_dequeue_chan(&cl_te, ch);
04059 
04060    /* releasing jitterbuffer */
04061    if (ch->jb) {
04062       misdn_jb_destroy(ch->jb);
04063       ch->jb = NULL;
04064    }
04065 
04066    if (ch->overlap_dial) {
04067       if (ch->overlap_dial_task != -1) {
04068          misdn_tasks_remove(ch->overlap_dial_task);
04069          ch->overlap_dial_task = -1;
04070       }
04071       ast_mutex_destroy(&ch->overlap_tv_lock);
04072    }
04073 
04074    if (ch->hold.state != MISDN_HOLD_IDLE) {
04075       if (ch->originator == ORG_AST) {
04076          --misdn_out_calls[ch->hold.port];
04077       } else {
04078          --misdn_in_calls[ch->hold.port];
04079       }
04080    }
04081 
04082    close(ch->pipe[0]);
04083    close(ch->pipe[1]);
04084 
04085    ast = ch->ast;
04086    if (ast) {
04087       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
04088       if (ast->_state != AST_STATE_RESERVED) {
04089          ast_setstate(ast, AST_STATE_DOWN);
04090       }
04091    }
04092 
04093    ast_free(ch);
04094 
04095    ast_mutex_unlock(&release_lock);
04096 }

static int reload ( void   )  [static]

Definition at line 5606 of file chan_misdn.c.

References reload_config().

05607 {
05608    reload_config();
05609 
05610    return 0;
05611 }

static void reload_config ( void   )  [static]

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

01332 {
01333    int i, cfg_debug;
01334 
01335    if (!g_config_initialized) {
01336       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
01337       return ;
01338    }
01339    
01340    free_robin_list();
01341    misdn_cfg_reload();
01342    misdn_cfg_update_ptp();
01343    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
01344    misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
01345 
01346    for (i = 0;  i <= max_ports; i++) {
01347       misdn_debug[i] = cfg_debug;
01348       misdn_debug_only[i] = 0;
01349    }
01350 }

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

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

04202                                                                                                      {
04203    if (!ast) {
04204       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
04205       return;
04206    }
04207    if (!bc) {
04208       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
04209       return;
04210    }
04211    if (!ch) {
04212       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
04213       return;
04214    }
04215 
04216    ast->hangupcause = bc->cause;
04217 
04218    switch (bc->cause) {
04219 
04220    case AST_CAUSE_UNALLOCATED:
04221    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
04222    case AST_CAUSE_NO_ROUTE_DESTINATION:
04223    case 4:  /* Send special information tone */
04224    case AST_CAUSE_NUMBER_CHANGED:
04225    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
04226       /* Congestion Cases */
04227       /*
04228        * Not Queueing the Congestion anymore, since we want to hear
04229        * the inband message
04230        *
04231       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
04232       ch->state = MISDN_BUSY;
04233       
04234       ast_queue_control(ast, AST_CONTROL_CONGESTION);
04235       */
04236       break;
04237 
04238    case AST_CAUSE_CALL_REJECTED:
04239    case AST_CAUSE_USER_BUSY:
04240       ch->state = MISDN_BUSY;
04241 
04242       if (!ch->need_busy) {
04243          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
04244          break;
04245       }
04246 
04247       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04248       
04249       ast_queue_control(ast, AST_CONTROL_BUSY);
04250       
04251       ch->need_busy = 0;
04252       
04253       break;
04254    }
04255 }

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

Definition at line 898 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().

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

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

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

01176 {
01177    char section[BUFFERSIZE];
01178    char name[BUFFERSIZE];
01179    char desc[BUFFERSIZE];
01180    char def[BUFFERSIZE];
01181    char tmp[BUFFERSIZE];
01182 
01183    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
01184    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
01185    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
01186 
01187    if (elem < MISDN_CFG_LAST) {
01188       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
01189    } else {
01190       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
01191    }
01192 
01193    if (*def) {
01194       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
01195    } else {
01196       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
01197    }
01198 }

static void sighandler ( int  sig  )  [static]

Definition at line 745 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00746 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

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

03388 {
03389    misdn_lib_tone_generator_stop(cl->bc);
03390    cl->notxtone = 0;
03391    cl->norxtone = 0;
03392    return 0;
03393 }

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

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

04353                                                                                                  {
04354    if (pbx_start_chan(ch) < 0) {
04355       hangup_chan(ch, bc);
04356       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04357       if (bc->nt) {
04358          hanguptone_indicate(ch);
04359          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04360       } else {
04361          misdn_lib_send_event(bc, EVENT_RELEASE);
04362       }
04363    }
04364 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3395 of file chan_misdn.c.

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

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

03396 {
03397    if (!cl) {
03398       return -1;
03399    }
03400 
03401    cl->notxtone = 1;
03402    cl->norxtone = 1;
03403    
03404    return 0;
03405 }

static int stop_indicate ( struct chan_list cl  )  [static]

Definition at line 3366 of file chan_misdn.c.

References chan_list::ast, ast_playtones_stop(), ast_tone_zone_sound_unref(), 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().

03367 {
03368    struct ast_channel *ast = cl->ast;
03369 
03370    if (!ast) {
03371       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03372       return -1;
03373    }
03374 
03375    chan_misdn_log(3, cl->bc->port, " --> None\n");
03376    misdn_lib_tone_generator_stop(cl->bc);
03377    ast_playtones_stop(ast);
03378 
03379    if (cl->ts) {
03380       cl->ts = ast_tone_zone_sound_unref(cl->ts);
03381    }
03382 
03383    return 0;
03384 }

static int unload_module ( void   )  [static]

TE STUFF END

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

05390 {
05391    /* First, take us out of the channel loop */
05392    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05393 
05394    misdn_tasks_destroy();
05395    
05396    if (!g_config_initialized) {
05397       return 0;
05398    }
05399    
05400    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05401 
05402    /* ast_unregister_application("misdn_crypt"); */
05403    ast_unregister_application("misdn_set_opt");
05404    ast_unregister_application("misdn_facility");
05405    ast_unregister_application("misdn_check_l2l1");
05406 
05407    ast_channel_unregister(&misdn_tech);
05408 
05409    free_robin_list();
05410    misdn_cfg_destroy();
05411    misdn_lib_destroy();
05412   
05413    ast_free(misdn_out_calls);
05414    ast_free(misdn_in_calls);
05415    ast_free(misdn_debug_only);
05416    ast_free(misdn_ports);
05417    ast_free(misdn_debug);
05418    
05419    return 0;
05420 }

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

Updates caller ID information from config.

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

02003 {
02004    struct ast_channel *ast;
02005    struct misdn_bchannel *bc;
02006    int port, hdlc = 0;
02007    int pres, screen;
02008 
02009    if (!ch) {
02010       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
02011       return -1;
02012    }
02013 
02014    ast = ch->ast;
02015    bc = ch->bc;
02016    if (! ast || ! bc) {
02017       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
02018       return -1;
02019    }
02020 
02021    port = bc->port;
02022 
02023    chan_misdn_log(7, port, "update_config: Getting Config\n");
02024 
02025    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
02026    
02027    if (hdlc) {
02028       switch (bc->capability) {
02029       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02030       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
02031          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
02032          bc->hdlc = 1;
02033          break;
02034       }
02035    }
02036 
02037    misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
02038    misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
02039    chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
02040       
02041    if (pres < 0 || screen < 0) {
02042       chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
02043          
02044       switch (ast->cid.cid_pres & 0x60) {
02045       case AST_PRES_RESTRICTED:
02046          bc->pres = 1;
02047          chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
02048          break;
02049       case AST_PRES_UNAVAILABLE:
02050          bc->pres = 2;
02051          chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
02052          break;
02053       default:
02054          bc->pres = 0;
02055          chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
02056          break;
02057       }
02058 
02059       switch (ast->cid.cid_pres & 0x3) {
02060       default:
02061       case AST_PRES_USER_NUMBER_UNSCREENED:
02062          bc->screen = 0;
02063          chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
02064          break;
02065       case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02066          bc->screen = 1;
02067          chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
02068          break;
02069       case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02070          bc->screen = 2;
02071          chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
02072          break;
02073       case AST_PRES_NETWORK_NUMBER:
02074          bc->screen = 3;
02075          chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
02076          break;
02077       }
02078    } else {
02079       bc->screen = screen;
02080       bc->pres = pres;
02081    }
02082 
02083    return 0;
02084 }

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

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

02167 {
02168    int ec;
02169    int port = bc->port;
02170 
02171    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
02172 
02173    if (ec == 1) {
02174       bc->ec_enable = 1;
02175    } else if (ec > 1) {
02176       bc->ec_enable = 1;
02177       bc->ec_deftaps = ec;
02178    }
02179 
02180    return 0;
02181 }

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

Definition at line 3682 of file chan_misdn.c.

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

Referenced by cb_events().

03683 {
03684    int chan_offset = 0;
03685    int tmp_port = misdn_cfg_get_next_port(0);
03686    char newname[255];
03687    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03688       if (tmp_port == port) {
03689          break;
03690       }
03691       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03692    }
03693    if (c < 0) {
03694       c = 0;
03695    }
03696 
03697    snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
03698    if (strncmp(tmp->name, newname, strlen(newname))) {
03699       snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03700       ast_change_name(tmp, newname);
03701       chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03702    }
03703 }

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

Definition at line 4366 of file chan_misdn.c.

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

Referenced by cb_events().

04366                                                                                                        {
04367    ch->state = MISDN_WAITING4DIGS;
04368    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04369    if (bc->nt && !bc->dad[0]) {
04370       dialtone_indicate(ch);
04371    }
04372 }


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

Definition at line 6203 of file chan_misdn.c.

Definition at line 591 of file chan_misdn.c.

Definition at line 6203 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1977 of file chan_misdn.c.

struct chan_list* cl_te = NULL

Global channel call record list head.

Definition at line 511 of file chan_misdn.c.

Definition at line 512 of file chan_misdn.c.

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

char global_tracefile[BUFFERSIZE+1]

Definition at line 75 of file chan_misdn.c.

int max_ports [static]

Definition at line 501 of file chan_misdn.c.

int MAXTICS = 8

Definition at line 415 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 499 of file chan_misdn.c.

int* misdn_debug_only [static]

Definition at line 500 of file chan_misdn.c.

int* misdn_in_calls [static]

Definition at line 503 of file chan_misdn.c.

int* misdn_out_calls [static]

Definition at line 504 of file chan_misdn.c.

int* misdn_ports [static]

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

pthread_t misdn_tasks_thread [static]

Definition at line 473 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

Definition at line 3642 of file chan_misdn.c.

Definition at line 3661 of file chan_misdn.c.

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

Definition at line 492 of file chan_misdn.c.

int prefformat = AST_FORMAT_ALAW [static]

Only alaw and mulaw is allowed for now.

Definition at line 497 of file chan_misdn.c.

Definition at line 114 of file chan_misdn.c.

struct robin_list * robin [static]
struct state_struct state_array[] [static]

Definition at line 1293 of file chan_misdn.c.

int tracing = 0 [static]

Definition at line 494 of file chan_misdn.c.


Generated by  doxygen 1.6.2