Tue Mar 2 17:32:54 2010

Asterisk developer's documentation


chan_misdn.c File Reference

the chan_misdn channel driver for Asterisk More...

#include "asterisk.h"
#include <pthread.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <sys/file.h>
#include <semaphore.h>
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/io.h"
#include "asterisk/frame.h"
#include "asterisk/translate.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/indications.h"
#include "asterisk/app.h"
#include "asterisk/features.h"
#include "asterisk/term.h"
#include "asterisk/sched.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/causes.h"
#include "chan_misdn_config.h"
#include "isdn_lib.h"
#include "asterisk/strings.h"
Include dependency graph for chan_misdn.c:

Go to the source code of this file.

Data Structures

struct  allowed_bearers
struct  chan_list
 Channel call record structure. More...
struct  hold_info
struct  misdn_jb
struct  robin_list
struct  state_struct

Defines

#define MISDN_ASTERISK_PVT(ast)   1
#define MISDN_ASTERISK_TECH_PVT(ast)   ast->tech_pvt
#define ORG_AST   1
#define ORG_MISDN   2
#define TRANSFER_ON_HELD_CALL_HANGUP   1

Enumerations

enum  misdn_chan_state {
  MISDN_NOTHING = 0, MISDN_WAITING4DIGS, MISDN_EXTCANTMATCH, MISDN_INCOMING_SETUP,
  MISDN_DIALING, MISDN_PROGRESS, MISDN_PROCEEDING, MISDN_CALLING,
  MISDN_CALLING_ACKNOWLEDGE, MISDN_ALERTING, MISDN_BUSY, MISDN_CONNECTED,
  MISDN_DISCONNECTED, MISDN_CLEANING
}
enum  misdn_hold_state { MISDN_HOLD_IDLE, MISDN_HOLD_ACTIVE, MISDN_HOLD_TRANSFER, MISDN_HOLD_DISCONNECT }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
int add_in_calls (int port)
int add_out_calls (int port)
static const char * bearer2str (int cap)
static enum event_response_e cb_events (enum event_e event, struct misdn_bchannel *bc, void *user_data)
int chan_misdn_jb_empty (struct misdn_bchannel *bc, char *buf, int len)
static void chan_misdn_log (int level, int port, char *tmpl,...)
static void cl_dequeue_chan (struct chan_list **list, struct chan_list *chan)
static void cl_queue_chan (struct chan_list **list, struct chan_list *chan)
static char * complete_ch (struct ast_cli_args *a)
static char * complete_debug_port (struct ast_cli_args *a)
static char * complete_show_config (struct ast_cli_args *a)
static void config_jitterbuffer (struct chan_list *ch)
void debug_numplan (int port, int numplan, char *type)
static int dialtone_indicate (struct chan_list *cl)
static void do_immediate_setup (struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
static void export_aoc_vars (int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
void export_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 Export parameters to the dialplan environment variables.
static struct chan_listfind_chan_by_bc (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_chan_by_pid (struct chan_list *list, int pid)
static struct chan_listfind_hold_active_call (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_hold_call (struct chan_list *list, struct misdn_bchannel *bc)
static struct chan_listfind_hold_call_l3 (struct chan_list *list, unsigned long l3_id)
static void free_robin_list (void)
static struct chan_listget_chan_by_ast (struct ast_channel *ast)
static struct chan_listget_chan_by_ast_name (char *name)
static struct robin_listget_robin_position (char *group)
static char * handle_cli_misdn_port_block (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_down (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_unblock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_up (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_restart_pid (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_restart_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_digit (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_display (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_facility (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_restart (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_crypt_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_tics (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_config (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_ports_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_stacks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_toggle_echocancel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void hangup_chan (struct chan_list *ch, struct misdn_bchannel *bc)
static void hanguptone_indicate (struct chan_list *cl)
void import_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 Import parameters from the dialplan environment variables.
static struct chan_listinit_chan_list (int orig)
static int load_module (void)
static int misdn_answer (struct ast_channel *ast)
static int misdn_attempt_transfer (struct chan_list *active_ch, struct chan_list *held_ch)
static enum ast_bridge_result misdn_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int misdn_call (struct ast_channel *ast, char *dest, int timeout)
static int misdn_check_l2l1 (struct ast_channel *chan, void *data)
static int misdn_digit_begin (struct ast_channel *chan, char digit)
static int misdn_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int misdn_facility_exec (struct ast_channel *chan, void *data)
static int misdn_fixup (struct ast_channel *oldast, struct ast_channel *ast)
static const char * misdn_get_ch_state (struct chan_list *p)
static int misdn_hangup (struct ast_channel *ast)
static int misdn_indication (struct ast_channel *ast, int cond, const void *data, size_t datalen)
void misdn_jb_destroy (struct misdn_jb *jb)
 frees the data and destroys the given jitterbuffer struct
int misdn_jb_empty (struct misdn_jb *jb, char *data, int len)
 gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data.
int misdn_jb_fill (struct misdn_jb *jb, const char *data, int len)
 fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).
struct misdn_jbmisdn_jb_init (int size, int upper_threshold)
 allocates the jb-structure and initialize the elements
static int misdn_l1_task (const void *data)
static struct ast_channelmisdn_new (struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c)
static int misdn_overlap_dial_task (const void *data)
static struct ast_framemisdn_read (struct ast_channel *ast)
static struct ast_channelmisdn_request (const char *type, int format, void *data, int *cause)
static int misdn_send_text (struct ast_channel *chan, const char *text)
static int misdn_set_opt_exec (struct ast_channel *chan, void *data)
static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data)
static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data)
static void misdn_tasks_destroy (void)
static void misdn_tasks_init (void)
static void misdn_tasks_remove (int task_id)
static void * misdn_tasks_thread_func (void *data)
static void misdn_tasks_wakeup (void)
static int misdn_write (struct ast_channel *ast, struct ast_frame *frame)
static int pbx_start_chan (struct chan_list *ch)
static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
static void print_bearer (struct misdn_bchannel *bc)
static void print_facility (struct FacParm *fac, struct misdn_bchannel *bc)
static struct ast_frameprocess_ast_dsp (struct chan_list *tmp, struct ast_frame *frame)
static int read_config (struct chan_list *ch, int orig)
static void release_chan (struct chan_list *ch, struct misdn_bchannel *bc)
static void release_chan_early (struct chan_list *ch)
static int reload (void)
static void reload_config (void)
static void send_cause2ast (struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
static void send_digit_to_chan (struct chan_list *cl, char digit)
static void show_config_description (int fd, enum misdn_cfg_elements elem)
static void sighandler (int sig)
static int start_bc_tones (struct chan_list *cl)
static void start_pbx (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
static int stop_bc_tones (struct chan_list *cl)
static int stop_indicate (struct chan_list *cl)
static int unload_module (void)
static int update_config (struct chan_list *ch, int orig)
 Updates caller ID information from config.
static int update_ec_config (struct misdn_bchannel *bc)
static void update_name (struct ast_channel *tmp, int port, int c)
static void wait_for_digits (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Channel driver for mISDN Support (BRI/PRI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct allowed_bearers allowed_bearers_array []
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry chan_misdn_clis []
struct chan_listcl_te = NULL
 Global channel call record list head.
ast_mutex_t cl_te_lock
struct chan_list dummy_cl
static int g_config_initialized = 0
static int glob_channel = 0
char global_tracefile [BUFFERSIZE+1]
ast_mutex_t lock
static int max_ports
int MAXTICS = 8
static int * misdn_debug
static int * misdn_debug_only
static int * misdn_in_calls
static int * misdn_out_calls
static int * misdn_ports
static struct sched_contextmisdn_tasks = NULL
 the main schedule context for stuff like l1 watcher, overlap dial, ...
static pthread_t misdn_tasks_thread
static struct ast_channel_tech misdn_tech
static struct ast_channel_tech misdn_tech_wo_bridge
static const char misdn_type [] = "mISDN"
static int prefformat = AST_FORMAT_ALAW
 Only alaw and mulaw is allowed for now.
ast_mutex_t release_lock
static struct robin_listrobin = NULL
static struct state_struct state_array []
static int tracing = 0

Detailed Description

the chan_misdn channel driver for Asterisk

Author:
Christian Richter <crich@beronet.com>
ExtRef:
MISDN http://www.misdn.org/

Definition in file chan_misdn.c.


Define Documentation

#define MISDN_ASTERISK_PVT ( ast   )     1

Definition at line 490 of file chan_misdn.c.

Referenced by cb_events(), and do_immediate_setup().

#define MISDN_ASTERISK_TECH_PVT ( ast   )     ast->tech_pvt
#define ORG_AST   1
#define ORG_MISDN   2

Definition at line 134 of file chan_misdn.c.

Referenced by cb_events(), and misdn_indication().

#define TRANSFER_ON_HELD_CALL_HANGUP   1

Definition at line 3771 of file chan_misdn.c.


Enumeration Type Documentation

Enumerator:
MISDN_NOTHING 

at beginning

MISDN_WAITING4DIGS 

when waiting for infos

MISDN_EXTCANTMATCH 

when asterisk couldn't match our ext

MISDN_INCOMING_SETUP 

for incoming setups

MISDN_DIALING 

when pbx_start

MISDN_PROGRESS 

we got a progress

MISDN_PROCEEDING 

we got a progress

MISDN_CALLING 

when misdn_call is called

MISDN_CALLING_ACKNOWLEDGE 

when we get SETUP_ACK

MISDN_ALERTING 

when Alerting

MISDN_BUSY 

when BUSY

MISDN_CONNECTED 

when connected

MISDN_DISCONNECTED 

when connected

MISDN_CLEANING 

when hangup from * but we were connected before

Definition at line 116 of file chan_misdn.c.

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

Enumerator:
MISDN_HOLD_IDLE 

HOLD not active

MISDN_HOLD_ACTIVE 

Call is held

MISDN_HOLD_TRANSFER 

Held call is being transferred

MISDN_HOLD_DISCONNECT 

Held call is being disconnected

Definition at line 136 of file chan_misdn.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 6138 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

Definition at line 6138 of file chan_misdn.c.

static int _misdn_tasks_add_variable ( int  timeout,
ast_sched_cb  callback,
const void *  data,
int  variable 
) [inline, static]

Definition at line 809 of file chan_misdn.c.

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

Referenced by misdn_tasks_add(), and misdn_tasks_add_variable().

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

int add_in_calls ( int  port  ) 

Definition at line 4258 of file chan_misdn.c.

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

Referenced by cb_events().

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

int add_out_calls ( int  port  ) 

Definition at line 4273 of file chan_misdn.c.

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

Referenced by misdn_call().

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

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

Definition at line 607 of file chan_misdn.c.

References ARRAY_LEN, and allowed_bearers::display.

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

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

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

queue new chan

Sending SETUP_ACK

Supplementary Services

Definition at line 4313 of file chan_misdn.c.

References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, misdn_bchannel::AOCDtype, ARRAY_LEN, chan_list::ast, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, ast_cdr_update(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_deactivate_generator(), ast_exists_extension(), AST_FORMAT_ALAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pickup_call(), ast_pickup_ext(), AST_PRES_ALLOWED, AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_queue_frame(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_strlen_zero(), ast_transfercapability2str(), ast_tv(), ast_tvnow(), chan_list::bc, misdn_bchannel::bc_state, bc_state2str(), bearer2str(), misdn_bchannel::bframe, misdn_bchannel::bframe_len, misdn_bchannel::cad, misdn_bchannel::capability, misdn_bchannel::cause, cb_log, chan, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, misdn_bchannel::chargingUnit, ast_channel::cid, ast_callerid::cid_pres, cl_queue_chan(), chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::currency, misdn_bchannel::cw, misdn_bchannel::dad, ast_frame::data, ast_frame::datalen, ast_frame::delivery, do_immediate_setup(), misdn_bchannel::dtmf, misdn_bchannel::dummy, errno, EVENT_ALERTING, EVENT_BCHAN_ACTIVATED, EVENT_BCHAN_DATA, EVENT_BCHAN_ERROR, EVENT_CLEANUP, EVENT_CONNECT, EVENT_CONNECT_ACKNOWLEDGE, EVENT_DISCONNECT, EVENT_DTMF_TONE, EVENT_FACILITY, EVENT_HOLD, EVENT_HOLD_ACKNOWLEDGE, EVENT_HOLD_REJECT, EVENT_INFORMATION, EVENT_NEW_BC, EVENT_NEW_CHANNEL, EVENT_NEW_L3ID, EVENT_PORT_ALARM, EVENT_PROCEEDING, EVENT_PROGRESS, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, EVENT_RESTART, EVENT_RETRIEVE, EVENT_RETRIEVE_ACKNOWLEDGE, EVENT_RETRIEVE_REJECT, EVENT_SETUP, EVENT_SETUP_ACKNOWLEDGE, EVENT_STATUS, EVENT_TIMEOUT, EVENT_TONE_GENERATE, export_aoc_vars(), export_ch(), ast_channel::exten, misdn_bchannel::fac_in, chan_list::far_alerting, find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), ast_frame::frametype, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, hangup_chan(), ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::info_dad, INFO_PI_INBAND_AVAILABLE, misdn_bchannel::infos_pending, init_chan_list(), misdn_bchannel::keypad, misdn_bchannel::l3_id, chan_list::l3id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_isdn_get_info(), MISDN_ALERTING, MISDN_ASTERISK_PVT, MISDN_ASTERISK_TECH_PVT, misdn_attempt_transfer(), MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, misdn_cap_is_speech(), MISDN_CFG_ALARM_BLOCK, MISDN_CFG_ALWAYS_IMMEDIATE, misdn_cfg_get(), MISDN_CFG_HOLD_ALLOWED, MISDN_CFG_IMMEDIATE, misdn_cfg_is_msn_valid(), MISDN_CFG_REJECT_CAUSE, MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, MISDN_EXTCANTMATCH, MISDN_GEN_APPEND_DIGITS2EXTEN, misdn_get_ch_state(), MISDN_HOLD_ACTIVE, MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, misdn_inband_avail(), MISDN_INCOMING_SETUP, misdn_lib_is_ptp(), misdn_lib_log_ies(), misdn_lib_port_block(), misdn_lib_send_event(), misdn_new(), MISDN_NOTHING, misdn_overlap_dial_task(), MISDN_PROCEEDING, MISDN_PROGRESS, misdn_tasks_add_variable(), MISDN_WAITING4DIGS, allowed_bearers::name, chan_list::need_busy, misdn_bchannel::need_disconnect, misdn_bchannel::need_more_infos, misdn_bchannel::need_release, misdn_bchannel::need_release_complete, chan_list::noautorespond_on_setup, misdn_bchannel::nt, chan_list::nttimeout, misdn_bchannel::oad, ast_frame::offset, ORG_AST, ORG_MISDN, chan_list::originator, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_builtin_setvar_helper(), pbx_start_chan(), misdn_bchannel::pid, chan_list::pipe, hold_info::port, misdn_bchannel::port, misdn_bchannel::pres, print_bearer(), print_facility(), misdn_bchannel::progress_indicator, ast_frame::ptr, read_config(), release_chan(), RESPONSE_IGNORE_SETUP, RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE, RESPONSE_OK, RESPONSE_RELEASE_SETUP, ast_channel::rings, ast_frame::samples, misdn_bchannel::screen, misdn_bchannel::sending_complete, ast_frame::src, start_bc_tones(), start_pbx(), hold_info::state, chan_list::state, stop_bc_tones(), stop_indicate(), ast_frame::subclass, ast_channel::tech, misdn_bchannel::tone_cnt, ast_channel::transfercapability, ast_channel_tech::type, update_name(), and wait_for_digits().

Referenced by load_module().

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

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

Definition at line 5891 of file chan_misdn.c.

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

Referenced by load_module().

05892 {
05893    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05894    
05895    if (ch && ch->jb) {
05896       return misdn_jb_empty(ch->jb, buf, len);
05897    }
05898    
05899    return -1;
05900 }

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

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

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

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

Definition at line 3823 of file chan_misdn.c.

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

Referenced by release_chan(), and release_chan_early().

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

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

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

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

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

Definition at line 1864 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_set_debug().

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

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

Definition at line 1884 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_show_config().

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

static void config_jitterbuffer ( struct chan_list ch  )  [static]

Definition at line 2039 of file chan_misdn.c.

References chan_list::bc, cb_log, chan_misdn_log(), chan_list::jb, chan_list::jb_len, chan_list::jb_upper_threshold, len(), misdn_jb_destroy(), misdn_jb_init(), misdn_bchannel::nojitter, and misdn_bchannel::port.

Referenced by misdn_set_opt_exec(), and read_config().

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

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

Definition at line 2073 of file chan_misdn.c.

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

Referenced by read_config().

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

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

Definition at line 3278 of file chan_misdn.c.

References chan_list::ast, ast_get_indication_tone(), ast_playtones_start(), chan_list::bc, chan_misdn_log(), tone_zone_sound::data, misdn_cfg_get(), MISDN_CFG_NODIALTONE, chan_list::norxtone, chan_list::notxtone, misdn_bchannel::port, chan_list::ts, and ast_channel::zone.

Referenced by wait_for_digits().

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

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

Definition at line 4081 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Definition at line 687 of file chan_misdn.c.

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

Referenced by cb_events().

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

void export_ch ( struct ast_channel chan,
struct misdn_bchannel bc,
struct chan_list ch 
)

Export parameters to the dialplan environment variables.

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

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

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

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

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

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

Definition at line 3729 of file chan_misdn.c.

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

Referenced by import_ch().

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

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

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

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

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

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

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

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

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

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

static void free_robin_list ( void   )  [static]

Definition at line 435 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

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

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

Definition at line 564 of file chan_misdn.c.

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

Referenced by misdn_bridge().

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

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

Definition at line 575 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_send_digit(), handle_cli_misdn_send_display(), handle_cli_misdn_send_facility(), and handle_cli_misdn_toggle_echocancel().

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

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

Definition at line 447 of file chan_misdn.c.

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

Referenced by misdn_request().

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

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

Definition at line 1028 of file chan_misdn.c.

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

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

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

Definition at line 1133 of file chan_misdn.c.

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

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

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

Definition at line 1049 of file chan_misdn.c.

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

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

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

Definition at line 1112 of file chan_misdn.c.

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

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

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

Definition at line 1326 of file chan_misdn.c.

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

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

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

Definition at line 1091 of file chan_misdn.c.

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

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

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

Definition at line 1070 of file chan_misdn.c.

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

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

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

Definition at line 1728 of file chan_misdn.c.

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

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

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

Definition at line 1821 of file chan_misdn.c.

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

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

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

Definition at line 1608 of file chan_misdn.c.

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

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

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

Definition at line 1698 of file chan_misdn.c.

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

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

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

Definition at line 1006 of file chan_misdn.c.

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

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

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

Definition at line 931 of file chan_misdn.c.

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

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

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

Definition at line 1503 of file chan_misdn.c.

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

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

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

Definition at line 1465 of file chan_misdn.c.

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

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

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

Definition at line 1403 of file chan_misdn.c.

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

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

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

Definition at line 1177 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), BUFFERSIZE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_config(), ast_cli_args::fd, MISDN_CFG_FIRST, misdn_cfg_get_config_string(), misdn_cfg_get_elem(), misdn_cfg_get_next_port(), misdn_cfg_is_port_valid(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, show_config_description(), and ast_cli_entry::usage.

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

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

Definition at line 1580 of file chan_misdn.c.

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

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

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

Definition at line 1552 of file chan_misdn.c.

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

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

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

Definition at line 1523 of file chan_misdn.c.

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

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

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

Definition at line 1776 of file chan_misdn.c.

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

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

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

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

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

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

References ast_copy_string(), ast_log(), chan_misdn_log(), find_chan_by_pid(), misdn_bchannel::keypad, LOG_NOTICE, chan_list::other_ch, chan_list::other_pid, pbx_builtin_getvar_helper(), misdn_bchannel::port, misdn_bchannel::sending_complete, misdn_bchannel::uu, and misdn_bchannel::uulen.

Referenced by misdn_call().

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

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

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

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

static int load_module ( void   )  [static]

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

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

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 2492 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_PROTOCOL_ERROR, ast_copy_string(), ast_log(), ast_queue_hangup_with_cause(), ast_strlen_zero(), ast_true(), chan_list::bc, misdn_bchannel::cad, chan_misdn_log(), misdn_bchannel::crypt_key, misdn_bchannel::dad, EVENT_CONNECT, misdn_bchannel::hdlc, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_lib_send_event(), misdn_bchannel::nodsp, misdn_bchannel::nojitter, pbx_builtin_getvar_helper(), misdn_bchannel::port, start_bc_tones(), chan_list::state, and stop_indicate().

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

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

Definition at line 4046 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_read(), ast_verb, ast_waitfor_n(), ast_write(), chan_list::bc, chan_misdn_log(), ast_channel::exten, f, ast_frame::frametype, get_chan_by_ast(), chan_list::ignore_dtmf, LOG_NOTICE, MISDN_CFG_BRIDGING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_bridge(), misdn_lib_split_bridge(), misdn_bchannel::oad, misdn_bchannel::pid, misdn_bchannel::port, and ast_frame::subclass.

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

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

we should have l3id after sending setup

Definition at line 2352 of file chan_misdn.c.

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

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

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

Definition at line 5610 of file chan_misdn.c.

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

Referenced by load_module().

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

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

Definition at line 2542 of file chan_misdn.c.

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

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

Definition at line 2548 of file chan_misdn.c.

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

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

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

Definition at line 5564 of file chan_misdn.c.

References ast_copy_string(), ast_log(), ast_strdupa, ast_strlen_zero(), chan_list::bc, chan_misdn_log(), EVENT_FACILITY, misdn_bchannel::fac_out, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, misdn_lib_send_event(), parse(), misdn_bchannel::port, ast_channel::tech, and ast_channel_tech::type.

Referenced by load_module().

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

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

Definition at line 2591 of file chan_misdn.c.

References chan_list::ast, chan_list::bc, chan_misdn_log(), chan_list::l3id, MISDN_ASTERISK_TECH_PVT, misdn_get_ch_state(), and misdn_bchannel::port.

02592 {
02593    struct chan_list *p;
02594 
02595    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
02596 
02597    chan_misdn_log(1, p->bc ? p->bc->port : 0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
02598 
02599    p->ast = ast;
02600 
02601    return 0;
02602 }

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

Definition at line 1286 of file chan_misdn.c.

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

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

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

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 2734 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_copy_string(), ast_debug, ast_log(), AST_STATE_RESERVED, chan_list::bc, misdn_bchannel::cause, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, ast_channel::exten, ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, INFO_PI_INBAND_AVAILABLE, chan_list::l3id, LOG_NOTICE, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_BUSY, MISDN_CALLING, MISDN_CALLING_ACKNOWLEDGE, MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, misdn_get_ch_state(), MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, MISDN_INCOMING_SETUP, misdn_lib_find_held_bc(), misdn_lib_release(), misdn_lib_send_event(), MISDN_NOTHING, MISDN_PROCEEDING, MISDN_PROGRESS, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, misdn_bchannel::nt, ORG_AST, chan_list::originator, misdn_bchannel::out_cause, pbx_builtin_getvar_helper(), misdn_bchannel::pid, misdn_bchannel::port, hold_info::port, misdn_bchannel::progress_indicator, release_chan(), release_chan_early(), start_bc_tones(), chan_list::state, hold_info::state, stop_bc_tones(), misdn_bchannel::uu, misdn_bchannel::uulen, and var.

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

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

Definition at line 2606 of file chan_misdn.c.

References AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_setstate(), AST_STATE_BUSY, AST_STATE_RING, chan_list::bc, chan_misdn_log(), EVENT_ALERTING, EVENT_DISCONNECT, EVENT_PROCEEDING, EVENT_PROGRESS, hanguptone_indicate(), chan_list::hold, chan_list::incoming_early_audio, LOG_WARNING, MISDN_ALERTING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, MISDN_HOLD_IDLE, misdn_inband_avail(), misdn_lib_send_event(), chan_list::mohinterpret, misdn_bchannel::nt, ORG_MISDN, chan_list::originator, chan_list::other_ch, misdn_bchannel::out_cause, misdn_bchannel::pid, misdn_bchannel::port, start_bc_tones(), chan_list::state, hold_info::state, and stop_indicate().

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

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

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

05952 {
05953    ast_mutex_destroy(&jb->mutexjb);
05954    
05955    ast_free(jb->ok);
05956    ast_free(jb->samples);
05957    ast_free(jb);
05958 }

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

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

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

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

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

allocates the jb-structure and initialize the elements

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

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

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

Definition at line 837 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

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

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

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

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

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

Definition at line 844 of file chan_misdn.c.

References chan_list::ast, AST_CAUSE_UNALLOCATED, ast_exists_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), chan_list::bc, chan_misdn_log(), chan_list::context, misdn_bchannel::dad, EVENT_DISCONNECT, ast_channel::exten, hanguptone_indicate(), MISDN_CLEANING, MISDN_DIALING, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::oad, misdn_bchannel::out_cause, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv, chan_list::overlap_tv_lock, pbx_start_chan(), misdn_bchannel::port, chan_list::state, and stop_indicate().

Referenced by cb_events().

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

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

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

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

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

Definition at line 3373 of file chan_misdn.c.

References chan_list::ast, ast_copy_string(), ast_free, ast_log(), AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, cl_queue_chan(), misdn_bchannel::dec, ext, get_robin_position(), init_chan_list(), LOG_ERROR, LOG_WARNING, METHOD_ROUND_ROBIN, METHOD_STANDARD_DEC, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_next_port_spin(), MISDN_CFG_GROUPNAME, misdn_cfg_is_group_method(), MISDN_CFG_PMP_L1_CHECK, misdn_lib_get_free_bc(), misdn_lib_get_maxchans(), misdn_lib_port_up(), misdn_new(), chan_list::need_hangup, ORG_AST, misdn_bchannel::port, robin_list::port, read_config(), and strsep().

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

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

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

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

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

Definition at line 5686 of file chan_misdn.c.

References ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_log(), ast_strdupa, ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), config_jitterbuffer(), misdn_bchannel::crypt_key, misdn_bchannel::display, chan_list::dsp, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_GEN_CRYPT_KEYS, misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_bchannel::orig, chan_list::originator, parse(), misdn_bchannel::port, misdn_bchannel::pres, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, strsep(), ast_channel::tech, chan_list::trans, misdn_bchannel::txgain, and ast_channel_tech::type.

Referenced by load_module(), and misdn_call().

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

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

Definition at line 822 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

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

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

Definition at line 827 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

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

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 792 of file chan_misdn.c.

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

Referenced by unload_module().

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

static void misdn_tasks_init ( void   )  [static]

Definition at line 773 of file chan_misdn.c.

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

Referenced by _misdn_tasks_add_variable().

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

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 832 of file chan_misdn.c.

References AST_SCHED_DEL.

Referenced by release_chan(), and release_chan_early().

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

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

Definition at line 749 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 804 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

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

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

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

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

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

03859 {
03860    int ret = ast_pbx_start(ch->ast);   
03861 
03862    if (ret >= 0) 
03863       ch->need_hangup = 0;
03864    else
03865       ch->need_hangup = 1;
03866 
03867    return ret;
03868 }

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

Definition at line 1348 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_show_channel(), and handle_cli_misdn_show_channels().

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

static void print_bearer ( struct misdn_bchannel bc  )  [static]

Definition at line 672 of file chan_misdn.c.

References bearer2str(), misdn_bchannel::capability, chan_misdn_log(), INFO_CODEC_ALAW, INFO_CODEC_ULAW, misdn_bchannel::law, and misdn_bchannel::port.

Referenced by cb_events().

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

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

Definition at line 621 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by cb_events().

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

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

Definition at line 2904 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), ast_debug, chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_frfree, ast_log(), ast_strlen_zero(), ast_translate(), ast_verb, chan_list::bc, BUFFERSIZE, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, context, chan_list::dsp, misdn_bchannel::ec_enable, ast_channel::exten, f, chan_list::faxdetect, chan_list::faxhandled, ast_frame::frametype, isdn_lib_stop_dtmf(), isdn_lib_update_ec(), isdn_lib_update_rxgain(), isdn_lib_update_txgain(), LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, ast_frame::subclass, chan_list::trans, and misdn_bchannel::txgain.

Referenced by misdn_read().

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

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

Definition at line 2134 of file chan_misdn.c.

References chan_list::allowed_bearers, misdn_bchannel::AOCDtype, chan_list::ast, ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, ast_free, ast_log(), ast_mutex_init(), ast_print_group(), ast_set_callerid(), ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_translator_build_path(), chan_list::bc, buf, BUFFERSIZE, ast_channel::callgroup, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_rdnis, config_jitterbuffer(), ast_channel::context, chan_list::context, misdn_bchannel::cpnnumplan, misdn_bchannel::dad, debug_numplan(), misdn_bchannel::dnumplan, chan_list::dsp, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, misdn_bchannel::early_bconnect, ast_channel::exten, chan_list::far_alerting, chan_list::faxdetect, chan_list::faxdetect_timeout, misdn_bchannel::hdlc, chan_list::ignore_dtmf, chan_list::incoming_early_audio, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, chan_list::jb_len, chan_list::jb_upper_threshold, misdn_bchannel::keypad, language, LOG_WARNING, MISDN_CFG_ALLOWED_BEARERS, MISDN_CFG_ASTDTMF, MISDN_CFG_CALLERID, MISDN_CFG_CALLGROUP, MISDN_CFG_CONTEXT, MISDN_CFG_CPNDIALPLAN, MISDN_CFG_DIALPLAN, MISDN_CFG_EARLY_BCONNECT, MISDN_CFG_FAR_ALERTING, MISDN_CFG_FAXDETECT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CFG_INTERNATPREFIX, MISDN_CFG_JITTERBUFFER, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CFG_LANGUAGE, MISDN_CFG_LOCALDIALPLAN, MISDN_CFG_MUSICCLASS, MISDN_CFG_NATPREFIX, MISDN_CFG_NEED_MORE_INFOS, MISDN_CFG_NOAUTORESPOND_ON_SETUP, MISDN_CFG_NTTIMEOUT, MISDN_CFG_OVERLAP_DIAL, MISDN_CFG_PICKUPGROUP, MISDN_CFG_RXGAIN, MISDN_CFG_SENDDTMF, MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CFG_TXGAIN, chan_list::mohinterpret, misdn_bchannel::need_more_infos, chan_list::noautorespond_on_setup, chan_list::nttimeout, NUMPLAN_INTERNATIONAL, NUMPLAN_NATIONAL, misdn_bchannel::oad, misdn_bchannel::onumplan, ORG_AST, misdn_bchannel::orig_dad, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, ast_channel::pickupgroup, misdn_bchannel::port, prefix, misdn_bchannel::rad, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, misdn_bchannel::te_choose_channel, chan_list::trans, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

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

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

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

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

static void release_chan_early ( struct chan_list ch  )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 5555 of file chan_misdn.c.

References reload_config().

05556 {
05557    reload_config();
05558 
05559    return 0;
05560 }

static void reload_config ( void   )  [static]

Definition at line 1305 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_reload(), and reload().

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

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

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

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

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

Definition at line 895 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().

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

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

Definition at line 1154 of file chan_misdn.c.

References ast_cli(), BUFFERSIZE, COLOR_BRWHITE, COLOR_YELLOW, desc, misdn_cfg_get_desc(), misdn_cfg_get_name(), MISDN_CFG_LAST, name, and term_color().

Referenced by handle_cli_misdn_show_config().

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

static void sighandler ( int  sig  )  [static]

Definition at line 746 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

00747 {}

static int start_bc_tones ( struct chan_list cl  )  [static]

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

03336 {
03337    misdn_lib_tone_generator_stop(cl->bc);
03338    cl->notxtone = 0;
03339    cl->norxtone = 0;
03340    return 0;
03341 }

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

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

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

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 3343 of file chan_misdn.c.

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

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

03344 {
03345    if (!cl) return -1;
03346 
03347    cl->notxtone = 1;
03348    cl->norxtone = 1;
03349    
03350    return 0;
03351 }

static int stop_indicate ( struct chan_list cl  )  [static]

Definition at line 3315 of file chan_misdn.c.

References chan_list::ast, ast_playtones_stop(), chan_list::bc, chan_misdn_log(), misdn_lib_tone_generator_stop(), misdn_bchannel::port, and chan_list::ts.

Referenced by cb_events(), misdn_answer(), misdn_indication(), and misdn_overlap_dial_task().

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

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 5342 of file chan_misdn.c.

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

Referenced by load_module().

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

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

Updates caller ID information from config.

Definition at line 1954 of file chan_misdn.c.

References chan_list::ast, ast_log(), AST_PRES_NETWORK_NUMBER, AST_PRES_RESTRICTED, AST_PRES_UNAVAILABLE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, AST_PRES_USER_NUMBER_UNSCREENED, chan_list::bc, misdn_bchannel::capability, chan_misdn_log(), ast_channel::cid, ast_callerid::cid_pres, misdn_bchannel::hdlc, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, LOG_WARNING, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_PRES, MISDN_CFG_SCREEN, misdn_bchannel::port, misdn_bchannel::pres, and misdn_bchannel::screen.

Referenced by misdn_call().

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

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

Definition at line 2115 of file chan_misdn.c.

References misdn_bchannel::ec_deftaps, misdn_bchannel::ec_enable, MISDN_CFG_ECHOCANCEL, misdn_cfg_get(), and misdn_bchannel::port.

Referenced by handle_cli_misdn_toggle_echocancel(), and read_config().

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

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

Definition at line 3625 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Channel driver for mISDN Support (BRI/PRI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 6138 of file chan_misdn.c.

Definition at line 596 of file chan_misdn.c.

Definition at line 6138 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 1929 of file chan_misdn.c.

struct chan_list* cl_te = NULL

Global channel call record list head.

Definition at line 516 of file chan_misdn.c.

Definition at line 517 of file chan_misdn.c.

Definition at line 511 of file chan_misdn.c.

int g_config_initialized = 0 [static]

Definition at line 77 of file chan_misdn.c.

int glob_channel = 0 [static]

Definition at line 3623 of file chan_misdn.c.

char global_tracefile[BUFFERSIZE+1]

Definition at line 75 of file chan_misdn.c.

Definition at line 1500 of file chan_misdn.c.

int max_ports [static]

Definition at line 505 of file chan_misdn.c.

int MAXTICS = 8

Definition at line 1501 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 503 of file chan_misdn.c.

int* misdn_debug_only [static]

Definition at line 504 of file chan_misdn.c.

int* misdn_in_calls [static]

Definition at line 507 of file chan_misdn.c.

int* misdn_out_calls [static]

Definition at line 508 of file chan_misdn.c.

int* misdn_ports [static]

Definition at line 479 of file chan_misdn.c.

struct sched_context* misdn_tasks = NULL [static]

the main schedule context for stuff like l1 watcher, overlap dial, ...

Definition at line 476 of file chan_misdn.c.

pthread_t misdn_tasks_thread [static]

Definition at line 477 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

Definition at line 3585 of file chan_misdn.c.

Definition at line 3604 of file chan_misdn.c.

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

Definition at line 496 of file chan_misdn.c.

int prefformat = AST_FORMAT_ALAW [static]

Only alaw and mulaw is allowed for now.

Definition at line 501 of file chan_misdn.c.

Definition at line 114 of file chan_misdn.c.

struct robin_list* robin = NULL [static]

Definition at line 427 of file chan_misdn.c.

struct state_struct state_array[] [static]

Definition at line 1269 of file chan_misdn.c.

int tracing = 0 [static]

Definition at line 498 of file chan_misdn.c.


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