Sat Mar 10 01:54:59 2012

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 void __reg_module (void)
static void __unreg_module (void)
static int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
int add_in_calls (int port)
int add_out_calls (int port)
static 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).
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 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 ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Channel driver for mISDN Support (BRI/PRI)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static struct allowed_bearers allowed_bearers_array []
static struct ast_module_infoast_module_info = &__mod_info
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))

Definition at line 342 of file chan_misdn.c.

Referenced by cl_queue_chan(), find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), get_chan_by_ast(), get_chan_by_ast_name(), and misdn_new().

#define chan_list_unref ( obj,
debug   )     (ao2_t_ref((obj), -1, (debug)), NULL)

Definition at line 343 of file chan_misdn.c.

Referenced by cb_events(), chan_misdn_jb_empty(), cl_dequeue_chan(), handle_cli_misdn_send_display(), handle_cli_misdn_send_facility(), handle_cli_misdn_toggle_echocancel(), misdn_bridge(), misdn_hangup(), release_chan(), and release_chan_early().

#define MISDN_ASTERISK_TECH_PVT ( ast   )     ast->tech_pvt

Definition at line 654 of file chan_misdn.c.

Referenced by cb_events(), do_immediate_setup(), misdn_answer(), misdn_call(), misdn_digit_end(), misdn_facility_exec(), misdn_fixup(), misdn_hangup(), misdn_indication(), misdn_new(), misdn_read(), misdn_send_text(), misdn_set_opt_exec(), misdn_update_connected_line(), misdn_write(), release_chan(), and release_chan_early().

#define ORG_AST   1

Asterisk created the channel (outgoing call)

Definition at line 314 of file chan_misdn.c.

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

#define ORG_MISDN   2

mISDN created the channel (incoming call)

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


Enumeration Type Documentation

enum misdn_chan_state

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

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

enum misdn_hold_state

Enumerator:
MISDN_HOLD_IDLE  HOLD not active
MISDN_HOLD_ACTIVE  Call is held
MISDN_HOLD_TRANSFER  Held call is being transferred
MISDN_HOLD_DISCONNECT  Held call is being disconnected

Definition at line 318 of file chan_misdn.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 12702 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

Definition at line 12702 of file chan_misdn.c.

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

Definition at line 3559 of file chan_misdn.c.

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

Referenced by misdn_tasks_add(), and misdn_tasks_add_variable().

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

int add_in_calls ( int  port  ) 

Definition at line 8802 of file chan_misdn.c.

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

Referenced by cb_events().

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(), MISDN_CFG_MAX_OUT, and misdn_out_calls.

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 }

static enum mISDN_NUMBER_PLAN ast_to_misdn_plan ( unsigned  ast_number_plan  )  [static]

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

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

static int ast_to_misdn_pres ( int  presentation  )  [static]

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

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

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

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

02246 {
02247    unsigned index;
02248 
02249    static const struct misdn_reasons {
02250       enum AST_REDIRECTING_REASON ast;
02251       enum mISDN_REDIRECTING_REASON q931;
02252    } misdn_reason_table[] = {
02253    /* *INDENT-OFF* */
02254       { AST_REDIRECTING_REASON_UNKNOWN,        mISDN_REDIRECTING_REASON_UNKNOWN },
02255       { AST_REDIRECTING_REASON_USER_BUSY,      mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
02256       { AST_REDIRECTING_REASON_NO_ANSWER,      mISDN_REDIRECTING_REASON_NO_REPLY },
02257       { AST_REDIRECTING_REASON_UNAVAILABLE,    mISDN_REDIRECTING_REASON_NO_REPLY },
02258       { AST_REDIRECTING_REASON_UNCONDITIONAL,  mISDN_REDIRECTING_REASON_CALL_FWD },
02259       { AST_REDIRECTING_REASON_TIME_OF_DAY,    mISDN_REDIRECTING_REASON_UNKNOWN },
02260       { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
02261       { AST_REDIRECTING_REASON_DEFLECTION,     mISDN_REDIRECTING_REASON_DEFLECTION },
02262       { AST_REDIRECTING_REASON_FOLLOW_ME,      mISDN_REDIRECTING_REASON_UNKNOWN },
02263       { AST_REDIRECTING_REASON_OUT_OF_ORDER,   mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
02264       { AST_REDIRECTING_REASON_AWAY,           mISDN_REDIRECTING_REASON_UNKNOWN },
02265       { AST_REDIRECTING_REASON_CALL_FWD_DTE,   mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
02266    /* *INDENT-ON* */
02267    };
02268 
02269    for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
02270       if (misdn_reason_table[index].ast == ast) {
02271          return misdn_reason_table[index].q931;
02272       }
02273    }
02274    return mISDN_REDIRECTING_REASON_UNKNOWN;
02275 }

static int ast_to_misdn_screen ( int  screening  )  [static]

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

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

static enum mISDN_NUMBER_TYPE ast_to_misdn_ton ( unsigned  ast_number_type  )  [static]

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

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

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

Definition at line 2344 of file chan_misdn.c.

References allowed_bearers_array, ARRAY_LEN, and allowed_bearers::display.

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

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

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

Definition at line 9859 of file chan_misdn.c.

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

static void chan_list_destructor ( void *  obj  )  [static]

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

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

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

Returns a reference to the new chan_list.

Definition at line 7749 of file chan_misdn.c.

References ao2_alloc, chan_list_destructor(), and chan_misdn_log().

Referenced by cb_events().

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

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

Definition at line 12433 of file chan_misdn.c.

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

Referenced by load_module().

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

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

Definition at line 12627 of file chan_misdn.c.

References ast_console_puts(), ast_log(), ast_strlen_zero(), errno, LOG_WARNING, max_ports, misdn_debug, and misdn_debug_only.

Referenced by cb_events(), chan_list_init(), cl_queue_chan(), config_jitterbuffer(), debug_numtype(), dialtone_indicate(), do_immediate_setup(), export_ch(), 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_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().

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

static int cl_dequeue_chan ( struct chan_list chan  )  [static]

Definition at line 8324 of file chan_misdn.c.

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

Referenced by release_chan(), and release_chan_early().

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

static void cl_queue_chan ( struct chan_list chan  )  [static]

Definition at line 8303 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Definition at line 5623 of file chan_misdn.c.

References ast_complete_channels(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, and ast_cli_args::word.

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

05624 {
05625    return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
05626 }

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

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

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

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

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]

Returns a reference to the found chan_list.

Definition at line 8185 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, chan_list::bc, chan_list_ref, cl_te, cl_te_lock, and chan_list::next.

Referenced by cb_events(), and chan_misdn_jb_empty().

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

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

Definition at line 8277 of file chan_misdn.c.

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

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

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

Returns a reference to the found chan_list.

Definition at line 8209 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, chan_list::bc, misdn_bchannel::caller, chan_list_ref, chan_misdn_log(), hold_info::channel, misdn_bchannel::channel, cl_te, cl_te_lock, 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().

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

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

Returns a reference to the found chan_list.

Definition at line 8243 of file chan_misdn.c.

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

Referenced by cb_events().

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

static void free_robin_list ( void   )  [static]

Definition at line 600 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

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

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

Returns a reference to the found chan_list.

Definition at line 739 of file chan_misdn.c.

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

Referenced by misdn_bridge().

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

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

Returns a reference to the found chan_list.

Definition at line 757 of file chan_misdn.c.

References chan_list::ast, ast_mutex_lock, ast_mutex_unlock, chan_list_ref, cl_te, cl_te_lock, ast_channel::name, and chan_list::next.

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

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

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

Definition at line 612 of file chan_misdn.c.

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

Referenced by misdn_request().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3688 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, max_ports, misdn_debug, misdn_debug_only, and ast_cli_entry::usage.

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

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, chan_list::bc, cl_te, cl_te_lock, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_ch(), ast_cli_args::fd, ast_channel::name, 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 4198 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, cl_te, cl_te_lock, 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_debug, 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.

04199 {
04200    struct chan_list *help;
04201 
04202    switch (cmd) {
04203    case CLI_INIT:
04204       e->command = "misdn show channels";
04205       e->usage =
04206          "Usage: misdn show channels\n"
04207          "       Show the internal mISDN channel list\n";
04208       return NULL;
04209    case CLI_GENERATE:
04210       return NULL;
04211    }
04212 
04213    if (a->argc != 3) {
04214       return CLI_SHOWUSAGE;
04215    }
04216 
04217    ast_cli(a->fd, "Channel List: %p\n", cl_te);
04218 
04219    /*
04220     * Walking the list and dumping the channel information could
04221     * take awhile.  With the list locked for the duration, the
04222     * channel driver cannot process signaling messages.  However,
04223     * since this is a CLI command it should not be run very often.
04224     */
04225    ast_mutex_lock(&cl_te_lock);
04226    for (help = cl_te; help; help = help->next) {
04227       struct misdn_bchannel *bc = help->bc;
04228       struct ast_channel *ast = help->ast;
04229       if (!ast) {
04230          if (!bc) {
04231             ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
04232             continue;
04233          }
04234          ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
04235          continue;
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 3955 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_elem(), MISDN_CFG_LAST, MISDN_GEN_FIRST, MISDN_GEN_LAST, show_config_description(), and ast_cli_entry::usage.

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

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(), misdn_debug, misdn_debug_only, 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(), misdn_in_calls, misdn_out_calls, 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(), misdn_debug, misdn_debug_only, 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 8373 of file chan_misdn.c.

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

08374 {
08375    int port;
08376 
08377    if (!ch) {
08378       cb_log(1, 0, "Cannot hangup chan, no ch\n");
08379       return;
08380    }
08381 
08382    port = bc->port;
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]

Definition at line 7656 of file chan_misdn.c.

References chan_list::bc, misdn_lib_send_tone(), and TONE_HANGUP.

Referenced by cb_events(), do_immediate_setup(), misdn_hangup(), misdn_indication(), misdn_overlap_dial_task(), and start_pbx().

07657 {
07658    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
07659 }

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 11180 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_clis, chan_misdn_jb_empty(), chan_misdn_log(), cl_te_lock, LOG_ERROR, max_ports, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), MISDN_CFG_L1_TIMEOUT, misdn_cfg_update_ptp(), misdn_check_l2l1(), misdn_debug, misdn_debug_only, misdn_facility_exec(), MISDN_GEN_DEBUG, MISDN_GEN_NTDEBUGFILE, MISDN_GEN_NTDEBUGFLAGS, MISDN_GEN_NTKEEPCALLS, MISDN_GEN_TRACEFILE, misdn_in_calls, misdn_l1_task(), misdn_lib_init(), misdn_lib_maxports_get(), misdn_lib_nt_debug_init(), misdn_lib_nt_keepcalls(), misdn_out_calls, misdn_ports, misdn_set_opt_exec(), misdn_tasks_add(), misdn_tech, misdn_type, release_lock, tracing, and unload_module.

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

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

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

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

static int misdn_answer ( struct ast_channel ast  )  [static]

Definition at line 6753 of file chan_misdn.c.

References chan_list::ast, 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, ast_channel::name, 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 7512 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, get_chan_by_ast(), chan_list::ignore_dtmf, LOG_NOTICE, MISDN_CFG_BRIDGING, misdn_cfg_get(), MISDN_GEN_BRIDGING, misdn_lib_bridge(), misdn_lib_split_bridge(), misdn_party_id::name, ast_channel::name, misdn_party_id::number, misdn_bchannel::pid, and misdn_bchannel::port.

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

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

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, ast_channel::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 722 of file chan_misdn.c.

References ast_mutex_lock, ast_mutex_unlock, cl_te, cl_te_lock, and chan_list::next.

Referenced by misdn_hangup().

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

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

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

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

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 chan_list::ast, ast_copy_string(), ast_to_misdn_plan(), ast_to_misdn_pres(), ast_to_misdn_reason(), ast_to_misdn_screen(), ast_to_misdn_ton(), chan_list::bc, 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, 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, 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, update_redirecting(), 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 12027 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_type, misdn_bchannel::port, print_facility(), ast_channel::tech, and ast_channel_tech::type.

Referenced by load_module().

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

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

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

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

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

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, ast_channel::name, chan_list::need_busy, misdn_bchannel::need_disconnect, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::need_release, misdn_bchannel::nt, 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(), release_lock, 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 chan_list::ast, 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, ast_channel::name, 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\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 12498 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().

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

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

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

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

References ast_mutex_lock, misdn_jb::mutexjb, misdn_jb::ok, misdn_jb::rp, misdn_jb::samples, misdn_jb::size, misdn_jb::state_full, and misdn_jb::wp.

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

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

Definition at line 12461 of file chan_misdn.c.

References ast_calloc, ast_free, ast_mutex_init, and chan_misdn_log().

Referenced by config_jitterbuffer().

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

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

Definition at line 3587 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

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

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]

Definition at line 8110 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(), misdn_tech, misdn_tech_wo_bridge, misdn_type, ast_channel::nativeformats, ast_party_id::number, chan_list::pipe, prefformat, 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().

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

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

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

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

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

Definition at line 3352 of file chan_misdn.c.

Referenced by misdn_add_number_prefix().

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

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]

Definition at line 6077 of file chan_misdn.c.

References ast_channel_queue_connected_line_update(), ast_party_connected_line_init(), connected, id, misdn_to_ast_plan(), misdn_to_ast_pres(), misdn_to_ast_screen(), and misdn_to_ast_ton().

Referenced by misdn_update_remote_party().

06078 {
06079    struct ast_party_connected_line connected;
06080    struct ast_set_party_connected_line update_connected;
06081 
06082    ast_party_connected_line_init(&connected);
06083    memset(&update_connected, 0, sizeof(update_connected));
06084    update_connected.id.number = 1;
06085    connected.id.number.valid = 1;
06086    connected.id.number.str = (char *) id->number;
06087    connected.id.number.plan = misdn_to_ast_ton(id->number_type)
06088       | misdn_to_ast_plan(id->number_plan);
06089    connected.id.number.presentation = misdn_to_ast_pres(id->presentation)
06090       | misdn_to_ast_screen(id->screening);
06091    connected.id.tag = cid_tag;
06092    connected.source = source;
06093    ast_channel_queue_connected_line_update(ast, &connected, &update_connected);
06094 }

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

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]

Definition at line 7773 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_strdupa, ast_strlen_zero(), BUFFERSIZE, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, misdn_bchannel::dec, ext, get_robin_position(), 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_type, misdn_bchannel::port, and robin_list::port.

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

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

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

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

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

Definition at line 12224 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_type, 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, strsep(), ast_channel::tech, misdn_bchannel::txgain, and ast_channel_tech::type.

Referenced by load_module(), and misdn_call().

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

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

Definition at line 3572 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

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

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

Definition at line 3577 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

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

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 3542 of file chan_misdn.c.

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

Referenced by unload_module().

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

static void misdn_tasks_init ( void   )  [static]

Definition at line 3522 of file chan_misdn.c.

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

Referenced by _misdn_tasks_add_variable().

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

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 3582 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by chan_list_destructor().

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

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

Definition at line 3496 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 3554 of file chan_misdn.c.

References misdn_tasks_thread.

Referenced by _misdn_tasks_add_variable().

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

static int misdn_to_ast_plan ( enum mISDN_NUMBER_PLAN  number_plan  )  [static]

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

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

static int misdn_to_ast_pres ( int  presentation  )  [static]

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

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

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

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

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

static int misdn_to_ast_screen ( int  screening  )  [static]

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

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

static int misdn_to_ast_ton ( enum mISDN_NUMBER_TYPE  number_type  )  [static]

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

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

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

Definition at line 1929 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Definition at line 2055 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

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

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

Definition at line 2144 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

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

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

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

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

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

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

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

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

Definition at line 4135 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_debug, misdn_get_ch_state(), ast_channel::name, 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().

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

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

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

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

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

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

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

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, chan_misdn_log(), ast_channel::context, context, chan_list::dsp, misdn_bchannel::ec_enable, ast_channel::exten, f, chan_list::faxdetect, chan_list::faxhandled, isdn_lib_stop_dtmf(), isdn_lib_update_ec(), isdn_lib_update_rxgain(), isdn_lib_update_txgain(), LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, MISDN_CFG_FAXDETECT_CONTEXT, misdn_cfg_get(), ast_channel::name, pbx_builtin_setvar_helper(), misdn_bchannel::port, misdn_bchannel::rxgain, S_COR, and misdn_bchannel::txgain.

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

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, chan_list::bc, 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, misdn_in_calls, misdn_out_calls, ast_party_id::name, ast_party_id::number, ORG_AST, chan_list::originator, misdn_bchannel::pid, misdn_bchannel::port, release_lock, 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, misdn_in_calls, misdn_out_calls, ORG_AST, chan_list::originator, hold_info::port, release_lock, 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 11397 of file chan_misdn.c.

References reload_config().

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

static void reload_config ( void   )  [static]

Definition at line 4091 of file chan_misdn.c.

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

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

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

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

Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().

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

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

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

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

static void sighandler ( int  sig  )  [static]

Definition at line 3492 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

03493 {
03494 }

static int start_bc_tones ( struct chan_list cl  )  [static]

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

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

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

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

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

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

static int stop_indicate ( struct chan_list cl  )  [static]

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

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

static int unload_module ( void   )  [static]

TE STUFF END

Definition at line 11139 of file chan_misdn.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_free, ast_log(), ast_unregister_application(), chan_misdn_clis, free_robin_list(), LOG_VERBOSE, misdn_cfg_destroy(), misdn_debug, misdn_debug_only, misdn_in_calls, misdn_lib_destroy(), misdn_out_calls, misdn_ports, misdn_tasks_destroy(), and misdn_tech.

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

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

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

Referenced by cb_events().

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

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

Definition at line 8847 of file chan_misdn.c.

References misdn_bchannel::dialed, dialtone_indicate(), EVENT_SETUP_ACKNOWLEDGE, misdn_lib_send_event(), MISDN_WAITING4DIGS, misdn_bchannel::nt, misdn_party_dialing::number, and chan_list::state.

Referenced by cb_events().

08848 {
08849    ch->state = MISDN_WAITING4DIGS;
08850    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08851    if (bc->nt && !bc->dialed.number[0]) {
08852       dialtone_indicate(ch);
08853    }
08854 }


Variable Documentation

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

Definition at line 12702 of file chan_misdn.c.

struct allowed_bearers allowed_bearers_array[] [static]

Definition at line 2333 of file chan_misdn.c.

Referenced by bearer2str(), and cb_events().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 12702 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 5703 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

struct chan_list* cl_te = NULL [static]

Global channel call record list head.

Definition at line 677 of file chan_misdn.c.

Referenced by cl_dequeue_chan(), cl_queue_chan(), find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), get_chan_by_ast(), get_chan_by_ast_name(), handle_cli_misdn_show_channel(), handle_cli_misdn_show_channels(), and misdn_chan_is_valid().

ast_mutex_t cl_te_lock [static]

Definition at line 678 of file chan_misdn.c.

Referenced by cl_dequeue_chan(), cl_queue_chan(), find_chan_by_bc(), find_hold_active_call(), find_hold_call(), find_hold_call_l3(), get_chan_by_ast(), get_chan_by_ast_name(), handle_cli_misdn_show_channel(), handle_cli_misdn_show_channels(), load_module(), and misdn_chan_is_valid().

int g_config_initialized = 0 [static]

Definition at line 100 of file chan_misdn.c.

int glob_channel = 0 [static]

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

int max_ports [static]

Definition at line 669 of file chan_misdn.c.

Referenced by _build_port_config(), chan_misdn_log(), handle_cli_misdn_set_debug(), load_module(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_init(), misdn_cfg_is_group_method(), misdn_cfg_is_port_valid(), misdn_cfg_update_ptp(), and reload_config().

int MAXTICS = 8

Definition at line 583 of file chan_misdn.c.

int* misdn_debug [static]

Definition at line 667 of file chan_misdn.c.

Referenced by chan_misdn_log(), handle_cli_misdn_set_debug(), handle_cli_misdn_show_channels(), handle_cli_misdn_show_port(), handle_cli_misdn_show_stacks(), load_module(), print_bc_info(), reload_config(), and unload_module().

int* misdn_debug_only [static]

Definition at line 668 of file chan_misdn.c.

Referenced by chan_misdn_log(), handle_cli_misdn_set_debug(), handle_cli_misdn_show_port(), handle_cli_misdn_show_stacks(), load_module(), reload_config(), and unload_module().

int* misdn_in_calls [static]

Definition at line 671 of file chan_misdn.c.

Referenced by add_in_calls(), handle_cli_misdn_show_ports_stats(), load_module(), release_chan(), release_chan_early(), and unload_module().

int* misdn_out_calls [static]

Definition at line 672 of file chan_misdn.c.

Referenced by add_out_calls(), handle_cli_misdn_show_ports_stats(), load_module(), release_chan(), release_chan_early(), and unload_module().

int* misdn_ports [static]

Definition at line 644 of file chan_misdn.c.

Referenced by load_module(), and unload_module().

struct sched_context* misdn_tasks = NULL [static]

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

Definition at line 641 of file chan_misdn.c.

Referenced by _misdn_tasks_add_variable(), misdn_tasks_destroy(), misdn_tasks_init(), misdn_tasks_remove(), and misdn_tasks_thread_func().

pthread_t misdn_tasks_thread [static]

Definition at line 642 of file chan_misdn.c.

Referenced by misdn_tasks_destroy(), misdn_tasks_init(), and misdn_tasks_wakeup().

struct ast_channel_tech misdn_tech [static]

Definition at line 8046 of file chan_misdn.c.

Referenced by load_module(), misdn_new(), and unload_module().

struct ast_channel_tech misdn_tech_wo_bridge [static]

Definition at line 8065 of file chan_misdn.c.

Referenced by misdn_new().

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

Definition at line 660 of file chan_misdn.c.

Referenced by load_module(), misdn_facility_exec(), misdn_new(), misdn_request(), misdn_set_opt_exec(), and update_name().

int prefformat = AST_FORMAT_ALAW [static]

Only alaw and mulaw is allowed for now.

Definition at line 665 of file chan_misdn.c.

Referenced by misdn_new(), and misdn_write().

ast_mutex_t release_lock [static]

Definition at line 294 of file chan_misdn.c.

Referenced by load_module(), misdn_hangup(), release_chan(), and release_chan_early().

struct robin_list* robin = NULL [static]

Definition at line 597 of file chan_misdn.c.

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 4051 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 662 of file chan_misdn.c.

Referenced by load_module().


Generated on Sat Mar 10 01:55:01 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7