Thu Sep 7 01:03:18 2017

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 <ctype.h>
#include <time.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"

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 chan_list_ref(obj, debug)   (ao2_t_ref((obj), +1, (debug)), (obj))
#define chan_list_unref(obj, debug)   (ao2_t_ref((obj), -1, (debug)), NULL)
#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 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)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,"Channel driver for mISDN Support (BRI/PRI)",.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DRIVER,)
static enum mISDN_NUMBER_PLAN ast_to_misdn_plan (unsigned ast_number_plan)
static int ast_to_misdn_pres (int presentation)
static enum
mISDN_REDIRECTING_REASON 
ast_to_misdn_reason (const enum AST_REDIRECTING_REASON ast)
static int ast_to_misdn_screen (int screening)
static enum mISDN_NUMBER_TYPE ast_to_misdn_ton (unsigned ast_number_type)
static const char * bearer2str (int cap)
static enum event_response_e cb_events (enum event_e event, struct misdn_bchannel *bc, void *user_data)
static void chan_list_destructor (void *obj)
static struct chan_listchan_list_init (int orig)
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 int cl_dequeue_chan (struct chan_list *chan)
static void cl_queue_chan (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_numtype (int port, int numtype, 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 misdn_bchannel *bc)
static struct chan_listfind_hold_active_call (struct misdn_bchannel *bc)
static struct chan_listfind_hold_call (struct misdn_bchannel *bc)
static struct chan_listfind_hold_call_l3 (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 (const 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 int load_module (void)
static void misdn_add_number_prefix (int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
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_chan_is_valid (struct chan_list *ch)
static int misdn_check_l2l1 (struct ast_channel *chan, const char *data)
static void misdn_copy_redirecting_from_ast (struct misdn_bchannel *bc, struct ast_channel *ast)
static void misdn_copy_redirecting_to_ast (struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag)
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, const char *data)
static void misdn_facility_ie_handler (enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch)
static int misdn_fixup (struct ast_channel *oldast, struct ast_channel *ast)
static const char * misdn_get_ch_state (struct chan_list *p)
static void misdn_get_connected_line (struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
static int misdn_hangup (struct ast_channel *ast)
static int misdn_indication (struct ast_channel *ast, int cond, const void *data, size_t datalen)
static int misdn_is_msn_valid (int port, const struct misdn_party_dialing *dialed)
void misdn_jb_destroy (struct misdn_jb *jb)
 frees the data and destroys the given jitterbuffer struct
int misdn_jb_empty (struct misdn_jb *jb, char *data, int len)
 gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data.
int misdn_jb_fill (struct misdn_jb *jb, const char *data, int len)
 fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).
struct misdn_jbmisdn_jb_init (int size, int upper_threshold)
 allocates the jb-structure and initialize the elements
static int misdn_l1_task (const void *vdata)
static struct ast_channelmisdn_new (struct chan_list *cl, int state, char *exten, char *callerid, int format, const char *linkedid, int port, int c)
static int misdn_overlap_dial_task (const void *data)
static void misdn_prefix_string (const char *str_prefix, char *str_main, size_t size)
static void misdn_queue_connected_line_update (struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
static struct ast_framemisdn_read (struct ast_channel *ast)
static struct ast_channelmisdn_request (const char *type, format_t format, const struct ast_channel *requestor, 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, const char *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_to_ast_plan (enum mISDN_NUMBER_PLAN number_plan)
static int misdn_to_ast_pres (int presentation)
static enum AST_REDIRECTING_REASON misdn_to_ast_reason (const enum mISDN_REDIRECTING_REASON q931)
static int misdn_to_ast_screen (int screening)
static int misdn_to_ast_ton (enum mISDN_NUMBER_TYPE number_type)
static const char * misdn_to_str_plan (enum mISDN_NUMBER_PLAN number_plan)
static const char * misdn_to_str_pres (int presentation)
static const char * misdn_to_str_screen (int screening)
static const char * misdn_to_str_ton (enum mISDN_NUMBER_TYPE number_type)
static void misdn_update_caller_id (struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
static void misdn_update_connected_line (struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
static void misdn_update_redirecting (struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
static void misdn_update_remote_party (struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
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 (const struct FacParm *fac, const 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)
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 int 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 void update_config (struct chan_list *ch)
 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 allowed_bearers allowed_bearers_array []
static struct ast_cli_entry chan_misdn_clis []
static struct chan_listcl_te = NULL
 Global channel call record list head.
static ast_mutex_t cl_te_lock
static int g_config_initialized = 0
static int glob_channel = 0
static char global_tracefile [BUFFERSIZE+1]
static int max_ports
int MAXTICS = 8
static int * misdn_debug
static int * misdn_debug_only
static int * misdn_in_calls
static int * misdn_out_calls
static int * misdn_ports
static struct sched_contextmisdn_tasks = NULL
 the main schedule context for stuff like l1 watcher, overlap dial, ...
static pthread_t misdn_tasks_thread
static struct ast_channel_tech misdn_tech
static struct ast_channel_tech misdn_tech_wo_bridge
static const char misdn_type [] = "mISDN"
static int prefformat = AST_FORMAT_ALAW
 Only alaw and mulaw is allowed for now.
static 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 chan_list_ref ( obj,
debug   )     (ao2_t_ref((obj), +1, (debug)), (obj))
#define chan_list_unref ( obj,
debug   )     (ao2_t_ref((obj), -1, (debug)), NULL)
#define MISDN_ASTERISK_TECH_PVT ( ast   )     ast->tech_pvt
#define ORG_AST   1

Asterisk created the channel (outgoing call)

Definition at line 315 of file chan_misdn.c.

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

#define ORG_MISDN   2

mISDN created the channel (incoming call)

Definition at line 317 of file chan_misdn.c.

Referenced by cb_events(), misdn_get_connected_line(), misdn_indication(), misdn_update_connected_line(), and misdn_update_redirecting().

#define TRANSFER_ON_HELD_CALL_HANGUP   1

Definition at line 8261 of file chan_misdn.c.


Enumeration Type Documentation

Enumerator:
MISDN_NOTHING 

at beginning

MISDN_WAITING4DIGS 

when waiting for info

MISDN_EXTCANTMATCH 

when asterisk couldn't match our ext

MISDN_INCOMING_SETUP 

for incoming setup

MISDN_DIALING 

when pbx_start

MISDN_PROGRESS 

we have progress

MISDN_PROCEEDING 

we have progress

MISDN_CALLING 

when misdn_call is called

MISDN_CALLING_ACKNOWLEDGE 

when we get SETUP_ACK

MISDN_ALERTING 

when Alerting

MISDN_BUSY 

when BUSY

MISDN_CONNECTED 

when connected

MISDN_DISCONNECTED 

when connected

MISDN_CLEANING 

when hangup from * but we were connected before

Definition at line 297 of file chan_misdn.c.

00297                       {
00298    MISDN_NOTHING = 0,         /*!< at beginning */
00299    MISDN_WAITING4DIGS,        /*!< when waiting for info */
00300    MISDN_EXTCANTMATCH,        /*!< when asterisk couldn't match our ext */
00301    MISDN_INCOMING_SETUP,      /*!< for incoming setup */
00302    MISDN_DIALING,             /*!< when pbx_start */
00303    MISDN_PROGRESS,            /*!< we have progress */
00304    MISDN_PROCEEDING,          /*!< we have progress */
00305    MISDN_CALLING,             /*!< when misdn_call is called */
00306    MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
00307    MISDN_ALERTING,            /*!< when Alerting */
00308    MISDN_BUSY,                /*!< when BUSY */
00309    MISDN_CONNECTED,           /*!< when connected */
00310    MISDN_DISCONNECTED,        /*!< when connected */
00311    MISDN_CLEANING,            /*!< when hangup from * but we were connected before */
00312 };

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

00319                       {
00320    MISDN_HOLD_IDLE,     /*!< HOLD not active */
00321    MISDN_HOLD_ACTIVE,      /*!< Call is held */
00322    MISDN_HOLD_TRANSFER, /*!< Held call is being transferred */
00323    MISDN_HOLD_DISCONNECT,  /*!< Held call is being disconnected */
00324 };


Function Documentation

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

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

03561 {
03562    int task_id;
03563 
03564    if (!misdn_tasks) {
03565       misdn_tasks_init();
03566    }
03567    task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
03568    misdn_tasks_wakeup();
03569 
03570    return task_id;
03571 }

int add_in_calls ( int  port  ) 

Definition at line 8802 of file chan_misdn.c.

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

Referenced by cb_events().

08803 {
08804    int max_in_calls;
08805 
08806    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
08807    misdn_in_calls[port]++;
08808 
08809    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
08810       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
08811       return misdn_in_calls[port] - max_in_calls;
08812    }
08813 
08814    return 0;
08815 }

int add_out_calls ( int  port  ) 

Definition at line 8817 of file chan_misdn.c.

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

Referenced by misdn_call().

08818 {
08819    int max_out_calls;
08820 
08821    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
08822 
08823    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
08824       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
08825       return (misdn_out_calls[port] + 1) - max_out_calls;
08826    }
08827 
08828    misdn_out_calls[port]++;
08829 
08830    return 0;
08831 }

AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_LOAD_ORDER  ,
"Channel driver for mISDN Support (BRI/PRI)"  ,
load = load_module,
unload = unload_module,
reload = reload,
load_pri = AST_MODPRI_CHANNEL_DRIVER 
)
static enum mISDN_NUMBER_PLAN ast_to_misdn_plan ( unsigned  ast_number_plan  )  [static]

Definition at line 2014 of file chan_misdn.c.

References NUMPLAN_DATA, NUMPLAN_ISDN, NUMPLAN_NATIONAL, NUMPLAN_PRIVATE, NUMPLAN_TELEX, and NUMPLAN_UNKNOWN.

Referenced by misdn_call(), misdn_copy_redirecting_from_ast(), and misdn_get_connected_line().

02015 {
02016    enum mISDN_NUMBER_PLAN number_plan;
02017 
02018    switch (ast_number_plan & 0x0F) {
02019    default:
02020    case NUMPLAN_UNKNOWN:
02021       number_plan = NUMPLAN_UNKNOWN;
02022       break;
02023 
02024    case NUMPLAN_ISDN:
02025       number_plan = NUMPLAN_ISDN;
02026       break;
02027 
02028    case NUMPLAN_DATA:
02029       number_plan = NUMPLAN_DATA;
02030       break;
02031 
02032    case NUMPLAN_TELEX:
02033       number_plan = NUMPLAN_TELEX;
02034       break;
02035 
02036    case NUMPLAN_NATIONAL:
02037       number_plan = NUMPLAN_NATIONAL;
02038       break;
02039 
02040    case NUMPLAN_PRIVATE:
02041       number_plan = NUMPLAN_PRIVATE;
02042       break;
02043    }
02044 
02045    return number_plan;
02046 }

static int ast_to_misdn_pres ( int  presentation  )  [static]

Definition at line 2117 of file chan_misdn.c.

References AST_PRES_ALLOWED, AST_PRES_RESTRICTED, AST_PRES_RESTRICTION, and AST_PRES_UNAVAILABLE.

Referenced by misdn_copy_redirecting_from_ast(), misdn_get_connected_line(), and update_config().

02118 {
02119    switch (presentation & AST_PRES_RESTRICTION) {
02120    default:
02121    case AST_PRES_ALLOWED:
02122       presentation = 0;
02123       break;
02124 
02125    case AST_PRES_RESTRICTED:
02126       presentation = 1;
02127       break;
02128 
02129    case AST_PRES_UNAVAILABLE:
02130       presentation = 2;
02131       break;
02132    }
02133 
02134    return presentation;
02135 }

static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason ( const enum AST_REDIRECTING_REASON  ast  )  [static]

Definition at line 2246 of file chan_misdn.c.

References ARRAY_LEN, AST_REDIRECTING_REASON_AWAY, AST_REDIRECTING_REASON_CALL_FWD_DTE, AST_REDIRECTING_REASON_DEFLECTION, AST_REDIRECTING_REASON_DO_NOT_DISTURB, AST_REDIRECTING_REASON_FOLLOW_ME, AST_REDIRECTING_REASON_NO_ANSWER, AST_REDIRECTING_REASON_OUT_OF_ORDER, AST_REDIRECTING_REASON_TIME_OF_DAY, AST_REDIRECTING_REASON_UNAVAILABLE, AST_REDIRECTING_REASON_UNCONDITIONAL, AST_REDIRECTING_REASON_UNKNOWN, AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_NO_REPLY, mISDN_REDIRECTING_REASON_OUT_OF_ORDER, and mISDN_REDIRECTING_REASON_UNKNOWN.

Referenced by misdn_copy_redirecting_from_ast().

static int ast_to_misdn_screen ( int  screening  )  [static]

Definition at line 2214 of file chan_misdn.c.

References AST_PRES_NETWORK_NUMBER, AST_PRES_NUMBER_TYPE, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.

Referenced by misdn_copy_redirecting_from_ast(), misdn_get_connected_line(), and update_config().

02215 {
02216    switch (screening & AST_PRES_NUMBER_TYPE) {
02217    default:
02218    case AST_PRES_USER_NUMBER_UNSCREENED:
02219       screening = 0;
02220       break;
02221 
02222    case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02223       screening = 1;
02224       break;
02225 
02226    case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02227       screening = 2;
02228       break;
02229 
02230    case AST_PRES_NETWORK_NUMBER:
02231       screening = 3;
02232       break;
02233    }
02234 
02235    return screening;
02236 }

static enum mISDN_NUMBER_TYPE ast_to_misdn_ton ( unsigned  ast_number_type  )  [static]

Definition at line 1888 of file chan_misdn.c.

References NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.

Referenced by misdn_call(), misdn_copy_redirecting_from_ast(), and misdn_get_connected_line().

01889 {
01890    enum mISDN_NUMBER_TYPE number_type;
01891 
01892    switch ((ast_number_type >> 4) & 0x07) {
01893    default:
01894    case NUMTYPE_UNKNOWN:
01895       number_type = NUMTYPE_UNKNOWN;
01896       break;
01897 
01898    case NUMTYPE_INTERNATIONAL:
01899       number_type = NUMTYPE_INTERNATIONAL;
01900       break;
01901 
01902    case NUMTYPE_NATIONAL:
01903       number_type = NUMTYPE_NATIONAL;
01904       break;
01905 
01906    case NUMTYPE_NETWORK_SPECIFIC:
01907       number_type = NUMTYPE_NETWORK_SPECIFIC;
01908       break;
01909 
01910    case NUMTYPE_SUBSCRIBER:
01911       number_type = NUMTYPE_SUBSCRIBER;
01912       break;
01913 
01914    case NUMTYPE_ABBREVIATED:
01915       number_type = NUMTYPE_ABBREVIATED;
01916       break;
01917    }
01918 
01919    return number_type;
01920 }

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

Definition at line 2345 of file chan_misdn.c.

References ARRAY_LEN, and allowed_bearers::display.

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

02346 {
02347    unsigned index;
02348 
02349    for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
02350       if (allowed_bearers_array[index].cap == cap) {
02351          return allowed_bearers_array[index].display;
02352       }
02353    }
02354 
02355    return "Unknown Bearer";
02356 }

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

queue new chan

Supplementary Services

Definition at line 9859 of file chan_misdn.c.

References add_in_calls(), misdn_bchannel::addr, chan_list::addr, chan_list::allowed_bearers, ao2_ref, misdn_bchannel::AOCD_need_export, 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_channel_lock, ast_channel_queue_redirecting_update(), ast_channel_unlock, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, 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_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pickup_call(), ast_pickup_ext(), ast_poll, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_queue_frame(), ast_set_callerid(), ast_setstate(), AST_STATE_RESERVED, AST_STATE_RINGING, ast_strdup, 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, ast_channel::caller, misdn_bchannel::caller, misdn_bchannel::capability, misdn_bchannel::cause, cb_log, chan_list_init(), chan_list_unref, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, cl_queue_chan(), ast_frame_subclass::codec, misdn_bchannel::connected, chan_list::context, misdn_bchannel::cw, ast_frame::data, ast_frame::datalen, ast_frame::delivery, misdn_bchannel::dialed, 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_NOTIFY, EVENT_PORT_ALARM, EVENT_PROCEEDING, EVENT_PROGRESS, EVENT_REGISTER, 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, misdn_bchannel::fac_out, chan_list::far_alerting, find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), ast_frame::frametype, misdn_party_redirecting::from, ast_generator::generate, ast_channel::generator, ast_channel::generatordata, hangup_chan(), ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, ast_party_caller::id, chan_list::ignore_dtmf, misdn_bchannel::incoming_cid_tag, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::info_dad, INFO_PI_INBAND_AVAILABLE, misdn_bchannel::infos_pending, ast_frame_subclass::integer, misdn_bchannel::keypad, misdn_bchannel::l3_id, chan_list::l3id, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, manager_isdn_get_info(), misdn_add_number_prefix(), MISDN_ALERTING, 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_APPEND_MSN_TO_CALLERID_TAG, misdn_cfg_get(), MISDN_CFG_HOLD_ALLOWED, MISDN_CFG_IMMEDIATE, MISDN_CFG_REJECT_CAUSE, MISDN_CLEANING, MISDN_CONNECTED, misdn_copy_redirecting_to_ast(), MISDN_DIALING, MISDN_DISCONNECTED, MISDN_EXTCANTMATCH, misdn_facility_ie_handler(), MISDN_GEN_APPEND_DIGITS2EXTEN, misdn_get_ch_state(), MISDN_HOLD_ACTIVE, MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, misdn_inband_avail(), MISDN_INCOMING_SETUP, misdn_is_msn_valid(), misdn_lib_is_ptp(), misdn_lib_log_ies(), misdn_lib_port_block(), misdn_lib_send_event(), misdn_new(), MISDN_NOTHING, mISDN_NOTIFY_CODE_CALL_IS_DIVERTING, mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE, mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING, mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED, mISDN_NOTIFY_CODE_INVALID, misdn_overlap_dial_task(), MISDN_PROCEEDING, MISDN_PROGRESS, mISDN_REDIRECTING_REASON_NO_REPLY, mISDN_REDIRECTING_REASON_UNKNOWN, misdn_tasks_add_variable(), misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_screen(), misdn_to_ast_ton(), misdn_to_str_plan(), misdn_to_str_pres(), misdn_to_str_screen(), misdn_to_str_ton(), misdn_update_remote_party(), MISDN_WAITING4DIGS, allowed_bearers::name, misdn_party_id::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::notify_description_code, misdn_bchannel::nt, chan_list::nttimeout, ast_party_id::number, misdn_party_dialing::number, misdn_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, 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(), misdn_bchannel::pid, chan_list::pipe, ast_party_number::plan, hold_info::port, misdn_bchannel::port, ast_party_number::presentation, misdn_party_id::presentation, print_bearer(), misdn_bchannel::progress_indicator, ast_frame::ptr, read_config(), misdn_party_redirecting::reason, ast_channel::redirecting, misdn_bchannel::redirecting, release_chan(), RESPONSE_IGNORE_SETUP, RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE, RESPONSE_OK, RESPONSE_RELEASE_SETUP, ast_channel::rings, ast_frame::samples, misdn_party_id::screening, 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_party_id::tag, ast_channel::tech, misdn_party_redirecting::to, ast_party_redirecting::to, misdn_party_redirecting::to_changed, misdn_bchannel::tone_cnt, ast_channel::transfercapability, ast_channel_tech::type, update_name(), and wait_for_digits().

Referenced by load_module().

09860 {
09861 #if defined(AST_MISDN_ENHANCEMENTS)
09862    struct misdn_cc_record *cc_record;
09863 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
09864    struct chan_list *held_ch;
09865    struct chan_list *ch = find_chan_by_bc(bc);
09866 
09867    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
09868       int debuglevel = 1;
09869 
09870       /*  Debug Only Non-Bchan */
09871       if (event == EVENT_CLEANUP && !user_data) {
09872          debuglevel = 5;
09873       }
09874 
09875       chan_misdn_log(debuglevel, bc->port,
09876          "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
09877          manager_isdn_get_info(event),
09878          bc->caller.name,
09879          bc->caller.number,
09880          bc->dialed.number,
09881          bc->pid,
09882          ch ? misdn_get_ch_state(ch) : "none");
09883       if (debuglevel == 1) {
09884          misdn_lib_log_ies(bc);
09885          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
09886       }
09887    }
09888 
09889    if (!ch) {
09890       switch(event) {
09891       case EVENT_SETUP:
09892       case EVENT_DISCONNECT:
09893       case EVENT_RELEASE:
09894       case EVENT_RELEASE_COMPLETE:
09895       case EVENT_PORT_ALARM:
09896       case EVENT_RETRIEVE:
09897       case EVENT_NEW_BC:
09898       case EVENT_FACILITY:
09899       case EVENT_REGISTER:
09900          break;
09901       case EVENT_CLEANUP:
09902       case EVENT_TONE_GENERATE:
09903       case EVENT_BCHAN_DATA:
09904          return -1;
09905       default:
09906          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);
09907          return -1;
09908       }
09909    } else {
09910       switch (event) {
09911       case EVENT_TONE_GENERATE:
09912          break;
09913       case EVENT_DISCONNECT:
09914       case EVENT_RELEASE:
09915       case EVENT_RELEASE_COMPLETE:
09916       case EVENT_CLEANUP:
09917       case EVENT_TIMEOUT:
09918          if (!ch->ast) {
09919             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));
09920          }
09921          break;
09922       default:
09923          if (!ch->ast || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
09924             if (event != EVENT_BCHAN_DATA) {
09925                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
09926             }
09927             chan_list_unref(ch, "No Ast or Ast private pointer");
09928             return -1;
09929          }
09930          break;
09931       }
09932    }
09933 
09934 
09935    switch (event) {
09936    case EVENT_PORT_ALARM:
09937       {
09938          int boa = 0;
09939          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
09940          if (boa) {
09941             cb_log(1, bc->port, " --> blocking\n");
09942             misdn_lib_port_block(bc->port);
09943          }
09944       }
09945       break;
09946    case EVENT_BCHAN_ACTIVATED:
09947       break;
09948 
09949    case EVENT_NEW_CHANNEL:
09950       update_name(ch->ast,bc->port,bc->channel);
09951       break;
09952 
09953    case EVENT_NEW_L3ID:
09954       ch->l3id=bc->l3_id;
09955       ch->addr=bc->addr;
09956       break;
09957 
09958    case EVENT_NEW_BC:
09959       if (!ch) {
09960          ch = find_hold_call(bc);
09961       }
09962 
09963       if (!ch) {
09964          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
09965          break;
09966       }
09967 
09968       if (bc) {
09969          ch->bc = (struct misdn_bchannel *) user_data;
09970       }
09971       break;
09972 
09973    case EVENT_DTMF_TONE:
09974    {
09975       /*  sending INFOS as DTMF-Frames :) */
09976       struct ast_frame fr;
09977 
09978       memset(&fr, 0, sizeof(fr));
09979       fr.frametype = AST_FRAME_DTMF;
09980       fr.subclass.integer = bc->dtmf ;
09981       fr.src = NULL;
09982       fr.data.ptr = NULL;
09983       fr.datalen = 0;
09984       fr.samples = 0;
09985       fr.mallocd = 0;
09986       fr.offset = 0;
09987       fr.delivery = ast_tv(0,0);
09988 
09989       if (!ch->ignore_dtmf) {
09990          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
09991          ast_queue_frame(ch->ast, &fr);
09992       } else {
09993          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
09994       }
09995       break;
09996    }
09997    case EVENT_STATUS:
09998       break;
09999 
10000    case EVENT_INFORMATION:
10001       if (ch->state != MISDN_CONNECTED) {
10002          stop_indicate(ch);
10003       }
10004 
10005       if (!ch->ast) {
10006          break;
10007       }
10008 
10009       if (ch->state == MISDN_WAITING4DIGS) {
10010          /*  Ok, incomplete Setup, waiting till extension exists */
10011          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
10012             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
10013             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
10014          }
10015 
10016          strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10017          ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
10018 
10019          /* Check for Pickup Request first */
10020          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
10021             if (ast_pickup_call(ch->ast)) {
10022                hangup_chan(ch, bc);
10023             } else {
10024                ch->state = MISDN_CALLING_ACKNOWLEDGE;
10025                hangup_chan(ch, bc);
10026                ch->ast = NULL;
10027                break;
10028             }
10029          }
10030 
10031          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10032             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10033                ast_log(LOG_WARNING,
10034                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10035                   bc->dialed.number, ch->context, bc->port);
10036                pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10037                strcpy(ch->ast->exten, "i");
10038                ch->state = MISDN_DIALING;
10039                start_pbx(ch, bc, ch->ast);
10040                break;
10041             }
10042 
10043             ast_log(LOG_WARNING,
10044                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10045                "\tMaybe you want to add an 'i' extension to catch this case.\n",
10046                bc->dialed.number, ch->context, bc->port);
10047 
10048             if (bc->nt) {
10049                hanguptone_indicate(ch);
10050             }
10051             ch->state = MISDN_EXTCANTMATCH;
10052             bc->out_cause = AST_CAUSE_UNALLOCATED;
10053 
10054             misdn_lib_send_event(bc, EVENT_DISCONNECT);
10055             break;
10056          }
10057 
10058          if (ch->overlap_dial) {
10059             ast_mutex_lock(&ch->overlap_tv_lock);
10060             ch->overlap_tv = ast_tvnow();
10061             ast_mutex_unlock(&ch->overlap_tv_lock);
10062             if (ch->overlap_dial_task == -1) {
10063                ch->overlap_dial_task =
10064                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
10065             }
10066             break;
10067          }
10068 
10069          if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number))  {
10070             ch->state = MISDN_DIALING;
10071             start_pbx(ch, bc, ch->ast);
10072          }
10073       } else {
10074          /*  sending INFOS as DTMF-Frames :) */
10075          struct ast_frame fr;
10076          int digits;
10077 
10078          memset(&fr, 0, sizeof(fr));
10079          fr.frametype = AST_FRAME_DTMF;
10080          fr.subclass.integer = bc->info_dad[0] ;
10081          fr.src = NULL;
10082          fr.data.ptr = NULL;
10083          fr.datalen = 0;
10084          fr.samples = 0;
10085          fr.mallocd = 0;
10086          fr.offset = 0;
10087          fr.delivery = ast_tv(0,0);
10088 
10089          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
10090          if (ch->state != MISDN_CONNECTED) {
10091             if (digits) {
10092                strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10093                ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
10094                ast_cdr_update(ch->ast);
10095             }
10096 
10097             ast_queue_frame(ch->ast, &fr);
10098          }
10099       }
10100       break;
10101    case EVENT_SETUP:
10102    {
10103       struct ast_channel *chan;
10104       int exceed;
10105       int ai;
10106       int im;
10107       int append_msn = 0;
10108 
10109       if (ch) {
10110          switch (ch->state) {
10111          case MISDN_NOTHING:
10112             chan_list_unref(ch, "Ignore found ch.  Is it for an outgoing call?");
10113             ch = NULL;
10114             break;
10115          default:
10116             chan_list_unref(ch, "Already have a call.");
10117             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
10118             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
10119          }
10120       }
10121 
10122       if (!bc->nt && !misdn_is_msn_valid(bc->port, &bc->dialed)) {
10123          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
10124          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
10125       }
10126 
10127       if (bc->cw) {
10128          int cause;
10129          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
10130          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
10131          bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
10132          return RESPONSE_RELEASE_SETUP;
10133       }
10134 
10135       print_bearer(bc);
10136 
10137       ch = chan_list_init(ORG_MISDN);
10138       if (!ch) {
10139          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
10140          return RESPONSE_RELEASE_SETUP;
10141       }
10142 
10143       ch->bc = bc;
10144       ch->l3id = bc->l3_id;
10145       ch->addr = bc->addr;
10146 
10147       chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, AST_FORMAT_ALAW, NULL, bc->port, bc->channel);
10148       if (!chan) {
10149          chan_list_unref(ch, "Failed to create a new channel");
10150          ast_log(LOG_ERROR, "cb_events: misdn_new failed!\n");
10151          return RESPONSE_RELEASE_SETUP;
10152       }
10153 
10154       if ((exceed = add_in_calls(bc->port))) {
10155          char tmp[16];
10156          snprintf(tmp, sizeof(tmp), "%d", exceed);
10157          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
10158       }
10159 
10160       read_config(ch);
10161 
10162       export_ch(chan, bc, ch);
10163 
10164       ch->ast->rings = 1;
10165       ast_setstate(ch->ast, AST_STATE_RINGING);
10166 
10167       /* Update asterisk channel caller information */
10168       chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
10169       chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
10170       chan->caller.id.number.plan = misdn_to_ast_ton(bc->caller.number_type)
10171          | misdn_to_ast_plan(bc->caller.number_plan);
10172 
10173       chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
10174       chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
10175       chan->caller.id.number.presentation = misdn_to_ast_pres(bc->caller.presentation)
10176          | misdn_to_ast_screen(bc->caller.screening);
10177 
10178       ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
10179 
10180       misdn_cfg_get(bc->port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
10181       if (append_msn) {
10182          strncat(bc->incoming_cid_tag, "_", sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10183          strncat(bc->incoming_cid_tag, bc->dialed.number, sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10184       }
10185 
10186       ast_channel_lock(chan);
10187       chan->caller.id.tag = ast_strdup(bc->incoming_cid_tag);
10188       ast_channel_unlock(chan);
10189 
10190       if (!ast_strlen_zero(bc->redirecting.from.number)) {
10191          /* Add configured prefix to redirecting.from.number */
10192          misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
10193 
10194          /* Update asterisk channel redirecting information */
10195          misdn_copy_redirecting_to_ast(chan, &bc->redirecting, bc->incoming_cid_tag);
10196       }
10197 
10198       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
10199       chan->transfercapability = bc->capability;
10200 
10201       switch (bc->capability) {
10202       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
10203          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
10204          break;
10205       default:
10206          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
10207          break;
10208       }
10209 
10210       if (!strstr(ch->allowed_bearers, "all")) {
10211          int i;
10212 
10213          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
10214             if (allowed_bearers_array[i].cap == bc->capability) {
10215                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
10216                   /* The bearer capability is allowed */
10217                   if (allowed_bearers_array[i].deprecated) {
10218                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
10219                         allowed_bearers_array[i].name);
10220                   }
10221                   break;
10222                }
10223             }
10224          }
10225          if (i == ARRAY_LEN(allowed_bearers_array)) {
10226             /* We did not find the bearer capability */
10227             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
10228                bearer2str(bc->capability), bc->capability);
10229 
10230             ch->state = MISDN_EXTCANTMATCH;
10231             chan_list_unref(ch, "BC not allowed, releasing call");
10232             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
10233             return RESPONSE_RELEASE_SETUP;
10234          }
10235       }
10236 
10237       /** queue new chan **/
10238       cl_queue_chan(ch);
10239 
10240       if (bc->fac_in.Function != Fac_None) {
10241          misdn_facility_ie_handler(event, bc, ch);
10242       }
10243 
10244       /* Check for Pickup Request first */
10245       if (!strcmp(chan->exten, ast_pickup_ext())) {
10246          if (!ch->noautorespond_on_setup) {
10247             /* Sending SETUP_ACK */
10248             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
10249          } else {
10250             ch->state = MISDN_INCOMING_SETUP;
10251          }
10252          if (ast_pickup_call(chan)) {
10253             hangup_chan(ch, bc);
10254          } else {
10255             ch->state = MISDN_CALLING_ACKNOWLEDGE;
10256             hangup_chan(ch, bc);
10257             ch->ast = NULL;
10258             break;
10259          }
10260       }
10261 
10262       /*
10263        * added support for s extension hope it will help those poor cretains
10264        * which haven't overlap dial.
10265        */
10266       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
10267       if (ai) {
10268          do_immediate_setup(bc, ch, chan);
10269          break;
10270       }
10271 
10272       /* check if we should jump into s when we have no dialed.number */
10273       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
10274       if (im && ast_strlen_zero(bc->dialed.number)) {
10275          do_immediate_setup(bc, ch, chan);
10276          break;
10277       }
10278 
10279       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
10280       if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10281          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10282             ast_log(LOG_WARNING,
10283                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10284                bc->dialed.number, ch->context, bc->port);
10285             pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10286             strcpy(ch->ast->exten, "i");
10287             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
10288             ch->state = MISDN_DIALING;
10289             start_pbx(ch, bc, chan);
10290             break;
10291          }
10292 
10293          ast_log(LOG_WARNING,
10294             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10295             "\tMaybe you want to add an 'i' extension to catch this case.\n",
10296             bc->dialed.number, ch->context, bc->port);
10297          if (bc->nt) {
10298             hanguptone_indicate(ch);
10299          }
10300 
10301          ch->state = MISDN_EXTCANTMATCH;
10302          bc->out_cause = AST_CAUSE_UNALLOCATED;
10303 
10304          misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_RELEASE);
10305          break;
10306       }
10307 
10308       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
10309        * jump into the dialplan, when the dialed extension does not exist, the 's' extension
10310        * will be used by Asterisk automatically. */
10311       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
10312          if (!ch->noautorespond_on_setup) {
10313             ch->state=MISDN_DIALING;
10314             misdn_lib_send_event(bc, EVENT_PROCEEDING);
10315          } else {
10316             ch->state = MISDN_INCOMING_SETUP;
10317          }
10318          start_pbx(ch, bc, chan);
10319          break;
10320       }
10321 
10322 
10323       /*
10324        * When we are NT and overlapdial is set and if
10325        * the number is empty, we wait for the ISDN timeout
10326        * instead of our own timer.
10327        */
10328       if (ch->overlap_dial && bc->nt && !bc->dialed.number[0]) {
10329          wait_for_digits(ch, bc, chan);
10330          break;
10331       }
10332 
10333       /*
10334        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
10335        * Infos with a Interdigit Timeout.
10336        * */
10337       if (ch->overlap_dial) {
10338          ast_mutex_lock(&ch->overlap_tv_lock);
10339          ch->overlap_tv = ast_tvnow();
10340          ast_mutex_unlock(&ch->overlap_tv_lock);
10341 
10342          wait_for_digits(ch, bc, chan);
10343          if (ch->overlap_dial_task == -1) {
10344             ch->overlap_dial_task =
10345                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
10346          }
10347          break;
10348       }
10349 
10350       /* If the extension does not exist and we're not TE_PTMP we wait for more digits
10351        * without interdigit timeout.
10352        * */
10353       if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number))  {
10354          wait_for_digits(ch, bc, chan);
10355          break;
10356       }
10357 
10358       /*
10359        * If the extension exists let's just jump into it.
10360        * */
10361       if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10362          misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
10363          ch->state = MISDN_DIALING;
10364          start_pbx(ch, bc, chan);
10365          break;
10366       }
10367       break;
10368    }
10369 #if defined(AST_MISDN_ENHANCEMENTS)
10370    case EVENT_REGISTER:
10371       if (bc->fac_in.Function != Fac_None) {
10372          misdn_facility_ie_handler(event, bc, ch);
10373       }
10374       /*
10375        * Shut down this connection immediately.
10376        * The current design of chan_misdn data structures
10377        * does not allow the proper handling of inbound call records
10378        * without an assigned B channel.  Therefore, we cannot
10379        * be the CCBS User-B party in a point-to-point setup.
10380        */
10381       bc->fac_out.Function = Fac_None;
10382       bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10383       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
10384       break;
10385 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10386    case EVENT_SETUP_ACKNOWLEDGE:
10387       ch->state = MISDN_CALLING_ACKNOWLEDGE;
10388 
10389       if (bc->channel) {
10390          update_name(ch->ast,bc->port,bc->channel);
10391       }
10392 
10393       if (bc->fac_in.Function != Fac_None) {
10394          misdn_facility_ie_handler(event, bc, ch);
10395       }
10396 
10397       if (!ast_strlen_zero(bc->infos_pending)) {
10398          /* TX Pending Infos */
10399          strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10400 
10401          if (!ch->ast) {
10402             break;
10403          }
10404          ast_copy_string(ch->ast->exten, bc->dialed.number, sizeof(ch->ast->exten));
10405          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
10406          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
10407 
10408          misdn_lib_send_event(bc, EVENT_INFORMATION);
10409       }
10410       break;
10411    case EVENT_PROCEEDING:
10412       if (misdn_cap_is_speech(bc->capability) &&
10413          misdn_inband_avail(bc)) {
10414          start_bc_tones(ch);
10415       }
10416 
10417       ch->state = MISDN_PROCEEDING;
10418 
10419       if (bc->fac_in.Function != Fac_None) {
10420          misdn_facility_ie_handler(event, bc, ch);
10421       }
10422 
10423       if (!ch->ast) {
10424          break;
10425       }
10426 
10427       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
10428       break;
10429    case EVENT_PROGRESS:
10430       if (bc->channel) {
10431          update_name(ch->ast, bc->port, bc->channel);
10432       }
10433 
10434       if (bc->fac_in.Function != Fac_None) {
10435          misdn_facility_ie_handler(event, bc, ch);
10436       }
10437 
10438       if (!bc->nt) {
10439          if (misdn_cap_is_speech(bc->capability) &&
10440             misdn_inband_avail(bc)) {
10441             start_bc_tones(ch);
10442          }
10443 
10444          ch->state = MISDN_PROGRESS;
10445 
10446          if (!ch->ast) {
10447             break;
10448          }
10449          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
10450       }
10451       break;
10452    case EVENT_ALERTING:
10453       ch->state = MISDN_ALERTING;
10454 
10455       if (!ch->ast) {
10456          break;
10457       }
10458 
10459       if (bc->fac_in.Function != Fac_None) {
10460          misdn_facility_ie_handler(event, bc, ch);
10461       }
10462 
10463       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
10464       ast_setstate(ch->ast, AST_STATE_RINGING);
10465 
10466       cb_log(7, bc->port, " --> Set State Ringing\n");
10467 
10468       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
10469          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
10470          start_bc_tones(ch);
10471       } else {
10472          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
10473          if (ch->far_alerting) {
10474             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
10475             start_bc_tones(ch);
10476             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
10477          }
10478       }
10479       break;
10480    case EVENT_CONNECT:
10481       if (bc->fac_in.Function != Fac_None) {
10482          misdn_facility_ie_handler(event, bc, ch);
10483       }
10484 #if defined(AST_MISDN_ENHANCEMENTS)
10485       if (bc->div_leg_3_rx_wanted) {
10486          bc->div_leg_3_rx_wanted = 0;
10487 
10488          if (ch->ast) {
10489             ch->ast->redirecting.to.number.presentation =
10490                AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
10491             ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting, NULL);
10492          }
10493       }
10494 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10495 
10496       /* we answer when we've got our very new L3 ID from the NT stack */
10497       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
10498 
10499       if (!ch->ast) {
10500          break;
10501       }
10502 
10503       stop_indicate(ch);
10504 
10505 #if defined(AST_MISDN_ENHANCEMENTS)
10506       if (ch->record_id != -1) {
10507          /*
10508           * We will delete the associated call completion
10509           * record since we now have a completed call.
10510           * We will not wait/depend on the network to tell
10511           * us to delete it.
10512           */
10513          AST_LIST_LOCK(&misdn_cc_records_db);
10514          cc_record = misdn_cc_find_by_id(ch->record_id);
10515          if (cc_record) {
10516             if (cc_record->ptp && cc_record->mode.ptp.bc) {
10517                /* Close the call-completion signaling link */
10518                cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
10519                cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10520                misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
10521             }
10522             misdn_cc_delete(cc_record);
10523          }
10524          AST_LIST_UNLOCK(&misdn_cc_records_db);
10525          ch->record_id = -1;
10526          if (ch->peer) {
10527             misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, "");
10528 
10529             ao2_ref(ch->peer, -1);
10530             ch->peer = NULL;
10531          }
10532       }
10533 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10534 
10535       if (!ast_strlen_zero(bc->connected.number)) {
10536          /* Add configured prefix to connected.number */
10537          misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
10538 
10539          /* Update the connected line information on the other channel */
10540          misdn_update_remote_party(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, bc->incoming_cid_tag);
10541       }
10542 
10543       ch->l3id = bc->l3_id;
10544       ch->addr = bc->addr;
10545 
10546       start_bc_tones(ch);
10547 
10548       ch->state = MISDN_CONNECTED;
10549 
10550       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
10551       break;
10552    case EVENT_CONNECT_ACKNOWLEDGE:
10553       ch->l3id = bc->l3_id;
10554       ch->addr = bc->addr;
10555 
10556       start_bc_tones(ch);
10557 
10558       ch->state = MISDN_CONNECTED;
10559       break;
10560    case EVENT_DISCONNECT:
10561       /* we might not have an ch->ast ptr here anymore */
10562       if (ch) {
10563          if (bc->fac_in.Function != Fac_None) {
10564             misdn_facility_ie_handler(event, bc, ch);
10565          }
10566 
10567          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);
10568          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
10569             /* If there's inband information available (e.g. a
10570                recorded message saying what was wrong with the
10571                dialled number, or perhaps even giving an
10572                alternative number, then play it instead of
10573                immediately releasing the call */
10574             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
10575 
10576             ch->state = MISDN_DISCONNECTED;
10577             start_bc_tones(ch);
10578 
10579             if (ch->ast) {
10580                ch->ast->hangupcause = bc->cause;
10581                if (bc->cause == AST_CAUSE_USER_BUSY) {
10582                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
10583                }
10584             }
10585             ch->need_busy = 0;
10586             break;
10587          }
10588 
10589          bc->need_disconnect = 0;
10590          stop_bc_tones(ch);
10591 
10592          /* Check for held channel, to implement transfer */
10593          held_ch = find_hold_call(bc);
10594          if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
10595             hangup_chan(ch, bc);
10596          }
10597       } else {
10598          held_ch = find_hold_call_l3(bc->l3_id);
10599          if (held_ch) {
10600             if (bc->fac_in.Function != Fac_None) {
10601                misdn_facility_ie_handler(event, bc, held_ch);
10602             }
10603 
10604             if (held_ch->hold.state == MISDN_HOLD_ACTIVE) {
10605                bc->need_disconnect = 0;
10606 
10607 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
10608                /*
10609                 * Some phones disconnect the held call and the active call at the
10610                 * same time to do the transfer.  Unfortunately, either call could
10611                 * be disconnected first.
10612                 */
10613                ch = find_hold_active_call(bc);
10614                if (!ch || misdn_attempt_transfer(ch, held_ch)) {
10615                   held_ch->hold.state = MISDN_HOLD_DISCONNECT;
10616                   hangup_chan(held_ch, bc);
10617                }
10618 #else
10619                hangup_chan(held_ch, bc);
10620 #endif   /* defined(TRANSFER_ON_HELD_CALL_HANGUP) */
10621             }
10622          }
10623       }
10624       if (held_ch) {
10625          chan_list_unref(held_ch, "Done with held call");
10626       }
10627       bc->out_cause = -1;
10628       if (bc->need_release) {
10629          misdn_lib_send_event(bc, EVENT_RELEASE);
10630       }
10631       break;
10632    case EVENT_RELEASE:
10633       if (!ch) {
10634          ch = find_hold_call_l3(bc->l3_id);
10635          if (!ch) {
10636             chan_misdn_log(1, bc->port,
10637                " --> no Ch, so we've already released. (%s)\n",
10638                manager_isdn_get_info(event));
10639             return -1;
10640          }
10641       }
10642       if (bc->fac_in.Function != Fac_None) {
10643          misdn_facility_ie_handler(event, bc, ch);
10644       }
10645 
10646       bc->need_disconnect = 0;
10647       bc->need_release = 0;
10648 
10649       hangup_chan(ch, bc);
10650       release_chan(ch, bc);
10651       break;
10652    case EVENT_RELEASE_COMPLETE:
10653       if (!ch) {
10654          ch = find_hold_call_l3(bc->l3_id);
10655       }
10656 
10657       bc->need_disconnect = 0;
10658       bc->need_release = 0;
10659       bc->need_release_complete = 0;
10660 
10661       if (ch) {
10662          if (bc->fac_in.Function != Fac_None) {
10663             misdn_facility_ie_handler(event, bc, ch);
10664          }
10665 
10666          stop_bc_tones(ch);
10667          hangup_chan(ch, bc);
10668          release_chan(ch, bc);
10669       } else {
10670 #if defined(AST_MISDN_ENHANCEMENTS)
10671          /*
10672           * A call-completion signaling link established with
10673           * REGISTER does not have a struct chan_list record
10674           * associated with it.
10675           */
10676          AST_LIST_LOCK(&misdn_cc_records_db);
10677          cc_record = misdn_cc_find_by_bc(bc);
10678          if (cc_record) {
10679             /* The call-completion signaling link is closed. */
10680             misdn_cc_delete(cc_record);
10681          }
10682          AST_LIST_UNLOCK(&misdn_cc_records_db);
10683 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
10684 
10685          chan_misdn_log(1, bc->port,
10686             " --> no Ch, so we've already released. (%s)\n",
10687             manager_isdn_get_info(event));
10688       }
10689       break;
10690    case EVENT_BCHAN_ERROR:
10691    case EVENT_CLEANUP:
10692       stop_bc_tones(ch);
10693 
10694       switch (ch->state) {
10695       case MISDN_CALLING:
10696          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
10697          break;
10698       default:
10699          break;
10700       }
10701 
10702       hangup_chan(ch, bc);
10703       release_chan(ch, bc);
10704       break;
10705    case EVENT_TONE_GENERATE:
10706    {
10707       int tone_len = bc->tone_cnt;
10708       struct ast_channel *ast = ch->ast;
10709       void *tmp;
10710       int res;
10711       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
10712 
10713       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
10714 
10715       if (!ast) {
10716          break;
10717       }
10718 
10719       if (!ast->generator) {
10720          break;
10721       }
10722 
10723       tmp = ast->generatordata;
10724       ast->generatordata = NULL;
10725       generate = ast->generator->generate;
10726 
10727       if (tone_len < 0 || tone_len > 512) {
10728          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
10729          tone_len = 128;
10730       }
10731 
10732       res = generate(ast, tmp, tone_len, tone_len);
10733       ast->generatordata = tmp;
10734 
10735       if (res) {
10736          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
10737          ast_deactivate_generator(ast);
10738       } else {
10739          bc->tone_cnt = 0;
10740       }
10741       break;
10742    }
10743    case EVENT_BCHAN_DATA:
10744       if (ch->bc->AOCD_need_export) {
10745          export_aoc_vars(ch->originator, ch->ast, ch->bc);
10746       }
10747       if (!misdn_cap_is_speech(ch->bc->capability)) {
10748          struct ast_frame frame;
10749 
10750          /* In Data Modes we queue frames */
10751          memset(&frame, 0, sizeof(frame));
10752          frame.frametype = AST_FRAME_VOICE; /* we have no data frames yet */
10753          frame.subclass.codec = AST_FORMAT_ALAW;
10754          frame.datalen = bc->bframe_len;
10755          frame.samples = bc->bframe_len;
10756          frame.mallocd = 0;
10757          frame.offset = 0;
10758          frame.delivery = ast_tv(0, 0);
10759          frame.src = NULL;
10760          frame.data.ptr = bc->bframe;
10761 
10762          if (ch->ast) {
10763             ast_queue_frame(ch->ast, &frame);
10764          }
10765       } else {
10766          struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
10767          int t;
10768 
10769          t = ast_poll(&pfd, 1, 0);
10770 
10771          if (t < 0) {
10772             chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
10773             break;
10774          }
10775          if (!t) {
10776             chan_misdn_log(9, bc->port, "poll() timed out\n");
10777             break;
10778          }
10779 
10780          if (pfd.revents & POLLOUT) {
10781             chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
10782             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
10783                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
10784 
10785                stop_bc_tones(ch);
10786                hangup_chan(ch, bc);
10787                release_chan(ch, bc);
10788             }
10789          } else {
10790             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
10791          }
10792       }
10793       break;
10794    case EVENT_TIMEOUT:
10795       if (ch && bc) {
10796          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
10797       }
10798 
10799       switch (ch->state) {
10800       case MISDN_DIALING:
10801       case MISDN_PROGRESS:
10802          if (bc->nt && !ch->nttimeout) {
10803             break;
10804          }
10805          /* fall-through */
10806       case MISDN_CALLING:
10807       case MISDN_ALERTING:
10808       case MISDN_PROCEEDING:
10809       case MISDN_CALLING_ACKNOWLEDGE:
10810          if (bc->nt) {
10811             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
10812             hanguptone_indicate(ch);
10813          }
10814 
10815          bc->out_cause = AST_CAUSE_UNALLOCATED;
10816          misdn_lib_send_event(bc, EVENT_DISCONNECT);
10817          break;
10818       case MISDN_WAITING4DIGS:
10819          if (bc->nt) {
10820             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
10821             bc->out_cause = AST_CAUSE_UNALLOCATED;
10822             hanguptone_indicate(ch);
10823             misdn_lib_send_event(bc, EVENT_DISCONNECT);
10824          } else {
10825             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10826             misdn_lib_send_event(bc, EVENT_RELEASE);
10827          }
10828          break;
10829       case MISDN_CLEANING:
10830          chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
10831          break;
10832       default:
10833          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
10834          break;
10835       }
10836       break;
10837 
10838    /****************************/
10839    /** Supplementary Services **/
10840    /****************************/
10841    case EVENT_RETRIEVE:
10842       if (!ch) {
10843          chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
10844          ch = find_hold_call_l3(bc->l3_id);
10845          if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
10846             ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
10847             misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
10848             break;
10849          }
10850       }
10851 
10852       /* remember the channel again */
10853       ch->bc = bc;
10854 
10855       ch->hold.state = MISDN_HOLD_IDLE;
10856       ch->hold.port = 0;
10857       ch->hold.channel = 0;
10858 
10859       ast_queue_control(ch->ast, AST_CONTROL_UNHOLD);
10860 
10861       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
10862          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
10863          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
10864       }
10865       break;
10866    case EVENT_HOLD:
10867    {
10868       int hold_allowed;
10869       struct ast_channel *bridged;
10870 
10871       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
10872       if (!hold_allowed) {
10873          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
10874          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
10875          break;
10876       }
10877 
10878       bridged = ast_bridged_channel(ch->ast);
10879       if (bridged) {
10880          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
10881          ch->l3id = bc->l3_id;
10882 
10883          /* forget the channel now */
10884          ch->bc = NULL;
10885          ch->hold.state = MISDN_HOLD_ACTIVE;
10886          ch->hold.port = bc->port;
10887          ch->hold.channel = bc->channel;
10888 
10889          ast_queue_control(ch->ast, AST_CONTROL_HOLD);
10890 
10891          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
10892       } else {
10893          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
10894          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
10895       }
10896       break;
10897    }
10898    case EVENT_NOTIFY:
10899       if (bc->redirecting.to_changed) {
10900          /* Add configured prefix to redirecting.to.number */
10901          misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
10902             bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
10903       }
10904       switch (bc->notify_description_code) {
10905       case mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED:
10906          /* Ignore for now. */
10907          bc->redirecting.to_changed = 0;
10908          break;
10909       case mISDN_NOTIFY_CODE_CALL_IS_DIVERTING:
10910          if (!bc->redirecting.to_changed) {
10911             break;
10912          }
10913          bc->redirecting.to_changed = 0;
10914          if (!ch || !ch->ast) {
10915             break;
10916          }
10917          switch (ch->state) {
10918          case MISDN_ALERTING:
10919             /* Call is deflecting after we have seen an ALERTING message */
10920             bc->redirecting.reason = mISDN_REDIRECTING_REASON_NO_REPLY;
10921             break;
10922          default:
10923             /* Call is deflecting for call forwarding unconditional or busy reason. */
10924             bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
10925             break;
10926          }
10927          misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
10928          ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting, NULL);
10929          break;
10930       case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
10931          /*
10932           * It would be preferable to update the connected line information
10933           * only when the message callStatus is active.  However, the
10934           * optional redirection number may not be present in the active
10935           * message if an alerting message were received earlier.
10936           *
10937           * The consequences if we wind up sending two updates is benign.
10938           * The other end will think that it got transferred twice.
10939           */
10940          if (!bc->redirecting.to_changed) {
10941             break;
10942          }
10943          bc->redirecting.to_changed = 0;
10944          if (!ch || !ch->ast) {
10945             break;
10946          }
10947          misdn_update_remote_party(ch->ast, &bc->redirecting.to,
10948             AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING,
10949             bc->incoming_cid_tag);
10950          break;
10951       case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
10952          if (!bc->redirecting.to_changed) {
10953             break;
10954          }
10955          bc->redirecting.to_changed = 0;
10956          if (!ch || !ch->ast) {
10957             break;
10958          }
10959          misdn_update_remote_party(ch->ast, &bc->redirecting.to,
10960             AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
10961          break;
10962       default:
10963          bc->redirecting.to_changed = 0;
10964          chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
10965             bc->notify_description_code);
10966          break;
10967       }
10968       bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
10969       break;
10970    case EVENT_FACILITY:
10971       if (bc->fac_in.Function == Fac_None) {
10972          /* This is a FACILITY message so we MUST have a facility ie */
10973          chan_misdn_log(0, bc->port," --> Missing facility ie or unknown facility ie contents.\n");
10974       } else {
10975          misdn_facility_ie_handler(event, bc, ch);
10976       }
10977 
10978       /* In case it came in on a FACILITY message and we did not handle it. */
10979       bc->redirecting.to_changed = 0;
10980       bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
10981       break;
10982    case EVENT_RESTART:
10983       if (!bc->dummy) {
10984          stop_bc_tones(ch);
10985          release_chan(ch, bc);
10986       }
10987       break;
10988    default:
10989       chan_misdn_log(1, 0, "Got Unknown Event\n");
10990       break;
10991    }
10992 
10993    if (ch) {
10994       chan_list_unref(ch, "cb_event complete OK");
10995    }
10996    return RESPONSE_OK;
10997 }

static void chan_list_destructor ( void *  obj  )  [static]

Definition at line 7709 of file chan_misdn.c.

References ao2_ref, ast_dsp_free(), ast_mutex_destroy, chan_list::dsp, chan_list::jb, misdn_jb_destroy(), misdn_tasks_remove(), chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, and chan_list::pipe.

Referenced by chan_list_init().

07710 {
07711    struct chan_list *ch = obj;
07712 
07713 #if defined(AST_MISDN_ENHANCEMENTS)
07714    if (ch->peer) {
07715       ao2_ref(ch->peer, -1);
07716       ch->peer = NULL;
07717    }
07718 #endif /* AST_MISDN_ENHANCEMENTS */
07719 
07720    if (ch->dsp) {
07721       ast_dsp_free(ch->dsp);
07722       ch->dsp = NULL;
07723    }
07724 
07725    /* releasing jitterbuffer */
07726    if (ch->jb) {
07727       misdn_jb_destroy(ch->jb);
07728       ch->jb = NULL;
07729    }
07730 
07731    if (ch->overlap_dial) {
07732       if (ch->overlap_dial_task != -1) {
07733          misdn_tasks_remove(ch->overlap_dial_task);
07734          ch->overlap_dial_task = -1;
07735       }
07736       ast_mutex_destroy(&ch->overlap_tv_lock);
07737    }
07738 
07739    if (-1 < ch->pipe[0]) {
07740       close(ch->pipe[0]);
07741    }
07742    if (-1 < ch->pipe[1]) {
07743       close(ch->pipe[1]);
07744    }
07745 }

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

Returns a reference to the new chan_list.

Definition at line 7748 of file chan_misdn.c.

References ao2_alloc, chan_list_destructor(), chan_misdn_log(), chan_list::need_busy, chan_list::need_hangup, chan_list::need_queue_hangup, chan_list::originator, chan_list::overlap_dial_task, and chan_list::pipe.

Referenced by cb_events(), and misdn_request().

07749 {
07750    struct chan_list *cl;
07751 
07752    cl = ao2_alloc(sizeof(*cl), chan_list_destructor);
07753    if (!cl) {
07754       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
07755       return NULL;
07756    }
07757 
07758    cl->originator = orig;
07759    cl->need_queue_hangup = 1;
07760    cl->need_hangup = 1;
07761    cl->need_busy = 1;
07762    cl->overlap_dial_task = -1;
07763 #if defined(AST_MISDN_ENHANCEMENTS)
07764    cl->record_id = -1;
07765 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
07766    cl->pipe[0] = -1;
07767    cl->pipe[1] = -1;
07768 
07769    return cl;
07770 }

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

Definition at line 12432 of file chan_misdn.c.

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

Referenced by load_module().

12433 {
12434    struct chan_list *ch;
12435    int res;
12436 
12437    ch = find_chan_by_bc(bc);
12438    if (!ch) {
12439       return 0;
12440    }
12441 
12442    if (ch->jb) {
12443       res = misdn_jb_empty(ch->jb, buf, len);
12444    } else {
12445       res = 0;
12446    }
12447    chan_list_unref(ch, "Done emptying jb");
12448 
12449    return res;
12450 }

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

Definition at line 12626 of file chan_misdn.c.

References ast_log(), ast_strlen_zero(), ast_verbose, errno, and LOG_WARNING.

Referenced by cb_events(), chan_list_init(), cl_queue_chan(), config_jitterbuffer(), debug_numtype(), dialtone_indicate(), do_immediate_setup(), export_ch(), find_chan_by_bc(), find_hold_call(), load_module(), misdn_answer(), misdn_attempt_transfer(), misdn_bridge(), misdn_call(), misdn_check_l2l1(), misdn_digit_end(), misdn_facility_exec(), misdn_facility_ie_handler(), 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().

12627 {
12628    va_list ap;
12629    char buf[1024];
12630    char port_buf[8];
12631 
12632    if (!(0 <= port && port <= max_ports)) {
12633       ast_log(LOG_WARNING, "chan_misdn_log called with out-of-range port number! (%d)\n", port);
12634       port = 0;
12635       level = -1;
12636    } else if (!(level == -1
12637       || (misdn_debug_only[port]
12638          ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12639          : level <= misdn_debug[port])
12640       || (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
12641       /*
12642        * We are not going to print anything so lets not
12643        * go to all the work of generating a string.
12644        */
12645       return;
12646    }
12647 
12648    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
12649    va_start(ap, tmpl);
12650    vsnprintf(buf, sizeof(buf), tmpl, ap);
12651    va_end(ap);
12652 
12653    if (level == -1) {
12654       ast_log(LOG_WARNING, "%s", buf);
12655    } else if (misdn_debug_only[port]
12656       ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12657       : level <= misdn_debug[port]) {
12658       ast_verbose("%s%s", port_buf, buf);
12659    }
12660 
12661    if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
12662       char ctimebuf[30];
12663       time_t tm;
12664       char *tmp;
12665       char *p;
12666       FILE *fp;
12667 
12668       fp = fopen(global_tracefile, "a+");
12669       if (!fp) {
12670          ast_verbose("Error opening Tracefile: [ %s ] %s\n", global_tracefile, strerror(errno));
12671          return;
12672       }
12673 
12674       tm = time(NULL);
12675       tmp = ctime_r(&tm, ctimebuf);
12676       p = strchr(tmp, '\n');
12677       if (p) {
12678          *p = ':';
12679       }
12680       fputs(tmp, fp);
12681       fputs(" ", fp);
12682       fputs(port_buf, fp);
12683       fputs(" ", fp);
12684       fputs(buf, fp);
12685 
12686       fclose(fp);
12687    }
12688 }

static int cl_dequeue_chan ( struct chan_list chan  )  [static]

Definition at line 8325 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, chan_list_unref, and chan_list::next.

Referenced by release_chan(), and release_chan_early().

08326 {
08327    int found_it;
08328    struct chan_list *help;
08329 
08330    ast_mutex_lock(&cl_te_lock);
08331    if (!cl_te) {
08332       /* List is empty. */
08333       ast_mutex_unlock(&cl_te_lock);
08334       return 0;
08335    }
08336 
08337    if (cl_te == chan) {
08338       /* What we want is the head of the list. */
08339       cl_te = cl_te->next;
08340       ast_mutex_unlock(&cl_te_lock);
08341       chan_list_unref(chan, "Removed chan_list from list head");
08342       return 1;
08343    }
08344 
08345    found_it = 0;
08346    for (help = cl_te; help->next; help = help->next) {
08347       if (help->next == chan) {
08348          /* Found it in the list. */
08349          help->next = help->next->next;
08350          found_it = 1;
08351          break;
08352       }
08353    }
08354 
08355    ast_mutex_unlock(&cl_te_lock);
08356    if (found_it) {
08357       chan_list_unref(chan, "Removed chan_list from list");
08358    }
08359    return found_it;
08360 }

static void cl_queue_chan ( struct chan_list chan  )  [static]

Definition at line 8304 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_request().

08305 {
08306    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
08307 
08308    chan_list_ref(chan, "Adding chan_list to list");
08309    ast_mutex_lock(&cl_te_lock);
08310    chan->next = NULL;
08311    if (!cl_te) {
08312       /* List is empty, make head of list. */
08313       cl_te = chan;
08314    } else {
08315       struct chan_list *help;
08316 
08317       /* Put at end of list. */
08318       for (help = cl_te; help->next; help = help->next) {
08319       }
08320       help->next = chan;
08321    }
08322    ast_mutex_unlock(&cl_te_lock);
08323 }

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

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

05629 {
05630    if (a->n) {
05631       return NULL;
05632    }
05633 
05634    switch (a->pos) {
05635    case 4:
05636       if (a->word[0] == 'p') {
05637          return ast_strdup("port");
05638       } else if (a->word[0] == 'o') {
05639          return ast_strdup("only");
05640       }
05641       break;
05642    case 6:
05643       if (a->word[0] == 'o') {
05644          return ast_strdup("only");
05645       }
05646       break;
05647    }
05648    return NULL;
05649 }

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

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

05652 {
05653    char buffer[BUFFERSIZE];
05654    enum misdn_cfg_elements elem;
05655    int wordlen = strlen(a->word);
05656    int which = 0;
05657    int port = 0;
05658 
05659    switch (a->pos) {
05660    case 3:
05661       if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n)) {
05662          return ast_strdup("description");
05663       }
05664       if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n)) {
05665          return ast_strdup("descriptions");
05666       }
05667       if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n)) {
05668          return ast_strdup("0");
05669       }
05670       while ((port = misdn_cfg_get_next_port(port)) != -1) {
05671          snprintf(buffer, sizeof(buffer), "%d", port);
05672          if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
05673             return ast_strdup(buffer);
05674          }
05675       }
05676       break;
05677    case 4:
05678       if (strstr(a->line, "description ")) {
05679          for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
05680             if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) {
05681                continue;
05682             }
05683             misdn_cfg_get_name(elem, buffer, sizeof(buffer));
05684             if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
05685                if (++which > a->n) {
05686                   return ast_strdup(buffer);
05687                }
05688             }
05689          }
05690       } else if (strstr(a->line, "descriptions ")) {
05691          if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n)) {
05692             return ast_strdup("general");
05693          }
05694          if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n)) {
05695             return ast_strdup("ports");
05696          }
05697       }
05698       break;
05699    }
05700    return NULL;
05701 }

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

05787 {
05788    struct misdn_bchannel *bc = ch->bc;
05789    int len = ch->jb_len;
05790    int threshold = ch->jb_upper_threshold;
05791 
05792    chan_misdn_log(5, bc->port, "config_jb: Called\n");
05793 
05794    if (!len) {
05795       chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
05796       bc->nojitter = 1;
05797    } else {
05798       if (len <= 100 || len > 8000) {
05799          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
05800          len = 1000;
05801       }
05802 
05803       if (threshold > len) {
05804          chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
05805       }
05806 
05807       if (ch->jb) {
05808          cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
05809          misdn_jb_destroy(ch->jb);
05810          ch->jb = NULL;
05811       }
05812 
05813       ch->jb = misdn_jb_init(len, threshold);
05814 
05815       if (!ch->jb) {
05816          bc->nojitter = 1;
05817       }
05818    }
05819 }

void debug_numtype ( int  port,
int  numtype,
char *  type 
)

Definition at line 5822 of file chan_misdn.c.

References chan_misdn_log(), NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.

Referenced by misdn_call(), misdn_get_connected_line(), and read_config().

05823 {
05824    switch (numtype) {
05825    case NUMTYPE_UNKNOWN:
05826       chan_misdn_log(2, port, " --> %s: Unknown\n", type);
05827       break;
05828    case NUMTYPE_INTERNATIONAL:
05829       chan_misdn_log(2, port, " --> %s: International\n", type);
05830       break;
05831    case NUMTYPE_NATIONAL:
05832       chan_misdn_log(2, port, " --> %s: National\n", type);
05833       break;
05834    case NUMTYPE_NETWORK_SPECIFIC:
05835       chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
05836       break;
05837    case NUMTYPE_SUBSCRIBER:
05838       chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
05839       break;
05840    case NUMTYPE_ABBREVIATED:
05841       chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
05842       break;
05843       /* Maybe we should cut off the prefix if present ? */
05844    default:
05845       chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
05846       break;
05847    }
05848 }

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

Definition at line 7624 of file chan_misdn.c.

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

Referenced by wait_for_digits().

07625 {
07626    struct ast_channel *ast = cl->ast;
07627    int nd = 0;
07628 
07629    if (!ast) {
07630       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
07631       return -1;
07632    }
07633 
07634    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
07635 
07636    if (nd) {
07637       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
07638       return 0;
07639    }
07640 
07641    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
07642 
07643    cl->ts = ast_get_indication_tone(ast->zone, "dial");
07644 
07645    if (cl->ts) {
07646       cl->notxtone = 0;
07647       cl->norxtone = 0;
07648       /* This prods us in misdn_write */
07649       ast_playtones_start(ast, 0, cl->ts->data, 0);
07650    }
07651 
07652    return 0;
07653 }

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

Definition at line 8617 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(), misdn_bchannel::caller, ast_channel::caller, chan_misdn_log(), 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_party_caller::id, ast_frame_subclass::integer, ast_frame::mallocd, MISDN_ASTERISK_TECH_PVT, MISDN_DIALING, MISDN_INCOMING_SETUP, misdn_lib_is_ptp(), misdn_lib_send_event(), ast_party_id::name, chan_list::noautorespond_on_setup, misdn_bchannel::nt, misdn_party_id::number, ast_party_id::number, 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, ast_party_number::str, ast_party_name::str, ast_frame::subclass, ast_party_number::valid, and ast_party_name::valid.

Referenced by cb_events().

08618 {
08619    char *predial;
08620    struct ast_frame fr;
08621 
08622    predial = ast_strdupa(ast->exten);
08623 
08624    ch->state = MISDN_DIALING;
08625 
08626    if (!ch->noautorespond_on_setup) {
08627       if (bc->nt) {
08628          misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08629       } else {
08630          if (misdn_lib_is_ptp(bc->port)) {
08631             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08632          } else {
08633             misdn_lib_send_event(bc, EVENT_PROCEEDING);
08634          }
08635       }
08636    } else {
08637       ch->state = MISDN_INCOMING_SETUP;
08638    }
08639 
08640    chan_misdn_log(1, bc->port,
08641       "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
08642       ast->context,
08643       ast->exten,
08644       (ast->caller.id.name.valid && ast->caller.id.name.str)
08645          ? ast->caller.id.name.str : "",
08646       (ast->caller.id.number.valid && ast->caller.id.number.str)
08647          ? ast->caller.id.number.str : "");
08648 
08649    strcpy(ast->exten, "s");
08650 
08651    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
08652       ast = NULL;
08653       bc->out_cause = AST_CAUSE_UNALLOCATED;
08654       hangup_chan(ch, bc);
08655       hanguptone_indicate(ch);
08656 
08657       misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
08658    }
08659 
08660 
08661    while (!ast_strlen_zero(predial)) {
08662       fr.frametype = AST_FRAME_DTMF;
08663       fr.subclass.integer = *predial;
08664       fr.src = NULL;
08665       fr.data.ptr = NULL;
08666       fr.datalen = 0;
08667       fr.samples = 0;
08668       fr.mallocd = 0;
08669       fr.offset = 0;
08670       fr.delivery = ast_tv(0,0);
08671 
08672       if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
08673          ast_queue_frame(ch->ast, &fr);
08674       }
08675       predial++;
08676    }
08677 }

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

Definition at line 3430 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_facility_ie_handler().

03431 {
03432    char buf[128];
03433 
03434    if (!bc->AOCD_need_export || !ast) {
03435       return;
03436    }
03437 
03438    if (originator == ORG_AST) {
03439       ast = ast_bridged_channel(ast);
03440       if (!ast) {
03441          return;
03442       }
03443    }
03444 
03445    switch (bc->AOCDtype) {
03446    case Fac_AOCDCurrency:
03447       pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
03448       if (bc->AOCD.currency.chargeNotAvailable) {
03449          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
03450       } else {
03451          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
03452          if (bc->AOCD.currency.freeOfCharge) {
03453             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
03454          } else {
03455             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
03456             if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
03457                pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
03458                if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) {
03459                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
03460                }
03461             }
03462          }
03463       }
03464       break;
03465    case Fac_AOCDChargingUnit:
03466       pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
03467       if (bc->AOCD.chargingUnit.chargeNotAvailable) {
03468          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
03469       } else {
03470          pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
03471          if (bc->AOCD.chargingUnit.freeOfCharge) {
03472             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
03473          } else {
03474             pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
03475             if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
03476                pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
03477                if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) {
03478                   pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
03479                }
03480             }
03481          }
03482       }
03483       break;
03484    default:
03485       break;
03486    }
03487 
03488    bc->AOCD_need_export = 0;
03489 }

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

08770 {
08771    char tmp[32];
08772 
08773    /*
08774     * The only use for MISDN_PID is if there is a problem and you
08775     * have to use the "misdn restart pid" CLI command.  Otherwise,
08776     * the pid is not used by anyone.  The internal use of MISDN_PID
08777     * has been deleted.
08778     */
08779    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
08780    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
08781    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
08782 
08783    if (bc->sending_complete) {
08784       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
08785       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
08786    }
08787 
08788    if (bc->urate) {
08789       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
08790       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
08791    }
08792 
08793    if (bc->uulen) {
08794       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
08795    }
08796 
08797    if (!ast_strlen_zero(bc->keypad)) {
08798       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
08799    }
08800 }

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

Returns a reference to the found chan_list.

Definition at line 8186 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, chan_list::bc, misdn_bchannel::caller, chan_list_ref, chan_misdn_log(), misdn_bchannel::dialed, misdn_party_id::name, chan_list::next, misdn_party_id::number, misdn_party_dialing::number, and misdn_bchannel::port.

Referenced by cb_events(), and chan_misdn_jb_empty().

08187 {
08188    struct chan_list *help;
08189 
08190    ast_mutex_lock(&cl_te_lock);
08191    for (help = cl_te; help; help = help->next) {
08192       if (help->bc == bc) {
08193          chan_list_ref(help, "Found chan_list by bc");
08194          ast_mutex_unlock(&cl_te_lock);
08195          return help;
08196       }
08197    }
08198    ast_mutex_unlock(&cl_te_lock);
08199 
08200    chan_misdn_log(6, bc->port,
08201       "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08202       bc->dialed.number,
08203       bc->caller.name,
08204       bc->caller.number);
08205 
08206    return NULL;
08207 }

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

Definition at line 8278 of file chan_misdn.c.

References chan_list::ast, ast_mutex_lock, ast_mutex_unlock, chan_list::bc, chan_list_ref, 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().

08279 {
08280    struct chan_list *list;
08281 
08282    ast_mutex_lock(&cl_te_lock);
08283    for (list = cl_te; list; list = list->next) {
08284       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
08285          && list->ast) {
08286          switch (list->state) {
08287          case MISDN_PROCEEDING:
08288          case MISDN_PROGRESS:
08289          case MISDN_ALERTING:
08290          case MISDN_CONNECTED:
08291             chan_list_ref(list, "Found chan_list hold active call");
08292             ast_mutex_unlock(&cl_te_lock);
08293             return list;
08294          default:
08295             break;
08296          }
08297       }
08298    }
08299    ast_mutex_unlock(&cl_te_lock);
08300    return NULL;
08301 }

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

Returns a reference to the found chan_list.

Definition at line 8210 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, misdn_bchannel::caller, chan_list_ref, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, misdn_bchannel::dialed, chan_list::hold, MISDN_HOLD_ACTIVE, misdn_party_id::name, chan_list::next, misdn_party_id::number, misdn_party_dialing::number, hold_info::port, misdn_bchannel::port, misdn_bchannel::pri, and hold_info::state.

Referenced by cb_events().

08211 {
08212    struct chan_list *help;
08213 
08214    if (bc->pri) {
08215       return NULL;
08216    }
08217 
08218    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d dialed:%s caller:\"%s\" <%s>\n",
08219       bc->channel,
08220       bc->dialed.number,
08221       bc->caller.name,
08222       bc->caller.number);
08223    ast_mutex_lock(&cl_te_lock);
08224    for (help = cl_te; help; help = help->next) {
08225       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
08226       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
08227          chan_list_ref(help, "Found chan_list hold call");
08228          ast_mutex_unlock(&cl_te_lock);
08229          return help;
08230       }
08231    }
08232    ast_mutex_unlock(&cl_te_lock);
08233    chan_misdn_log(6, bc->port,
08234       "$$$ find_hold_call: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08235       bc->dialed.number,
08236       bc->caller.name,
08237       bc->caller.number);
08238 
08239    return NULL;
08240 }

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

Returns a reference to the found chan_list.

Definition at line 8244 of file chan_misdn.c.

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

Referenced by cb_events().

08245 {
08246    struct chan_list *help;
08247 
08248    ast_mutex_lock(&cl_te_lock);
08249    for (help = cl_te; help; help = help->next) {
08250       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
08251          chan_list_ref(help, "Found chan_list hold call l3");
08252          ast_mutex_unlock(&cl_te_lock);
08253          return help;
08254       }
08255    }
08256    ast_mutex_unlock(&cl_te_lock);
08257 
08258    return NULL;
08259 }

static void free_robin_list ( void   )  [static]

Definition at line 601 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

00602 {
00603    struct robin_list *r;
00604    struct robin_list *next;
00605 
00606    for (r = robin, robin = NULL; r; r = next) {
00607       next = r->next;
00608       ast_free(r->group);
00609       ast_free(r);
00610    }
00611 }

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

Returns a reference to the found chan_list.

Definition at line 740 of file chan_misdn.c.

References chan_list::ast, ast_mutex_lock, ast_mutex_unlock, chan_list_ref, and chan_list::next.

Referenced by misdn_bridge().

00741 {
00742    struct chan_list *tmp;
00743 
00744    ast_mutex_lock(&cl_te_lock);
00745    for (tmp = cl_te; tmp; tmp = tmp->next) {
00746       if (tmp->ast == ast) {
00747          chan_list_ref(tmp, "Found chan_list by ast");
00748          ast_mutex_unlock(&cl_te_lock);
00749          return tmp;
00750       }
00751    }
00752    ast_mutex_unlock(&cl_te_lock);
00753 
00754    return NULL;
00755 }

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

Returns a reference to the found chan_list.

Definition at line 758 of file chan_misdn.c.

References chan_list::ast, ast_mutex_lock, ast_mutex_unlock, chan_list_ref, 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().

00759 {
00760    struct chan_list *tmp;
00761 
00762    ast_mutex_lock(&cl_te_lock);
00763    for (tmp = cl_te; tmp; tmp = tmp->next) {
00764       if (tmp->ast && strcmp(tmp->ast->name, name) == 0) {
00765          chan_list_ref(tmp, "Found chan_list by ast name");
00766          ast_mutex_unlock(&cl_te_lock);
00767          return tmp;
00768       }
00769    }
00770    ast_mutex_unlock(&cl_te_lock);
00771 
00772    return NULL;
00773 }

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

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

00614 {
00615    struct robin_list *new;
00616    struct robin_list *iter = robin;
00617    for (; iter; iter = iter->next) {
00618       if (!strcasecmp(iter->group, group)) {
00619          return iter;
00620       }
00621    }
00622    new = ast_calloc(1, sizeof(*new));
00623    if (!new) {
00624       return NULL;
00625    }
00626    new->group = ast_strdup(group);
00627    if (!new->group) {
00628       ast_free(new);
00629       return NULL;
00630    }
00631    new->channel = 1;
00632    if (robin) {
00633       new->next = robin;
00634       robin->prev = new;
00635    }
00636    robin = new;
00637    return robin;
00638 }

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

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

03800 {
03801    switch (cmd) {
03802    case CLI_INIT:
03803       e->command = "misdn port block";
03804       e->usage =
03805          "Usage: misdn port block <port>\n"
03806          "       Block the specified port by <port>.\n";
03807       return NULL;
03808    case CLI_GENERATE:
03809       return NULL;
03810    }
03811 
03812    if (a->argc != 4) {
03813       return CLI_SHOWUSAGE;
03814    }
03815 
03816    misdn_lib_port_block(atoi(a->argv[3]));
03817 
03818    return CLI_SUCCESS;
03819 }

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

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

03910 {
03911    switch (cmd) {
03912    case CLI_INIT:
03913       e->command = "misdn port down";
03914       e->usage =
03915          "Usage: misdn port down <port>\n"
03916          "       Try to deactivate the L1 on the given port.\n";
03917       return NULL;
03918    case CLI_GENERATE:
03919       return NULL;
03920    }
03921 
03922    if (a->argc != 4) {
03923       return CLI_SHOWUSAGE;
03924    }
03925 
03926    misdn_lib_get_port_down(atoi(a->argv[3]));
03927 
03928    return CLI_SUCCESS;
03929 }

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

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

03822 {
03823    switch (cmd) {
03824    case CLI_INIT:
03825       e->command = "misdn port unblock";
03826       e->usage =
03827          "Usage: misdn port unblock <port>\n"
03828          "       Unblock the port specified by <port>.\n";
03829       return NULL;
03830    case CLI_GENERATE:
03831       return NULL;
03832    }
03833 
03834    if (a->argc != 4) {
03835       return CLI_SHOWUSAGE;
03836    }
03837 
03838    misdn_lib_port_unblock(atoi(a->argv[3]));
03839 
03840    return CLI_SUCCESS;
03841 }

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

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

03888 {
03889    switch (cmd) {
03890    case CLI_INIT:
03891       e->command = "misdn port up";
03892       e->usage =
03893          "Usage: misdn port up <port>\n"
03894          "       Try to establish L1 on the given port.\n";
03895       return NULL;
03896    case CLI_GENERATE:
03897       return NULL;
03898    }
03899 
03900    if (a->argc != 4) {
03901       return CLI_SHOWUSAGE;
03902    }
03903 
03904    misdn_lib_get_port_up(atoi(a->argv[3]));
03905 
03906    return CLI_SUCCESS;
03907 }

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

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

04114 {
04115    switch (cmd) {
04116    case CLI_INIT:
04117       e->command = "misdn reload";
04118       e->usage =
04119          "Usage: misdn reload\n"
04120          "       Reload internal mISDN config, read from the config\n"
04121          "       file.\n";
04122       return NULL;
04123    case CLI_GENERATE:
04124       return NULL;
04125    }
04126 
04127    if (a->argc != 2) {
04128       return CLI_SHOWUSAGE;
04129    }
04130 
04131    ast_cli(a->fd, "Reloading mISDN configuration\n");
04132    reload_config();
04133    return CLI_SUCCESS;
04134 }

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

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

03866 {
03867    switch (cmd) {
03868    case CLI_INIT:
03869       e->command = "misdn restart pid";
03870       e->usage =
03871          "Usage: misdn restart pid <pid>\n"
03872          "       Restart the given pid\n";
03873       return NULL;
03874    case CLI_GENERATE:
03875       return NULL;
03876    }
03877 
03878    if (a->argc != 4) {
03879       return CLI_SHOWUSAGE;
03880    }
03881 
03882    misdn_lib_pid_restart(atoi(a->argv[3]));
03883 
03884    return CLI_SUCCESS;
03885 }

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

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

03844 {
03845    switch (cmd) {
03846    case CLI_INIT:
03847       e->command = "misdn restart port";
03848       e->usage =
03849          "Usage: misdn restart port <port>\n"
03850          "       Restart the given port.\n";
03851       return NULL;
03852    case CLI_GENERATE:
03853       return NULL;
03854    }
03855 
03856    if (a->argc != 4) {
03857       return CLI_SHOWUSAGE;
03858    }
03859 
03860    misdn_lib_port_restart(atoi(a->argv[3]));
03861 
03862    return CLI_SUCCESS;
03863 }

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

Definition at line 5478 of file chan_misdn.c.

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

05479 {
05480    const char *channame;
05481    const char *msg;
05482    struct chan_list *tmp;
05483    int i, msglen;
05484 
05485    switch (cmd) {
05486    case CLI_INIT:
05487       e->command = "misdn send digit";
05488       e->usage =
05489          "Usage: misdn send digit <channel> \"<msg>\" \n"
05490          "       Send <digit> to <channel> as DTMF Tone\n"
05491          "       when channel is a mISDN channel\n";
05492       return NULL;
05493    case CLI_GENERATE:
05494       return complete_ch(a);
05495    }
05496 
05497    if (a->argc != 5) {
05498       return CLI_SHOWUSAGE;
05499    }
05500 
05501    channame = a->argv[3];
05502    msg = a->argv[4];
05503    msglen = strlen(msg);
05504 
05505    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
05506 
05507    tmp = get_chan_by_ast_name(channame);
05508    if (!tmp) {
05509       ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
05510       return CLI_SUCCESS;
05511    }
05512 #if 1
05513    for (i = 0; i < msglen; i++) {
05514       if (!tmp->ast) {
05515          break;
05516       }
05517       ast_cli(a->fd, "Sending: %c\n", msg[i]);
05518       send_digit_to_chan(tmp, msg[i]);
05519       /* res = ast_safe_sleep(tmp->ast, 250); */
05520       usleep(250000);
05521       /* res = ast_waitfor(tmp->ast,100); */
05522    }
05523 #else
05524    if (tmp->ast) {
05525       ast_dtmf_stream(tmp->ast, NULL, msg, 250);
05526    }
05527 #endif
05528    chan_list_unref(tmp, "Digit(s) sent");
05529 
05530    return CLI_SUCCESS;
05531 }

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

Definition at line 5580 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), chan_list::bc, chan_list_unref, 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(), and ast_cli_entry::usage.

05581 {
05582    const char *channame;
05583    const char *msg;
05584    struct chan_list *tmp;
05585 
05586    switch (cmd) {
05587    case CLI_INIT:
05588       e->command = "misdn send display";
05589       e->usage =
05590          "Usage: misdn send display <channel> \"<msg>\" \n"
05591          "       Send <msg> to <channel> as Display Message\n"
05592          "       when channel is a mISDN channel\n";
05593       return NULL;
05594    case CLI_GENERATE:
05595       return complete_ch(a);
05596    }
05597 
05598    if (a->argc != 5) {
05599       return CLI_SHOWUSAGE;
05600    }
05601 
05602    channame = a->argv[3];
05603    msg = a->argv[4];
05604 
05605    ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
05606 
05607    tmp = get_chan_by_ast_name(channame);
05608    if (tmp && tmp->bc) {
05609       ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
05610       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
05611       chan_list_unref(tmp, "Done sending display");
05612    } else {
05613       if (tmp) {
05614          chan_list_unref(tmp, "Display failed");
05615       }
05616       ast_cli(a->fd, "No such channel %s\n", channame);
05617       return CLI_SUCCESS;
05618    }
05619 
05620    return CLI_SUCCESS;
05621 }

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

Definition at line 5152 of file chan_misdn.c.

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

05153 {
05154    const char *channame;
05155    const char *nr;
05156    struct chan_list *tmp;
05157    int port;
05158    const char *served_nr;
05159    struct misdn_bchannel dummy, *bc=&dummy;
05160    unsigned max_len;
05161 
05162    switch (cmd) {
05163    case CLI_INIT:
05164       e->command = "misdn send facility";
05165       e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
05166       "\t type is one of:\n"
05167       "\t - calldeflect\n"
05168 #if defined(AST_MISDN_ENHANCEMENTS)
05169       "\t - callrerouting\n"
05170 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
05171       "\t - CFActivate\n"
05172       "\t - CFDeactivate\n";
05173 
05174       return NULL;
05175    case CLI_GENERATE:
05176       return complete_ch(a);
05177    }
05178 
05179    if (a->argc < 5) {
05180       return CLI_SHOWUSAGE;
05181    }
05182 
05183    if (strstr(a->argv[3], "calldeflect")) {
05184       if (a->argc < 6) {
05185          ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
05186          return 0;
05187       }
05188       channame = a->argv[4];
05189       nr = a->argv[5];
05190 
05191       ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
05192       tmp = get_chan_by_ast_name(channame);
05193       if (!tmp) {
05194          ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
05195          return 0;
05196       }
05197       ao2_lock(tmp);
05198 
05199 #if defined(AST_MISDN_ENHANCEMENTS)
05200       max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
05201       if (max_len < strlen(nr)) {
05202          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05203             nr, channame, max_len);
05204          ao2_unlock(tmp);
05205          chan_list_unref(tmp, "Number too long");
05206          return 0;
05207       }
05208       tmp->bc->fac_out.Function = Fac_CallDeflection;
05209       tmp->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
05210       tmp->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
05211       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
05212       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
05213       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
05214       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(nr);
05215       strcpy((char *) tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, nr);
05216       tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
05217 
05218 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
05219 
05220       max_len = sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
05221       if (max_len < strlen(nr)) {
05222          ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05223             nr, channame, max_len);
05224          ao2_unlock(tmp);
05225          chan_list_unref(tmp, "Number too long");
05226          return 0;
05227       }
05228       tmp->bc->fac_out.Function = Fac_CD;
05229       tmp->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
05230       //tmp->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
05231       strcpy((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr);
05232 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
05233 
05234       /* Send message */
05235       print_facility(&tmp->bc->fac_out, tmp->bc);
05236       ao2_unlock(tmp);
05237       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05238       chan_list_unref(tmp, "Send facility complete");
05239 #if defined(AST_MISDN_ENHANCEMENTS)
05240    } else if (strstr(a->argv[3], "callrerouteing") || strstr(a->argv[3], "callrerouting")) {
05241       if (a->argc < 6) {
05242          ast_verbose("callrerouting requires 1 arg: ToNumber\n\n");
05243          return 0;
05244       }
05245       channame = a->argv[4];
05246       nr = a->argv[5];
05247 
05248       ast_verbose("Sending Callrerouting (%s) to %s\n", nr, channame);
05249       tmp = get_chan_by_ast_name(channame);
05250       if (!tmp) {
05251          ast_verbose("Sending Call Rerouting with nr %s to %s failed: Channel does not exist.\n", nr, channame);
05252          return 0;
05253       }
05254       ao2_lock(tmp);
05255 
05256       max_len = sizeof(tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
05257       if (max_len < strlen(nr)) {
05258          ast_verbose("Sending Call Rerouting with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05259             nr, channame, max_len);
05260          ao2_unlock(tmp);
05261          chan_list_unref(tmp, "Number too long");
05262          return 0;
05263       }
05264       tmp->bc->fac_out.Function = Fac_CallRerouteing;
05265       tmp->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
05266       tmp->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
05267 
05268       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
05269       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
05270 
05271       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
05272       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(nr);
05273       strcpy((char *) tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, nr);
05274       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
05275 
05276       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
05277 
05278       /* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
05279       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
05280       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
05281       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
05282       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
05283       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
05284       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
05285       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
05286 
05287       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
05288       tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
05289 
05290       /* Send message */
05291       print_facility(&tmp->bc->fac_out, tmp->bc);
05292       ao2_unlock(tmp);
05293       misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05294       chan_list_unref(tmp, "Send facility complete");
05295 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
05296    } else if (strstr(a->argv[3], "CFActivate")) {
05297       if (a->argc < 7) {
05298          ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
05299          return 0;
05300       }
05301       port = atoi(a->argv[4]);
05302       served_nr = a->argv[5];
05303       nr = a->argv[6];
05304 
05305       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05306 
05307       ast_verbose("Sending CFActivate  Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
05308 
05309 #if defined(AST_MISDN_ENHANCEMENTS)
05310       bc->fac_out.Function = Fac_ActivationDiversion;
05311       bc->fac_out.u.ActivationDiversion.InvokeID = ++misdn_invoke_id;
05312       bc->fac_out.u.ActivationDiversion.ComponentType = FacComponent_Invoke;
05313       bc->fac_out.u.ActivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
05314       bc->fac_out.u.ActivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
05315       ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number,
05316          served_nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number));
05317       bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
05318          strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number);
05319       bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
05320       ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number,
05321          nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number));
05322       bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber =
05323          strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number);
05324       bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 0;/* unknown */
05325       bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Subaddress.Length = 0;
05326 
05327 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
05328 
05329       bc->fac_out.Function = Fac_CFActivate;
05330       bc->fac_out.u.CFActivate.BasicService = 0; /* All Services */
05331       bc->fac_out.u.CFActivate.Procedure = 0; /* Unconditional */
05332       ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
05333       ast_copy_string((char *) bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
05334 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
05335 
05336       /* Send message */
05337       print_facility(&bc->fac_out, bc);
05338       misdn_lib_send_event(bc, EVENT_FACILITY);
05339    } else if (strstr(a->argv[3], "CFDeactivate")) {
05340       if (a->argc < 6) {
05341          ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
05342          return 0;
05343       }
05344       port = atoi(a->argv[4]);
05345       served_nr = a->argv[5];
05346 
05347       misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05348       ast_verbose("Sending CFDeactivate  Port:(%d) FromNr. (%s)\n", port, served_nr);
05349 
05350 #if defined(AST_MISDN_ENHANCEMENTS)
05351       bc->fac_out.Function = Fac_DeactivationDiversion;
05352       bc->fac_out.u.DeactivationDiversion.InvokeID = ++misdn_invoke_id;
05353       bc->fac_out.u.DeactivationDiversion.ComponentType = FacComponent_Invoke;
05354       bc->fac_out.u.DeactivationDiversion.Component.Invoke.BasicService = 0;/* allServices */
05355       bc->fac_out.u.DeactivationDiversion.Component.Invoke.Procedure = 0;/* cfu (Call Forward Unconditional) */
05356       ast_copy_string((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number,
05357          served_nr, sizeof(bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number));
05358       bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
05359          strlen((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number);
05360       bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Type = 0;/* unknown */
05361 
05362 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
05363 
05364       bc->fac_out.Function = Fac_CFDeactivate;
05365       bc->fac_out.u.CFDeactivate.BasicService = 0; /* All Services */
05366       bc->fac_out.u.CFDeactivate.Procedure = 0; /* Unconditional */
05367       ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
05368 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
05369 
05370       /* Send message */
05371       print_facility(&bc->fac_out, bc);
05372       misdn_lib_send_event(bc, EVENT_FACILITY);
05373 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
05374    } else if (strstr(a->argv[3], "test")) {
05375       int msg_number;
05376 
05377       if (a->argc < 5) {
05378          ast_verbose("test (<port> [<msg#>]) | (<channel-name> <msg#>)\n\n");
05379          return 0;
05380       }
05381       port = atoi(a->argv[4]);
05382 
05383       channame = a->argv[4];
05384       tmp = get_chan_by_ast_name(channame);
05385       if (tmp) {
05386          /* We are going to send this FACILITY message out on an existing connection */
05387          msg_number = atoi(a->argv[5]);
05388          if (msg_number < ARRAY_LEN(Fac_Msgs)) {
05389             ao2_lock(tmp);
05390             tmp->bc->fac_out = Fac_Msgs[msg_number];
05391 
05392             /* Send message */
05393             print_facility(&tmp->bc->fac_out, tmp->bc);
05394             ao2_unlock(tmp);
05395             misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05396          } else {
05397             ast_verbose("test <channel-name> <msg#>\n\n");
05398          }
05399          chan_list_unref(tmp, "Facility test done");
05400       } else if (a->argc < 6) {
05401          for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) {
05402             misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05403             bc->fac_out = Fac_Msgs[msg_number];
05404 
05405             /* Send message */
05406             print_facility(&bc->fac_out, bc);
05407             misdn_lib_send_event(bc, EVENT_FACILITY);
05408             sleep(1);
05409          }
05410       } else {
05411          msg_number = atoi(a->argv[5]);
05412          if (msg_number < ARRAY_LEN(Fac_Msgs)) {
05413             misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05414             bc->fac_out = Fac_Msgs[msg_number];
05415 
05416             /* Send message */
05417             print_facility(&bc->fac_out, bc);
05418             misdn_lib_send_event(bc, EVENT_FACILITY);
05419          } else {
05420             ast_verbose("test <port> [<msg#>]\n\n");
05421          }
05422       }
05423    } else if (strstr(a->argv[3], "register")) {
05424       if (a->argc < 5) {
05425          ast_verbose("register <port>\n\n");
05426          return 0;
05427       }
05428       port = atoi(a->argv[4]);
05429 
05430       bc = misdn_lib_get_register_bc(port);
05431       if (!bc) {
05432          ast_verbose("Could not allocate REGISTER bc struct\n\n");
05433          return 0;
05434       }
05435       bc->fac_out = Fac_Msgs[45];
05436 
05437       /* Send message */
05438       print_facility(&bc->fac_out, bc);
05439       misdn_lib_send_event(bc, EVENT_REGISTER);
05440 #endif   /* defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES) */
05441    }
05442 
05443    return CLI_SUCCESS;
05444 }

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

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

05447 {
05448    int port;
05449    int channel;
05450 
05451    switch (cmd) {
05452    case CLI_INIT:
05453       e->command = "misdn send restart";
05454       e->usage =
05455          "Usage: misdn send restart [port [channel]]\n"
05456          "       Send a restart for every bchannel on the given port.\n";
05457       return NULL;
05458    case CLI_GENERATE:
05459       return NULL;
05460    }
05461 
05462    if (a->argc < 4 || a->argc > 5) {
05463       return CLI_SHOWUSAGE;
05464    }
05465 
05466    port = atoi(a->argv[3]);
05467 
05468    if (a->argc == 5) {
05469       channel = atoi(a->argv[4]);
05470       misdn_lib_send_restart(port, channel);
05471    } else {
05472       misdn_lib_send_restart(port, -1);
05473    }
05474 
05475    return CLI_SUCCESS;
05476 }

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

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

03777 {
03778    switch (cmd) {
03779    case CLI_INIT:
03780       e->command = "misdn set crypt debug";
03781       e->usage =
03782          "Usage: misdn set crypt debug <level>\n"
03783          "       Set the crypt debug level of the mISDN channel. Level\n"
03784          "       must be 1 or 2.\n";
03785       return NULL;
03786    case CLI_GENERATE:
03787       return NULL;
03788    }
03789 
03790    if (a->argc != 5) {
03791       return CLI_SHOWUSAGE;
03792    }
03793 
03794    /* XXX Is this supposed to not do anything? XXX */
03795 
03796    return CLI_SUCCESS;
03797 }

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

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

03690 {
03691    int level;
03692 
03693    switch (cmd) {
03694    case CLI_INIT:
03695       e->command = "misdn set debug [on|off]";
03696       e->usage =
03697          "Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
03698          "       Set the debug level of the mISDN channel.\n";
03699       return NULL;
03700    case CLI_GENERATE:
03701       return complete_debug_port(a);
03702    }
03703 
03704    if (a->argc < 4 || a->argc > 7) {
03705       return CLI_SHOWUSAGE;
03706    }
03707 
03708    if (!strcasecmp(a->argv[3], "on")) {
03709       level = 1;
03710    } else if (!strcasecmp(a->argv[3], "off")) {
03711       level = 0;
03712    } else if (isdigit(a->argv[3][0])) {
03713       level = atoi(a->argv[3]);
03714    } else {
03715       return CLI_SHOWUSAGE;
03716    }
03717 
03718    switch (a->argc) {
03719    case 4:
03720    case 5:
03721       {
03722          int i;
03723          int only = 0;
03724          if (a->argc == 5) {
03725             if (strncasecmp(a->argv[4], "only", strlen(a->argv[4]))) {
03726                return CLI_SHOWUSAGE;
03727             } else {
03728                only = 1;
03729             }
03730          }
03731 
03732          for (i = 0; i <= max_ports; i++) {
03733             misdn_debug[i] = level;
03734             misdn_debug_only[i] = only;
03735          }
03736          ast_cli(a->fd, "changing debug level for all ports to %d%s\n", misdn_debug[0], only ? " (only)" : "");
03737       }
03738       break;
03739    case 6:
03740    case 7:
03741       {
03742          int port;
03743          if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
03744             return CLI_SHOWUSAGE;
03745          port = atoi(a->argv[5]);
03746          if (port <= 0 || port > max_ports) {
03747             switch (max_ports) {
03748             case 0:
03749                ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
03750                break;
03751             case 1:
03752                ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
03753                break;
03754             default:
03755                ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
03756             }
03757             return 0;
03758          }
03759          if (a->argc == 7) {
03760             if (strncasecmp(a->argv[6], "only", strlen(a->argv[6]))) {
03761                return CLI_SHOWUSAGE;
03762             } else {
03763                misdn_debug_only[port] = 1;
03764             }
03765          } else {
03766             misdn_debug_only[port] = 0;
03767          }
03768          misdn_debug[port] = level;
03769          ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port] ? " (only)" : "", port);
03770       }
03771    }
03772 
03773    return CLI_SUCCESS;
03774 }

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

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

04309 {
04310    switch (cmd) {
04311    case CLI_INIT:
04312       e->command = "misdn set tics";
04313       e->usage =
04314          "Usage: misdn set tics <value>\n";
04315       return NULL;
04316    case CLI_GENERATE:
04317       return NULL;
04318    }
04319 
04320    if (a->argc != 4) {
04321       return CLI_SHOWUSAGE;
04322    }
04323 
04324    /* XXX Wow, this does... a whole lot of nothing... XXX */
04325    MAXTICS = atoi(a->argv[3]);
04326 
04327    return CLI_SUCCESS;
04328 }

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

Definition at line 4272 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, chan_list::ast, ast_mutex_lock, ast_mutex_unlock, 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.

04273 {
04274    struct chan_list *help;
04275 
04276    switch (cmd) {
04277    case CLI_INIT:
04278       e->command = "misdn show channel";
04279       e->usage =
04280          "Usage: misdn show channel <channel>\n"
04281          "       Show an internal mISDN channel\n.";
04282       return NULL;
04283    case CLI_GENERATE:
04284       return complete_ch(a);
04285    }
04286 
04287    if (a->argc != 4) {
04288       return CLI_SHOWUSAGE;
04289    }
04290 
04291    ast_mutex_lock(&cl_te_lock);
04292    for (help = cl_te; help; help = help->next) {
04293       struct misdn_bchannel *bc = help->bc;
04294       struct ast_channel *ast = help->ast;
04295 
04296       if (bc && ast) {
04297          if (!strcasecmp(ast->name, a->argv[3])) {
04298             print_bc_info(a->fd, help, bc);
04299             break;
04300          }
04301       }
04302    }
04303    ast_mutex_unlock(&cl_te_lock);
04304 
04305    return CLI_SUCCESS;
04306 }

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

Definition at line 4199 of file chan_misdn.c.

References ast_cli_args::argc, chan_list::ast, ast_cli(), ast_mutex_lock, ast_mutex_unlock, chan_list::bc, ast_channel::caller, hold_info::channel, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_channel::exten, ast_cli_args::fd, chan_list::hold, ast_party_caller::id, chan_list::l3id, misdn_dump_chanlist(), MISDN_HOLD_IDLE, ast_party_id::name, chan_list::next, ast_party_id::number, misdn_bchannel::pid, hold_info::port, print_bc_info(), S_COR, hold_info::state, ast_party_number::str, ast_party_name::str, ast_cli_entry::usage, ast_party_number::valid, and ast_party_name::valid.

04200 {
04201    struct chan_list *help;
04202 
04203    switch (cmd) {
04204    case CLI_INIT:
04205       e->command = "misdn show channels";
04206       e->usage =
04207          "Usage: misdn show channels\n"
04208          "       Show the internal mISDN channel list\n";
04209       return NULL;
04210    case CLI_GENERATE:
04211       return NULL;
04212    }
04213 
04214    if (a->argc != 3) {
04215       return CLI_SHOWUSAGE;
04216    }
04217 
04218    ast_cli(a->fd, "Channel List: %p\n", cl_te);
04219 
04220    /*
04221     * Walking the list and dumping the channel information could
04222     * take awhile.  With the list locked for the duration, the
04223     * channel driver cannot process signaling messages.  However,
04224     * since this is a CLI command it should not be run very often.
04225     */
04226    ast_mutex_lock(&cl_te_lock);
04227    for (help = cl_te; help; help = help->next) {
04228       struct misdn_bchannel *bc = help->bc;
04229       struct ast_channel *ast = help->ast;
04230       if (!ast) {
04231          if (!bc) {
04232             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
04233             continue;
04234          }
04235          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
04236       }
04237 
04238       if (misdn_debug[0] > 2) {
04239          ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
04240       }
04241       if (bc) {
04242          print_bc_info(a->fd, help, bc);
04243       } else {
04244          if (help->hold.state != MISDN_HOLD_IDLE) {
04245             ast_cli(a->fd, "ITS A HELD CALL BC:\n");
04246             ast_cli(a->fd, " --> l3_id: %x\n"
04247                " --> dialed:%s\n"
04248                " --> caller:\"%s\" <%s>\n"
04249                " --> hold_port: %d\n"
04250                " --> hold_channel: %d\n",
04251                help->l3id,
04252                ast->exten,
04253                S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
04254                S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
04255                help->hold.port,
04256                help->hold.channel
04257                );
04258          } else {
04259             ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n",
04260                ast->exten,
04261                S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""));
04262          }
04263       }
04264    }
04265    ast_mutex_unlock(&cl_te_lock);
04266 
04267    misdn_dump_chanlist();
04268 
04269    return CLI_SUCCESS;
04270 }

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

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

03957 {
03958    char buffer[BUFFERSIZE];
03959    enum misdn_cfg_elements elem;
03960    int linebreak;
03961    int onlyport = -1;
03962    int ok = 0;
03963 
03964    switch (cmd) {
03965    case CLI_INIT:
03966       e->command = "misdn show config";
03967       e->usage =
03968          "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
03969          "       Use 0 for <port> to only print the general config.\n";
03970       return NULL;
03971    case CLI_GENERATE:
03972       return complete_show_config(a);
03973    }
03974 
03975    if (a->argc >= 4) {
03976       if (!strcmp(a->argv[3], "description")) {
03977          if (a->argc == 5) {
03978             enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
03979             if (elem == MISDN_CFG_FIRST) {
03980                ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
03981             } else {
03982                show_config_description(a->fd, elem);
03983             }
03984             return CLI_SUCCESS;
03985          }
03986          return CLI_SHOWUSAGE;
03987       } else if (!strcmp(a->argv[3], "descriptions")) {
03988          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
03989             for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
03990                show_config_description(a->fd, elem);
03991                ast_cli(a->fd, "\n");
03992             }
03993             ok = 1;
03994          }
03995          if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
03996             for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
03997                show_config_description(a->fd, elem);
03998                ast_cli(a->fd, "\n");
03999             }
04000             ok = 1;
04001          }
04002          return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
04003       } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
04004          ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
04005          return CLI_SHOWUSAGE;
04006       }
04007    }
04008 
04009    if (a->argc == 3 || onlyport == 0) {
04010       ast_cli(a->fd, "mISDN General-Config:\n");
04011       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
04012          misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
04013          ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04014       }
04015       ast_cli(a->fd, "\n");
04016    }
04017 
04018    if (onlyport < 0) {
04019       int port = misdn_cfg_get_next_port(0);
04020 
04021       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
04022          ast_cli(a->fd, "\n[PORT %d]\n", port);
04023          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
04024             misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
04025             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04026          }
04027          ast_cli(a->fd, "\n");
04028       }
04029    }
04030 
04031    if (onlyport > 0) {
04032       if (misdn_cfg_is_port_valid(onlyport)) {
04033          ast_cli(a->fd, "[PORT %d]\n", onlyport);
04034          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
04035             misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
04036             ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04037          }
04038          ast_cli(a->fd, "\n");
04039       } else {
04040          ast_cli(a->fd, "Port %d is not active!\n", onlyport);
04041       }
04042    }
04043 
04044    return CLI_SUCCESS;
04045 }

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

Definition at line 4390 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, ast_cli_args::fd, get_show_stack_details(), and ast_cli_entry::usage.

04391 {
04392    int port;
04393    char buf[128];
04394 
04395    switch (cmd) {
04396    case CLI_INIT:
04397       e->command = "misdn show port";
04398       e->usage =
04399          "Usage: misdn show port <port>\n"
04400          "       Show detailed information for given port.\n";
04401       return NULL;
04402    case CLI_GENERATE:
04403       return NULL;
04404    }
04405 
04406    if (a->argc != 4) {
04407       return CLI_SHOWUSAGE;
04408    }
04409 
04410    port = atoi(a->argv[3]);
04411 
04412    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
04413    get_show_stack_details(port, buf);
04414    ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
04415 
04416    return CLI_SUCCESS;
04417 }

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

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

04362 {
04363    int port;
04364 
04365    switch (cmd) {
04366    case CLI_INIT:
04367       e->command = "misdn show ports stats";
04368       e->usage =
04369          "Usage: misdn show ports stats\n"
04370          "       Show mISDNs channel's call statistics per port.\n";
04371       return NULL;
04372    case CLI_GENERATE:
04373       return NULL;
04374    }
04375 
04376    if (a->argc != 4) {
04377       return CLI_SHOWUSAGE;
04378    }
04379 
04380    ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
04381    for (port = misdn_cfg_get_next_port(0); port > 0;
04382       port = misdn_cfg_get_next_port(port)) {
04383       ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
04384    }
04385    ast_cli(a->fd, "\n");
04386 
04387    return CLI_SUCCESS;
04388 }

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

Definition at line 4330 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, get_show_stack_details(), misdn_cfg_get_next_port(), and ast_cli_entry::usage.

04331 {
04332    int port;
04333 
04334    switch (cmd) {
04335    case CLI_INIT:
04336       e->command = "misdn show stacks";
04337       e->usage =
04338          "Usage: misdn show stacks\n"
04339          "       Show internal mISDN stack_list.\n";
04340       return NULL;
04341    case CLI_GENERATE:
04342       return NULL;
04343    }
04344 
04345    if (a->argc != 3) {
04346       return CLI_SHOWUSAGE;
04347    }
04348 
04349    ast_cli(a->fd, "BEGIN STACK_LIST:\n");
04350    for (port = misdn_cfg_get_next_port(0); port > 0;
04351       port = misdn_cfg_get_next_port(port)) {
04352       char buf[128];
04353 
04354       get_show_stack_details(port, buf);
04355       ast_cli(a->fd, "  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
04356    }
04357 
04358    return CLI_SUCCESS;
04359 }

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

Definition at line 5533 of file chan_misdn.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), chan_list::bc, chan_list_unref, 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.

05534 {
05535    const char *channame;
05536    struct chan_list *tmp;
05537 
05538    switch (cmd) {
05539    case CLI_INIT:
05540       e->command = "misdn toggle echocancel";
05541       e->usage =
05542          "Usage: misdn toggle echocancel <channel>\n"
05543          "       Toggle EchoCancel on mISDN Channel.\n";
05544       return NULL;
05545    case CLI_GENERATE:
05546       return complete_ch(a);
05547    }
05548 
05549    if (a->argc != 4) {
05550       return CLI_SHOWUSAGE;
05551    }
05552 
05553    channame = a->argv[3];
05554 
05555    ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
05556 
05557    tmp = get_chan_by_ast_name(channame);
05558    if (!tmp) {
05559       ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
05560       return CLI_SUCCESS;
05561    }
05562 
05563    tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
05564 
05565    if (tmp->toggle_ec) {
05566 #ifdef MISDN_1_2
05567       update_pipeline_config(tmp->bc);
05568 #else
05569       update_ec_config(tmp->bc);
05570 #endif
05571       manager_ec_enable(tmp->bc);
05572    } else {
05573       manager_ec_disable(tmp->bc);
05574    }
05575    chan_list_unref(tmp, "Done toggling echo cancel");
05576 
05577    return CLI_SUCCESS;
05578 }

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

Definition at line 8374 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(), local_hangup(), and start_pbx().

08375 {
08376    int port = bc->port;
08377 
08378    if (!ch) {
08379       cb_log(1, port, "Cannot hangup chan, no ch\n");
08380       return;
08381    }
08382 
08383    cb_log(5, port, "hangup_chan called\n");
08384 
08385    if (ch->need_hangup) {
08386       cb_log(2, port, " --> hangup\n");
08387       ch->need_hangup = 0;
08388       ch->need_queue_hangup = 0;
08389       if (ch->ast && send_cause2ast(ch->ast, bc, ch)) {
08390          ast_hangup(ch->ast);
08391       }
08392       return;
08393    }
08394 
08395    if (!ch->need_queue_hangup) {
08396       cb_log(2, port, " --> No need to queue hangup\n");
08397       return;
08398    }
08399 
08400    ch->need_queue_hangup = 0;
08401    if (ch->ast) {
08402       if (send_cause2ast(ch->ast, bc, ch)) {
08403          ast_queue_hangup_with_cause(ch->ast, bc->cause);
08404          cb_log(2, port, " --> queue_hangup\n");
08405       }
08406    } else {
08407       cb_log(1, port, "Cannot hangup chan, no ast\n");
08408    }
08409 }

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

References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), misdn_bchannel::keypad, LOG_NOTICE, pbx_builtin_getvar_helper(), misdn_bchannel::sending_complete, misdn_bchannel::uu, and misdn_bchannel::uulen.

Referenced by misdn_call().

08745 {
08746    const char *tmp;
08747 
08748    ast_channel_lock(chan);
08749    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
08750    if (tmp && (atoi(tmp) == 1)) {
08751       bc->sending_complete = 1;
08752    }
08753 
08754    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
08755    if (tmp) {
08756       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
08757       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
08758       bc->uulen = strlen(bc->uu);
08759    }
08760 
08761    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
08762    if (tmp) {
08763       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
08764    }
08765    ast_channel_unlock(chan);
08766 }

static int load_module ( void   )  [static]

Definition at line 11179 of file chan_misdn.c.

References ast_calloc, ast_channel_register(), ast_cli_register_multiple(), ast_custom_function_register, 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.

11180 {
11181    int i, port;
11182    int ntflags = 0, ntkc = 0;
11183    char ports[256] = "";
11184    char tempbuf[BUFFERSIZE + 1];
11185    char ntfile[BUFFERSIZE + 1];
11186    struct misdn_lib_iface iface = {
11187       .cb_event = cb_events,
11188       .cb_log = chan_misdn_log,
11189       .cb_jb_empty = chan_misdn_jb_empty,
11190    };
11191 
11192    max_ports = misdn_lib_maxports_get();
11193 
11194    if (max_ports <= 0) {
11195       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
11196       return AST_MODULE_LOAD_DECLINE;
11197    }
11198 
11199    if (misdn_cfg_init(max_ports, 0)) {
11200       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
11201       return AST_MODULE_LOAD_DECLINE;
11202    }
11203    g_config_initialized = 1;
11204 
11205 #if defined(AST_MISDN_ENHANCEMENTS)
11206    misdn_cc_init();
11207 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11208 
11209    misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
11210    if (!misdn_debug) {
11211       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
11212       return AST_MODULE_LOAD_DECLINE;
11213    }
11214    misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
11215    if (!misdn_ports) {
11216       ast_free(misdn_debug);
11217       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
11218       return AST_MODULE_LOAD_DECLINE;
11219    }
11220    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
11221    for (i = 1; i <= max_ports; i++) {
11222       misdn_debug[i] = misdn_debug[0];
11223       misdn_ports[i] = i;
11224    }
11225    *misdn_ports = 0;
11226    misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
11227    if (!misdn_debug_only) {
11228       ast_free(misdn_ports);
11229       ast_free(misdn_debug);
11230       ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
11231       return AST_MODULE_LOAD_DECLINE;
11232    }
11233 
11234    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
11235    if (!ast_strlen_zero(tempbuf)) {
11236       tracing = 1;
11237    }
11238 
11239    misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11240    if (!misdn_in_calls) {
11241       ast_free(misdn_debug_only);
11242       ast_free(misdn_ports);
11243       ast_free(misdn_debug);
11244       ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
11245       return AST_MODULE_LOAD_DECLINE;
11246    }
11247    misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11248    if (!misdn_out_calls) {
11249       ast_free(misdn_in_calls);
11250       ast_free(misdn_debug_only);
11251       ast_free(misdn_ports);
11252       ast_free(misdn_debug);
11253       ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
11254       return AST_MODULE_LOAD_DECLINE;
11255    }
11256 
11257    for (i = 1; i <= max_ports; i++) {
11258       misdn_in_calls[i] = 0;
11259       misdn_out_calls[i] = 0;
11260    }
11261 
11262    ast_mutex_init(&cl_te_lock);
11263    ast_mutex_init(&release_lock);
11264 
11265    misdn_cfg_update_ptp();
11266    misdn_cfg_get_ports_string(ports);
11267 
11268    if (!ast_strlen_zero(ports)) {
11269       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
11270    }
11271    if (misdn_lib_init(ports, &iface, NULL)) {
11272       chan_misdn_log(0, 0, "No te ports initialized\n");
11273    }
11274 
11275    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
11276    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
11277    misdn_cfg_get(0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
11278 
11279    misdn_lib_nt_keepcalls(ntkc);
11280    misdn_lib_nt_debug_init(ntflags, ntfile);
11281 
11282    if (ast_channel_register(&misdn_tech)) {
11283       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
11284       unload_module();
11285       return AST_MODULE_LOAD_DECLINE;
11286    }
11287 
11288    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11289 
11290    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
11291       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
11292       "Sets mISDN opts. and optargs\n"
11293       "\n"
11294       "The available options are:\n"
11295       "    a - Have Asterisk detect DTMF tones on called channel\n"
11296       "    c - Make crypted outgoing call, optarg is keyindex\n"
11297       "    d - Send display text to called phone, text is the optarg\n"
11298       "    e - Perform echo cancellation on this channel,\n"
11299       "        takes taps as optarg (32,64,128,256)\n"
11300       "   e! - Disable echo cancellation on this channel\n"
11301       "    f - Enable fax detection\n"
11302       "    h - Make digital outgoing call\n"
11303       "   h1 - Make HDLC mode digital outgoing call\n"
11304       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
11305       "        they will be transported inband.\n"
11306       "   jb - Set jitter buffer length, optarg is length\n"
11307       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
11308       "   jn - Disable jitter buffer\n"
11309       "    n - Disable mISDN DSP on channel.\n"
11310       "        Disables: echo cancel, DTMF detection, and volume control.\n"
11311       "    p - Caller ID presentation,\n"
11312       "        optarg is either 'allowed' or 'restricted'\n"
11313       "    s - Send Non-inband DTMF as inband\n"
11314       "   vr - Rx gain control, optarg is gain\n"
11315       "   vt - Tx gain control, optarg is gain\n"
11316       );
11317 
11318 
11319    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
11320       "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
11321       "Sends the Facility Message FACILITY_TYPE with \n"
11322       "the given Arguments to the current ISDN Channel\n"
11323       "Supported Facilities are:\n"
11324       "\n"
11325       "type=calldeflect args=Nr where to deflect\n"
11326 #if defined(AST_MISDN_ENHANCEMENTS)
11327       "type=callrerouting args=Nr where to deflect\n"
11328 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11329       );
11330 
11331 
11332    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
11333       "misdn_check_l2l1(<port>||g:<groupname>,timeout)\n"
11334       "Checks if the L2 and L1 are up on either the given <port> or\n"
11335       "on the ports in the group with <groupname>\n"
11336       "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
11337       "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
11338       "\n"
11339       "This application, ensures the L1/L2 state of the Ports in a group\n"
11340       "it is intended to make the pmp_l1_check option redundant and to\n"
11341       "fix a buggy switch config from your provider\n"
11342       "\n"
11343       "a sample dialplan would look like:\n\n"
11344       "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
11345       "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
11346       );
11347 
11348 #if defined(AST_MISDN_ENHANCEMENTS)
11349    ast_register_application(misdn_command_name, misdn_command_exec, misdn_command_name,
11350       "misdn_command(<command>[,<options>])\n"
11351       "The following commands are defined:\n"
11352       "cc-initialize\n"
11353       "  Setup mISDN support for call completion\n"
11354       "  Must call before doing any Dial() involving call completion.\n"
11355       "ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11356       "  Request Call Completion No Reply activation\n"
11357       "ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11358       "  Request Call Completion Busy Subscriber activation\n"
11359       "cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11360       "  Set the dialplan location to notify when User-B is available but User-A is busy.\n"
11361       "  Setting this dialplan location is optional.\n"
11362       "cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>\n"
11363       "  Set the busy status of call completion User-A\n"
11364       "cc-deactivate,${MISDN_CC_RECORD_ID}\n"
11365       "  Deactivate the identified call completion request\n"
11366       "\n"
11367       "MISDN_CC_RECORD_ID is set when Dial() returns and call completion is possible\n"
11368       "MISDN_CC_STATUS is set to ACTIVATED or ERROR after the call completion\n"
11369       "activation request.\n"
11370       "MISDN_ERROR_MSG is set to a descriptive message on error.\n"
11371       );
11372 
11373    ast_custom_function_register(&misdn_cc_function);
11374 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11375 
11376    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
11377 
11378    /* start the l1 watchers */
11379 
11380    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
11381       int l1timeout;
11382       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
11383       if (l1timeout) {
11384          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
11385          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
11386       }
11387    }
11388 
11389    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
11390 
11391    return 0;
11392 }

static void misdn_add_number_prefix ( int  port,
enum mISDN_NUMBER_TYPE  number_type,
char *  number,
size_t  size 
) [static]

Definition at line 3396 of file chan_misdn.c.

References misdn_cfg_get(), MISDN_CFG_TON_PREFIX_ABBREVIATED, MISDN_CFG_TON_PREFIX_INTERNATIONAL, MISDN_CFG_TON_PREFIX_NATIONAL, MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC, MISDN_CFG_TON_PREFIX_SUBSCRIBER, MISDN_CFG_TON_PREFIX_UNKNOWN, MISDN_MAX_NUMBER_LEN, misdn_prefix_string(), NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.

Referenced by cb_events(), misdn_facility_ie_handler(), misdn_is_msn_valid(), and read_config().

03397 {
03398    enum misdn_cfg_elements type_prefix;
03399    char num_prefix[MISDN_MAX_NUMBER_LEN];
03400 
03401    /* Get prefix string. */
03402    switch (number_type) {
03403    case NUMTYPE_UNKNOWN:
03404       type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
03405       break;
03406    case NUMTYPE_INTERNATIONAL:
03407       type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
03408       break;
03409    case NUMTYPE_NATIONAL:
03410       type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
03411       break;
03412    case NUMTYPE_NETWORK_SPECIFIC:
03413       type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
03414       break;
03415    case NUMTYPE_SUBSCRIBER:
03416       type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
03417       break;
03418    case NUMTYPE_ABBREVIATED:
03419       type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
03420       break;
03421    default:
03422       /* Type-of-number does not have a prefix that can be added. */
03423       return;
03424    }
03425    misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
03426 
03427    misdn_prefix_string(num_prefix, number, size);
03428 }

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 6753 of file chan_misdn.c.

References AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_PROTOCOL_ERROR, ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_log(), ast_queue_hangup_with_cause(), ast_strlen_zero(), ast_true(), chan_list::bc, chan_misdn_log(), misdn_bchannel::connected, misdn_bchannel::crypt_key, misdn_bchannel::dialed, EVENT_CONNECT, misdn_bchannel::fac_out, misdn_bchannel::hdlc, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_lib_send_event(), misdn_bchannel::nodsp, misdn_bchannel::nojitter, misdn_party_dialing::number, misdn_party_id::number, misdn_party_dialing::number_plan, misdn_party_id::number_plan, misdn_party_dialing::number_type, misdn_party_id::number_type, misdn_bchannel::outgoing_colp, pbx_builtin_getvar_helper(), misdn_bchannel::port, misdn_bchannel::presentation, misdn_party_id::presentation, print_facility(), misdn_party_id::screening, start_bc_tones(), chan_list::state, and stop_indicate().

06754 {
06755    struct chan_list *p;
06756    const char *tmp;
06757 
06758    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06759       return -1;
06760    }
06761 
06762    chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
06763 
06764    if (!p) {
06765       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
06766       ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
06767    }
06768 
06769    if (!p->bc) {
06770       chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
06771 
06772       ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
06773    }
06774 
06775    ast_channel_lock(ast);
06776    tmp = pbx_builtin_getvar_helper(ast, "CRYPT_KEY");
06777    if (!ast_strlen_zero(tmp)) {
06778       chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
06779       ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
06780    } else {
06781       chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
06782    }
06783 
06784    tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
06785    if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
06786       chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
06787       p->bc->nodsp = 1;
06788       p->bc->hdlc = 0;
06789       p->bc->nojitter = 1;
06790    }
06791    ast_channel_unlock(ast);
06792 
06793    p->state = MISDN_CONNECTED;
06794    stop_indicate(p);
06795 
06796    if (ast_strlen_zero(p->bc->connected.number)) {
06797       chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
06798       ast_copy_string(p->bc->connected.number, p->bc->dialed.number, sizeof(p->bc->connected.number));
06799 
06800       /*
06801        * Use the misdn_set_opt() application to set the presentation
06802        * before we answer or you can use the CONECTEDLINE() function
06803        * to set everything before using the Answer() application.
06804        */
06805       p->bc->connected.presentation = p->bc->presentation;
06806       p->bc->connected.screening = 0;  /* unscreened */
06807       p->bc->connected.number_type = p->bc->dialed.number_type;
06808       p->bc->connected.number_plan = p->bc->dialed.number_plan;
06809    }
06810 
06811    switch (p->bc->outgoing_colp) {
06812    case 1:/* restricted */
06813    case 2:/* blocked */
06814       p->bc->connected.presentation = 1;/* restricted */
06815       break;
06816    default:
06817       break;
06818    }
06819 
06820 #if defined(AST_MISDN_ENHANCEMENTS)
06821    if (p->bc->div_leg_3_tx_pending) {
06822       p->bc->div_leg_3_tx_pending = 0;
06823 
06824       /* Send DivertingLegInformation3 */
06825       p->bc->fac_out.Function = Fac_DivertingLegInformation3;
06826       p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
06827       p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
06828          (p->bc->connected.presentation == 0) ? 1 : 0;
06829       print_facility(&p->bc->fac_out, p->bc);
06830    }
06831 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06832    misdn_lib_send_event(p->bc, EVENT_CONNECT);
06833    start_bc_tones(p);
06834 
06835    return 0;
06836 }

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

Definition at line 8546 of file chan_misdn.c.

References ao2_ref, chan_list::ast, ast_bridged_channel(), ast_channel_lock, ast_channel_transfer_masquerade(), ast_channel_trylock, ast_channel_unlock, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), chan_misdn_log(), CHANNEL_DEADLOCK_AVOIDANCE, ast_channel::connected, 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().

08547 {
08548    int retval;
08549    struct ast_channel *target;
08550    struct ast_channel *transferee;
08551    struct ast_party_connected_line target_colp;
08552    struct ast_party_connected_line transferee_colp;
08553 
08554    switch (active_ch->state) {
08555    case MISDN_PROCEEDING:
08556    case MISDN_PROGRESS:
08557    case MISDN_ALERTING:
08558    case MISDN_CONNECTED:
08559       break;
08560    default:
08561       return -1;
08562    }
08563 
08564    ast_channel_lock(held_ch->ast);
08565    while (ast_channel_trylock(active_ch->ast)) {
08566       CHANNEL_DEADLOCK_AVOIDANCE(held_ch->ast);
08567    }
08568 
08569    transferee = ast_bridged_channel(held_ch->ast);
08570    if (!transferee) {
08571       /*
08572        * Could not transfer.  Held channel is not bridged anymore.
08573        * Held party probably got tired of waiting and hung up.
08574        */
08575       ast_channel_unlock(held_ch->ast);
08576       ast_channel_unlock(active_ch->ast);
08577       return -1;
08578    }
08579 
08580    target = active_ch->ast;
08581    chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
08582       held_ch->ast->name, target->name);
08583 
08584    ast_party_connected_line_init(&target_colp);
08585    ast_party_connected_line_copy(&target_colp, &target->connected);
08586    ast_party_connected_line_init(&transferee_colp);
08587    ast_party_connected_line_copy(&transferee_colp, &held_ch->ast->connected);
08588    held_ch->hold.state = MISDN_HOLD_TRANSFER;
08589 
08590    /*
08591     * Before starting a masquerade, all channel and pvt locks must
08592     * be unlocked.  Any recursive channel locks held before
08593     * ast_channel_transfer_masquerade() invalidates deadlock
08594     * avoidance.  Since we are unlocking both the pvt and its owner
08595     * channel it is possible for "target" and "transferee" to be
08596     * destroyed by their pbx threads.  To prevent this we must give
08597     * "target" and "transferee" a reference before any unlocking
08598     * takes place.
08599     */
08600    ao2_ref(target, +1);
08601    ao2_ref(transferee, +1);
08602    ast_channel_unlock(held_ch->ast);
08603    ast_channel_unlock(active_ch->ast);
08604 
08605    /* Setup transfer masquerade. */
08606    retval = ast_channel_transfer_masquerade(target, &target_colp, 0,
08607       transferee, &transferee_colp, 1);
08608 
08609    ast_party_connected_line_free(&target_colp);
08610    ast_party_connected_line_free(&transferee_colp);
08611    ao2_ref(target, -1);
08612    ao2_ref(transferee, -1);
08613    return retval;
08614 }

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 7511 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, misdn_bchannel::caller, chan_list_unref, chan_misdn_log(), ast_channel::exten, f, ast_frame::frametype, get_chan_by_ast(), chan_list::ignore_dtmf, ast_frame_subclass::integer, LOG_NOTICE, MISDN_CFG_BRIDGING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_bridge(), misdn_lib_split_bridge(), misdn_party_id::name, misdn_party_id::number, misdn_bchannel::pid, misdn_bchannel::port, and ast_frame::subclass.

07516 {
07517    struct chan_list *ch1, *ch2;
07518    struct ast_channel *carr[2], *who;
07519    int to = -1;
07520    struct ast_frame *f;
07521    int p1_b, p2_b;
07522    int bridging;
07523 
07524    ch1 = get_chan_by_ast(c0);
07525    if (!ch1) {
07526       return -1;
07527    }
07528    ch2 = get_chan_by_ast(c1);
07529    if (!ch2) {
07530       chan_list_unref(ch1, "Failed to find ch2");
07531       return -1;
07532    }
07533 
07534    carr[0] = c0;
07535    carr[1] = c1;
07536 
07537    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
07538    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
07539 
07540    if (! p1_b || ! p2_b) {
07541       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
07542       chan_list_unref(ch1, "Bridge fallback ch1");
07543       chan_list_unref(ch2, "Bridge fallback ch2");
07544       return AST_BRIDGE_FAILED;
07545    }
07546 
07547    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
07548    if (bridging) {
07549       /* trying to make a mISDN_dsp conference */
07550       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
07551       misdn_lib_bridge(ch1->bc, ch2->bc);
07552    }
07553 
07554    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
07555 
07556    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
07557       ch1->bc->caller.name,
07558       ch1->bc->caller.number,
07559       ch2->bc->caller.name,
07560       ch2->bc->caller.number);
07561 
07562    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
07563       ch1->ignore_dtmf = 1;
07564    }
07565 
07566    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
07567       ch2->ignore_dtmf = 1;
07568    }
07569 
07570    for (;/*ever*/;) {
07571       to = -1;
07572       who = ast_waitfor_n(carr, 2, &to);
07573 
07574       if (!who) {
07575          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
07576          break;
07577       }
07578       f = ast_read(who);
07579 
07580       if (!f || f->frametype == AST_FRAME_CONTROL) {
07581          /* got hangup .. */
07582 
07583          if (!f) {
07584             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
07585          } else {
07586             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass.integer);
07587          }
07588 
07589          *fo = f;
07590          *rc = who;
07591          break;
07592       }
07593 
07594       if (f->frametype == AST_FRAME_DTMF) {
07595          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass.integer, who->exten);
07596 
07597          *fo = f;
07598          *rc = who;
07599          break;
07600       }
07601 
07602 #if 0
07603       if (f->frametype == AST_FRAME_VOICE) {
07604          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
07605 
07606          continue;
07607       }
07608 #endif
07609 
07610       ast_write((who == c0) ? c1 : c0, f);
07611    }
07612 
07613    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
07614 
07615    misdn_lib_split_bridge(ch1->bc, ch2->bc);
07616 
07617    chan_list_unref(ch1, "Bridge complete ch1");
07618    chan_list_unref(ch2, "Bridge complete ch2");
07619    return AST_BRIDGE_COMPLETE;
07620 }

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

we should have l3id after sending setup

Definition at line 6485 of file chan_misdn.c.

References ast_channel::_state, add_out_calls(), args, AST_APP_ARG, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, ast_strdup, ast_strdupa, ast_strlen_zero(), ast_to_misdn_plan(), ast_to_misdn_ton(), ast_transfercapability2str(), chan_list::bc, ast_channel::caller, misdn_bchannel::caller, misdn_bchannel::capability, chan_misdn_log(), ast_channel::connected, ast_channel::context, misdn_party_redirecting::count, debug_numtype(), misdn_bchannel::dialed, ENOCHAN, EVENT_SETUP, ext, ast_channel::exten, misdn_bchannel::fac_out, misdn_party_redirecting::from, ast_channel::hangupcause, misdn_bchannel::hdlc, ast_party_caller::id, ast_party_connected_line::id, import_ch(), misdn_bchannel::incoming_cid_tag, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, misdn_bchannel::l3_id, chan_list::l3id, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, MISDN_CALLING, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, misdn_cfg_get(), MISDN_CFG_LOCALDIALPLAN, misdn_copy_redirecting_from_ast(), misdn_lib_is_ptp(), misdn_lib_send_event(), misdn_set_opt_exec(), ast_party_id::name, misdn_party_id::name, misdn_bchannel::nt, ast_party_id::number, misdn_party_id::number, misdn_party_dialing::number, misdn_party_id::number_plan, misdn_party_id::number_type, NUMPLAN_ISDN, NUMTYPE_UNKNOWN, misdn_bchannel::outgoing_colp, pbx_builtin_setvar_helper(), misdn_bchannel::pid, ast_party_number::plan, misdn_bchannel::port, misdn_bchannel::presentation, misdn_party_id::presentation, print_facility(), misdn_party_redirecting::reason, misdn_bchannel::redirecting, misdn_bchannel::sending_complete, misdn_bchannel::set_presentation, chan_list::state, stop_bc_tones(), ast_party_number::str, ast_party_name::str, ast_party_id::tag, ast_channel::transfercapability, update_config(), ast_party_number::valid, and ast_party_name::valid.

06486 {
06487    int port = 0;
06488    int r;
06489    int exceed;
06490    int number_type;
06491    struct chan_list *ch;
06492    struct misdn_bchannel *newbc;
06493    char *dest_cp;
06494    int append_msn = 0;
06495 
06496    AST_DECLARE_APP_ARGS(args,
06497       AST_APP_ARG(intf);   /* The interface token is discarded. */
06498       AST_APP_ARG(ext); /* extension token */
06499       AST_APP_ARG(opts);   /* options token */
06500    );
06501 
06502    if (!ast) {
06503       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
06504       return -1;
06505    }
06506 
06507    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest) {
06508       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
06509       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
06510       ast_setstate(ast, AST_STATE_DOWN);
06511       return -1;
06512    }
06513 
06514    ch = MISDN_ASTERISK_TECH_PVT(ast);
06515    if (!ch) {
06516       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast->name);
06517       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
06518       ast_setstate(ast, AST_STATE_DOWN);
06519       return -1;
06520    }
06521 
06522    newbc = ch->bc;
06523    if (!newbc) {
06524       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast->name);
06525       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
06526       ast_setstate(ast, AST_STATE_DOWN);
06527       return -1;
06528    }
06529 
06530    port = newbc->port;
06531 
06532 #if defined(AST_MISDN_ENHANCEMENTS)
06533    if ((ch->peer = misdn_cc_caller_get(ast))) {
06534       chan_misdn_log(3, port, " --> Found CC caller data, peer:%s\n",
06535          ch->peer->chan ? "available" : "NULL");
06536    }
06537 
06538    if (ch->record_id != -1) {
06539       struct misdn_cc_record *cc_record;
06540 
06541       /* This is a call completion retry call */
06542       AST_LIST_LOCK(&misdn_cc_records_db);
06543       cc_record = misdn_cc_find_by_id(ch->record_id);
06544       if (!cc_record) {
06545          AST_LIST_UNLOCK(&misdn_cc_records_db);
06546          ast_log(LOG_WARNING, " --> ! misdn_call called on %s, cc_record==NULL\n", ast->name);
06547          ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
06548          ast_setstate(ast, AST_STATE_DOWN);
06549          return -1;
06550       }
06551 
06552       /* Setup calling parameters to retry the call. */
06553       newbc->dialed = cc_record->redial.dialed;
06554       newbc->caller = cc_record->redial.caller;
06555       memset(&newbc->redirecting, 0, sizeof(newbc->redirecting));
06556       newbc->capability = cc_record->redial.capability;
06557       newbc->hdlc = cc_record->redial.hdlc;
06558       newbc->sending_complete = 1;
06559 
06560       if (cc_record->ptp) {
06561          newbc->fac_out.Function = Fac_CCBS_T_Call;
06562          newbc->fac_out.u.CCBS_T_Call.InvokeID = ++misdn_invoke_id;
06563       } else {
06564          newbc->fac_out.Function = Fac_CCBSCall;
06565          newbc->fac_out.u.CCBSCall.InvokeID = ++misdn_invoke_id;
06566          newbc->fac_out.u.CCBSCall.CCBSReference = cc_record->mode.ptmp.reference_id;
06567       }
06568       AST_LIST_UNLOCK(&misdn_cc_records_db);
06569 
06570       ast_copy_string(ast->exten, newbc->dialed.number, sizeof(ast->exten));
06571 
06572       chan_misdn_log(1, port, "* Call completion to: %s\n", newbc->dialed.number);
06573       chan_misdn_log(2, port, " --> * tech:%s context:%s\n", ast->name, ast->context);
06574    } else
06575 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06576    {
06577       /*
06578        * dest is ---v
06579        * Dial(mISDN/g:group_name[/extension[/options]])
06580        * Dial(mISDN/port[:preselected_channel][/extension[/options]])
06581        *
06582        * The dial extension could be empty if you are using MISDN_KEYPAD
06583        * to control ISDN provider features.
06584        */
06585       dest_cp = ast_strdupa(dest);
06586       AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
06587       if (!args.ext) {
06588          args.ext = "";
06589       }
06590 
06591       chan_misdn_log(1, port, "* CALL: %s\n", dest);
06592       chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast->name, ast->context);
06593 
06594       ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
06595       ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
06596 
06597       if (ast_strlen_zero(newbc->caller.name)
06598          && ast->connected.id.name.valid
06599          && !ast_strlen_zero(ast->connected.id.name.str)) {
06600          ast_copy_string(newbc->caller.name, ast->connected.id.name.str, sizeof(newbc->caller.name));
06601          chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
06602       }
06603       if (ast_strlen_zero(newbc->caller.number)
06604          && ast->connected.id.number.valid
06605          && !ast_strlen_zero(ast->connected.id.number.str)) {
06606          ast_copy_string(newbc->caller.number, ast->connected.id.number.str, sizeof(newbc->caller.number));
06607          chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
06608       }
06609 
06610       misdn_cfg_get(port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
06611       if (append_msn) {
06612          strncat(newbc->incoming_cid_tag, "_", sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
06613          strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
06614       }
06615 
06616       ast->caller.id.tag = ast_strdup(newbc->incoming_cid_tag);
06617 
06618       misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
06619       if (number_type < 0) {
06620          if (ast->connected.id.number.valid) {
06621             newbc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number.plan);
06622             newbc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number.plan);
06623          } else {
06624             newbc->caller.number_type = NUMTYPE_UNKNOWN;
06625             newbc->caller.number_plan = NUMPLAN_ISDN;
06626          }
06627       } else {
06628          /* Force us to send in SETUP message */
06629          newbc->caller.number_type = number_type;
06630          newbc->caller.number_plan = NUMPLAN_ISDN;
06631       }
06632       debug_numtype(port, newbc->caller.number_type, "LTON");
06633 
06634       newbc->capability = ast->transfercapability;
06635       pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
06636       if (ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
06637          chan_misdn_log(2, port, " --> * Call with flag Digital\n");
06638       }
06639 
06640       /* update caller screening and presentation */
06641       update_config(ch);
06642 
06643       /* fill in some ies from channel dialplan variables */
06644       import_ch(ast, newbc, ch);
06645 
06646       /* Finally The Options Override Everything */
06647       if (!ast_strlen_zero(args.opts)) {
06648          misdn_set_opt_exec(ast, args.opts);
06649       } else {
06650          chan_misdn_log(2, port, "NO OPTS GIVEN\n");
06651       }
06652       if (newbc->set_presentation) {
06653          newbc->caller.presentation = newbc->presentation;
06654       }
06655 
06656       misdn_copy_redirecting_from_ast(newbc, ast);
06657       switch (newbc->outgoing_colp) {
06658       case 1:/* restricted */
06659       case 2:/* blocked */
06660          newbc->redirecting.from.presentation = 1;/* restricted */
06661          break;
06662       default:
06663          break;
06664       }
06665 #if defined(AST_MISDN_ENHANCEMENTS)
06666       if (newbc->redirecting.from.number[0] && misdn_lib_is_ptp(port)) {
06667          if (newbc->redirecting.count < 1) {
06668             newbc->redirecting.count = 1;
06669          }
06670 
06671          /* Create DivertingLegInformation2 facility */
06672          newbc->fac_out.Function = Fac_DivertingLegInformation2;
06673          newbc->fac_out.u.DivertingLegInformation2.InvokeID = ++misdn_invoke_id;
06674          newbc->fac_out.u.DivertingLegInformation2.DivertingPresent = 1;
06675          misdn_PresentedNumberUnscreened_fill(
06676             &newbc->fac_out.u.DivertingLegInformation2.Diverting,
06677             &newbc->redirecting.from);
06678          switch (newbc->outgoing_colp) {
06679          case 2:/* blocked */
06680             /* Block the number going out */
06681             newbc->fac_out.u.DivertingLegInformation2.Diverting.Type = 1;/* presentationRestricted */
06682 
06683             /* Don't tell about any previous diversions or why for that matter. */
06684             newbc->fac_out.u.DivertingLegInformation2.DiversionCounter = 1;
06685             newbc->fac_out.u.DivertingLegInformation2.DiversionReason = 0;/* unknown */
06686             break;
06687          default:
06688             newbc->fac_out.u.DivertingLegInformation2.DiversionCounter =
06689                newbc->redirecting.count;
06690             newbc->fac_out.u.DivertingLegInformation2.DiversionReason =
06691                misdn_to_diversion_reason(newbc->redirecting.reason);
06692             break;
06693          }
06694          newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
06695          if (1 < newbc->fac_out.u.DivertingLegInformation2.DiversionCounter) {
06696             newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
06697             newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;/* numberNotAvailableDueToInterworking */
06698          }
06699 
06700          /*
06701           * Expect a DivertingLegInformation3 to update the COLR of the
06702           * redirecting-to party we are attempting to call now.
06703           */
06704          newbc->div_leg_3_rx_wanted = 1;
06705       }
06706 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06707    }
06708 
06709    exceed = add_out_calls(port);
06710    if (exceed != 0) {
06711       char tmp[16];
06712 
06713       snprintf(tmp, sizeof(tmp), "%d", exceed);
06714       pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
06715       ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
06716       ast_setstate(ast, AST_STATE_DOWN);
06717       return -1;
06718    }
06719 
06720 #if defined(AST_MISDN_ENHANCEMENTS)
06721    if (newbc->fac_out.Function != Fac_None) {
06722       print_facility(&newbc->fac_out, newbc);
06723    }
06724 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06725    r = misdn_lib_send_event(newbc, EVENT_SETUP);
06726 
06727    /** we should have l3id after sending setup **/
06728    ch->l3id = newbc->l3_id;
06729 
06730    if (r == -ENOCHAN) {
06731       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
06732       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
06733       ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
06734       ast_setstate(ast, AST_STATE_DOWN);
06735       return -1;
06736    }
06737 
06738    chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
06739 
06740    ast_setstate(ast, AST_STATE_DIALING);
06741    ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
06742 
06743    if (newbc->nt) {
06744       stop_bc_tones(ch);
06745    }
06746 
06747    ch->state = MISDN_CALLING;
06748 
06749    return 0;
06750 }

static int misdn_chan_is_valid ( struct chan_list ch  )  [static]

Definition at line 723 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, and chan_list::next.

Referenced by misdn_hangup().

00724 {
00725    struct chan_list *list;
00726 
00727    ast_mutex_lock(&cl_te_lock);
00728    for (list = cl_te; list; list = list->next) {
00729       if (list == ch) {
00730          ast_mutex_unlock(&cl_te_lock);
00731          return 1;
00732       }
00733    }
00734    ast_mutex_unlock(&cl_te_lock);
00735 
00736    return 0;
00737 }

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

Definition at line 12149 of file chan_misdn.c.

References args, 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(), and misdn_lib_port_up().

Referenced by load_module().

12150 {
12151    char *parse;
12152    char group[BUFFERSIZE + 1];
12153    char *port_str;
12154    int port = 0;
12155    int timeout;
12156    int dowait = 0;
12157    int port_up;
12158 
12159    AST_DECLARE_APP_ARGS(args,
12160       AST_APP_ARG(grouppar);
12161       AST_APP_ARG(timeout);
12162    );
12163 
12164    if (ast_strlen_zero((char *) data)) {
12165       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
12166       return -1;
12167    }
12168 
12169    parse = ast_strdupa(data);
12170    AST_STANDARD_APP_ARGS(args, parse);
12171 
12172    if (args.argc != 2) {
12173       ast_log(LOG_WARNING, "Wrong argument count\n");
12174       return 0;
12175    }
12176 
12177    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
12178    timeout = atoi(args.timeout);
12179    port_str = args.grouppar;
12180 
12181    if (port_str[0] == 'g' && port_str[1] == ':') {
12182       /* We make a group call lets checkout which ports are in my group */
12183       port_str += 2;
12184       ast_copy_string(group, port_str, sizeof(group));
12185       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
12186 
12187       for (port = misdn_cfg_get_next_port(port);
12188          port > 0;
12189          port = misdn_cfg_get_next_port(port)) {
12190          char cfg_group[BUFFERSIZE + 1];
12191 
12192          chan_misdn_log(2, 0, "trying port %d\n", port);
12193 
12194          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
12195 
12196          if (!strcasecmp(cfg_group, group)) {
12197             port_up = misdn_lib_port_up(port, 1);
12198             if (!port_up) {
12199                chan_misdn_log(2, 0, " --> port '%d'\n", port);
12200                misdn_lib_get_port_up(port);
12201                dowait = 1;
12202             }
12203          }
12204       }
12205    } else {
12206       port = atoi(port_str);
12207       chan_misdn_log(2, 0, "Checking Port: %d\n", port);
12208       port_up = misdn_lib_port_up(port, 1);
12209       if (!port_up) {
12210          misdn_lib_get_port_up(port);
12211          dowait = 1;
12212       }
12213    }
12214 
12215    if (dowait) {
12216       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
12217       ast_safe_sleep(chan, timeout * 1000);
12218    }
12219 
12220    return 0;
12221 }

static void misdn_copy_redirecting_from_ast ( struct misdn_bchannel bc,
struct ast_channel ast 
) [static]

Definition at line 6316 of file chan_misdn.c.

References ast_copy_string(), ast_to_misdn_plan(), ast_to_misdn_pres(), ast_to_misdn_reason(), ast_to_misdn_screen(), ast_to_misdn_ton(), ast_party_redirecting::count, misdn_party_redirecting::count, ast_party_redirecting::from, misdn_party_redirecting::from, ast_party_id::name, misdn_party_id::name, misdn_party_id::number, ast_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, NUMPLAN_UNKNOWN, NUMTYPE_UNKNOWN, ast_party_number::plan, ast_party_number::presentation, misdn_party_id::presentation, ast_party_redirecting::reason, misdn_party_redirecting::reason, ast_channel::redirecting, misdn_bchannel::redirecting, S_COR, S_OR, misdn_party_id::screening, ast_party_number::str, ast_party_name::str, ast_party_redirecting::to, misdn_party_redirecting::to, ast_party_number::valid, and ast_party_name::valid.

Referenced by misdn_call(), and misdn_update_redirecting().

06317 {
06318    ast_copy_string(bc->redirecting.from.name,
06319       S_COR(ast->redirecting.from.name.valid, ast->redirecting.from.name.str, ""),
06320       sizeof(bc->redirecting.from.name));
06321    if (ast->redirecting.from.number.valid) {
06322       ast_copy_string(bc->redirecting.from.number, S_OR(ast->redirecting.from.number.str, ""),
06323          sizeof(bc->redirecting.from.number));
06324       bc->redirecting.from.presentation = ast_to_misdn_pres(ast->redirecting.from.number.presentation);
06325       bc->redirecting.from.screening = ast_to_misdn_screen(ast->redirecting.from.number.presentation);
06326       bc->redirecting.from.number_type = ast_to_misdn_ton(ast->redirecting.from.number.plan);
06327       bc->redirecting.from.number_plan = ast_to_misdn_plan(ast->redirecting.from.number.plan);
06328    } else {
06329       bc->redirecting.from.number[0] = '\0';
06330       bc->redirecting.from.presentation = 0;/* Allowed */
06331       bc->redirecting.from.screening = 0;/* Unscreened */
06332       bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
06333       bc->redirecting.from.number_plan = NUMPLAN_UNKNOWN;
06334    }
06335 
06336    ast_copy_string(bc->redirecting.to.name,
06337       S_COR(ast->redirecting.to.name.valid, ast->redirecting.to.name.str, ""),
06338       sizeof(bc->redirecting.to.name));
06339    if (ast->redirecting.to.number.valid) {
06340       ast_copy_string(bc->redirecting.to.number, S_OR(ast->redirecting.to.number.str, ""),
06341          sizeof(bc->redirecting.to.number));
06342       bc->redirecting.to.presentation = ast_to_misdn_pres(ast->redirecting.to.number.presentation);
06343       bc->redirecting.to.screening = ast_to_misdn_screen(ast->redirecting.to.number.presentation);
06344       bc->redirecting.to.number_type = ast_to_misdn_ton(ast->redirecting.to.number.plan);
06345       bc->redirecting.to.number_plan = ast_to_misdn_plan(ast->redirecting.to.number.plan);
06346    } else {
06347       bc->redirecting.to.number[0] = '\0';
06348       bc->redirecting.to.presentation = 0;/* Allowed */
06349       bc->redirecting.to.screening = 0;/* Unscreened */
06350       bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
06351       bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
06352    }
06353 
06354    bc->redirecting.reason = ast_to_misdn_reason(ast->redirecting.reason);
06355    bc->redirecting.count = ast->redirecting.count;
06356 }

static void misdn_copy_redirecting_to_ast ( struct ast_channel ast,
const struct misdn_party_redirecting redirect,
char *  tag 
) [static]

Definition at line 6368 of file chan_misdn.c.

References ast_channel_set_redirecting(), ast_party_redirecting_set_init(), misdn_party_redirecting::count, ast_party_redirecting::count, misdn_party_redirecting::from, ast_party_redirecting::from, ast_set_party_redirecting::from, misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_reason(), misdn_to_ast_screen(), misdn_to_ast_ton(), misdn_party_id::number, ast_party_id::number, ast_set_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, ast_party_number::plan, misdn_party_id::presentation, ast_party_number::presentation, misdn_party_redirecting::reason, ast_party_redirecting::reason, ast_channel::redirecting, misdn_party_id::screening, ast_party_number::str, ast_party_id::tag, misdn_party_redirecting::to, ast_party_redirecting::to, ast_set_party_redirecting::to, and ast_party_number::valid.

Referenced by cb_events(), and misdn_facility_ie_handler().

06369 {
06370    struct ast_party_redirecting redirecting;
06371    struct ast_set_party_redirecting update_redirecting;
06372 
06373    ast_party_redirecting_set_init(&redirecting, &ast->redirecting);
06374    memset(&update_redirecting, 0, sizeof(update_redirecting));
06375 
06376    update_redirecting.from.number = 1;
06377    redirecting.from.number.valid = 1;
06378    redirecting.from.number.str = (char *) redirect->from.number;
06379    redirecting.from.number.plan =
06380       misdn_to_ast_ton(redirect->from.number_type)
06381       | misdn_to_ast_plan(redirect->from.number_plan);
06382    redirecting.from.number.presentation =
06383       misdn_to_ast_pres(redirect->from.presentation)
06384       | misdn_to_ast_screen(redirect->from.screening);
06385    redirecting.from.tag = tag;
06386 
06387    update_redirecting.to.number = 1;
06388    redirecting.to.number.valid = 1;
06389    redirecting.to.number.str = (char *) redirect->to.number;
06390    redirecting.to.number.plan =
06391       misdn_to_ast_ton(redirect->to.number_type)
06392       | misdn_to_ast_plan(redirect->to.number_plan);
06393    redirecting.to.number.presentation =
06394       misdn_to_ast_pres(redirect->to.presentation)
06395       | misdn_to_ast_screen(redirect->to.screening);
06396    redirecting.to.tag = tag;
06397 
06398    redirecting.reason = misdn_to_ast_reason(redirect->reason);
06399    redirecting.count = redirect->count;
06400 
06401    ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
06402 }

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

Definition at line 6838 of file chan_misdn.c.

06839 {
06840    /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
06841    return 0;
06842 }

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

Definition at line 6844 of file chan_misdn.c.

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

06845 {
06846    struct chan_list *p;
06847    struct misdn_bchannel *bc;
06848    char buf[2] = { digit, 0 };
06849 
06850    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06851       return -1;
06852    }
06853 
06854    bc = p->bc;
06855    chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
06856 
06857    if (!bc) {
06858       ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
06859       return -1;
06860    }
06861 
06862    switch (p->state) {
06863    case MISDN_CALLING:
06864       if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
06865          strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
06866       }
06867       break;
06868    case MISDN_CALLING_ACKNOWLEDGE:
06869       ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
06870       if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
06871          strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
06872       }
06873       ast_copy_string(p->ast->exten, bc->dialed.number, sizeof(p->ast->exten));
06874       misdn_lib_send_event(bc, EVENT_INFORMATION);
06875       break;
06876    default:
06877       if (bc->send_dtmf) {
06878          send_digit_to_chan(p, digit);
06879       }
06880       break;
06881    }
06882 
06883    return 0;
06884 }

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

Definition at line 12026 of file chan_misdn.c.

References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, 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(), misdn_bchannel::port, print_facility(), ast_channel::tech, and ast_channel_tech::type.

Referenced by load_module().

12027 {
12028    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12029    char *parse;
12030    unsigned max_len;
12031 
12032    AST_DECLARE_APP_ARGS(args,
12033       AST_APP_ARG(facility_type);
12034       AST_APP_ARG(arg)[99];
12035    );
12036 
12037    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
12038 
12039    if (strcasecmp(chan->tech->type, misdn_type)) {
12040       ast_log(LOG_WARNING, "misdn_facility only makes sense with %s channels!\n", misdn_type);
12041       return -1;
12042    }
12043 
12044    if (ast_strlen_zero((char *) data)) {
12045       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12046       return -1;
12047    }
12048 
12049    parse = ast_strdupa(data);
12050    AST_STANDARD_APP_ARGS(args, parse);
12051 
12052    if (ast_strlen_zero(args.facility_type)) {
12053       ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12054       return -1;
12055    }
12056 
12057    if (!strcasecmp(args.facility_type, "calldeflect")) {
12058       if (ast_strlen_zero(args.arg[0])) {
12059          ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
12060       }
12061 
12062 #if defined(AST_MISDN_ENHANCEMENTS)
12063       max_len = sizeof(ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
12064       if (max_len < strlen(args.arg[0])) {
12065          ast_log(LOG_WARNING,
12066             "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12067             max_len);
12068          return 0;
12069       }
12070       ch->bc->fac_out.Function = Fac_CallDeflection;
12071       ch->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
12072       ch->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
12073       ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
12074       ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
12075       ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;/* unknown */
12076       ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(args.arg[0]);
12077       strcpy((char *) ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, args.arg[0]);
12078       ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
12079 
12080 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
12081 
12082       max_len = sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
12083       if (max_len < strlen(args.arg[0])) {
12084          ast_log(LOG_WARNING,
12085             "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12086             max_len);
12087          return 0;
12088       }
12089       ch->bc->fac_out.Function = Fac_CD;
12090       ch->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
12091       //ch->bc->fac_out.u.CDeflection.DeflectedToSubaddress[0] = 0;
12092       strcpy((char *) ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0]);
12093 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
12094 
12095       /* Send message */
12096       print_facility(&ch->bc->fac_out, ch->bc);
12097       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
12098 #if defined(AST_MISDN_ENHANCEMENTS)
12099    } else if (!strcasecmp(args.facility_type, "callrerouteing")
12100       || !strcasecmp(args.facility_type, "callrerouting")) {
12101       if (ast_strlen_zero(args.arg[0])) {
12102          ast_log(LOG_WARNING, "Facility: Call rerouting requires an argument: Number\n");
12103       }
12104 
12105       max_len = sizeof(ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
12106       if (max_len < strlen(args.arg[0])) {
12107          ast_log(LOG_WARNING,
12108             "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12109             max_len);
12110          return 0;
12111       }
12112       ch->bc->fac_out.Function = Fac_CallRerouteing;
12113       ch->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
12114       ch->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
12115 
12116       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;/* unknown */
12117       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
12118 
12119       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;/* unknown */
12120       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(args.arg[0]);
12121       strcpy((char *) ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, args.arg[0]);
12122       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
12123 
12124       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
12125 
12126       /* 0x90 0x90 0xa3 3.1 kHz audio, circuit mode, 64kbit/sec, level1/a-Law */
12127       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
12128       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
12129       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
12130       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
12131       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
12132       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
12133       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
12134 
12135       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;/* presentationRestricted */
12136       ch->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;/* no notification to caller */
12137 
12138       /* Send message */
12139       print_facility(&ch->bc->fac_out, ch->bc);
12140       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
12141 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
12142    } else {
12143       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
12144    }
12145 
12146    return 0;
12147 }

static void misdn_facility_ie_handler ( enum event_e  event,
struct misdn_bchannel bc,
struct chan_list ch 
) [static]

Definition at line 9051 of file chan_misdn.c.

References misdn_bchannel::AOCD, misdn_bchannel::AOCD_need_export, misdn_bchannel::AOCDtype, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_channel_queue_redirecting_update(), AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING, AST_CONTROL_BUSY, ast_copy_string(), AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PRES_ALLOWED, AST_PRES_RESTRICTED, AST_PRES_USER_NUMBER_UNSCREENED, ast_queue_control(), ast_string_field_set, misdn_bchannel::caller, misdn_bchannel::capability, chan_misdn_log(), misdn_bchannel::chargingUnit, misdn_party_redirecting::count, misdn_bchannel::currency, misdn_bchannel::dialed, EVENT_ALERTING, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, EVENT_SETUP, export_aoc_vars(), misdn_bchannel::fac_in, misdn_bchannel::fac_out, misdn_party_redirecting::from, misdn_bchannel::hdlc, misdn_bchannel::incoming_cid_tag, misdn_add_number_prefix(), misdn_copy_redirecting_to_ast(), misdn_lib_send_event(), mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE, mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING, mISDN_NOTIFY_CODE_INVALID, mISDN_REDIRECTING_REASON_DEFLECTION, misdn_update_remote_party(), misdn_party_id::name, misdn_bchannel::notify_description_code, ast_party_id::number, misdn_party_dialing::number, misdn_party_id::number, misdn_party_dialing::number_plan, misdn_party_id::number_plan, misdn_party_dialing::number_type, misdn_party_id::number_type, NUMPLAN_ISDN, NUMPLAN_UNKNOWN, NUMTYPE_UNKNOWN, chan_list::originator, misdn_bchannel::port, ast_party_number::presentation, misdn_party_id::presentation, print_facility(), misdn_party_redirecting::reason, ast_channel::redirecting, misdn_bchannel::redirecting, misdn_party_id::screening, ast_party_redirecting::to, misdn_party_redirecting::to, and misdn_party_redirecting::to_changed.

Referenced by cb_events().

09052 {
09053 #if defined(AST_MISDN_ENHANCEMENTS)
09054    const char *diagnostic_msg;
09055    struct misdn_cc_record *cc_record;
09056    char buf[32];
09057    struct misdn_party_id party_id;
09058    long new_record_id;
09059 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
09060 
09061    print_facility(&bc->fac_in, bc);
09062    switch (bc->fac_in.Function) {
09063 #if defined(AST_MISDN_ENHANCEMENTS)
09064    case Fac_ActivationDiversion:
09065       switch (bc->fac_in.u.ActivationDiversion.ComponentType) {
09066       case FacComponent_Result:
09067          /* Positive ACK to activation */
09068          /* We don't handle this yet */
09069          break;
09070       default:
09071          chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
09072             bc->fac_in.Function);
09073          break;
09074       }
09075       break;
09076    case Fac_DeactivationDiversion:
09077       switch (bc->fac_in.u.DeactivationDiversion.ComponentType) {
09078       case FacComponent_Result:
09079          /* Positive ACK to deactivation */
09080          /* We don't handle this yet */
09081          break;
09082       default:
09083          chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
09084             bc->fac_in.Function);
09085          break;
09086       }
09087       break;
09088    case Fac_ActivationStatusNotificationDiv:
09089       /* Sent to other MSN numbers on the line when a user activates call forwarding. */
09090       /* Sent in the first call control message of an outgoing call from the served user. */
09091       /* We do not have anything to do for this message. */
09092       break;
09093    case Fac_DeactivationStatusNotificationDiv:
09094       /* Sent to other MSN numbers on the line when a user deactivates call forwarding. */
09095       /* We do not have anything to do for this message. */
09096       break;
09097 #if 0 /* We don't handle this yet */
09098    case Fac_InterrogationDiversion:
09099       /* We don't handle this yet */
09100       break;
09101    case Fac_InterrogateServedUserNumbers:
09102       /* We don't handle this yet */
09103       break;
09104 #endif   /* We don't handle this yet */
09105    case Fac_DiversionInformation:
09106       /* Sent to the served user when a call is forwarded. */
09107       /* We do not have anything to do for this message. */
09108       break;
09109    case Fac_CallDeflection:
09110       if (ch && ch->ast) {
09111          switch (bc->fac_in.u.CallDeflection.ComponentType) {
09112          case FacComponent_Invoke:
09113             ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
09114                sizeof(bc->redirecting.from.number));
09115             bc->redirecting.from.name[0] = 0;
09116             bc->redirecting.from.number_plan = bc->dialed.number_plan;
09117             bc->redirecting.from.number_type = bc->dialed.number_type;
09118             bc->redirecting.from.screening = 0;/* Unscreened */
09119             if (bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
09120                bc->redirecting.from.presentation =
09121                   bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser
09122                   ? 0 /* Allowed */ : 1 /* Restricted */;
09123             } else {
09124                bc->redirecting.from.presentation = 0;/* Allowed */
09125             }
09126 
09127             /* Add configured prefix to the call deflection number */
09128             memset(&party_id, 0, sizeof(party_id));
09129             misdn_PartyNumber_extract(&party_id,
09130                &bc->fac_in.u.CallDeflection.Component.Invoke.Deflection.Party);
09131             misdn_add_number_prefix(bc->port, party_id.number_type,
09132                party_id.number, sizeof(party_id.number));
09133             //party_id.presentation = 0;/* Allowed */
09134             //party_id.screening = 0;/* Unscreened */
09135             bc->redirecting.to = party_id;
09136 
09137             ++bc->redirecting.count;
09138             bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
09139 
09140             misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09141             ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number);
09142 
09143             /* Send back positive ACK */
09144 #if 1
09145             /*
09146              * Since there are no return result arguments it must be a
09147              * generic result message.  ETSI 300-196
09148              */
09149             bc->fac_out.Function = Fac_RESULT;
09150             bc->fac_out.u.RESULT.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
09151 #else
09152             bc->fac_out.Function = Fac_CallDeflection;
09153             bc->fac_out.u.CallDeflection.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
09154             bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Result;
09155 #endif
09156             print_facility(&bc->fac_out, bc);
09157             misdn_lib_send_event(bc, EVENT_DISCONNECT);
09158 
09159             /* This line is BUSY to further attempts by this dialing attempt. */
09160             ast_queue_control(ch->ast, AST_CONTROL_BUSY);
09161             break;
09162 
09163          case FacComponent_Result:
09164             /* Positive ACK to call deflection */
09165             /*
09166              * Sent in DISCONNECT or FACILITY message depending upon network option.
09167              * It is in the FACILITY message if the call is still offered to the user
09168              * while trying to alert the deflected to party.
09169              */
09170             /* Ignore the ACK */
09171             break;
09172 
09173          default:
09174             break;
09175          }
09176       }
09177       break;
09178 #if 0 /* We don't handle this yet */
09179    case Fac_CallRerouteing:
09180       /* Private-Public ISDN interworking message */
09181       /* We don't handle this yet */
09182       break;
09183 #endif   /* We don't handle this yet */
09184    case Fac_DivertingLegInformation1:
09185       /* Private-Public ISDN interworking message */
09186       bc->div_leg_3_rx_wanted = 0;
09187       if (ch && ch->ast) {
09188          bc->redirecting.reason =
09189             diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation1.DiversionReason);
09190          if (bc->fac_in.u.DivertingLegInformation1.DivertedToPresent) {
09191             misdn_PresentedNumberUnscreened_extract(&bc->redirecting.to,
09192                &bc->fac_in.u.DivertingLegInformation1.DivertedTo);
09193 
09194             /* Add configured prefix to redirecting.to.number */
09195             misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
09196                bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
09197          } else {
09198             bc->redirecting.to.number[0] = '\0';
09199             bc->redirecting.to.number_plan = NUMPLAN_ISDN;
09200             bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
09201             bc->redirecting.to.presentation = 1;/* restricted */
09202             bc->redirecting.to.screening = 0;/* unscreened */
09203          }
09204          misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09205          bc->div_leg_3_rx_wanted = 1;
09206       }
09207       break;
09208    case Fac_DivertingLegInformation2:
09209       /* Private-Public ISDN interworking message */
09210       switch (event) {
09211       case EVENT_SETUP:
09212          /* Comes in on a SETUP with redirecting.from information */
09213          bc->div_leg_3_tx_pending = 1;
09214          if (ch && ch->ast) {
09215             /*
09216              * Setup the redirecting.to informtion so we can identify
09217              * if the user wants to manually supply the COLR for this
09218              * redirected to number if further redirects could happen.
09219              *
09220              * All the user needs to do is set the REDIRECTING(to-pres)
09221              * to the COLR and REDIRECTING(to-num) = ${EXTEN} to be safe
09222              * after determining that the incoming call was redirected by
09223              * checking if there is a REDIRECTING(from-num).
09224              */
09225             ast_copy_string(bc->redirecting.to.number, bc->dialed.number,
09226                sizeof(bc->redirecting.to.number));
09227             bc->redirecting.to.number_plan = bc->dialed.number_plan;
09228             bc->redirecting.to.number_type = bc->dialed.number_type;
09229             bc->redirecting.to.presentation = 1;/* restricted */
09230             bc->redirecting.to.screening = 0;/* unscreened */
09231 
09232             bc->redirecting.reason =
09233                diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation2.DiversionReason);
09234             bc->redirecting.count = bc->fac_in.u.DivertingLegInformation2.DiversionCounter;
09235             if (bc->fac_in.u.DivertingLegInformation2.DivertingPresent) {
09236                /* This information is redundant if there was a redirecting ie in the SETUP. */
09237                misdn_PresentedNumberUnscreened_extract(&bc->redirecting.from,
09238                   &bc->fac_in.u.DivertingLegInformation2.Diverting);
09239 
09240                /* Add configured prefix to redirecting.from.number */
09241                misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type,
09242                   bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
09243             }
09244 #if 0
09245             if (bc->fac_in.u.DivertingLegInformation2.OriginalCalledPresent) {
09246                /* We have no place to put the OriginalCalled number */
09247             }
09248 #endif
09249             misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09250          }
09251          break;
09252       default:
09253          chan_misdn_log(0, bc->port," --> Expected in a SETUP message: facility type:0x%04X\n",
09254             bc->fac_in.Function);
09255          break;
09256       }
09257       break;
09258    case Fac_DivertingLegInformation3:
09259       /* Private-Public ISDN interworking message */
09260       if (bc->div_leg_3_rx_wanted) {
09261          bc->div_leg_3_rx_wanted = 0;
09262 
09263          if (ch && ch->ast) {
09264             ch->ast->redirecting.to.number.presentation =
09265                bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
09266                ? AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED
09267                : AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
09268             ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting, NULL);
09269          }
09270       }
09271       break;
09272 
09273 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
09274 
09275    case Fac_CD:
09276       if (ch && ch->ast) {
09277          ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
09278             sizeof(bc->redirecting.from.number));
09279          bc->redirecting.from.name[0] = 0;
09280          bc->redirecting.from.number_plan = bc->dialed.number_plan;
09281          bc->redirecting.from.number_type = bc->dialed.number_type;
09282          bc->redirecting.from.screening = 0;/* Unscreened */
09283          bc->redirecting.from.presentation =
09284             bc->fac_in.u.CDeflection.PresentationAllowed
09285             ? 0 /* Allowed */ : 1 /* Restricted */;
09286 
09287          ast_copy_string(bc->redirecting.to.number,
09288             (char *) bc->fac_in.u.CDeflection.DeflectedToNumber,
09289             sizeof(bc->redirecting.to.number));
09290          bc->redirecting.to.name[0] = 0;
09291          bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
09292          bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
09293          bc->redirecting.to.presentation = 0;/* Allowed */
09294          bc->redirecting.to.screening = 0;/* Unscreened */
09295 
09296          ++bc->redirecting.count;
09297          bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
09298 
09299          misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09300          ast_string_field_set(ch->ast, call_forward, bc->redirecting.to.number);
09301 
09302          misdn_lib_send_event(bc, EVENT_DISCONNECT);
09303 
09304          /* This line is BUSY to further attempts by this dialing attempt. */
09305          ast_queue_control(ch->ast, AST_CONTROL_BUSY);
09306       }
09307       break;
09308 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
09309    case Fac_AOCDCurrency:
09310       if (ch && ch->ast) {
09311          bc->AOCDtype = Fac_AOCDCurrency;
09312          memcpy(&bc->AOCD.currency, &bc->fac_in.u.AOCDcur, sizeof(bc->AOCD.currency));
09313          bc->AOCD_need_export = 1;
09314          export_aoc_vars(ch->originator, ch->ast, bc);
09315       }
09316       break;
09317    case Fac_AOCDChargingUnit:
09318       if (ch && ch->ast) {
09319          bc->AOCDtype = Fac_AOCDChargingUnit;
09320          memcpy(&bc->AOCD.chargingUnit, &bc->fac_in.u.AOCDchu, sizeof(bc->AOCD.chargingUnit));
09321          bc->AOCD_need_export = 1;
09322          export_aoc_vars(ch->originator, ch->ast, bc);
09323       }
09324       break;
09325 #if defined(AST_MISDN_ENHANCEMENTS)
09326    case Fac_ERROR:
09327       diagnostic_msg = misdn_to_str_error_code(bc->fac_in.u.ERROR.errorValue);
09328       chan_misdn_log(1, bc->port, " --> Facility error code: %s\n", diagnostic_msg);
09329       switch (event) {
09330       case EVENT_DISCONNECT:
09331       case EVENT_RELEASE:
09332       case EVENT_RELEASE_COMPLETE:
09333          /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
09334          if (ch && ch->peer) {
09335             misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
09336          }
09337          break;
09338       default:
09339          break;
09340       }
09341       AST_LIST_LOCK(&misdn_cc_records_db);
09342       cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.ERROR.invokeId);
09343       if (cc_record) {
09344          cc_record->outstanding_message = 0;
09345          cc_record->error_code = bc->fac_in.u.ERROR.errorValue;
09346       }
09347       AST_LIST_UNLOCK(&misdn_cc_records_db);
09348       break;
09349    case Fac_REJECT:
09350       diagnostic_msg = misdn_to_str_reject_code(bc->fac_in.u.REJECT.Code);
09351       chan_misdn_log(1, bc->port, " --> Facility reject code: %s\n", diagnostic_msg);
09352       switch (event) {
09353       case EVENT_DISCONNECT:
09354       case EVENT_RELEASE:
09355       case EVENT_RELEASE_COMPLETE:
09356          /* Possible call failure as a result of Fac_CCBSCall/Fac_CCBS_T_Call */
09357          if (ch && ch->peer) {
09358             misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
09359          }
09360          break;
09361       default:
09362          break;
09363       }
09364       if (bc->fac_in.u.REJECT.InvokeIDPresent) {
09365          AST_LIST_LOCK(&misdn_cc_records_db);
09366          cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.REJECT.InvokeID);
09367          if (cc_record) {
09368             cc_record->outstanding_message = 0;
09369             cc_record->reject_code = bc->fac_in.u.REJECT.Code;
09370          }
09371          AST_LIST_UNLOCK(&misdn_cc_records_db);
09372       }
09373       break;
09374    case Fac_RESULT:
09375       AST_LIST_LOCK(&misdn_cc_records_db);
09376       cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.RESULT.InvokeID);
09377       if (cc_record) {
09378          cc_record->outstanding_message = 0;
09379       }
09380       AST_LIST_UNLOCK(&misdn_cc_records_db);
09381       break;
09382 #if 0 /* We don't handle this yet */
09383    case Fac_EctExecute:
09384       /* We don't handle this yet */
09385       break;
09386    case Fac_ExplicitEctExecute:
09387       /* We don't handle this yet */
09388       break;
09389    case Fac_EctLinkIdRequest:
09390       /* We don't handle this yet */
09391       break;
09392 #endif   /* We don't handle this yet */
09393    case Fac_SubaddressTransfer:
09394       /* We do not have anything to do for this message since we do not handle subaddreses. */
09395       break;
09396    case Fac_RequestSubaddress:
09397       /*
09398        * We do not have anything to do for this message since we do not handle subaddreses.
09399        * However, we do care about some other ie's that should be present.
09400        */
09401       if (bc->redirecting.to_changed) {
09402          /* Add configured prefix to redirecting.to.number */
09403          misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
09404             bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
09405       }
09406       switch (bc->notify_description_code) {
09407       case mISDN_NOTIFY_CODE_INVALID:
09408          /* Notify ie was not present. */
09409          bc->redirecting.to_changed = 0;
09410          break;
09411       case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
09412          /*
09413           * It would be preferable to update the connected line information
09414           * only when the message callStatus is active.  However, the
09415           * optional redirection number may not be present in the active
09416           * message if an alerting message were received earlier.
09417           *
09418           * The consequences if we wind up sending two updates is benign.
09419           * The other end will think that it got transferred twice.
09420           */
09421          if (!bc->redirecting.to_changed) {
09422             break;
09423          }
09424          bc->redirecting.to_changed = 0;
09425          if (!ch || !ch->ast) {
09426             break;
09427          }
09428          misdn_update_remote_party(ch->ast, &bc->redirecting.to,
09429             AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING,
09430             bc->incoming_cid_tag);
09431          break;
09432       case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
09433          if (!bc->redirecting.to_changed) {
09434             break;
09435          }
09436          bc->redirecting.to_changed = 0;
09437          if (!ch || !ch->ast) {
09438             break;
09439          }
09440          misdn_update_remote_party(ch->ast, &bc->redirecting.to,
09441             AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
09442          break;
09443       default:
09444          bc->redirecting.to_changed = 0;
09445          chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
09446             bc->notify_description_code);
09447          break;
09448       }
09449       bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
09450       break;
09451    case Fac_EctInform:
09452       /* Private-Public ISDN interworking message */
09453       if (ch && ch->ast && bc->fac_in.u.EctInform.RedirectionPresent) {
09454          /* Add configured prefix to the redirection number */
09455          memset(&party_id, 0, sizeof(party_id));
09456          misdn_PresentedNumberUnscreened_extract(&party_id,
09457             &bc->fac_in.u.EctInform.Redirection);
09458          misdn_add_number_prefix(bc->port, party_id.number_type,
09459             party_id.number, sizeof(party_id.number));
09460 
09461          /*
09462           * It would be preferable to update the connected line information
09463           * only when the message callStatus is active.  However, the
09464           * optional redirection number may not be present in the active
09465           * message if an alerting message were received earlier.
09466           *
09467           * The consequences if we wind up sending two updates is benign.
09468           * The other end will think that it got transferred twice.
09469           */
09470          misdn_update_remote_party(ch->ast, &party_id,
09471             (bc->fac_in.u.EctInform.Status == 0 /* alerting */)
09472                ? AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
09473                : AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
09474                bc->incoming_cid_tag);
09475       }
09476       break;
09477 #if 0 /* We don't handle this yet */
09478    case Fac_EctLoopTest:
09479       /* The use of this message is unclear on how it works to detect loops. */
09480       /* We don't handle this yet */
09481       break;
09482 #endif   /* We don't handle this yet */
09483    case Fac_CallInfoRetain:
09484       switch (event) {
09485       case EVENT_ALERTING:
09486       case EVENT_DISCONNECT:
09487          /* CCBS/CCNR is available */
09488          if (ch && ch->peer) {
09489             AST_LIST_LOCK(&misdn_cc_records_db);
09490             if (ch->record_id == -1) {
09491                cc_record = misdn_cc_new();
09492             } else {
09493                /*
09494                 * We are doing a call-completion attempt
09495                 * or the switch is sending us extra call-completion
09496                 * availability indications (erroneously?).
09497                 *
09498                 * Assume that the network request retention option
09499                 * is not on and that the current call-completion
09500                 * request is disabled.
09501                 */
09502                cc_record = misdn_cc_find_by_id(ch->record_id);
09503                if (cc_record) {
09504                   if (cc_record->ptp && cc_record->mode.ptp.bc) {
09505                      /*
09506                       * What?  We are getting mixed messages from the
09507                       * switch.  We are currently setup for
09508                       * point-to-point.  Now we are switching to
09509                       * point-to-multipoint.
09510                       *
09511                       * Close the call-completion signaling link
09512                       */
09513                      cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
09514                      cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
09515                      misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
09516                   }
09517 
09518                   /*
09519                    * Resetup the existing record for a possible new
09520                    * call-completion request.
09521                    */
09522                   new_record_id = misdn_cc_record_id_new();
09523                   if (new_record_id < 0) {
09524                      /* Looks like we must keep the old id anyway. */
09525                   } else {
09526                      cc_record->record_id = new_record_id;
09527                      ch->record_id = new_record_id;
09528                   }
09529                   cc_record->ptp = 0;
09530                   cc_record->port = bc->port;
09531                   memset(&cc_record->mode, 0, sizeof(cc_record->mode));
09532                   cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
09533                   cc_record->invoke_id = ++misdn_invoke_id;
09534                   cc_record->activated = 0;
09535                   cc_record->outstanding_message = 0;
09536                   cc_record->activation_requested = 0;
09537                   cc_record->error_code = FacError_None;
09538                   cc_record->reject_code = FacReject_None;
09539                   memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
09540                   memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
09541                   cc_record->time_created = time(NULL);
09542 
09543                   cc_record = NULL;
09544                } else {
09545                   /*
09546                    * Where did the record go?  We will have to recapture
09547                    * the call setup information.  Unfortunately, some
09548                    * setup information may have been changed.
09549                    */
09550                   ch->record_id = -1;
09551                   cc_record = misdn_cc_new();
09552                }
09553             }
09554             if (cc_record) {
09555                ch->record_id = cc_record->record_id;
09556                cc_record->ptp = 0;
09557                cc_record->port = bc->port;
09558                cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
09559 
09560                /* Record call information for possible call-completion attempt. */
09561                cc_record->redial.caller = bc->caller;
09562                cc_record->redial.dialed = bc->dialed;
09563                cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
09564                cc_record->redial.capability = bc->capability;
09565                cc_record->redial.hdlc = bc->hdlc;
09566             }
09567             AST_LIST_UNLOCK(&misdn_cc_records_db);
09568 
09569             /* Set MISDN_CC_RECORD_ID in original channel */
09570             if (ch->record_id != -1) {
09571                snprintf(buf, sizeof(buf), "%ld", ch->record_id);
09572             } else {
09573                buf[0] = 0;
09574             }
09575             misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
09576          }
09577          break;
09578       default:
09579          chan_misdn_log(0, bc->port,
09580             " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
09581             bc->fac_in.Function);
09582          break;
09583       }
09584       break;
09585    case Fac_CCBS_T_Call:
09586    case Fac_CCBSCall:
09587       switch (event) {
09588       case EVENT_SETUP:
09589          /*
09590           * This is a call completion retry call.
09591           * If we had anything to do we would do it here.
09592           */
09593          break;
09594       default:
09595          chan_misdn_log(0, bc->port, " --> Expected in a SETUP message: facility type:0x%04X\n",
09596             bc->fac_in.Function);
09597          break;
09598       }
09599       break;
09600    case Fac_CCBSDeactivate:
09601       switch (bc->fac_in.u.CCBSDeactivate.ComponentType) {
09602       case FacComponent_Result:
09603          AST_LIST_LOCK(&misdn_cc_records_db);
09604          cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSDeactivate.InvokeID);
09605          if (cc_record) {
09606             cc_record->outstanding_message = 0;
09607          }
09608          AST_LIST_UNLOCK(&misdn_cc_records_db);
09609          break;
09610 
09611       default:
09612          chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09613             bc->fac_in.Function);
09614          break;
09615       }
09616       break;
09617    case Fac_CCBSErase:
09618       AST_LIST_LOCK(&misdn_cc_records_db);
09619       cc_record = misdn_cc_find_by_reference(bc->port, bc->fac_in.u.CCBSErase.CCBSReference);
09620       if (cc_record) {
09621          misdn_cc_delete(cc_record);
09622       }
09623       AST_LIST_UNLOCK(&misdn_cc_records_db);
09624       break;
09625    case Fac_CCBSRemoteUserFree:
09626       misdn_cc_handle_remote_user_free(bc->port, &bc->fac_in);
09627       break;
09628    case Fac_CCBSBFree:
09629       misdn_cc_handle_b_free(bc->port, &bc->fac_in);
09630       break;
09631    case Fac_CCBSStatusRequest:
09632       misdn_cc_handle_ccbs_status_request(bc->port, &bc->fac_in);
09633       break;
09634    case Fac_EraseCallLinkageID:
09635       AST_LIST_LOCK(&misdn_cc_records_db);
09636       cc_record = misdn_cc_find_by_linkage(bc->port,
09637          bc->fac_in.u.EraseCallLinkageID.CallLinkageID);
09638       if (cc_record && !cc_record->activation_requested) {
09639          /*
09640           * The T-RETENTION timer expired before we requested
09641           * call completion activation.  Call completion is no
09642           * longer available.
09643           */
09644          misdn_cc_delete(cc_record);
09645       }
09646       AST_LIST_UNLOCK(&misdn_cc_records_db);
09647       break;
09648    case Fac_CCBSStopAlerting:
09649       /* We do not have anything to do for this message. */
09650       break;
09651    case Fac_CCBSRequest:
09652    case Fac_CCNRRequest:
09653       switch (bc->fac_in.u.CCBSRequest.ComponentType) {
09654       case FacComponent_Result:
09655          AST_LIST_LOCK(&misdn_cc_records_db);
09656          cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSRequest.InvokeID);
09657          if (cc_record && !cc_record->ptp) {
09658             cc_record->outstanding_message = 0;
09659             cc_record->activated = 1;
09660             cc_record->mode.ptmp.recall_mode = bc->fac_in.u.CCBSRequest.Component.Result.RecallMode;
09661             cc_record->mode.ptmp.reference_id = bc->fac_in.u.CCBSRequest.Component.Result.CCBSReference;
09662          }
09663          AST_LIST_UNLOCK(&misdn_cc_records_db);
09664          break;
09665 
09666       default:
09667          chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09668             bc->fac_in.Function);
09669          break;
09670       }
09671       break;
09672 #if 0 /* We don't handle this yet */
09673    case Fac_CCBSInterrogate:
09674    case Fac_CCNRInterrogate:
09675       /* We don't handle this yet */
09676       break;
09677    case Fac_StatusRequest:
09678       /* We don't handle this yet */
09679       break;
09680 #endif   /* We don't handle this yet */
09681 #if 0 /* We don't handle this yet */
09682    case Fac_CCBS_T_Suspend:
09683    case Fac_CCBS_T_Resume:
09684       /* We don't handle this yet */
09685       break;
09686 #endif   /* We don't handle this yet */
09687    case Fac_CCBS_T_RemoteUserFree:
09688       misdn_cc_handle_T_remote_user_free(bc);
09689       break;
09690    case Fac_CCBS_T_Available:
09691       switch (event) {
09692       case EVENT_ALERTING:
09693       case EVENT_DISCONNECT:
09694          /* CCBS-T/CCNR-T is available */
09695          if (ch && ch->peer) {
09696             int set_id = 1;
09697 
09698             AST_LIST_LOCK(&misdn_cc_records_db);
09699             if (ch->record_id == -1) {
09700                cc_record = misdn_cc_new();
09701             } else {
09702                /*
09703                 * We are doing a call-completion attempt
09704                 * or the switch is sending us extra call-completion
09705                 * availability indications (erroneously?).
09706                 */
09707                cc_record = misdn_cc_find_by_id(ch->record_id);
09708                if (cc_record) {
09709                   if (cc_record->ptp && cc_record->mode.ptp.retention_enabled) {
09710                      /*
09711                       * Call-completion is still activated.
09712                       * The user does not have to request it again.
09713                       */
09714                      chan_misdn_log(1, bc->port, " --> Call-completion request retention option is enabled\n");
09715 
09716                      set_id = 0;
09717                   } else {
09718                      if (cc_record->ptp && cc_record->mode.ptp.bc) {
09719                         /*
09720                          * The network request retention option
09721                          * is not on and the current call-completion
09722                          * request is to be disabled.
09723                          *
09724                          * We should get here only if EVENT_DISCONNECT
09725                          *
09726                          * Close the call-completion signaling link
09727                          */
09728                         cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
09729                         cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
09730                         misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
09731                      }
09732 
09733                      /*
09734                       * Resetup the existing record for a possible new
09735                       * call-completion request.
09736                       */
09737                      new_record_id = misdn_cc_record_id_new();
09738                      if (new_record_id < 0) {
09739                         /* Looks like we must keep the old id anyway. */
09740                      } else {
09741                         cc_record->record_id = new_record_id;
09742                         ch->record_id = new_record_id;
09743                      }
09744                      cc_record->ptp = 1;
09745                      cc_record->port = bc->port;
09746                      memset(&cc_record->mode, 0, sizeof(cc_record->mode));
09747                      cc_record->invoke_id = ++misdn_invoke_id;
09748                      cc_record->activated = 0;
09749                      cc_record->outstanding_message = 0;
09750                      cc_record->activation_requested = 0;
09751                      cc_record->error_code = FacError_None;
09752                      cc_record->reject_code = FacReject_None;
09753                      memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
09754                      memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
09755                      cc_record->time_created = time(NULL);
09756                   }
09757                   cc_record = NULL;
09758                } else {
09759                   /*
09760                    * Where did the record go?  We will have to recapture
09761                    * the call setup information.  Unfortunately, some
09762                    * setup information may have been changed.
09763                    */
09764                   ch->record_id = -1;
09765                   cc_record = misdn_cc_new();
09766                }
09767             }
09768             if (cc_record) {
09769                ch->record_id = cc_record->record_id;
09770                cc_record->ptp = 1;
09771                cc_record->port = bc->port;
09772 
09773                /* Record call information for possible call-completion attempt. */
09774                cc_record->redial.caller = bc->caller;
09775                cc_record->redial.dialed = bc->dialed;
09776                cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
09777                cc_record->redial.capability = bc->capability;
09778                cc_record->redial.hdlc = bc->hdlc;
09779             }
09780             AST_LIST_UNLOCK(&misdn_cc_records_db);
09781 
09782             /* Set MISDN_CC_RECORD_ID in original channel */
09783             if (ch->record_id != -1 && set_id) {
09784                snprintf(buf, sizeof(buf), "%ld", ch->record_id);
09785             } else {
09786                buf[0] = 0;
09787             }
09788             misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
09789          }
09790          break;
09791       default:
09792          chan_misdn_log(0, bc->port,
09793             " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
09794             bc->fac_in.Function);
09795          break;
09796       }
09797       break;
09798    case Fac_CCBS_T_Request:
09799    case Fac_CCNR_T_Request:
09800       switch (bc->fac_in.u.CCBS_T_Request.ComponentType) {
09801       case FacComponent_Result:
09802          AST_LIST_LOCK(&misdn_cc_records_db);
09803          cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBS_T_Request.InvokeID);
09804          if (cc_record && cc_record->ptp) {
09805             cc_record->outstanding_message = 0;
09806             cc_record->activated = 1;
09807             cc_record->mode.ptp.retention_enabled =
09808                cc_record->mode.ptp.requested_retention
09809                ? bc->fac_in.u.CCBS_T_Request.Component.Result.RetentionSupported
09810                ? 1 : 0
09811                : 0;
09812          }
09813          AST_LIST_UNLOCK(&misdn_cc_records_db);
09814          break;
09815 
09816       case FacComponent_Invoke:
09817          /* We cannot be User-B in ptp mode. */
09818       default:
09819          chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09820             bc->fac_in.Function);
09821          break;
09822       }
09823       break;
09824 
09825 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
09826    case Fac_None:
09827       break;
09828    default:
09829       chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09830          bc->fac_in.Function);
09831       break;
09832    }
09833 }

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

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

06888 {
06889    struct chan_list *p;
06890 
06891    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06892       return -1;
06893    }
06894 
06895    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);
06896 
06897    p->ast = ast;
06898 
06899    return 0;
06900 }

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

Definition at line 4071 of file chan_misdn.c.

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

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

04072 {
04073    int i;
04074    static char state[8];
04075 
04076    if (!p) {
04077       return NULL;
04078    }
04079 
04080    for (i = 0; i < ARRAY_LEN(state_array); i++) {
04081       if (state_array[i].state == p->state) {
04082          return state_array[i].txt;
04083       }
04084    }
04085 
04086    snprintf(state, sizeof(state), "%d", p->state) ;
04087 
04088    return state;
04089 }

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

Definition at line 6161 of file chan_misdn.c.

References ast_copy_string(), ast_to_misdn_plan(), ast_to_misdn_pres(), ast_to_misdn_screen(), ast_to_misdn_ton(), misdn_bchannel::caller, ast_channel::connected, misdn_bchannel::connected, debug_numtype(), ast_party_connected_line::id, MISDN_CFG_CPNDIALPLAN, misdn_cfg_get(), MISDN_CFG_LOCALDIALPLAN, ast_party_id::name, misdn_party_id::name, misdn_party_id::number, ast_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, NUMPLAN_ISDN, NUMPLAN_UNKNOWN, NUMTYPE_UNKNOWN, ORG_MISDN, ast_party_number::plan, misdn_bchannel::port, ast_party_number::presentation, misdn_party_id::presentation, S_COR, S_OR, misdn_party_id::screening, ast_party_number::str, ast_party_name::str, ast_party_number::valid, and ast_party_name::valid.

Referenced by misdn_update_connected_line().

06162 {
06163    int number_type;
06164 
06165    if (originator == ORG_MISDN) {
06166       /* ORIGINATOR MISDN (incoming call) */
06167 
06168       ast_copy_string(bc->connected.name,
06169          S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
06170          sizeof(bc->connected.name));
06171       if (ast->connected.id.number.valid) {
06172          ast_copy_string(bc->connected.number, S_OR(ast->connected.id.number.str, ""),
06173             sizeof(bc->connected.number));
06174          bc->connected.presentation = ast_to_misdn_pres(ast->connected.id.number.presentation);
06175          bc->connected.screening = ast_to_misdn_screen(ast->connected.id.number.presentation);
06176          bc->connected.number_type = ast_to_misdn_ton(ast->connected.id.number.plan);
06177          bc->connected.number_plan = ast_to_misdn_plan(ast->connected.id.number.plan);
06178       } else {
06179          bc->connected.number[0] = '\0';
06180          bc->connected.presentation = 0;/* Allowed */
06181          bc->connected.screening = 0;/* Unscreened */
06182          bc->connected.number_type = NUMTYPE_UNKNOWN;
06183          bc->connected.number_plan = NUMPLAN_UNKNOWN;
06184       }
06185 
06186       misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
06187       if (0 <= number_type) {
06188          /* Force us to send in CONNECT message */
06189          bc->connected.number_type = number_type;
06190          bc->connected.number_plan = NUMPLAN_ISDN;
06191       }
06192       debug_numtype(bc->port, bc->connected.number_type, "CTON");
06193    } else {
06194       /* ORIGINATOR Asterisk (outgoing call) */
06195 
06196       ast_copy_string(bc->caller.name,
06197          S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
06198          sizeof(bc->caller.name));
06199       if (ast->connected.id.number.valid) {
06200          ast_copy_string(bc->caller.number, S_OR(ast->connected.id.number.str, ""),
06201             sizeof(bc->caller.number));
06202          bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number.presentation);
06203          bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number.presentation);
06204          bc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number.plan);
06205          bc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number.plan);
06206       } else {
06207          bc->caller.number[0] = '\0';
06208          bc->caller.presentation = 0;/* Allowed */
06209          bc->caller.screening = 0;/* Unscreened */
06210          bc->caller.number_type = NUMTYPE_UNKNOWN;
06211          bc->caller.number_plan = NUMPLAN_UNKNOWN;
06212       }
06213 
06214       misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
06215       if (0 <= number_type) {
06216          /* Force us to send in SETUP message */
06217          bc->caller.number_type = number_type;
06218          bc->caller.number_plan = NUMPLAN_ISDN;
06219       }
06220       debug_numtype(bc->port, bc->caller.number_type, "LTON");
06221    }
06222 }

static int misdn_hangup ( struct ast_channel ast  )  [static]

Definition at line 7043 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, AST_CAUSE_NORMAL_CLEARING, ast_copy_string(), ast_debug, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, chan_list::bc, ast_channel::caller, misdn_bchannel::cause, chan_list_unref, chan_misdn_log(), ast_channel::context, EVENT_DISCONNECT, EVENT_RELEASE, EVENT_RELEASE_COMPLETE, ast_channel::exten, ast_channel::hangupcause, hanguptone_indicate(), chan_list::hold, ast_party_caller::id, 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_chan_is_valid(), MISDN_CLEANING, MISDN_CONNECTED, MISDN_DIALING, MISDN_DISCONNECTED, misdn_get_ch_state(), MISDN_HOLD_DISCONNECT, MISDN_HOLD_IDLE, MISDN_INCOMING_SETUP, misdn_lib_find_held_bc(), misdn_lib_release(), misdn_lib_send_event(), MISDN_NOTHING, MISDN_PROCEEDING, MISDN_PROGRESS, ast_party_id::name, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, misdn_bchannel::nt, ast_party_id::number, 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(), ast_party_number::str, ast_party_name::str, misdn_bchannel::uu, misdn_bchannel::uulen, ast_party_number::valid, and ast_party_name::valid.

07044 {
07045    struct chan_list *p;
07046    struct misdn_bchannel *bc;
07047    const char *var;
07048 
07049    if (!ast) {
07050       return -1;
07051    }
07052 
07053    ast_debug(1, "misdn_hangup(%s)\n", ast->name);
07054 
07055    /* Take the ast_channel's tech_pvt reference. */
07056    ast_mutex_lock(&release_lock);
07057    p = MISDN_ASTERISK_TECH_PVT(ast);
07058    if (!p) {
07059       ast_mutex_unlock(&release_lock);
07060       return -1;
07061    }
07062    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
07063 
07064    if (!misdn_chan_is_valid(p)) {
07065       ast_mutex_unlock(&release_lock);
07066       chan_list_unref(p, "Release ast_channel reference.  Was not active?");
07067       return 0;
07068    }
07069 
07070    if (p->hold.state == MISDN_HOLD_IDLE) {
07071       bc = p->bc;
07072    } else {
07073       p->hold.state = MISDN_HOLD_DISCONNECT;
07074       bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
07075       if (!bc) {
07076          chan_misdn_log(4, p->hold.port,
07077             "misdn_hangup: Could not find held bc for (%s)\n", ast->name);
07078          release_chan_early(p);
07079          ast_mutex_unlock(&release_lock);
07080          chan_list_unref(p, "Release ast_channel reference");
07081          return 0;
07082       }
07083    }
07084 
07085    if (ast->_state == AST_STATE_RESERVED || p->state == MISDN_NOTHING) {
07086       /* between request and call */
07087       ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
07088       release_chan_early(p);
07089       if (bc) {
07090          misdn_lib_release(bc);
07091       }
07092       ast_mutex_unlock(&release_lock);
07093       chan_list_unref(p, "Release ast_channel reference");
07094       return 0;
07095    }
07096    if (!bc) {
07097       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
07098          misdn_get_ch_state(p), p->l3id);
07099       release_chan_early(p);
07100       ast_mutex_unlock(&release_lock);
07101       chan_list_unref(p, "Release ast_channel reference");
07102       return 0;
07103    }
07104 
07105    p->ast = NULL;
07106    p->need_hangup = 0;
07107    p->need_queue_hangup = 0;
07108    p->need_busy = 0;
07109 
07110    if (!bc->nt) {
07111       stop_bc_tones(p);
07112    }
07113 
07114    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
07115 
07116    /* Channel lock is already held when we are called. */
07117    //ast_channel_lock(ast);
07118    var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
07119    if (!var) {
07120       var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
07121    }
07122    if (var) {
07123       int tmpcause;
07124 
07125       tmpcause = atoi(var);
07126       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
07127    }
07128 
07129    var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
07130    if (var) {
07131       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
07132       ast_copy_string(bc->uu, var, sizeof(bc->uu));
07133       bc->uulen = strlen(bc->uu);
07134    }
07135    //ast_channel_unlock(ast);
07136 
07137    chan_misdn_log(1, bc->port,
07138       "* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
07139       bc->pid,
07140       ast->context,
07141       ast->exten,
07142       (ast->caller.id.name.valid && ast->caller.id.name.str)
07143          ? ast->caller.id.name.str : "",
07144       (ast->caller.id.number.valid && ast->caller.id.number.str)
07145          ? ast->caller.id.number.str : "",
07146       misdn_get_ch_state(p));
07147    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
07148    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
07149    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
07150 
07151    switch (p->state) {
07152    case MISDN_INCOMING_SETUP:
07153       /*
07154        * This is the only place in misdn_hangup, where we
07155        * can call release_chan, else it might create a lot of trouble.
07156        */
07157       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
07158       release_chan(p, bc);
07159       misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
07160       ast_mutex_unlock(&release_lock);
07161       chan_list_unref(p, "Release ast_channel reference");
07162       return 0;
07163    case MISDN_DIALING:
07164       if (p->hold.state == MISDN_HOLD_IDLE) {
07165          start_bc_tones(p);
07166          hanguptone_indicate(p);
07167       }
07168 
07169       if (bc->need_disconnect) {
07170          misdn_lib_send_event(bc, EVENT_DISCONNECT);
07171       }
07172       break;
07173    case MISDN_CALLING_ACKNOWLEDGE:
07174       if (p->hold.state == MISDN_HOLD_IDLE) {
07175          start_bc_tones(p);
07176          hanguptone_indicate(p);
07177       }
07178 
07179       if (bc->need_disconnect) {
07180          misdn_lib_send_event(bc, EVENT_DISCONNECT);
07181       }
07182       break;
07183 
07184    case MISDN_CALLING:
07185    case MISDN_ALERTING:
07186    case MISDN_PROGRESS:
07187    case MISDN_PROCEEDING:
07188       if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
07189          hanguptone_indicate(p);
07190       }
07191 
07192       if (bc->need_disconnect) {
07193          misdn_lib_send_event(bc, EVENT_DISCONNECT);
07194       }
07195       break;
07196    case MISDN_CONNECTED:
07197       /*  Alerting or Disconnect */
07198       if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
07199          start_bc_tones(p);
07200          hanguptone_indicate(p);
07201          bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
07202       }
07203       if (bc->need_disconnect) {
07204          misdn_lib_send_event(bc, EVENT_DISCONNECT);
07205       }
07206       break;
07207    case MISDN_DISCONNECTED:
07208       if (bc->need_release) {
07209          misdn_lib_send_event(bc, EVENT_RELEASE);
07210       }
07211       break;
07212 
07213    case MISDN_CLEANING:
07214       ast_mutex_unlock(&release_lock);
07215       chan_list_unref(p, "Release ast_channel reference");
07216       return 0;
07217 
07218    case MISDN_BUSY:
07219       break;
07220    default:
07221       if (bc->nt) {
07222          bc->out_cause = -1;
07223          if (bc->need_release) {
07224             misdn_lib_send_event(bc, EVENT_RELEASE);
07225          }
07226       } else {
07227          if (bc->need_disconnect) {
07228             misdn_lib_send_event(bc, EVENT_DISCONNECT);
07229          }
07230       }
07231       break;
07232    }
07233 
07234    p->state = MISDN_CLEANING;
07235    chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast->name,
07236       misdn_get_ch_state(p));
07237 
07238    ast_mutex_unlock(&release_lock);
07239    chan_list_unref(p, "Release ast_channel reference");
07240    return 0;
07241 }

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

Definition at line 6904 of file chan_misdn.c.

References AST_CAUSE_INVALID_NUMBER_FORMAT, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_OFFHOOK, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_REDIRECTING, 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_lib_send_event(), misdn_update_connected_line(), misdn_update_redirecting(), chan_list::mohinterpret, misdn_bchannel::nt, ORG_MISDN, chan_list::originator, misdn_bchannel::out_cause, chan_list::overlap_dial, misdn_bchannel::pid, misdn_bchannel::port, start_bc_tones(), chan_list::state, hold_info::state, and stop_indicate().

06905 {
06906    struct chan_list *p;
06907 
06908    if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06909       ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
06910       return -1;
06911    }
06912 
06913    if (!p->bc) {
06914       if (p->hold.state == MISDN_HOLD_IDLE) {
06915          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
06916             ast->name);
06917          ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
06918       } else {
06919          chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
06920             cond, ast->name);
06921       }
06922       return -1;
06923    }
06924 
06925    chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n", cond, ast->name);
06926 
06927    switch (cond) {
06928    case AST_CONTROL_BUSY:
06929       chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
06930       ast_setstate(ast, AST_STATE_BUSY);
06931 
06932       p->bc->out_cause = AST_CAUSE_USER_BUSY;
06933       if (p->state != MISDN_CONNECTED) {
06934          start_bc_tones(p);
06935          misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
06936       }
06937       return -1;
06938    case AST_CONTROL_RING:
06939       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
06940       return -1;
06941    case AST_CONTROL_RINGING:
06942       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
06943       switch (p->state) {
06944       case MISDN_ALERTING:
06945          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
06946          break;
06947       case MISDN_CONNECTED:
06948          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc->pid);
06949          return -1;
06950       default:
06951          p->state = MISDN_ALERTING;
06952          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
06953          misdn_lib_send_event(p->bc, EVENT_ALERTING);
06954 
06955          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
06956          ast_setstate(ast, AST_STATE_RING);
06957 
06958          if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
06959             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
06960          } else {
06961             return -1;
06962          }
06963       }
06964       break;
06965    case AST_CONTROL_ANSWER:
06966       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
06967       start_bc_tones(p);
06968       break;
06969    case AST_CONTROL_TAKEOFFHOOK:
06970       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
06971       return -1;
06972    case AST_CONTROL_OFFHOOK:
06973       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
06974       return -1;
06975    case AST_CONTROL_FLASH:
06976       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
06977       break;
06978    case AST_CONTROL_PROGRESS:
06979       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
06980       misdn_lib_send_event(p->bc, EVENT_PROGRESS);
06981       break;
06982    case AST_CONTROL_PROCEEDING:
06983       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
06984       misdn_lib_send_event(p->bc, EVENT_PROCEEDING);
06985       break;
06986    case AST_CONTROL_INCOMPLETE:
06987       chan_misdn_log(1, p->bc->port, " --> *\tincomplete pid:%d\n", p->bc->pid);
06988       if (!p->overlap_dial) {
06989          /* Overlapped dialing not enabled - send hangup */
06990          p->bc->out_cause = AST_CAUSE_INVALID_NUMBER_FORMAT;
06991          start_bc_tones(p);
06992          misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
06993 
06994          if (p->bc->nt) {
06995             hanguptone_indicate(p);
06996          }
06997       }
06998       break;
06999    case AST_CONTROL_CONGESTION:
07000       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
07001 
07002       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
07003       start_bc_tones(p);
07004       misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
07005 
07006       if (p->bc->nt) {
07007          hanguptone_indicate(p);
07008       }
07009       break;
07010    case -1 :
07011       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
07012 
07013       stop_indicate(p);
07014 
07015       if (p->state == MISDN_CONNECTED) {
07016          start_bc_tones(p);
07017       }
07018       break;
07019    case AST_CONTROL_HOLD:
07020       ast_moh_start(ast, data, p->mohinterpret);
07021       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
07022       break;
07023    case AST_CONTROL_UNHOLD:
07024       ast_moh_stop(ast);
07025       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
07026       break;
07027    case AST_CONTROL_CONNECTED_LINE:
07028       chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
07029       misdn_update_connected_line(ast, p->bc, p->originator);
07030       break;
07031    case AST_CONTROL_REDIRECTING:
07032       chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
07033       misdn_update_redirecting(ast, p->bc, p->originator);
07034       break;
07035    default:
07036       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
07037       return -1;
07038    }
07039 
07040    return 0;
07041 }

static int misdn_is_msn_valid ( int  port,
const struct misdn_party_dialing dialed 
) [static]

Definition at line 9846 of file chan_misdn.c.

References ast_copy_string(), misdn_add_number_prefix(), misdn_cfg_is_msn_valid(), misdn_party_dialing::number, and misdn_party_dialing::number_type.

Referenced by cb_events().

09847 {
09848    char number[sizeof(dialed->number)];
09849 
09850    ast_copy_string(number, dialed->number, sizeof(number));
09851    misdn_add_number_prefix(port, dialed->number_type, number, sizeof(number));
09852    return misdn_cfg_is_msn_valid(port, number);
09853 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

Definition at line 12497 of file chan_misdn.c.

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

Referenced by chan_list_destructor(), and config_jitterbuffer().

12498 {
12499    ast_mutex_destroy(&jb->mutexjb);
12500 
12501    ast_free(jb->ok);
12502    ast_free(jb->samples);
12503    ast_free(jb);
12504 }

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

12575 {
12576    int i;
12577    int wp;
12578    int rp;
12579    int read = 0;
12580 
12581    ast_mutex_lock(&jb->mutexjb);
12582 
12583    rp = jb->rp;
12584    wp = jb->wp;
12585 
12586    if (jb->state_empty) {
12587       for (i = 0; i < len; i++) {
12588          if (wp == rp) {
12589             jb->rp = rp;
12590             jb->state_empty = 0;
12591 
12592             ast_mutex_unlock(&jb->mutexjb);
12593 
12594             return read;
12595          } else {
12596             if (jb->ok[rp] == 1) {
12597                data[i] = jb->samples[rp];
12598                jb->ok[rp] = 0;
12599                rp = (rp != jb->size - 1) ? rp + 1 : 0;
12600                read += 1;
12601             }
12602          }
12603       }
12604 
12605       if (wp >= rp) {
12606          jb->state_buffer = wp - rp;
12607       } else {
12608          jb->state_buffer = jb->size - rp + wp;
12609       }
12610       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12611 
12612       jb->rp = rp;
12613    } else {
12614       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
12615    }
12616 
12617    ast_mutex_unlock(&jb->mutexjb);
12618 
12619    return read;
12620 }

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

12509 {
12510    int i;
12511    int j;
12512    int rp;
12513    int wp;
12514 
12515    if (!jb || ! data) {
12516       return 0;
12517    }
12518 
12519    ast_mutex_lock(&jb->mutexjb);
12520 
12521    wp = jb->wp;
12522    rp = jb->rp;
12523 
12524    for (i = 0; i < len; i++) {
12525       jb->samples[wp] = data[i];
12526       jb->ok[wp] = 1;
12527       wp = (wp != jb->size - 1) ? wp + 1 : 0;
12528 
12529       if (wp == jb->rp) {
12530          jb->state_full = 1;
12531       }
12532    }
12533 
12534    if (wp >= rp) {
12535       jb->state_buffer = wp - rp;
12536    } else {
12537       jb->state_buffer = jb->size - rp + wp;
12538    }
12539    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12540 
12541    if (jb->state_full) {
12542       jb->wp = wp;
12543 
12544       rp = wp;
12545       for (j = 0; j < jb->upper_threshold; j++) {
12546          rp = (rp != 0) ? rp - 1 : jb->size - 1;
12547       }
12548       jb->rp = rp;
12549       jb->state_full = 0;
12550       jb->state_empty = 1;
12551 
12552       ast_mutex_unlock(&jb->mutexjb);
12553 
12554       return -1;
12555    }
12556 
12557    if (!jb->state_empty) {
12558       jb->bytes_wrote += len;
12559       if (jb->bytes_wrote >= jb->upper_threshold) {
12560          jb->state_empty = 1;
12561          jb->bytes_wrote = 0;
12562       }
12563    }
12564    jb->wp = wp;
12565 
12566    ast_mutex_unlock(&jb->mutexjb);
12567 
12568    return 0;
12569 }

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

allocates the jb-structure and initialize the elements

Definition at line 12460 of file chan_misdn.c.

References ast_calloc, ast_free, ast_mutex_init, chan_misdn_log(), misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::samples, misdn_jb::size, and misdn_jb::upper_threshold.

Referenced by config_jitterbuffer().

12461 {
12462    struct misdn_jb *jb;
12463 
12464    jb = ast_calloc(1, sizeof(*jb));
12465    if (!jb) {
12466        chan_misdn_log(-1, 0, "No free Mem for jb\n");
12467        return NULL;
12468    }
12469    jb->size = size;
12470    jb->upper_threshold = upper_threshold;
12471    //jb->wp = 0;
12472    //jb->rp = 0;
12473    //jb->state_full = 0;
12474    //jb->state_empty = 0;
12475    //jb->bytes_wrote = 0;
12476    jb->samples = ast_calloc(size, sizeof(*jb->samples));
12477    if (!jb->samples) {
12478       ast_free(jb);
12479       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
12480       return NULL;
12481    }
12482 
12483    jb->ok = ast_calloc(size, sizeof(*jb->ok));
12484    if (!jb->ok) {
12485       ast_free(jb->samples);
12486       ast_free(jb);
12487       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
12488       return NULL;
12489    }
12490 
12491    ast_mutex_init(&jb->mutexjb);
12492 
12493    return jb;
12494 }

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

Definition at line 3588 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

03589 {
03590    const int *data = vdata;
03591 
03592    misdn_lib_isdn_l1watcher(*data);
03593    chan_misdn_log(5, *data, "L1watcher timeout\n");
03594    return 1;
03595 }

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

Definition at line 8111 of file chan_misdn.c.

References ast_party_caller::ani, chan_list::ast, ast_callerid_parse(), ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_jb_configure(), ast_log(), AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_channel::caller, chan_list_ref, chan_misdn_log(), cid_name, cid_num, ast_channel::exten, LOG_ERROR, MISDN_ASTERISK_TECH_PVT, misdn_cfg_get(), misdn_cfg_get_next_port(), MISDN_GEN_BRIDGING, misdn_get_global_jbconf(), misdn_lib_port_is_pri(), ast_channel::nativeformats, ast_party_id::number, chan_list::pipe, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, ast_party_number::str, ast_channel::tech, ast_party_number::valid, and ast_channel::writeformat.

Referenced by cb_events(), and misdn_request().

08112 {
08113    struct ast_channel *tmp;
08114    char *cid_name = NULL;
08115    char *cid_num = NULL;
08116    int chan_offset = 0;
08117    int tmp_port = misdn_cfg_get_next_port(0);
08118    int bridging;
08119 
08120    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
08121       if (tmp_port == port) {
08122          break;
08123       }
08124       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
08125    }
08126    if (c < 0) {
08127       c = 0;
08128    }
08129 
08130    if (callerid) {
08131       ast_callerid_parse(callerid, &cid_name, &cid_num);
08132    }
08133 
08134    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", linkedid, 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
08135    if (tmp) {
08136       chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
08137 
08138       tmp->nativeformats = prefformat;
08139 
08140       tmp->readformat = format;
08141       tmp->rawreadformat = format;
08142       tmp->writeformat = format;
08143       tmp->rawwriteformat = format;
08144 
08145       /* Link the channel and private together */
08146       chan_list_ref(chlist, "Give a reference to ast_channel");
08147       MISDN_ASTERISK_TECH_PVT(tmp) = chlist;
08148       chlist->ast = tmp;
08149 
08150       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
08151       tmp->tech = bridging ? &misdn_tech : &misdn_tech_wo_bridge;
08152 
08153       tmp->writeformat = format;
08154       tmp->readformat = format;
08155       tmp->priority = 1;
08156 
08157       if (exten) {
08158          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
08159       } else {
08160          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
08161       }
08162 
08163       if (!ast_strlen_zero(cid_num)) {
08164          /* Don't use ast_set_callerid() here because it will
08165           * generate a needless NewCallerID event */
08166          tmp->caller.ani.number.valid = 1;
08167          tmp->caller.ani.number.str = ast_strdup(cid_num);
08168       }
08169 
08170       if (pipe(chlist->pipe) < 0) {
08171          ast_log(LOG_ERROR, "Pipe failed\n");
08172       }
08173       ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
08174 
08175       tmp->rings = (state == AST_STATE_RING) ? 1 : 0;
08176 
08177       ast_jb_configure(tmp, misdn_get_global_jbconf());
08178    } else {
08179       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
08180    }
08181 
08182    return tmp;
08183 }

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

Definition at line 3597 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, misdn_bchannel::caller, chan_misdn_log(), chan_list::context, misdn_bchannel::dialed, EVENT_DISCONNECT, ast_channel::exten, hanguptone_indicate(), MISDN_CLEANING, MISDN_DIALING, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_party_id::number, misdn_party_dialing::number, 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().

03598 {
03599    struct timeval tv_end, tv_now;
03600    int diff;
03601    struct chan_list *ch = (struct chan_list *) data;
03602    char *dad;
03603 
03604    chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
03605 
03606    if (ch->state != MISDN_WAITING4DIGS) {
03607       ch->overlap_dial_task = -1;
03608       return 0;
03609    }
03610 
03611    ast_mutex_lock(&ch->overlap_tv_lock);
03612    tv_end = ch->overlap_tv;
03613    ast_mutex_unlock(&ch->overlap_tv_lock);
03614 
03615    tv_end.tv_sec += ch->overlap_dial;
03616    tv_now = ast_tvnow();
03617 
03618    diff = ast_tvdiff_ms(tv_end, tv_now);
03619    if (100 < diff) {
03620       return diff;
03621    }
03622 
03623    /* if we are 100ms near the timeout, we are satisfied.. */
03624    stop_indicate(ch);
03625 
03626    if (ast_strlen_zero(ch->bc->dialed.number)) {
03627       dad = "s";
03628       strcpy(ch->ast->exten, dad);
03629    } else {
03630       dad = ch->bc->dialed.number;
03631    }
03632 
03633    if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
03634       ch->state = MISDN_DIALING;
03635       if (pbx_start_chan(ch) < 0) {
03636          chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
03637          goto misdn_overlap_dial_task_disconnect;
03638       }
03639    } else {
03640 misdn_overlap_dial_task_disconnect:
03641       hanguptone_indicate(ch);
03642       ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
03643       ch->state = MISDN_CLEANING;
03644       misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
03645    }
03646    ch->overlap_dial_task = -1;
03647    return 0;
03648 }

static void misdn_prefix_string ( const char *  str_prefix,
char *  str_main,
size_t  size 
) [static]

Definition at line 3353 of file chan_misdn.c.

Referenced by misdn_add_number_prefix().

03354 {
03355    size_t len_over;
03356    size_t len_total;
03357    size_t len_main;
03358    size_t len_prefix;
03359 
03360    len_prefix = strlen(str_prefix);
03361    if (!len_prefix) {
03362       /* There is no prefix to prepend. */
03363       return;
03364    }
03365    len_main = strlen(str_main);
03366    len_total = len_prefix + len_main;
03367    if (size <= len_total) {
03368       /* We need to truncate since the buffer is too small. */
03369       len_over = len_total + 1 - size;
03370       if (len_over <= len_main) {
03371          len_main -= len_over;
03372       } else {
03373          len_over -= len_main;
03374          len_main = 0;
03375          len_prefix -= len_over;
03376       }
03377    }
03378    if (len_main) {
03379       memmove(str_main + len_prefix, str_main, len_main);
03380    }
03381    memcpy(str_main, str_prefix, len_prefix);
03382    str_main[len_prefix + len_main] = '\0';
03383 }

static void misdn_queue_connected_line_update ( struct ast_channel ast,
const struct misdn_party_id id,
enum AST_CONNECTED_LINE_UPDATE_SOURCE  source,
char *  cid_tag 
) [static]
static struct ast_frame* misdn_read ( struct ast_channel ast  )  [static, read]

Definition at line 7319 of file chan_misdn.c.

References chan_list::ast_dsp, AST_FORMAT_ALAW, AST_FRAME_VOICE, ast_poll, chan_list::ast_rd_buf, ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), chan_list::bc, chan_misdn_log(), ast_frame_subclass::codec, 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.

07320 {
07321    struct chan_list *tmp;
07322    int len, t;
07323    struct pollfd pfd = { .fd = -1, .events = POLLIN };
07324 
07325    if (!ast) {
07326       chan_misdn_log(1, 0, "misdn_read called without ast\n");
07327       return NULL;
07328    }
07329    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
07330       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
07331       return NULL;
07332    }
07333 
07334    if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
07335       chan_misdn_log(1, 0, "misdn_read called without bc\n");
07336       return NULL;
07337    }
07338 
07339    pfd.fd = tmp->pipe[0];
07340    t = ast_poll(&pfd, 1, 20);
07341 
07342    if (t < 0) {
07343       chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
07344       return NULL;
07345    }
07346 
07347    if (!t) {
07348       chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
07349       len = 160;
07350    } else if (pfd.revents & POLLIN) {
07351       len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
07352 
07353       if (len <= 0) {
07354          /* we hangup here, since our pipe is closed */
07355          chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
07356          return NULL;
07357       }
07358    } else {
07359       return NULL;
07360    }
07361 
07362    tmp->frame.frametype = AST_FRAME_VOICE;
07363    tmp->frame.subclass.codec = AST_FORMAT_ALAW;
07364    tmp->frame.datalen = len;
07365    tmp->frame.samples = len;
07366    tmp->frame.mallocd = 0;
07367    tmp->frame.offset = 0;
07368    tmp->frame.delivery = ast_tv(0, 0);
07369    tmp->frame.src = NULL;
07370    tmp->frame.data.ptr = tmp->ast_rd_buf;
07371 
07372    if (tmp->faxdetect && !tmp->faxhandled) {
07373       if (tmp->faxdetect_timeout) {
07374          if (ast_tvzero(tmp->faxdetect_tv)) {
07375             tmp->faxdetect_tv = ast_tvnow();
07376             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
07377             return process_ast_dsp(tmp, &tmp->frame);
07378          } else {
07379             struct timeval tv_now = ast_tvnow();
07380             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
07381             if (diff <= (tmp->faxdetect_timeout * 1000)) {
07382                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
07383                return process_ast_dsp(tmp, &tmp->frame);
07384             } else {
07385                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
07386                tmp->faxdetect = 0;
07387                return &tmp->frame;
07388             }
07389          }
07390       } else {
07391          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
07392          return process_ast_dsp(tmp, &tmp->frame);
07393       }
07394    } else {
07395       if (tmp->ast_dsp) {
07396          return process_ast_dsp(tmp, &tmp->frame);
07397       } else {
07398          return &tmp->frame;
07399       }
07400    }
07401 }

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

Definition at line 7772 of file chan_misdn.c.

References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, chan_list_init(), chan_list_unref, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, cl_queue_chan(), misdn_bchannel::dec, ext, get_robin_position(), 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_lib_release(), misdn_new(), chan_list::need_hangup, ORG_AST, misdn_bchannel::port, robin_list::port, and read_config().

07773 {
07774    struct ast_channel *ast;
07775    char group[BUFFERSIZE + 1] = "";
07776    char dial_str[128];
07777    char *dest_cp;
07778    char *p = NULL;
07779    int channel = 0;
07780    int port = 0;
07781    struct misdn_bchannel *newbc = NULL;
07782    int dec = 0;
07783 #if defined(AST_MISDN_ENHANCEMENTS)
07784    int cc_retry_call = 0;  /* TRUE if this is a call completion retry call */
07785    long record_id = -1;
07786    struct misdn_cc_record *cc_record;
07787    const char *err_msg;
07788 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
07789    struct chan_list *cl;
07790 
07791    AST_DECLARE_APP_ARGS(args,
07792       AST_APP_ARG(intf);   /* interface token */
07793       AST_APP_ARG(ext); /* extension token */
07794       AST_APP_ARG(opts);   /* options token */
07795    );
07796 
07797    snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
07798 
07799    /*
07800     * data is ---v
07801     * Dial(mISDN/g:group_name[/extension[/options]])
07802     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
07803     * Dial(mISDN/cc/cc-record-id)
07804     *
07805     * The dial extension could be empty if you are using MISDN_KEYPAD
07806     * to control ISDN provider features.
07807     */
07808    dest_cp = ast_strdupa(data);
07809    AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
07810    if (!args.ext) {
07811       args.ext = "";
07812    }
07813 
07814    if (!ast_strlen_zero(args.intf)) {
07815       if (args.intf[0] == 'g' && args.intf[1] == ':') {
07816          /* We make a group call lets checkout which ports are in my group */
07817          args.intf += 2;
07818          ast_copy_string(group, args.intf, sizeof(group));
07819          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
07820 #if defined(AST_MISDN_ENHANCEMENTS)
07821       } else if (strcmp(args.intf, "cc") == 0) {
07822          cc_retry_call = 1;
07823 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
07824       } else if ((p = strchr(args.intf, ':'))) {
07825          /* we have a preselected channel */
07826          *p++ = 0;
07827          channel = atoi(p);
07828          port = atoi(args.intf);
07829          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
07830       } else {
07831          port = atoi(args.intf);
07832       }
07833    } else {
07834       ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
07835       return NULL;
07836    }
07837 
07838 #if defined(AST_MISDN_ENHANCEMENTS)
07839    if (cc_retry_call) {
07840       if (ast_strlen_zero(args.ext)) {
07841          ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT cc-record-id, check extensions.conf\n", dial_str);
07842          return NULL;
07843       }
07844       if (!isdigit(*args.ext)) {
07845          ast_log(LOG_WARNING, " --> ! IND : Dial(%s) cc-record-id must be a number.\n", dial_str);
07846          return NULL;
07847       }
07848       record_id = atol(args.ext);
07849 
07850       AST_LIST_LOCK(&misdn_cc_records_db);
07851       cc_record = misdn_cc_find_by_id(record_id);
07852       if (!cc_record) {
07853          AST_LIST_UNLOCK(&misdn_cc_records_db);
07854          err_msg = misdn_cc_record_not_found;
07855          ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
07856          return NULL;
07857       }
07858       if (!cc_record->activated) {
07859          AST_LIST_UNLOCK(&misdn_cc_records_db);
07860          err_msg = "Call completion has not been activated";
07861          ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
07862          return NULL;
07863       }
07864       port = cc_record->port;
07865       AST_LIST_UNLOCK(&misdn_cc_records_db);
07866    }
07867 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
07868 
07869    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
07870       chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
07871       dec = 1;
07872    }
07873 
07874    if (!ast_strlen_zero(group)) {
07875       char cfg_group[BUFFERSIZE + 1];
07876       struct robin_list *rr = NULL;
07877 
07878       /* Group dial */
07879 
07880       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
07881          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
07882          rr = get_robin_position(group);
07883       }
07884 
07885       if (rr) {
07886          int port_start;
07887          int bchan_start;
07888          int port_up;
07889          int check;
07890          int maxbchans;
07891          int wraped = 0;
07892 
07893          if (!rr->port) {
07894             rr->port = misdn_cfg_get_next_port_spin(0);
07895          }
07896 
07897          if (!rr->channel) {
07898             rr->channel = 1;
07899          }
07900 
07901          bchan_start = rr->channel;
07902          port_start = rr->port;
07903          do {
07904             misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
07905             if (strcasecmp(cfg_group, group)) {
07906                wraped = 1;
07907                rr->port = misdn_cfg_get_next_port_spin(rr->port);
07908                rr->channel = 1;
07909                continue;
07910             }
07911 
07912             misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
07913             port_up = misdn_lib_port_up(rr->port, check);
07914 
07915             if (!port_up) {
07916                chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
07917                rr->port = misdn_cfg_get_next_port_spin(rr->port);
07918                rr->channel = 1;
07919             } else if (port_up < 0) {
07920                ast_log(LOG_WARNING, "This port (%d) is blocked\n", rr->port);
07921                rr->port = misdn_cfg_get_next_port_spin(rr->port);
07922                rr->channel = 1;
07923             } else {
07924                chan_misdn_log(4, rr->port, "portup\n");
07925                maxbchans = misdn_lib_get_maxchans(rr->port);
07926 
07927                for (;rr->channel <= maxbchans;rr->channel++) {
07928                   /* ive come full circle and can stop now */
07929                   if (wraped && (rr->port == port_start) && (rr->channel == bchan_start)) {
07930                      break;
07931                   }
07932 
07933                   chan_misdn_log(4, rr->port, "Checking channel %d\n",  rr->channel);
07934 
07935                   if ((newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0))) {
07936                      chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
07937                      rr->channel++;
07938                      break;
07939                   }
07940                }
07941                if (wraped && (rr->port == port_start) && (rr->channel <= bchan_start)) {
07942                   break;
07943                } else if (!newbc || (rr->channel == maxbchans)) {
07944                   rr->port = misdn_cfg_get_next_port_spin(rr->port);
07945                   rr->channel = 1;
07946                }
07947 
07948             }
07949             wraped = 1;
07950          } while (!newbc && (rr->port > 0));
07951       } else {
07952          for (port = misdn_cfg_get_next_port(0); port > 0;
07953             port = misdn_cfg_get_next_port(port)) {
07954             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
07955 
07956             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
07957             if (!strcasecmp(cfg_group, group)) {
07958                int port_up;
07959                int check;
07960 
07961                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
07962                port_up = misdn_lib_port_up(port, check);
07963 
07964                chan_misdn_log(4, port, "portup:%d\n", port_up);
07965 
07966                if (port_up > 0) {
07967                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
07968                   if (newbc) {
07969                      break;
07970                   }
07971                }
07972             }
07973          }
07974       }
07975 
07976       /* Group dial failed ?*/
07977       if (!newbc) {
07978          ast_log(LOG_WARNING,
07979             "Could not Dial out on group '%s'.\n"
07980             "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
07981             "\tOr there was no free channel on none of the ports\n\n",
07982             group);
07983          return NULL;
07984       }
07985    } else {
07986       /* 'Normal' Port dial * Port dial */
07987       if (channel) {
07988          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
07989       }
07990       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
07991       if (!newbc) {
07992          ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
07993          return NULL;
07994       }
07995    }
07996 
07997    /* create ast_channel and link all the objects together */
07998    cl = chan_list_init(ORG_AST);
07999    if (!cl) {
08000       misdn_lib_release(newbc);
08001       ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
08002       return NULL;
08003    }
08004    cl->bc = newbc;
08005 
08006    ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, format, requestor ? requestor->linkedid : NULL, port, channel);
08007    if (!ast) {
08008       chan_list_unref(cl, "Failed to create a new channel");
08009       misdn_lib_release(newbc);
08010       ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
08011       return NULL;
08012    }
08013 
08014 #if defined(AST_MISDN_ENHANCEMENTS)
08015    cl->record_id = record_id;
08016 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
08017 
08018    /* register chan in local list */
08019    cl_queue_chan(cl);
08020 
08021    /* fill in the config into the objects */
08022    read_config(cl);
08023 
08024    /* important */
08025    cl->need_hangup = 0;
08026 
08027    chan_list_unref(cl, "Successful misdn_request()");
08028    return ast;
08029 }

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

Definition at line 8032 of file chan_misdn.c.

References ast_copy_string(), ast_log(), chan_list::bc, misdn_bchannel::display, EVENT_INFORMATION, LOG_WARNING, MISDN_ASTERISK_TECH_PVT, and misdn_lib_send_event().

08033 {
08034    struct chan_list *tmp = MISDN_ASTERISK_TECH_PVT(chan);
08035 
08036    if (tmp && tmp->bc) {
08037       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
08038       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
08039    } else {
08040       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
08041       return -1;
08042    }
08043 
08044    return 0;
08045 }

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

Definition at line 12223 of file chan_misdn.c.

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

Referenced by load_module(), and misdn_call().

12224 {
12225    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12226    char *tok;
12227    char *tokb;
12228    char *parse;
12229    int keyidx = 0;
12230    int rxgain = 0;
12231    int txgain = 0;
12232    int change_jitter = 0;
12233 
12234    if (strcasecmp(chan->tech->type, misdn_type)) {
12235       ast_log(LOG_WARNING, "misdn_set_opt makes sense only with %s channels!\n", misdn_type);
12236       return -1;
12237    }
12238 
12239    if (ast_strlen_zero((char *) data)) {
12240       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
12241       return -1;
12242    }
12243 
12244    parse = ast_strdupa(data);
12245    for (tok = strtok_r(parse, ":", &tokb);
12246       tok;
12247       tok = strtok_r(NULL, ":", &tokb)) {
12248       int neglect = 0;
12249 
12250       if (tok[0] == '!') {
12251          neglect = 1;
12252          tok++;
12253       }
12254 
12255       switch(tok[0]) {
12256       case 'd' :
12257          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
12258          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
12259          break;
12260       case 'n':
12261          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
12262          ch->bc->nodsp = 1;
12263          break;
12264       case 'j':
12265          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
12266          tok++;
12267          change_jitter = 1;
12268 
12269          switch (tok[0]) {
12270          case 'b':
12271             ch->jb_len = atoi(++tok);
12272             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
12273             break;
12274          case 't' :
12275             ch->jb_upper_threshold = atoi(++tok);
12276             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
12277             break;
12278          case 'n':
12279             ch->bc->nojitter = 1;
12280             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
12281             break;
12282          default:
12283             ch->jb_len = 4000;
12284             ch->jb_upper_threshold = 0;
12285             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
12286             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
12287             break;
12288          }
12289          break;
12290       case 'v':
12291          tok++;
12292 
12293          switch (tok[0]) {
12294          case 'r' :
12295             rxgain = atoi(++tok);
12296             if (rxgain < -8) {
12297                rxgain = -8;
12298             }
12299             if (rxgain > 8) {
12300                rxgain = 8;
12301             }
12302             ch->bc->rxgain = rxgain;
12303             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
12304             break;
12305          case 't':
12306             txgain = atoi(++tok);
12307             if (txgain < -8) {
12308                txgain = -8;
12309             }
12310             if (txgain > 8) {
12311                txgain = 8;
12312             }
12313             ch->bc->txgain = txgain;
12314             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
12315             break;
12316          }
12317          break;
12318       case 'c':
12319          keyidx = atoi(++tok);
12320          {
12321             char keys[4096];
12322             char *key = NULL;
12323             char *tmp = keys;
12324             int i;
12325 
12326             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
12327 
12328             for (i = 0; i < keyidx; i++) {
12329                key = strsep(&tmp, ",");
12330             }
12331 
12332             if (key) {
12333                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
12334             }
12335 
12336             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
12337             break;
12338          }
12339       case 'e':
12340          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
12341 
12342          if (neglect) {
12343             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
12344 #ifdef MISDN_1_2
12345             *ch->bc->pipeline = 0;
12346 #else
12347             ch->bc->ec_enable = 0;
12348 #endif
12349          } else {
12350 #ifdef MISDN_1_2
12351             update_pipeline_config(ch->bc);
12352 #else
12353             ch->bc->ec_enable = 1;
12354             ch->bc->orig = ch->originator;
12355             tok++;
12356             if (*tok) {
12357                ch->bc->ec_deftaps = atoi(tok);
12358             }
12359 #endif
12360          }
12361          break;
12362       case 'h':
12363          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
12364 
12365          if (strlen(tok) > 1 && tok[1] == '1') {
12366             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
12367             if (!ch->bc->hdlc) {
12368                ch->bc->hdlc = 1;
12369             }
12370          }
12371          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
12372          break;
12373       case 's':
12374          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
12375          ch->bc->send_dtmf = 1;
12376          break;
12377       case 'f':
12378          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
12379          ch->faxdetect = 1;
12380          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
12381          break;
12382       case 'a':
12383          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
12384          ch->ast_dsp = 1;
12385          break;
12386       case 'p':
12387          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
12388          /* CRICH: callingpres!!! */
12389          if (strstr(tok, "allowed")) {
12390             ch->bc->presentation = 0;
12391             ch->bc->set_presentation = 1;
12392          } else if (strstr(tok, "restricted")) {
12393             ch->bc->presentation = 1;
12394             ch->bc->set_presentation = 1;
12395          } else if (strstr(tok, "not_screened")) {
12396             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
12397             ch->bc->presentation = 1;
12398             ch->bc->set_presentation = 1;
12399          }
12400          break;
12401       case 'i' :
12402          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
12403          ch->ignore_dtmf = 1;
12404          break;
12405       default:
12406          break;
12407       }
12408    }
12409 
12410    if (change_jitter) {
12411       config_jitterbuffer(ch);
12412    }
12413 
12414    if (ch->faxdetect || ch->ast_dsp) {
12415       if (!ch->dsp) {
12416          ch->dsp = ast_dsp_new();
12417       }
12418       if (ch->dsp) {
12419          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
12420       }
12421    }
12422 
12423    if (ch->ast_dsp) {
12424       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
12425       ch->bc->nodsp = 1;
12426    }
12427 
12428    return 0;
12429 }

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

Definition at line 3573 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

03574 {
03575    return _misdn_tasks_add_variable(timeout, callback, data, 0);
03576 }

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

Definition at line 3578 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

03579 {
03580    return _misdn_tasks_add_variable(timeout, callback, data, 1);
03581 }

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 3543 of file chan_misdn.c.

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

Referenced by unload_module().

03544 {
03545    if (misdn_tasks) {
03546       chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
03547       if (pthread_cancel(misdn_tasks_thread) == 0) {
03548          cb_log(4, 0, "Joining misdn_tasks thread\n");
03549          pthread_join(misdn_tasks_thread, NULL);
03550       }
03551       sched_context_destroy(misdn_tasks);
03552    }
03553 }

static void misdn_tasks_init ( void   )  [static]

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

03524 {
03525    sem_t blocker;
03526    int i = 5;
03527 
03528    if (sem_init(&blocker, 0, 0)) {
03529       perror("chan_misdn: Failed to initialize semaphore!");
03530       exit(1);
03531    }
03532 
03533    chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
03534 
03535    misdn_tasks = sched_context_create();
03536    pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
03537 
03538    while (sem_wait(&blocker) && --i) {
03539    }
03540    sem_destroy(&blocker);
03541 }

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 3583 of file chan_misdn.c.

References AST_SCHED_DEL.

Referenced by chan_list_destructor().

03584 {
03585    AST_SCHED_DEL(misdn_tasks, task_id);
03586 }

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

Definition at line 3497 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

03498 {
03499    int wait;
03500    struct sigaction sa;
03501 
03502    sa.sa_handler = sighandler;
03503    sa.sa_flags = SA_NODEFER;
03504    sigemptyset(&sa.sa_mask);
03505    sigaddset(&sa.sa_mask, SIGUSR1);
03506    sigaction(SIGUSR1, &sa, NULL);
03507 
03508    sem_post((sem_t *)data);
03509 
03510    while (1) {
03511       wait = ast_sched_wait(misdn_tasks);
03512       if (wait < 0) {
03513          wait = 8000;
03514       }
03515       if (poll(NULL, 0, wait) < 0) {
03516          chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
03517       }
03518       ast_sched_runq(misdn_tasks);
03519    }
03520    return NULL;
03521 }

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 3555 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable().

03556 {
03557    pthread_kill(misdn_tasks_thread, SIGUSR1);
03558 }

static int misdn_to_ast_plan ( enum mISDN_NUMBER_PLAN  number_plan  )  [static]

Definition at line 1972 of file chan_misdn.c.

References NUMPLAN_DATA, NUMPLAN_ISDN, NUMPLAN_NATIONAL, NUMPLAN_PRIVATE, NUMPLAN_TELEX, and NUMPLAN_UNKNOWN.

Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().

01973 {
01974    int ast_number_plan;
01975 
01976    switch (number_plan) {
01977    default:
01978    case NUMPLAN_UNKNOWN:
01979       ast_number_plan = NUMPLAN_UNKNOWN;
01980       break;
01981 
01982    case NUMPLAN_ISDN:
01983       ast_number_plan = NUMPLAN_ISDN;
01984       break;
01985 
01986    case NUMPLAN_DATA:
01987       ast_number_plan = NUMPLAN_DATA;
01988       break;
01989 
01990    case NUMPLAN_TELEX:
01991       ast_number_plan = NUMPLAN_TELEX;
01992       break;
01993 
01994    case NUMPLAN_NATIONAL:
01995       ast_number_plan = NUMPLAN_NATIONAL;
01996       break;
01997 
01998    case NUMPLAN_PRIVATE:
01999       ast_number_plan = NUMPLAN_PRIVATE;
02000       break;
02001    }
02002 
02003    return ast_number_plan;
02004 }

static int misdn_to_ast_pres ( int  presentation  )  [static]

Definition at line 2089 of file chan_misdn.c.

References AST_PRES_ALLOWED, AST_PRES_RESTRICTED, and AST_PRES_UNAVAILABLE.

Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().

02090 {
02091    switch (presentation) {
02092    default:
02093    case 0:
02094       presentation = AST_PRES_ALLOWED;
02095       break;
02096 
02097    case 1:
02098       presentation = AST_PRES_RESTRICTED;
02099       break;
02100 
02101    case 2:
02102       presentation = AST_PRES_UNAVAILABLE;
02103       break;
02104    }
02105 
02106    return presentation;
02107 }

static enum AST_REDIRECTING_REASON misdn_to_ast_reason ( const enum mISDN_REDIRECTING_REASON  q931  )  [static]

Definition at line 2286 of file chan_misdn.c.

References AST_REDIRECTING_REASON_CALL_FWD_DTE, AST_REDIRECTING_REASON_DEFLECTION, AST_REDIRECTING_REASON_NO_ANSWER, AST_REDIRECTING_REASON_OUT_OF_ORDER, AST_REDIRECTING_REASON_UNCONDITIONAL, AST_REDIRECTING_REASON_UNKNOWN, AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_NO_REPLY, mISDN_REDIRECTING_REASON_OUT_OF_ORDER, and mISDN_REDIRECTING_REASON_UNKNOWN.

Referenced by misdn_copy_redirecting_to_ast().

02287 {
02288    enum AST_REDIRECTING_REASON ast;
02289 
02290    switch (q931) {
02291    default:
02292    case mISDN_REDIRECTING_REASON_UNKNOWN:
02293       ast = AST_REDIRECTING_REASON_UNKNOWN;
02294       break;
02295 
02296    case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
02297       ast = AST_REDIRECTING_REASON_USER_BUSY;
02298       break;
02299 
02300    case mISDN_REDIRECTING_REASON_NO_REPLY:
02301       ast = AST_REDIRECTING_REASON_NO_ANSWER;
02302       break;
02303 
02304    case mISDN_REDIRECTING_REASON_DEFLECTION:
02305       ast = AST_REDIRECTING_REASON_DEFLECTION;
02306       break;
02307 
02308    case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
02309       ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
02310       break;
02311 
02312    case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
02313       ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
02314       break;
02315 
02316    case mISDN_REDIRECTING_REASON_CALL_FWD:
02317       ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
02318       break;
02319    }
02320 
02321    return ast;
02322 }

static int misdn_to_ast_screen ( int  screening  )  [static]

Definition at line 2182 of file chan_misdn.c.

References AST_PRES_NETWORK_NUMBER, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.

Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().

02183 {
02184    switch (screening) {
02185    default:
02186    case 0:
02187       screening = AST_PRES_USER_NUMBER_UNSCREENED;
02188       break;
02189 
02190    case 1:
02191       screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
02192       break;
02193 
02194    case 2:
02195       screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
02196       break;
02197 
02198    case 3:
02199       screening = AST_PRES_NETWORK_NUMBER;
02200       break;
02201    }
02202 
02203    return screening;
02204 }

static int misdn_to_ast_ton ( enum mISDN_NUMBER_TYPE  number_type  )  [static]

Definition at line 1846 of file chan_misdn.c.

References NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, and NUMTYPE_UNKNOWN.

Referenced by cb_events(), misdn_copy_redirecting_to_ast(), misdn_queue_connected_line_update(), and misdn_update_caller_id().

01847 {
01848    int ast_number_type;
01849 
01850    switch (number_type) {
01851    default:
01852    case NUMTYPE_UNKNOWN:
01853       ast_number_type = NUMTYPE_UNKNOWN << 4;
01854       break;
01855 
01856    case NUMTYPE_INTERNATIONAL:
01857       ast_number_type = NUMTYPE_INTERNATIONAL << 4;
01858       break;
01859 
01860    case NUMTYPE_NATIONAL:
01861       ast_number_type = NUMTYPE_NATIONAL << 4;
01862       break;
01863 
01864    case NUMTYPE_NETWORK_SPECIFIC:
01865       ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
01866       break;
01867 
01868    case NUMTYPE_SUBSCRIBER:
01869       ast_number_type = NUMTYPE_SUBSCRIBER << 4;
01870       break;
01871 
01872    case NUMTYPE_ABBREVIATED:
01873       ast_number_type = NUMTYPE_ABBREVIATED << 4;
01874       break;
01875    }
01876 
01877    return ast_number_type;
01878 }

static const char* misdn_to_str_plan ( enum mISDN_NUMBER_PLAN  number_plan  )  [static]

Definition at line 1930 of file chan_misdn.c.

References NUMPLAN_DATA, NUMPLAN_ISDN, NUMPLAN_NATIONAL, NUMPLAN_PRIVATE, NUMPLAN_TELEX, NUMPLAN_UNKNOWN, and str.

Referenced by cb_events().

01931 {
01932    const char *str;
01933 
01934    switch (number_plan) {
01935    default:
01936    case NUMPLAN_UNKNOWN:
01937       str = "Unknown";
01938       break;
01939 
01940    case NUMPLAN_ISDN:
01941       str = "ISDN";
01942       break;
01943 
01944    case NUMPLAN_DATA:
01945       str = "Data";
01946       break;
01947 
01948    case NUMPLAN_TELEX:
01949       str = "Telex";
01950       break;
01951 
01952    case NUMPLAN_NATIONAL:
01953       str = "National";
01954       break;
01955 
01956    case NUMPLAN_PRIVATE:
01957       str = "Private";
01958       break;
01959    }
01960 
01961    return str;
01962 }

static const char* misdn_to_str_pres ( int  presentation  )  [static]

Definition at line 2056 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

02057 {
02058    const char *str;
02059 
02060    switch (presentation) {
02061    case 0:
02062       str = "Allowed";
02063       break;
02064 
02065    case 1:
02066       str = "Restricted";
02067       break;
02068 
02069    case 2:
02070       str = "Unavailable";
02071       break;
02072 
02073    default:
02074       str = "Unknown";
02075       break;
02076    }
02077 
02078    return str;
02079 }

static const char* misdn_to_str_screen ( int  screening  )  [static]

Definition at line 2145 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

02146 {
02147    const char *str;
02148 
02149    switch (screening) {
02150    case 0:
02151       str = "Unscreened";
02152       break;
02153 
02154    case 1:
02155       str = "Passed Screen";
02156       break;
02157 
02158    case 2:
02159       str = "Failed Screen";
02160       break;
02161 
02162    case 3:
02163       str = "Network Number";
02164       break;
02165 
02166    default:
02167       str = "Unknown";
02168       break;
02169    }
02170 
02171    return str;
02172 }

static const char* misdn_to_str_ton ( enum mISDN_NUMBER_TYPE  number_type  )  [static]

Definition at line 1804 of file chan_misdn.c.

References NUMTYPE_ABBREVIATED, NUMTYPE_INTERNATIONAL, NUMTYPE_NATIONAL, NUMTYPE_NETWORK_SPECIFIC, NUMTYPE_SUBSCRIBER, NUMTYPE_UNKNOWN, and str.

Referenced by cb_events().

01805 {
01806    const char *str;
01807 
01808    switch (number_type) {
01809    default:
01810    case NUMTYPE_UNKNOWN:
01811       str = "Unknown";
01812       break;
01813 
01814    case NUMTYPE_INTERNATIONAL:
01815       str = "International";
01816       break;
01817 
01818    case NUMTYPE_NATIONAL:
01819       str = "National";
01820       break;
01821 
01822    case NUMTYPE_NETWORK_SPECIFIC:
01823       str = "Network Specific";
01824       break;
01825 
01826    case NUMTYPE_SUBSCRIBER:
01827       str = "Subscriber";
01828       break;
01829 
01830    case NUMTYPE_ABBREVIATED:
01831       str = "Abbreviated";
01832       break;
01833    }
01834 
01835    return str;
01836 }

static void misdn_update_caller_id ( struct ast_channel ast,
const struct misdn_party_id id,
char *  cid_tag 
) [static]

Definition at line 6106 of file chan_misdn.c.

References ast_party_caller::ani, ast_set_party_caller::ani, ast_channel_lock, ast_channel_set_caller_event(), ast_channel_unlock, ast_party_caller_set_init(), ast_channel::caller, ast_party_caller::id, ast_set_party_caller::id, misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_screen(), misdn_to_ast_ton(), misdn_party_id::number, ast_party_id::number, ast_set_party_id::number, misdn_party_id::number_plan, misdn_party_id::number_type, ast_party_number::plan, misdn_party_id::presentation, ast_party_number::presentation, misdn_party_id::screening, ast_party_number::str, ast_party_id::tag, and ast_party_number::valid.

Referenced by misdn_update_remote_party().

06107 {
06108    struct ast_party_caller caller;
06109    struct ast_set_party_caller update_caller;
06110 
06111    memset(&update_caller, 0, sizeof(update_caller));
06112    update_caller.id.number = 1;
06113    update_caller.ani.number = 1;
06114 
06115    ast_channel_lock(ast);
06116    ast_party_caller_set_init(&caller, &ast->caller);
06117 
06118    caller.id.number.valid = 1;
06119    caller.id.number.str = (char *) id->number;
06120    caller.id.number.plan = misdn_to_ast_ton(id->number_type)
06121       | misdn_to_ast_plan(id->number_plan);
06122    caller.id.number.presentation = misdn_to_ast_pres(id->presentation)
06123       | misdn_to_ast_screen(id->screening);
06124 
06125    caller.ani.number = caller.id.number;
06126 
06127    caller.id.tag = cid_tag;
06128    caller.ani.tag = cid_tag;
06129 
06130    ast_channel_set_caller_event(ast, &caller, &update_caller);
06131    ast_channel_unlock(ast);
06132 }

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

Definition at line 6234 of file chan_misdn.c.

References misdn_bchannel::caller, misdn_bchannel::connected, EVENT_FACILITY, EVENT_NOTIFY, misdn_bchannel::fac_out, MISDN_ASTERISK_TECH_PVT, MISDN_CONNECTED, misdn_get_connected_line(), misdn_lib_is_ptp(), misdn_lib_port_is_nt(), misdn_lib_send_event(), mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE, misdn_bchannel::notify_description_code, ORG_MISDN, misdn_bchannel::outgoing_colp, misdn_bchannel::port, misdn_party_id::presentation, print_facility(), misdn_bchannel::redirecting, chan_list::state, misdn_party_redirecting::to, and misdn_party_redirecting::to_changed.

Referenced by misdn_indication().

06235 {
06236    struct chan_list *ch;
06237 
06238    misdn_get_connected_line(ast, bc, originator);
06239    if (originator == ORG_MISDN) {
06240       bc->redirecting.to = bc->connected;
06241    } else {
06242       bc->redirecting.to = bc->caller;
06243    }
06244    switch (bc->outgoing_colp) {
06245    case 1:/* restricted */
06246       bc->redirecting.to.presentation = 1;/* restricted */
06247       break;
06248    case 2:/* blocked */
06249       /* Don't tell the remote party that the call was transferred. */
06250       return;
06251    default:
06252       break;
06253    }
06254 
06255    ch = MISDN_ASTERISK_TECH_PVT(ast);
06256    if (ch->state == MISDN_CONNECTED
06257       || originator != ORG_MISDN) {
06258       int is_ptmp;
06259 
06260       is_ptmp = !misdn_lib_is_ptp(bc->port);
06261       if (is_ptmp) {
06262          /*
06263           * We should not send these messages to the network if we are
06264           * the CPE side since phones do not transfer calls within
06265           * themselves.  Well... If you consider handing the handset to
06266           * someone else a transfer then how is the network to know?
06267           */
06268          if (!misdn_lib_port_is_nt(bc->port)) {
06269             return;
06270          }
06271          if (ch->state != MISDN_CONNECTED) {
06272             /* Send NOTIFY(Nie(transfer-active), RDNie(redirecting.to data)) */
06273             bc->redirecting.to_changed = 1;
06274             bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE;
06275             misdn_lib_send_event(bc, EVENT_NOTIFY);
06276 #if defined(AST_MISDN_ENHANCEMENTS)
06277          } else {
06278             /* Send FACILITY(Fie(RequestSubaddress), Nie(transfer-active), RDNie(redirecting.to data)) */
06279             bc->redirecting.to_changed = 1;
06280             bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE;
06281             bc->fac_out.Function = Fac_RequestSubaddress;
06282             bc->fac_out.u.RequestSubaddress.InvokeID = ++misdn_invoke_id;
06283 
06284             /* Send message */
06285             print_facility(&bc->fac_out, bc);
06286             misdn_lib_send_event(bc, EVENT_FACILITY);
06287 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06288          }
06289 #if defined(AST_MISDN_ENHANCEMENTS)
06290       } else {
06291          /* Send FACILITY(Fie(EctInform(transfer-active, redirecting.to data))) */
06292          bc->fac_out.Function = Fac_EctInform;
06293          bc->fac_out.u.EctInform.InvokeID = ++misdn_invoke_id;
06294          bc->fac_out.u.EctInform.Status = 1;/* active */
06295          bc->fac_out.u.EctInform.RedirectionPresent = 1;/* Must be present when status is active */
06296          misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.EctInform.Redirection,
06297             &bc->redirecting.to);
06298 
06299          /* Send message */
06300          print_facility(&bc->fac_out, bc);
06301          misdn_lib_send_event(bc, EVENT_FACILITY);
06302 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06303       }
06304    }
06305 }

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

Definition at line 6414 of file chan_misdn.c.

References EVENT_FACILITY, EVENT_NOTIFY, ast_channel::exten, misdn_bchannel::fac_out, match(), misdn_copy_redirecting_from_ast(), misdn_lib_is_ptp(), misdn_lib_port_is_nt(), misdn_lib_send_event(), mISDN_NOTIFY_CODE_CALL_IS_DIVERTING, misdn_bchannel::notify_description_code, misdn_party_id::number, ORG_MISDN, misdn_bchannel::outgoing_colp, misdn_bchannel::port, misdn_party_id::presentation, print_facility(), misdn_party_redirecting::reason, misdn_bchannel::redirecting, misdn_party_redirecting::to, and misdn_party_redirecting::to_changed.

Referenced by misdn_indication().

06415 {
06416    int is_ptmp;
06417 
06418    misdn_copy_redirecting_from_ast(bc, ast);
06419    switch (bc->outgoing_colp) {
06420    case 1:/* restricted */
06421       bc->redirecting.to.presentation = 1;/* restricted */
06422       break;
06423    case 2:/* blocked */
06424       /* Don't tell the remote party that the call was redirected. */
06425       return;
06426    default:
06427       break;
06428    }
06429 
06430    if (originator != ORG_MISDN) {
06431       return;
06432    }
06433 
06434    is_ptmp = !misdn_lib_is_ptp(bc->port);
06435    if (is_ptmp) {
06436       /*
06437        * We should not send these messages to the network if we are
06438        * the CPE side since phones do not redirect calls within
06439        * themselves.  Well... If you consider someone else picking up
06440        * the handset a redirection then how is the network to know?
06441        */
06442       if (!misdn_lib_port_is_nt(bc->port)) {
06443          return;
06444       }
06445       /* Send NOTIFY(call-is-diverting, redirecting.to data) */
06446       bc->redirecting.to_changed = 1;
06447       bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_IS_DIVERTING;
06448       misdn_lib_send_event(bc, EVENT_NOTIFY);
06449 #if defined(AST_MISDN_ENHANCEMENTS)
06450    } else {
06451       int match;  /* TRUE if the dialed number matches the redirecting to number */
06452 
06453       match = (strcmp(ast->exten, bc->redirecting.to.number) == 0) ? 1 : 0;
06454       if (!bc->div_leg_3_tx_pending
06455          || !match) {
06456          /* Send DivertingLegInformation1 */
06457          bc->fac_out.Function = Fac_DivertingLegInformation1;
06458          bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
06459          bc->fac_out.u.DivertingLegInformation1.DiversionReason =
06460             misdn_to_diversion_reason(bc->redirecting.reason);
06461          bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;/* notificationWithDivertedToNr */
06462          bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
06463          misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
06464          print_facility(&bc->fac_out, bc);
06465          misdn_lib_send_event(bc, EVENT_FACILITY);
06466       }
06467       bc->div_leg_3_tx_pending = 0;
06468 
06469       /* Send DivertingLegInformation3 */
06470       bc->fac_out.Function = Fac_DivertingLegInformation3;
06471       bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
06472       bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
06473          bc->redirecting.to.presentation == 0 ? 1 : 0;
06474       print_facility(&bc->fac_out, bc);
06475       misdn_lib_send_event(bc, EVENT_FACILITY);
06476 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
06477    }
06478 }

static void misdn_update_remote_party ( struct ast_channel ast,
const struct misdn_party_id id,
enum AST_CONNECTED_LINE_UPDATE_SOURCE  source,
char *  cid_tag 
) [static]

Definition at line 6145 of file chan_misdn.c.

References misdn_queue_connected_line_update(), and misdn_update_caller_id().

Referenced by cb_events(), and misdn_facility_ie_handler().

06146 {
06147    misdn_update_caller_id(ast, id, cid_tag);
06148    misdn_queue_connected_line_update(ast, id, source, cid_tag);
06149 }

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

Definition at line 7404 of file chan_misdn.c.

References misdn_bchannel::active, misdn_bchannel::addr, ast_debug, ast_getformatname(), ast_log(), chan_list::bc, misdn_bchannel::bc_state, BCHAN_ACTIVATED, BCHAN_BRIDGED, ast_channel::caller, misdn_bchannel::capability, cb_log, chan_misdn_log(), ast_frame_subclass::codec, ast_frame::data, chan_list::dropped_frame_cnt, ast_channel::exten, chan_list::hold, ast_party_caller::id, 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, ast_party_id::number, misdn_bchannel::port, ast_frame::ptr, S_COR, ast_frame::samples, ast_frame::src, hold_info::state, ast_party_number::str, ast_frame::subclass, chan_list::ts, and ast_party_number::valid.

07405 {
07406    struct chan_list *ch;
07407 
07408    if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
07409       return -1;
07410    }
07411 
07412    if (ch->hold.state != MISDN_HOLD_IDLE) {
07413       chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
07414       return 0;
07415    }
07416 
07417    if (!ch->bc) {
07418       ast_log(LOG_WARNING, "private but no bc\n");
07419       return -1;
07420    }
07421 
07422    if (ch->notxtone) {
07423       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
07424       return 0;
07425    }
07426 
07427 
07428    if (!frame->subclass.codec) {
07429       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
07430       return 0;
07431    }
07432 
07433    if (!(frame->subclass.codec & prefformat)) {
07434       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(frame->subclass.codec));
07435       return 0;
07436    }
07437 
07438 
07439    if (!frame->samples) {
07440       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
07441 
07442       if (!strcmp(frame->src,"ast_prod")) {
07443          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
07444 
07445          if (ch->ts) {
07446             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
07447             misdn_lib_tone_generator_start(ch->bc);
07448          }
07449          return 0;
07450       }
07451 
07452       return -1;
07453    }
07454 
07455    if (!ch->bc->addr) {
07456       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
07457       return 0;
07458    }
07459 
07460 #ifdef MISDN_DEBUG
07461    {
07462       int i;
07463       int max = 5 > frame->samples ? frame->samples : 5;
07464 
07465       ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
07466 
07467       for (i = 0; i < max; i++) {
07468          ast_debug(1, "%2.2x ", ((char *) frame->data.ptr)[i]);
07469       }
07470    }
07471 #endif
07472 
07473    switch (ch->bc->bc_state) {
07474    case BCHAN_ACTIVATED:
07475    case BCHAN_BRIDGED:
07476       break;
07477    default:
07478       if (!ch->dropped_frame_cnt) {
07479          chan_misdn_log(5, ch->bc->port,
07480             "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",
07481             frame->samples, ch->bc->addr, ast->exten,
07482             S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
07483             misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
07484       }
07485 
07486       if (++ch->dropped_frame_cnt > 100) {
07487          ch->dropped_frame_cnt = 0;
07488          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);
07489       }
07490 
07491       return 0;
07492    }
07493 
07494    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
07495    if (!ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability)) {
07496       /* Buffered Transmit (triggered by read from isdn side)*/
07497       if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
07498          if (ch->bc->active) {
07499             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
07500          }
07501       }
07502 
07503    } else {
07504       /* transmit without jitterbuffer */
07505       misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
07506    }
07507 
07508    return 0;
07509 }

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

Definition at line 8365 of file chan_misdn.c.

References chan_list::ast, ast_pbx_start(), and chan_list::need_hangup.

Referenced by do_immediate_setup(), misdn_overlap_dial_task(), and start_pbx().

08366 {
08367    int ret = ast_pbx_start(ch->ast);
08368 
08369    ch->need_hangup = (ret >= 0) ? 0 : 1;
08370 
08371    return ret;
08372 }

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

Definition at line 4136 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(), ast_channel::caller, misdn_bchannel::capability, misdn_bchannel::channel, ast_channel::context, misdn_bchannel::display, misdn_bchannel::ec_enable, ast_channel::exten, misdn_party_redirecting::from, misdn_bchannel::holded, ast_party_caller::id, misdn_bchannel::l3_id, chan_list::l3id, misdn_get_ch_state(), misdn_party_id::name, ast_party_id::name, chan_list::norxtone, chan_list::notxtone, misdn_bchannel::nt, misdn_party_id::number, ast_party_id::number, ORG_AST, chan_list::originator, misdn_bchannel::pid, misdn_bchannel::port, misdn_bchannel::redirecting, ast_party_number::str, ast_party_name::str, misdn_party_redirecting::to, ast_party_number::valid, and ast_party_name::valid.

Referenced by handle_cli_misdn_show_channel(), and handle_cli_misdn_show_channels().

04137 {
04138    struct ast_channel *ast = help->ast;
04139 
04140    ast_cli(fd,
04141       "* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
04142       "  --> caller:\"%s\" <%s>\n"
04143       "  --> redirecting-from:\"%s\" <%s>\n"
04144       "  --> redirecting-to:\"%s\" <%s>\n"
04145       "  --> context:%s state:%s\n",
04146       bc->pid,
04147       bc->port,
04148       bc->channel,
04149       bc->nt ? "NT" : "TE",
04150       help->originator == ORG_AST ? "*" : "I",
04151       ast ? ast->exten : "",
04152       (ast && ast->caller.id.name.valid && ast->caller.id.name.str)
04153          ? ast->caller.id.name.str : "",
04154       (ast && ast->caller.id.number.valid && ast->caller.id.number.str)
04155          ? ast->caller.id.number.str : "",
04156       bc->redirecting.from.name,
04157       bc->redirecting.from.number,
04158       bc->redirecting.to.name,
04159       bc->redirecting.to.number,
04160       ast ? ast->context : "",
04161       misdn_get_ch_state(help));
04162    if (misdn_debug[bc->port] > 0) {
04163       ast_cli(fd,
04164          "  --> astname: %s\n"
04165          "  --> ch_l3id: %x\n"
04166          "  --> ch_addr: %x\n"
04167          "  --> bc_addr: %x\n"
04168          "  --> bc_l3id: %x\n"
04169          "  --> display: %s\n"
04170          "  --> activated: %d\n"
04171          "  --> state: %s\n"
04172          "  --> capability: %s\n"
04173 #ifdef MISDN_1_2
04174          "  --> pipeline: %s\n"
04175 #else
04176          "  --> echo_cancel: %d\n"
04177 #endif
04178          "  --> notone : rx %d tx:%d\n"
04179          "  --> bc_hold: %d\n",
04180          ast ? ast->name : "",
04181          help->l3id,
04182          help->addr,
04183          bc->addr,
04184          bc->l3_id,
04185          bc->display,
04186          bc->active,
04187          bc_state2str(bc->bc_state),
04188          bearer2str(bc->capability),
04189 #ifdef MISDN_1_2
04190          bc->pipeline,
04191 #else
04192          bc->ec_enable,
04193 #endif
04194          help->norxtone, help->notxtone,
04195          bc->holded);
04196    }
04197 }

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

03328 {
03329    chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
03330 
03331    switch(bc->law) {
03332    case INFO_CODEC_ALAW:
03333       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
03334       break;
03335    case INFO_CODEC_ULAW:
03336       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
03337       break;
03338    }
03339 }

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

Definition at line 2734 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

Referenced by handle_cli_misdn_send_facility(), misdn_answer(), misdn_call(), misdn_facility_exec(), misdn_facility_ie_handler(), misdn_update_connected_line(), and misdn_update_redirecting().

02735 {
02736 #if defined(AST_MISDN_ENHANCEMENTS)
02737    unsigned Index;
02738 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
02739 
02740    switch (fac->Function) {
02741 #if defined(AST_MISDN_ENHANCEMENTS)
02742    case Fac_ActivationDiversion:
02743       chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
02744          fac->u.ActivationDiversion.InvokeID);
02745       switch (fac->u.ActivationDiversion.ComponentType) {
02746       case FacComponent_Invoke:
02747          chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
02748             fac->u.ActivationDiversion.Component.Invoke.Procedure,
02749             fac->u.ActivationDiversion.Component.Invoke.BasicService);
02750          chan_misdn_log(1, bc->port, " -->   ForwardedTo:\n");
02751          print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
02752          chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
02753          print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
02754          break;
02755       case FacComponent_Result:
02756          chan_misdn_log(1, bc->port, " -->  Result\n");
02757          break;
02758       default:
02759          break;
02760       }
02761       break;
02762    case Fac_DeactivationDiversion:
02763       chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
02764          fac->u.DeactivationDiversion.InvokeID);
02765       switch (fac->u.DeactivationDiversion.ComponentType) {
02766       case FacComponent_Invoke:
02767          chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
02768             fac->u.DeactivationDiversion.Component.Invoke.Procedure,
02769             fac->u.DeactivationDiversion.Component.Invoke.BasicService);
02770          chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
02771          print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
02772          break;
02773       case FacComponent_Result:
02774          chan_misdn_log(1, bc->port, " -->  Result\n");
02775          break;
02776       default:
02777          break;
02778       }
02779       break;
02780    case Fac_ActivationStatusNotificationDiv:
02781       chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
02782          fac->u.ActivationStatusNotificationDiv.InvokeID,
02783          fac->u.ActivationStatusNotificationDiv.Procedure,
02784          fac->u.ActivationStatusNotificationDiv.BasicService);
02785       chan_misdn_log(1, bc->port, " -->  ForwardedTo:\n");
02786       print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
02787       chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
02788       print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
02789       break;
02790    case Fac_DeactivationStatusNotificationDiv:
02791       chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
02792          fac->u.DeactivationStatusNotificationDiv.InvokeID,
02793          fac->u.DeactivationStatusNotificationDiv.Procedure,
02794          fac->u.DeactivationStatusNotificationDiv.BasicService);
02795       chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
02796       print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
02797       break;
02798    case Fac_InterrogationDiversion:
02799       chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
02800          fac->u.InterrogationDiversion.InvokeID);
02801       switch (fac->u.InterrogationDiversion.ComponentType) {
02802       case FacComponent_Invoke:
02803          chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
02804             fac->u.InterrogationDiversion.Component.Invoke.Procedure,
02805             fac->u.InterrogationDiversion.Component.Invoke.BasicService);
02806          chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
02807          print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
02808          break;
02809       case FacComponent_Result:
02810          chan_misdn_log(1, bc->port, " -->  Result:\n");
02811          if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
02812             for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
02813                chan_misdn_log(1, bc->port, " -->   IntResult[%d]:\n", Index);
02814                print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
02815             }
02816          }
02817          break;
02818       default:
02819          break;
02820       }
02821       break;
02822    case Fac_DiversionInformation:
02823       chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
02824          fac->u.DiversionInformation.InvokeID,
02825          fac->u.DiversionInformation.DiversionReason,
02826          fac->u.DiversionInformation.BasicService);
02827       if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
02828          chan_misdn_log(1, bc->port, " -->  ServedUserSubaddress:\n");
02829          print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
02830       }
02831       if (fac->u.DiversionInformation.CallingAddressPresent) {
02832          chan_misdn_log(1, bc->port, " -->  CallingAddress:\n");
02833          print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
02834       }
02835       if (fac->u.DiversionInformation.OriginalCalledPresent) {
02836          chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
02837          print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
02838       }
02839       if (fac->u.DiversionInformation.LastDivertingPresent) {
02840          chan_misdn_log(1, bc->port, " -->  LastDivertingNr:\n");
02841          print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
02842       }
02843       if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
02844          chan_misdn_log(1, bc->port, " -->  LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
02845       }
02846       if (fac->u.DiversionInformation.UserInfo.Length) {
02847          chan_misdn_log(1, bc->port, " -->  UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
02848       }
02849       break;
02850    case Fac_CallDeflection:
02851       chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
02852          fac->u.CallDeflection.InvokeID);
02853       switch (fac->u.CallDeflection.ComponentType) {
02854       case FacComponent_Invoke:
02855          chan_misdn_log(1, bc->port, " -->  Invoke:\n");
02856          if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
02857             chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
02858                fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
02859          }
02860          chan_misdn_log(1, bc->port, " -->   DeflectionAddress:\n");
02861          print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
02862          break;
02863       case FacComponent_Result:
02864          chan_misdn_log(1, bc->port, " -->  Result\n");
02865          break;
02866       default:
02867          break;
02868       }
02869       break;
02870    case Fac_CallRerouteing:
02871       chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
02872          fac->u.CallRerouteing.InvokeID);
02873       switch (fac->u.CallRerouteing.ComponentType) {
02874       case FacComponent_Invoke:
02875          chan_misdn_log(1, bc->port, " -->  Invoke: Reason:%d Counter:%d\n",
02876             fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
02877             fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
02878          chan_misdn_log(1, bc->port, " -->   CalledAddress:\n");
02879          print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
02880          print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
02881          chan_misdn_log(1, bc->port, " -->   LastReroutingNr:\n");
02882          print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
02883          chan_misdn_log(1, bc->port, " -->   SubscriptionOption:%d\n",
02884             fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
02885          if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
02886             chan_misdn_log(1, bc->port, " -->   CallingParty:\n");
02887             print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
02888          }
02889          break;
02890       case FacComponent_Result:
02891          chan_misdn_log(1, bc->port, " -->  Result\n");
02892          break;
02893       default:
02894          break;
02895       }
02896       break;
02897    case Fac_InterrogateServedUserNumbers:
02898       chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
02899          fac->u.InterrogateServedUserNumbers.InvokeID);
02900       switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
02901       case FacComponent_Invoke:
02902          chan_misdn_log(1, bc->port, " -->  Invoke\n");
02903          break;
02904       case FacComponent_Result:
02905          chan_misdn_log(1, bc->port, " -->  Result:\n");
02906          if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
02907             for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
02908                chan_misdn_log(1, bc->port, " -->   ServedUserNr[%d]:\n", Index);
02909                print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
02910             }
02911          }
02912          break;
02913       default:
02914          break;
02915       }
02916       break;
02917    case Fac_DivertingLegInformation1:
02918       chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
02919          fac->u.DivertingLegInformation1.InvokeID,
02920          fac->u.DivertingLegInformation1.DiversionReason,
02921          fac->u.DivertingLegInformation1.SubscriptionOption);
02922       if (fac->u.DivertingLegInformation1.DivertedToPresent) {
02923          chan_misdn_log(1, bc->port, " -->  DivertedToNr:\n");
02924          print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
02925       }
02926       break;
02927    case Fac_DivertingLegInformation2:
02928       chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
02929          fac->u.DivertingLegInformation2.InvokeID,
02930          fac->u.DivertingLegInformation2.DiversionReason,
02931          fac->u.DivertingLegInformation2.DiversionCounter);
02932       if (fac->u.DivertingLegInformation2.DivertingPresent) {
02933          chan_misdn_log(1, bc->port, " -->  DivertingNr:\n");
02934          print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
02935       }
02936       if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
02937          chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
02938          print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
02939       }
02940       break;
02941    case Fac_DivertingLegInformation3:
02942       chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
02943          fac->u.DivertingLegInformation3.InvokeID,
02944          fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
02945       break;
02946 
02947 #else /* !defined(AST_MISDN_ENHANCEMENTS) */
02948 
02949    case Fac_CD:
02950       chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
02951          fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
02952       break;
02953 #endif   /* !defined(AST_MISDN_ENHANCEMENTS) */
02954    case Fac_AOCDCurrency:
02955       if (fac->u.AOCDcur.chargeNotAvailable) {
02956          chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
02957       } else if (fac->u.AOCDcur.freeOfCharge) {
02958          chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
02959       } else if (fac->u.AOCDchu.billingId >= 0) {
02960          chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
02961             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
02962             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
02963       } else {
02964          chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
02965             fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
02966             (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
02967       }
02968       break;
02969    case Fac_AOCDChargingUnit:
02970       if (fac->u.AOCDchu.chargeNotAvailable) {
02971          chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
02972       } else if (fac->u.AOCDchu.freeOfCharge) {
02973          chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
02974       } else if (fac->u.AOCDchu.billingId >= 0) {
02975          chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
02976             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
02977       } else {
02978          chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
02979             fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
02980       }
02981       break;
02982 #if defined(AST_MISDN_ENHANCEMENTS)
02983    case Fac_ERROR:
02984       chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
02985          fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
02986       break;
02987    case Fac_RESULT:
02988       chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
02989          fac->u.RESULT.InvokeID);
02990       break;
02991    case Fac_REJECT:
02992       if (fac->u.REJECT.InvokeIDPresent) {
02993          chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
02994             fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
02995       } else {
02996          chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
02997             fac->u.REJECT.Code);
02998       }
02999       break;
03000    case Fac_EctExecute:
03001       chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
03002          fac->u.EctExecute.InvokeID);
03003       break;
03004    case Fac_ExplicitEctExecute:
03005       chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
03006          fac->u.ExplicitEctExecute.InvokeID,
03007          fac->u.ExplicitEctExecute.LinkID);
03008       break;
03009    case Fac_RequestSubaddress:
03010       chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
03011          fac->u.RequestSubaddress.InvokeID);
03012       break;
03013    case Fac_SubaddressTransfer:
03014       chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
03015          fac->u.SubaddressTransfer.InvokeID);
03016       print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
03017       break;
03018    case Fac_EctLinkIdRequest:
03019       chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
03020          fac->u.EctLinkIdRequest.InvokeID);
03021       switch (fac->u.EctLinkIdRequest.ComponentType) {
03022       case FacComponent_Invoke:
03023          chan_misdn_log(1, bc->port, " -->  Invoke\n");
03024          break;
03025       case FacComponent_Result:
03026          chan_misdn_log(1, bc->port, " -->  Result: LinkID:%d\n",
03027             fac->u.EctLinkIdRequest.Component.Result.LinkID);
03028          break;
03029       default:
03030          break;
03031       }
03032       break;
03033    case Fac_EctInform:
03034       chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
03035          fac->u.EctInform.InvokeID,
03036          fac->u.EctInform.Status);
03037       if (fac->u.EctInform.RedirectionPresent) {
03038          chan_misdn_log(1, bc->port, " -->  Redirection Number\n");
03039          print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
03040       }
03041       break;
03042    case Fac_EctLoopTest:
03043       chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
03044          fac->u.EctLoopTest.InvokeID);
03045       switch (fac->u.EctLoopTest.ComponentType) {
03046       case FacComponent_Invoke:
03047          chan_misdn_log(1, bc->port, " -->  Invoke: CallTransferID:%d\n",
03048             fac->u.EctLoopTest.Component.Invoke.CallTransferID);
03049          break;
03050       case FacComponent_Result:
03051          chan_misdn_log(1, bc->port, " -->  Result: LoopResult:%d\n",
03052             fac->u.EctLoopTest.Component.Result.LoopResult);
03053          break;
03054       default:
03055          break;
03056       }
03057       break;
03058    case Fac_StatusRequest:
03059       chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
03060          fac->u.StatusRequest.InvokeID);
03061       switch (fac->u.StatusRequest.ComponentType) {
03062       case FacComponent_Invoke:
03063          chan_misdn_log(1, bc->port, " -->  Invoke: Compatibility:%d\n",
03064             fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
03065          break;
03066       case FacComponent_Result:
03067          chan_misdn_log(1, bc->port, " -->  Result: Status:%d\n",
03068             fac->u.StatusRequest.Component.Result.Status);
03069          break;
03070       default:
03071          break;
03072       }
03073       break;
03074    case Fac_CallInfoRetain:
03075       chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
03076          fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
03077       break;
03078    case Fac_CCBSDeactivate:
03079       chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
03080          fac->u.CCBSDeactivate.InvokeID);
03081       switch (fac->u.CCBSDeactivate.ComponentType) {
03082       case FacComponent_Invoke:
03083          chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d\n",
03084             fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
03085          break;
03086       case FacComponent_Result:
03087          chan_misdn_log(1, bc->port, " -->  Result\n");
03088          break;
03089       default:
03090          break;
03091       }
03092       break;
03093    case Fac_CCBSErase:
03094       chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
03095          fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
03096          fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
03097       chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
03098       print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
03099       print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
03100       break;
03101    case Fac_CCBSRemoteUserFree:
03102       chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
03103          fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
03104          fac->u.CCBSRemoteUserFree.RecallMode);
03105       chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
03106       print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
03107       print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
03108       break;
03109    case Fac_CCBSCall:
03110       chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
03111          fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
03112       break;
03113    case Fac_CCBSStatusRequest:
03114       chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
03115          fac->u.CCBSStatusRequest.InvokeID);
03116       switch (fac->u.CCBSStatusRequest.ComponentType) {
03117       case FacComponent_Invoke:
03118          chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d RecallMode:%d\n",
03119             fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
03120             fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
03121          print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
03122          break;
03123       case FacComponent_Result:
03124          chan_misdn_log(1, bc->port, " -->  Result: Free:%d\n",
03125             fac->u.CCBSStatusRequest.Component.Result.Free);
03126          break;
03127       default:
03128          break;
03129       }
03130       break;
03131    case Fac_CCBSBFree:
03132       chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
03133          fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
03134          fac->u.CCBSBFree.RecallMode);
03135       chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
03136       print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
03137       print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
03138       break;
03139    case Fac_EraseCallLinkageID:
03140       chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
03141          fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
03142       break;
03143    case Fac_CCBSStopAlerting:
03144       chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
03145          fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
03146       break;
03147    case Fac_CCBSRequest:
03148       chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
03149          fac->u.CCBSRequest.InvokeID);
03150       switch (fac->u.CCBSRequest.ComponentType) {
03151       case FacComponent_Invoke:
03152          chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
03153             fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
03154          break;
03155       case FacComponent_Result:
03156          chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
03157             fac->u.CCBSRequest.Component.Result.CCBSReference,
03158             fac->u.CCBSRequest.Component.Result.RecallMode);
03159          break;
03160       default:
03161          break;
03162       }
03163       break;
03164    case Fac_CCBSInterrogate:
03165       chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
03166          fac->u.CCBSInterrogate.InvokeID);
03167       switch (fac->u.CCBSInterrogate.ComponentType) {
03168       case FacComponent_Invoke:
03169          chan_misdn_log(1, bc->port, " -->  Invoke\n");
03170          if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
03171             chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
03172                fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
03173          }
03174          if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
03175             chan_misdn_log(1, bc->port, " -->   AParty\n");
03176             print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
03177          }
03178          break;
03179       case FacComponent_Result:
03180          chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
03181             fac->u.CCBSInterrogate.Component.Result.RecallMode);
03182          if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
03183             for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
03184                chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
03185                print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
03186             }
03187          }
03188          break;
03189       default:
03190          break;
03191       }
03192       break;
03193    case Fac_CCNRRequest:
03194       chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
03195          fac->u.CCNRRequest.InvokeID);
03196       switch (fac->u.CCNRRequest.ComponentType) {
03197       case FacComponent_Invoke:
03198          chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
03199             fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
03200          break;
03201       case FacComponent_Result:
03202          chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
03203             fac->u.CCNRRequest.Component.Result.CCBSReference,
03204             fac->u.CCNRRequest.Component.Result.RecallMode);
03205          break;
03206       default:
03207          break;
03208       }
03209       break;
03210    case Fac_CCNRInterrogate:
03211       chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
03212          fac->u.CCNRInterrogate.InvokeID);
03213       switch (fac->u.CCNRInterrogate.ComponentType) {
03214       case FacComponent_Invoke:
03215          chan_misdn_log(1, bc->port, " -->  Invoke\n");
03216          if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
03217             chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
03218                fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
03219          }
03220          if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
03221             chan_misdn_log(1, bc->port, " -->   AParty\n");
03222             print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
03223          }
03224          break;
03225       case FacComponent_Result:
03226          chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
03227             fac->u.CCNRInterrogate.Component.Result.RecallMode);
03228          if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
03229             for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
03230                chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
03231                print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
03232             }
03233          }
03234          break;
03235       default:
03236          break;
03237       }
03238       break;
03239    case Fac_CCBS_T_Call:
03240       chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
03241          fac->u.CCBS_T_Call.InvokeID);
03242       break;
03243    case Fac_CCBS_T_Suspend:
03244       chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
03245          fac->u.CCBS_T_Suspend.InvokeID);
03246       break;
03247    case Fac_CCBS_T_Resume:
03248       chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
03249          fac->u.CCBS_T_Resume.InvokeID);
03250       break;
03251    case Fac_CCBS_T_RemoteUserFree:
03252       chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
03253          fac->u.CCBS_T_RemoteUserFree.InvokeID);
03254       break;
03255    case Fac_CCBS_T_Available:
03256       chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
03257          fac->u.CCBS_T_Available.InvokeID);
03258       break;
03259    case Fac_CCBS_T_Request:
03260       chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
03261          fac->u.CCBS_T_Request.InvokeID);
03262       switch (fac->u.CCBS_T_Request.ComponentType) {
03263       case FacComponent_Invoke:
03264          chan_misdn_log(1, bc->port, " -->  Invoke\n");
03265          chan_misdn_log(1, bc->port, " -->   DestinationAddress:\n");
03266          print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
03267          print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
03268          if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
03269             chan_misdn_log(1, bc->port, " -->   RetentionSupported:1\n");
03270          }
03271          if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
03272             chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
03273                fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
03274          }
03275          if (fac->u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
03276             chan_misdn_log(1, bc->port, " -->   OriginatingAddress:\n");
03277             print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Originating, bc);
03278          }
03279          break;
03280       case FacComponent_Result:
03281          chan_misdn_log(1, bc->port, " -->  Result: RetentionSupported:%d\n",
03282             fac->u.CCBS_T_Request.Component.Result.RetentionSupported);
03283          break;
03284       default:
03285          break;
03286       }
03287       break;
03288    case Fac_CCNR_T_Request:
03289       chan_misdn_log(1, bc->port, " --> CCNR_T_Request: InvokeID:%d\n",
03290          fac->u.CCNR_T_Request.InvokeID);
03291       switch (fac->u.CCNR_T_Request.ComponentType) {
03292       case FacComponent_Invoke:
03293          chan_misdn_log(1, bc->port, " -->  Invoke\n");
03294          chan_misdn_log(1, bc->port, " -->   DestinationAddress:\n");
03295          print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Destination, bc);
03296          print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCNR_T_Request.Component.Invoke.Q931ie, bc);
03297          if (fac->u.CCNR_T_Request.Component.Invoke.RetentionSupported) {
03298             chan_misdn_log(1, bc->port, " -->   RetentionSupported:1\n");
03299          }
03300          if (fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
03301             chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
03302                fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicator);
03303          }
03304          if (fac->u.CCNR_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
03305             chan_misdn_log(1, bc->port, " -->   OriginatingAddress:\n");
03306             print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Originating, bc);
03307          }
03308          break;
03309       case FacComponent_Result:
03310          chan_misdn_log(1, bc->port, " -->  Result: RetentionSupported:%d\n",
03311             fac->u.CCNR_T_Request.Component.Result.RetentionSupported);
03312          break;
03313       default:
03314          break;
03315       }
03316       break;
03317 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
03318    case Fac_None:
03319       /* No facility so print nothing */
03320       break;
03321    default:
03322       chan_misdn_log(1, bc->port, " --> unknown facility\n");
03323       break;
03324    }
03325 }

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

Definition at line 7244 of file chan_misdn.c.

References chan_list::ast, ast_async_goto(), ast_debug, chan_list::ast_dsp, ast_dsp_process(), ast_exists_extension(), AST_FRAME_DTMF, ast_log(), ast_strlen_zero(), ast_verb, chan_list::bc, BUFFERSIZE, ast_channel::caller, chan_misdn_log(), ast_channel::context, context, chan_list::dsp, misdn_bchannel::ec_enable, ast_channel::exten, f, chan_list::faxdetect, chan_list::faxhandled, ast_frame::frametype, ast_party_caller::id, ast_frame_subclass::integer, isdn_lib_stop_dtmf(), isdn_lib_update_ec(), isdn_lib_update_rxgain(), isdn_lib_update_txgain(), LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), ast_party_id::number, pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, S_COR, ast_party_number::str, ast_frame::subclass, misdn_bchannel::txgain, and ast_party_number::valid.

Referenced by misdn_read().

07245 {
07246    struct ast_frame *f;
07247 
07248    if (tmp->dsp) {
07249       f = ast_dsp_process(tmp->ast, tmp->dsp, frame);
07250    } else {
07251       chan_misdn_log(0, tmp->bc->port, "No DSP-Path found\n");
07252       return NULL;
07253    }
07254 
07255    if (!f || (f->frametype != AST_FRAME_DTMF)) {
07256       return f;
07257    }
07258 
07259    ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass.integer);
07260 
07261    if (tmp->faxdetect && (f->subclass.integer == 'f')) {
07262       /* Fax tone -- Handle and return NULL */
07263       if (!tmp->faxhandled) {
07264          struct ast_channel *ast = tmp->ast;
07265          tmp->faxhandled++;
07266          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
07267          tmp->bc->rxgain = 0;
07268          isdn_lib_update_rxgain(tmp->bc);
07269          tmp->bc->txgain = 0;
07270          isdn_lib_update_txgain(tmp->bc);
07271 #ifdef MISDN_1_2
07272          *tmp->bc->pipeline = 0;
07273 #else
07274          tmp->bc->ec_enable = 0;
07275 #endif
07276          isdn_lib_update_ec(tmp->bc);
07277          isdn_lib_stop_dtmf(tmp->bc);
07278          switch (tmp->faxdetect) {
07279          case 1:
07280             if (strcmp(ast->exten, "fax")) {
07281                char *context;
07282                char context_tmp[BUFFERSIZE];
07283                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
07284                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
07285                if (ast_exists_extension(ast, context, "fax", 1,
07286                   S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
07287                   ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
07288                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
07289                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
07290                   if (ast_async_goto(ast, context, "fax", 1)) {
07291                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
07292                   }
07293                } else {
07294                   ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast->exten);
07295                }
07296             } else {
07297                ast_debug(1, "Already in a fax extension, not redirecting\n");
07298             }
07299             break;
07300          case 2:
07301             ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
07302             break;
07303          default:
07304             break;
07305          }
07306       } else {
07307          ast_debug(1, "Fax already handled\n");
07308       }
07309    }
07310 
07311    if (tmp->ast_dsp && (f->subclass.integer != 'f')) {
07312       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass.integer);
07313    }
07314 
07315    return f;
07316 }

static int read_config ( struct chan_list ch  )  [static]

Definition at line 5891 of file chan_misdn.c.

References chan_list::allowed_bearers, misdn_bchannel::AOCDtype, chan_list::ast, ast_callerid_parse(), ast_copy_string(), chan_list::ast_dsp, ast_dsp_new(), ast_dsp_set_features(), ast_log(), ast_mutex_init, ast_print_group(), ast_string_field_set, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, misdn_bchannel::caller, ast_channel::callgroup, misdn_bchannel::capability, chan_misdn_log(), cid_name, cid_num, config_jitterbuffer(), ast_channel::context, chan_list::context, debug_numtype(), misdn_bchannel::dialed, misdn_bchannel::display_connected, misdn_bchannel::display_setup, 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, misdn_bchannel::incoming_cid_tag, 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_add_number_prefix(), MISDN_CFG_ALLOWED_BEARERS, MISDN_CFG_ASTDTMF, MISDN_CFG_CALLERID, MISDN_CFG_CALLGROUP, MISDN_CFG_CONTEXT, MISDN_CFG_DIALPLAN, MISDN_CFG_DISPLAY_CONNECTED, MISDN_CFG_DISPLAY_SETUP, MISDN_CFG_EARLY_BCONNECT, MISDN_CFG_FAR_ALERTING, MISDN_CFG_FAXDETECT, MISDN_CFG_FAXDETECT_TIMEOUT, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_INCOMING_CALLERID_TAG, MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CFG_JITTERBUFFER, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CFG_LANGUAGE, MISDN_CFG_MUSICCLASS, MISDN_CFG_NEED_MORE_INFOS, MISDN_CFG_NOAUTORESPOND_ON_SETUP, MISDN_CFG_NTTIMEOUT, MISDN_CFG_OUTGOING_COLP, 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_party_id::name, misdn_bchannel::need_more_infos, chan_list::noautorespond_on_setup, chan_list::nttimeout, misdn_party_dialing::number, misdn_party_id::number, misdn_party_dialing::number_plan, misdn_party_id::number_type, misdn_party_dialing::number_type, NUMPLAN_ISDN, ORG_AST, chan_list::originator, misdn_bchannel::outgoing_colp, chan_list::overlap_dial, chan_list::overlap_dial_task, chan_list::overlap_tv_lock, ast_channel::pickupgroup, misdn_bchannel::port, misdn_bchannel::rxgain, misdn_bchannel::send_dtmf, misdn_bchannel::te_choose_channel, misdn_bchannel::txgain, and update_ec_config().

Referenced by cb_events(), and misdn_request().

05892 {
05893    struct ast_channel *ast;
05894    struct misdn_bchannel *bc;
05895    int port;
05896    int hdlc = 0;
05897    char lang[BUFFERSIZE + 1];
05898    char faxdetect[BUFFERSIZE + 1];
05899    char buf[256];
05900    char buf2[256];
05901    ast_group_t pg;
05902    ast_group_t cg;
05903 
05904    if (!ch) {
05905       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
05906       return -1;
05907    }
05908 
05909    ast = ch->ast;
05910    bc = ch->bc;
05911    if (! ast || ! bc) {
05912       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
05913       return -1;
05914    }
05915 
05916    port = bc->port;
05917    chan_misdn_log(1, port, "read_config: Getting Config\n");
05918 
05919    misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
05920    ast_string_field_set(ast, language, lang);
05921 
05922    misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
05923 
05924    misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
05925    misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
05926 
05927    misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
05928 
05929    misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
05930 
05931    misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
05932    if (ch->ast_dsp) {
05933       ch->ignore_dtmf = 1;
05934    }
05935 
05936    misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
05937    misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
05938 
05939    misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
05940 
05941    misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
05942 
05943    misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
05944 
05945    misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
05946 
05947    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
05948    if (hdlc) {
05949       switch (bc->capability) {
05950       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
05951       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
05952          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
05953          bc->hdlc = 1;
05954          break;
05955       }
05956 
05957    }
05958    /*Initialize new Jitterbuffer*/
05959    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
05960    misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
05961 
05962    config_jitterbuffer(ch);
05963 
05964    misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
05965 
05966    ast_copy_string(ast->context, ch->context, sizeof(ast->context));
05967 
05968 #ifdef MISDN_1_2
05969    update_pipeline_config(bc);
05970 #else
05971    update_ec_config(bc);
05972 #endif
05973 
05974    misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
05975 
05976    misdn_cfg_get(port, MISDN_CFG_DISPLAY_CONNECTED, &bc->display_connected, sizeof(bc->display_connected));
05977    misdn_cfg_get(port, MISDN_CFG_DISPLAY_SETUP, &bc->display_setup, sizeof(bc->display_setup));
05978    misdn_cfg_get(port, MISDN_CFG_OUTGOING_COLP, &bc->outgoing_colp, sizeof(bc->outgoing_colp));
05979 
05980    misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
05981    misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
05982    chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
05983    ast->pickupgroup = pg;
05984    ast->callgroup = cg;
05985 
05986    if (ch->originator == ORG_AST) {
05987       char callerid[BUFFERSIZE + 1];
05988 
05989       /* ORIGINATOR Asterisk (outgoing call) */
05990 
05991       misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
05992 
05993       if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
05994          ch->faxdetect = strstr(faxdetect, "nojump") ? 2 : 1;
05995       }
05996 
05997       misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
05998       if (!ast_strlen_zero(callerid)) {
05999          char *cid_name = NULL;
06000          char *cid_num = NULL;
06001 
06002          ast_callerid_parse(callerid, &cid_name, &cid_num);
06003          if (cid_name) {
06004             ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
06005          } else {
06006             bc->caller.name[0] = '\0';
06007          }
06008          if (cid_num) {
06009             ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
06010          } else {
06011             bc->caller.number[0] = '\0';
06012          }
06013          chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
06014       }
06015 
06016       misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dialed.number_type, sizeof(bc->dialed.number_type));
06017       bc->dialed.number_plan = NUMPLAN_ISDN;
06018       debug_numtype(port, bc->dialed.number_type, "TON");
06019 
06020       ch->overlap_dial = 0;
06021    } else {
06022       /* ORIGINATOR MISDN (incoming call) */
06023 
06024       if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
06025          ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
06026       }
06027 
06028       /* Add configured prefix to caller.number */
06029       misdn_add_number_prefix(bc->port, bc->caller.number_type, bc->caller.number, sizeof(bc->caller.number));
06030 
06031       if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
06032          ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
06033       }
06034 
06035       /* Add configured prefix to dialed.number */
06036       misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
06037 
06038       ast_copy_string(ast->exten, bc->dialed.number, sizeof(ast->exten));
06039 
06040       misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
06041       ast_mutex_init(&ch->overlap_tv_lock);
06042    } /* ORIG MISDN END */
06043 
06044    misdn_cfg_get(port, MISDN_CFG_INCOMING_CALLERID_TAG, bc->incoming_cid_tag, sizeof(bc->incoming_cid_tag));
06045    if (!ast_strlen_zero(bc->incoming_cid_tag)) {
06046       chan_misdn_log(1, port, " --> * Setting incoming caller id tag to \"%s\"\n", bc->incoming_cid_tag);
06047    }
06048    ch->overlap_dial_task = -1;
06049 
06050    if (ch->faxdetect  || ch->ast_dsp) {
06051       misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
06052       if (!ch->dsp) {
06053          ch->dsp = ast_dsp_new();
06054       }
06055       if (ch->dsp) {
06056          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | (ch->faxdetect ? DSP_FEATURE_FAX_DETECT : 0));
06057       }
06058    }
06059 
06060    /* AOCD initialization */
06061    bc->AOCDtype = Fac_None;
06062 
06063    return 0;
06064 }

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

Definition at line 8422 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, ast_channel_trylock, ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_channel::caller, chan_list_unref, chan_misdn_log(), cl_dequeue_chan(), ast_channel::context, DEADLOCK_AVOIDANCE, ast_channel::exten, ast_party_caller::id, misdn_bchannel::l3_id, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, ast_party_id::name, ast_party_id::number, ORG_AST, chan_list::originator, misdn_bchannel::pid, misdn_bchannel::port, S_COR, chan_list::state, ast_party_number::str, ast_party_name::str, ast_party_number::valid, and ast_party_name::valid.

Referenced by cb_events(), and misdn_hangup().

08423 {
08424    struct ast_channel *ast;
08425 
08426    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
08427 
08428    ast_mutex_lock(&release_lock);
08429    for (;;) {
08430       ast = ch->ast;
08431       if (!ast || !ast_channel_trylock(ast)) {
08432          break;
08433       }
08434       DEADLOCK_AVOIDANCE(&release_lock);
08435    }
08436    if (!cl_dequeue_chan(ch)) {
08437       /* Someone already released it. */
08438       if (ast) {
08439          ast_channel_unlock(ast);
08440       }
08441       ast_mutex_unlock(&release_lock);
08442       return;
08443    }
08444    ch->state = MISDN_CLEANING;
08445    ch->ast = NULL;
08446    if (ast) {
08447       struct chan_list *ast_ch;
08448 
08449       ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
08450       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
08451       chan_misdn_log(1, bc->port,
08452          "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
08453          bc->pid,
08454          ast->context,
08455          ast->exten,
08456          S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
08457          S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""));
08458 
08459       if (ast->_state != AST_STATE_RESERVED) {
08460          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
08461          ast_setstate(ast, AST_STATE_DOWN);
08462       }
08463       ast_channel_unlock(ast);
08464       if (ast_ch) {
08465          chan_list_unref(ast_ch, "Release ast_channel reference.");
08466       }
08467    }
08468 
08469    if (ch->originator == ORG_AST) {
08470       --misdn_out_calls[bc->port];
08471    } else {
08472       --misdn_in_calls[bc->port];
08473    }
08474 
08475    ast_mutex_unlock(&release_lock);
08476 }

static void release_chan_early ( struct chan_list ch  )  [static]

Definition at line 8488 of file chan_misdn.c.

References ast_channel::_state, chan_list::ast, ast_channel_trylock, ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, chan_list_unref, cl_dequeue_chan(), DEADLOCK_AVOIDANCE, chan_list::hold, MISDN_ASTERISK_TECH_PVT, MISDN_CLEANING, MISDN_HOLD_IDLE, ORG_AST, chan_list::originator, hold_info::port, hold_info::state, and chan_list::state.

Referenced by misdn_hangup().

08489 {
08490    struct ast_channel *ast;
08491 
08492    ast_mutex_lock(&release_lock);
08493    for (;;) {
08494       ast = ch->ast;
08495       if (!ast || !ast_channel_trylock(ast)) {
08496          break;
08497       }
08498       DEADLOCK_AVOIDANCE(&release_lock);
08499    }
08500    if (!cl_dequeue_chan(ch)) {
08501       /* Someone already released it. */
08502       if (ast) {
08503          ast_channel_unlock(ast);
08504       }
08505       ast_mutex_unlock(&release_lock);
08506       return;
08507    }
08508    ch->state = MISDN_CLEANING;
08509    ch->ast = NULL;
08510    if (ast) {
08511       struct chan_list *ast_ch;
08512 
08513       ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
08514       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
08515 
08516       if (ast->_state != AST_STATE_RESERVED) {
08517          ast_setstate(ast, AST_STATE_DOWN);
08518       }
08519       ast_channel_unlock(ast);
08520       if (ast_ch) {
08521          chan_list_unref(ast_ch, "Release ast_channel reference.");
08522       }
08523    }
08524 
08525    if (ch->hold.state != MISDN_HOLD_IDLE) {
08526       if (ch->originator == ORG_AST) {
08527          --misdn_out_calls[ch->hold.port];
08528       } else {
08529          --misdn_in_calls[ch->hold.port];
08530       }
08531    }
08532 
08533    ast_mutex_unlock(&release_lock);
08534 }

static int reload ( void   )  [static]

Definition at line 11396 of file chan_misdn.c.

References reload_config().

11397 {
11398    reload_config();
11399 
11400    return 0;
11401 }

static void reload_config ( void   )  [static]

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

04093 {
04094    int i, cfg_debug;
04095 
04096    if (!g_config_initialized) {
04097       ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
04098       return ;
04099    }
04100 
04101    free_robin_list();
04102    misdn_cfg_reload();
04103    misdn_cfg_update_ptp();
04104    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
04105    misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
04106 
04107    for (i = 0;  i <= max_ports; i++) {
04108       misdn_debug[i] = cfg_debug;
04109       misdn_debug_only[i] = 0;
04110    }
04111 }

static int send_cause2ast ( struct ast_channel ast,
struct misdn_bchannel bc,
struct chan_list ch 
) [static]
Return values:
-1 if can hangup after calling.
0 if cannot hangup after calling.

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

08684 {
08685    int can_hangup;
08686 
08687    if (!ast) {
08688       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
08689       return 0;
08690    }
08691    if (!bc) {
08692       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
08693       return 0;
08694    }
08695    if (!ch) {
08696       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
08697       return 0;
08698    }
08699 
08700    ast->hangupcause = bc->cause;
08701 
08702    can_hangup = -1;
08703    switch (bc->cause) {
08704    case AST_CAUSE_UNALLOCATED:
08705    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
08706    case AST_CAUSE_NO_ROUTE_DESTINATION:
08707    case 4:  /* Send special information tone */
08708    case AST_CAUSE_NUMBER_CHANGED:
08709    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
08710       /* Congestion Cases */
08711       /*
08712        * Not Queueing the Congestion anymore, since we want to hear
08713        * the inband message
08714        *
08715       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
08716       ch->state = MISDN_BUSY;
08717 
08718       ast_queue_control(ast, AST_CONTROL_CONGESTION);
08719       */
08720       break;
08721 
08722    case AST_CAUSE_CALL_REJECTED:
08723    case AST_CAUSE_USER_BUSY:
08724       ch->state = MISDN_BUSY;
08725 
08726       if (!ch->need_busy) {
08727          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
08728          break;
08729       }
08730       ch->need_busy = 0;
08731 
08732       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
08733       ast_queue_control(ast, AST_CONTROL_BUSY);
08734 
08735       /* The BUSY is likely to cause a hangup or the user needs to hear it. */
08736       can_hangup = 0;
08737       break;
08738    }
08739    return can_hangup;
08740 }

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

Definition at line 3650 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().

03651 {
03652    static const char * const dtmf_tones[] = {
03653 /* *INDENT-OFF* */
03654       "!941+1336/100,!0/100", /* 0 */
03655       "!697+1209/100,!0/100", /* 1 */
03656       "!697+1336/100,!0/100", /* 2 */
03657       "!697+1477/100,!0/100", /* 3 */
03658       "!770+1209/100,!0/100", /* 4 */
03659       "!770+1336/100,!0/100", /* 5 */
03660       "!770+1477/100,!0/100", /* 6 */
03661       "!852+1209/100,!0/100", /* 7 */
03662       "!852+1336/100,!0/100", /* 8 */
03663       "!852+1477/100,!0/100", /* 9 */
03664       "!697+1633/100,!0/100", /* A */
03665       "!770+1633/100,!0/100", /* B */
03666       "!852+1633/100,!0/100", /* C */
03667       "!941+1633/100,!0/100", /* D */
03668       "!941+1209/100,!0/100", /* * */
03669       "!941+1477/100,!0/100", /* # */
03670 /* *INDENT-ON* */
03671    };
03672    struct ast_channel *chan = cl->ast;
03673 
03674    if (digit >= '0' && digit <='9') {
03675       ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
03676    } else if (digit >= 'A' && digit <= 'D') {
03677       ast_playtones_start(chan, 0, dtmf_tones[digit - 'A' + 10], 0);
03678    } else if (digit == '*') {
03679       ast_playtones_start(chan, 0, dtmf_tones[14], 0);
03680    } else if (digit == '#') {
03681       ast_playtones_start(chan, 0, dtmf_tones[15], 0);
03682    } else {
03683       /* not handled */
03684       ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
03685    }
03686 }

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

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

03932 {
03933    char section[BUFFERSIZE];
03934    char name[BUFFERSIZE];
03935    char desc[BUFFERSIZE];
03936    char def[BUFFERSIZE];
03937    char tmp[BUFFERSIZE];
03938 
03939    misdn_cfg_get_name(elem, tmp, sizeof(tmp));
03940    term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
03941    misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
03942 
03943    if (elem < MISDN_CFG_LAST) {
03944       term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
03945    } else {
03946       term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
03947    }
03948 
03949    if (*def) {
03950       ast_cli(fd, "[%s] %s   (Default: %s)\n\t%s\n", section, name, def, desc);
03951    } else {
03952       ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
03953    }
03954 }

static void sighandler ( int  sig  )  [static]

Definition at line 3493 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

03494 {
03495 }

static int start_bc_tones ( struct chan_list cl  )  [static]

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

07682 {
07683    misdn_lib_tone_generator_stop(cl->bc);
07684    cl->notxtone = 0;
07685    cl->norxtone = 0;
07686    return 0;
07687 }

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

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

08834 {
08835    if (pbx_start_chan(ch) < 0) {
08836       hangup_chan(ch, bc);
08837       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
08838       if (bc->nt) {
08839          hanguptone_indicate(ch);
08840          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
08841       } else {
08842          misdn_lib_send_event(bc, EVENT_RELEASE);
08843       }
08844    }
08845 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 7689 of file chan_misdn.c.

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

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

07690 {
07691    if (!cl) {
07692       return -1;
07693    }
07694 
07695    cl->notxtone = 1;
07696    cl->norxtone = 1;
07697 
07698    return 0;
07699 }

static int stop_indicate ( struct chan_list cl  )  [static]

Definition at line 7660 of file chan_misdn.c.

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

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

07661 {
07662    struct ast_channel *ast = cl->ast;
07663 
07664    if (!ast) {
07665       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
07666       return -1;
07667    }
07668 
07669    chan_misdn_log(3, cl->bc->port, " --> None\n");
07670    misdn_lib_tone_generator_stop(cl->bc);
07671    ast_playtones_stop(ast);
07672 
07673    if (cl->ts) {
07674       cl->ts = ast_tone_zone_sound_unref(cl->ts);
07675    }
07676 
07677    return 0;
07678 }

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 11138 of file chan_misdn.c.

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

11139 {
11140    /* First, take us out of the channel loop */
11141    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
11142 
11143    misdn_tasks_destroy();
11144 
11145    if (!g_config_initialized) {
11146       return 0;
11147    }
11148 
11149    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11150 
11151    /* ast_unregister_application("misdn_crypt"); */
11152    ast_unregister_application("misdn_set_opt");
11153    ast_unregister_application("misdn_facility");
11154    ast_unregister_application("misdn_check_l2l1");
11155 #if defined(AST_MISDN_ENHANCEMENTS)
11156    ast_unregister_application(misdn_command_name);
11157    ast_custom_function_unregister(&misdn_cc_function);
11158 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11159 
11160    ast_channel_unregister(&misdn_tech);
11161 
11162    free_robin_list();
11163    misdn_cfg_destroy();
11164    misdn_lib_destroy();
11165 
11166    ast_free(misdn_out_calls);
11167    ast_free(misdn_in_calls);
11168    ast_free(misdn_debug_only);
11169    ast_free(misdn_ports);
11170    ast_free(misdn_debug);
11171 
11172 #if defined(AST_MISDN_ENHANCEMENTS)
11173    misdn_cc_destroy();
11174 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11175 
11176    return 0;
11177 }

static void update_config ( struct chan_list ch  )  [static]

Updates caller ID information from config.

Definition at line 5730 of file chan_misdn.c.

References chan_list::ast, ast_log(), ast_to_misdn_pres(), ast_to_misdn_screen(), chan_list::bc, misdn_bchannel::caller, misdn_bchannel::capability, chan_misdn_log(), ast_channel::connected, misdn_bchannel::hdlc, ast_party_connected_line::id, INFO_CAPABILITY_DIGITAL_RESTRICTED, INFO_CAPABILITY_DIGITAL_UNRESTRICTED, LOG_WARNING, misdn_cfg_get(), MISDN_CFG_HDLC, MISDN_CFG_PRES, MISDN_CFG_SCREEN, misdn_to_str_pres(), misdn_to_str_screen(), ast_party_id::number, misdn_bchannel::port, misdn_party_id::presentation, ast_party_number::presentation, and misdn_party_id::screening.

Referenced by misdn_call().

05731 {
05732    struct ast_channel *ast;
05733    struct misdn_bchannel *bc;
05734    int port;
05735    int hdlc = 0;
05736    int pres;
05737    int screen;
05738 
05739    if (!ch) {
05740       ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
05741       return;
05742    }
05743 
05744    ast = ch->ast;
05745    bc = ch->bc;
05746    if (! ast || ! bc) {
05747       ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
05748       return;
05749    }
05750 
05751    port = bc->port;
05752 
05753    chan_misdn_log(7, port, "update_config: Getting Config\n");
05754 
05755    misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
05756    if (hdlc) {
05757       switch (bc->capability) {
05758       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
05759       case INFO_CAPABILITY_DIGITAL_RESTRICTED:
05760          chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
05761          bc->hdlc = 1;
05762          break;
05763       }
05764    }
05765 
05766 
05767    misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
05768    misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
05769    chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
05770 
05771    if (pres < 0 || screen < 0) {
05772       chan_misdn_log(2, port, " --> pres: %x\n", ast->connected.id.number.presentation);
05773 
05774       bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number.presentation);
05775       chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
05776 
05777       bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number.presentation);
05778       chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
05779    } else {
05780       bc->caller.screening = screen;
05781       bc->caller.presentation = pres;
05782    }
05783 }

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

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

05873 {
05874    int ec;
05875    int port = bc->port;
05876 
05877    misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
05878 
05879    if (ec == 1) {
05880       bc->ec_enable = 1;
05881    } else if (ec > 1) {
05882       bc->ec_enable = 1;
05883       bc->ec_deftaps = ec;
05884    }
05885 
05886    return 0;
05887 }

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

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

08088 {
08089    int chan_offset = 0;
08090    int tmp_port = misdn_cfg_get_next_port(0);
08091    char newname[255];
08092 
08093    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
08094       if (tmp_port == port) {
08095          break;
08096       }
08097       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
08098    }
08099    if (c < 0) {
08100       c = 0;
08101    }
08102 
08103    snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
08104    if (strncmp(tmp->name, newname, strlen(newname))) {
08105       snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
08106       ast_change_name(tmp, newname);
08107       chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
08108    }
08109 }

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

Variable Documentation

Definition at line 2334 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 5703 of file chan_misdn.c.

struct chan_list* cl_te = NULL [static]

Global channel call record list head.

Definition at line 678 of file chan_misdn.c.

Definition at line 679 of file chan_misdn.c.

int g_config_initialized = 0 [static]

Definition at line 101 of file chan_misdn.c.

int glob_channel = 0 [static]

Definition at line 8085 of file chan_misdn.c.

char global_tracefile[BUFFERSIZE+1] [static]
Note:
To use the CCBS/CCNR supplementary service feature and other supplementary services using FACILITY messages requires a modified version of mISDN.
The latest modified mISDN v1.1.x based version is available at: http://svn.digium.com/svn/thirdparty/mISDN/trunk http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
Taged versions of the modified mISDN code are available under: http://svn.digium.com/svn/thirdparty/mISDN/tags http://svn.digium.com/svn/thirdparty/mISDNuser/tags

Definition at line 99 of file chan_misdn.c.

int max_ports [static]

Definition at line 670 of file chan_misdn.c.

int MAXTICS = 8

Definition at line 584 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 668 of file chan_misdn.c.

int* misdn_debug_only [static]

Definition at line 669 of file chan_misdn.c.

int* misdn_in_calls [static]

Definition at line 672 of file chan_misdn.c.

int* misdn_out_calls [static]

Definition at line 673 of file chan_misdn.c.

int* misdn_ports [static]

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

pthread_t misdn_tasks_thread [static]

Definition at line 643 of file chan_misdn.c.

struct ast_channel_tech misdn_tech [static]

Definition at line 8047 of file chan_misdn.c.

Definition at line 8066 of file chan_misdn.c.

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

Definition at line 661 of file chan_misdn.c.

int prefformat = AST_FORMAT_ALAW [static]

Only alaw and mulaw is allowed for now.

Definition at line 666 of file chan_misdn.c.

Definition at line 295 of file chan_misdn.c.

struct robin_list* robin = NULL [static]

Definition at line 598 of file chan_misdn.c.

struct state_struct state_array[] [static]

Definition at line 4052 of file chan_misdn.c.

int tracing = 0 [static]

Definition at line 663 of file chan_misdn.c.


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1