Wed Apr 6 11:29:57 2011

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 void send_cause2ast (struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
static void send_digit_to_chan (struct chan_list *cl, char digit)
static void show_config_description (int fd, enum misdn_cfg_elements elem)
static void sighandler (int sig)
static int start_bc_tones (struct chan_list *cl)
static void start_pbx (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
static int stop_bc_tones (struct chan_list *cl)
static int stop_indicate (struct chan_list *cl)
static int unload_module (void)
static 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 341 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 342 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(), misdn_request(), release_chan(), and release_chan_early().

#define MISDN_ASTERISK_TECH_PVT ( ast   )     ast->tech_pvt

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

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

#define ORG_MISDN   2

mISDN created the channel (incoming call)

Definition at line 315 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 8239 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 295 of file chan_misdn.c.

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

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

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 12679 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

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

int add_in_calls ( int  port  ) 

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

08775 {
08776    int max_in_calls;
08777 
08778    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
08779    misdn_in_calls[port]++;
08780 
08781    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
08782       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
08783       return misdn_in_calls[port] - max_in_calls;
08784    }
08785 
08786    return 0;
08787 }

int add_out_calls ( int  port  ) 

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

08790 {
08791    int max_out_calls;
08792 
08793    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
08794 
08795    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
08796       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
08797       return (misdn_out_calls[port] + 1) - max_out_calls;
08798    }
08799 
08800    misdn_out_calls[port]++;
08801 
08802    return 0;
08803 }

static enum mISDN_NUMBER_PLAN ast_to_misdn_plan ( unsigned  ast_number_plan  )  [static]

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

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

static int ast_to_misdn_pres ( int  presentation  )  [static]

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

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

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

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

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

static int ast_to_misdn_screen ( int  screening  )  [static]

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

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

static enum mISDN_NUMBER_TYPE ast_to_misdn_ton ( unsigned  ast_number_type  )  [static]

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

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

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

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

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

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

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

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

static void chan_list_destructor ( void *  obj  )  [static]

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

07697 {
07698    struct chan_list *ch = obj;
07699 
07700 #if defined(AST_MISDN_ENHANCEMENTS)
07701    if (ch->peer) {
07702       ao2_ref(ch->peer, -1);
07703       ch->peer = NULL;
07704    }
07705 #endif /* AST_MISDN_ENHANCEMENTS */
07706 
07707    if (ch->dsp) {
07708       ast_dsp_free(ch->dsp);
07709       ch->dsp = NULL;
07710    }
07711 
07712    /* releasing jitterbuffer */
07713    if (ch->jb) {
07714       misdn_jb_destroy(ch->jb);
07715       ch->jb = NULL;
07716    }
07717 
07718    if (ch->overlap_dial) {
07719       if (ch->overlap_dial_task != -1) {
07720          misdn_tasks_remove(ch->overlap_dial_task);
07721          ch->overlap_dial_task = -1;
07722       }
07723       ast_mutex_destroy(&ch->overlap_tv_lock);
07724    }
07725 
07726    if (-1 < ch->pipe[0]) {
07727       close(ch->pipe[0]);
07728    }
07729    if (-1 < ch->pipe[1]) {
07730       close(ch->pipe[1]);
07731    }
07732 }

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

Returns a reference to the new chan_list.

Definition at line 7735 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_request().

07736 {
07737    struct chan_list *cl;
07738 
07739    cl = ao2_alloc(sizeof(*cl), chan_list_destructor);
07740    if (!cl) {
07741       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
07742       return NULL;
07743    }
07744 
07745    cl->originator = orig;
07746    cl->need_queue_hangup = 1;
07747    cl->need_hangup = 1;
07748    cl->need_busy = 1;
07749    cl->overlap_dial_task = -1;
07750 #if defined(AST_MISDN_ENHANCEMENTS)
07751    cl->record_id = -1;
07752 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
07753    cl->pipe[0] = -1;
07754    cl->pipe[1] = -1;
07755 
07756    return cl;
07757 }

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

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

12406 {
12407    struct chan_list *ch;
12408    int res;
12409 
12410    ch = find_chan_by_bc(bc);
12411    if (!ch) {
12412       return 0;
12413    }
12414 
12415    if (ch->jb) {
12416       res = misdn_jb_empty(ch->jb, buf, len);
12417    } else {
12418       res = 0;
12419    }
12420    chan_list_unref(ch, "Done emptying jb");
12421 
12422    return res;
12423 }

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

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

12605 {
12606    va_list ap;
12607    char buf[1024];
12608    char port_buf[8];
12609 
12610    if (!(0 <= port && port <= max_ports)) {
12611       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
12612       port = 0;
12613       level = -1;
12614    } else if (!(level == -1
12615       || (misdn_debug_only[port]
12616          ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12617          : level <= misdn_debug[port])
12618       || (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
12619       /*
12620        * We are not going to print anything so lets not
12621        * go to all the work of generating a string.
12622        */
12623       return;
12624    }
12625 
12626    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
12627    va_start(ap, tmpl);
12628    vsnprintf(buf, sizeof(buf), tmpl, ap);
12629    va_end(ap);
12630 
12631    if (level == -1) {
12632       ast_log(LOG_WARNING, "%s", buf);
12633    } else if (misdn_debug_only[port]
12634       ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12635       : level <= misdn_debug[port]) {
12636       ast_console_puts(port_buf);
12637       ast_console_puts(buf);
12638    }
12639 
12640    if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
12641       char ctimebuf[30];
12642       time_t tm;
12643       char *tmp;
12644       char *p;
12645       FILE *fp;
12646 
12647       fp = fopen(global_tracefile, "a+");
12648       if (!fp) {
12649          ast_console_puts("Error opening Tracefile: [ ");
12650          ast_console_puts(global_tracefile);
12651          ast_console_puts(" ] ");
12652 
12653          ast_console_puts(strerror(errno));
12654          ast_console_puts("\n");
12655          return;
12656       }
12657 
12658       tm = time(NULL);
12659       tmp = ctime_r(&tm, ctimebuf);
12660       p = strchr(tmp, '\n');
12661       if (p) {
12662          *p = ':';
12663       }
12664       fputs(tmp, fp);
12665       fputs(" ", fp);
12666       fputs(port_buf, fp);
12667       fputs(" ", fp);
12668       fputs(buf, fp);
12669 
12670       fclose(fp);
12671    }
12672 }

static int cl_dequeue_chan ( struct chan_list chan  )  [static]

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

08304 {
08305    int found_it;
08306    struct chan_list *help;
08307 
08308    ast_mutex_lock(&cl_te_lock);
08309    if (!cl_te) {
08310       /* List is empty. */
08311       ast_mutex_unlock(&cl_te_lock);
08312       return 0;
08313    }
08314 
08315    if (cl_te == chan) {
08316       /* What we want is the head of the list. */
08317       cl_te = cl_te->next;
08318       ast_mutex_unlock(&cl_te_lock);
08319       chan_list_unref(chan, "Removed chan_list from list head");
08320       return 1;
08321    }
08322 
08323    found_it = 0;
08324    for (help = cl_te; help->next; help = help->next) {
08325       if (help->next == chan) {
08326          /* Found it in the list. */
08327          help->next = help->next->next;
08328          found_it = 1;
08329          break;
08330       }
08331    }
08332 
08333    ast_mutex_unlock(&cl_te_lock);
08334    if (found_it) {
08335       chan_list_unref(chan, "Removed chan_list from list");
08336    }
08337    return found_it;
08338 }

static void cl_queue_chan ( struct chan_list chan  )  [static]

Definition at line 8282 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(), and misdn_request().

08283 {
08284    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
08285 
08286    chan_list_ref(chan, "Adding chan_list to list");
08287    ast_mutex_lock(&cl_te_lock);
08288    chan->next = NULL;
08289    if (!cl_te) {
08290       /* List is empty, make head of list. */
08291       cl_te = chan;
08292    } else {
08293       struct chan_list *help;
08294 
08295       /* Put at end of list. */
08296       for (help = cl_te; help->next; help = help->next) {
08297       }
08298       help->next = chan;
08299    }
08300    ast_mutex_unlock(&cl_te_lock);
08301 }

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

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

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

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

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

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

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

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

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

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

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

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

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

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

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

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

07612 {
07613    struct ast_channel *ast = cl->ast;
07614    int nd = 0;
07615 
07616    if (!ast) {
07617       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
07618       return -1;
07619    }
07620 
07621    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
07622 
07623    if (nd) {
07624       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
07625       return 0;
07626    }
07627 
07628    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
07629 
07630    cl->ts = ast_get_indication_tone(ast->zone, "dial");
07631 
07632    if (cl->ts) {
07633       cl->notxtone = 0;
07634       cl->norxtone = 0;
07635       /* This prods us in misdn_write */
07636       ast_playtones_start(ast, 0, cl->ts->data, 0);
07637    }
07638 
07639    return 0;
07640 }

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

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

08596 {
08597    char *predial;
08598    struct ast_frame fr;
08599 
08600    predial = ast_strdupa(ast->exten);
08601 
08602    ch->state = MISDN_DIALING;
08603 
08604    if (!ch->noautorespond_on_setup) {
08605       if (bc->nt) {
08606          misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08607       } else {
08608          if (misdn_lib_is_ptp(bc->port)) {
08609             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08610          } else {
08611             misdn_lib_send_event(bc, EVENT_PROCEEDING);
08612          }
08613       }
08614    } else {
08615       ch->state = MISDN_INCOMING_SETUP;
08616    }
08617 
08618    chan_misdn_log(1, bc->port,
08619       "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
08620       ast->context,
08621       ast->exten,
08622       (ast->caller.id.name.valid && ast->caller.id.name.str)
08623          ? ast->caller.id.name.str : "",
08624       (ast->caller.id.number.valid && ast->caller.id.number.str)
08625          ? ast->caller.id.number.str : "");
08626 
08627    strcpy(ast->exten, "s");
08628 
08629    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
08630       ast = NULL;
08631       bc->out_cause = AST_CAUSE_UNALLOCATED;
08632       hangup_chan(ch, bc);
08633       hanguptone_indicate(ch);
08634 
08635       misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
08636    }
08637 
08638 
08639    while (!ast_strlen_zero(predial)) {
08640       fr.frametype = AST_FRAME_DTMF;
08641       fr.subclass.integer = *predial;
08642       fr.src = NULL;
08643       fr.data.ptr = NULL;
08644       fr.datalen = 0;
08645       fr.samples = 0;
08646       fr.mallocd = 0;
08647       fr.offset = 0;
08648       fr.delivery = ast_tv(0,0);
08649 
08650       if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
08651          ast_queue_frame(ch->ast, &fr);
08652       }
08653       predial++;
08654    }
08655 }

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

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

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

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

08742 {
08743    char tmp[32];
08744 
08745    /*
08746     * The only use for MISDN_PID is if there is a problem and you
08747     * have to use the "misdn restart pid" CLI command.  Otherwise,
08748     * the pid is not used by anyone.  The internal use of MISDN_PID
08749     * has been deleted.
08750     */
08751    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
08752    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
08753    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
08754 
08755    if (bc->sending_complete) {
08756       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
08757       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
08758    }
08759 
08760    if (bc->urate) {
08761       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
08762       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
08763    }
08764 
08765    if (bc->uulen) {
08766       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
08767    }
08768 
08769    if (!ast_strlen_zero(bc->keypad)) {
08770       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
08771    }
08772 }

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

Returns a reference to the found chan_list.

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

08165 {
08166    struct chan_list *help;
08167 
08168    ast_mutex_lock(&cl_te_lock);
08169    for (help = cl_te; help; help = help->next) {
08170       if (help->bc == bc) {
08171          chan_list_ref(help, "Found chan_list by bc");
08172          ast_mutex_unlock(&cl_te_lock);
08173          return help;
08174       }
08175    }
08176    ast_mutex_unlock(&cl_te_lock);
08177 
08178    chan_misdn_log(6, bc->port,
08179       "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08180       bc->dialed.number,
08181       bc->caller.name,
08182       bc->caller.number);
08183 
08184    return NULL;
08185 }

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

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

08257 {
08258    struct chan_list *list;
08259 
08260    ast_mutex_lock(&cl_te_lock);
08261    for (list = cl_te; list; list = list->next) {
08262       if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
08263          && list->ast) {
08264          switch (list->state) {
08265          case MISDN_PROCEEDING:
08266          case MISDN_PROGRESS:
08267          case MISDN_ALERTING:
08268          case MISDN_CONNECTED:
08269             chan_list_ref(list, "Found chan_list hold active call");
08270             ast_mutex_unlock(&cl_te_lock);
08271             return list;
08272          default:
08273             break;
08274          }
08275       }
08276    }
08277    ast_mutex_unlock(&cl_te_lock);
08278    return NULL;
08279 }

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

Returns a reference to the found chan_list.

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

08189 {
08190    struct chan_list *help;
08191 
08192    if (bc->pri) {
08193       return NULL;
08194    }
08195 
08196    chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d dialed:%s caller:\"%s\" <%s>\n",
08197       bc->channel,
08198       bc->dialed.number,
08199       bc->caller.name,
08200       bc->caller.number);
08201    ast_mutex_lock(&cl_te_lock);
08202    for (help = cl_te; help; help = help->next) {
08203       chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
08204       if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
08205          chan_list_ref(help, "Found chan_list hold call");
08206          ast_mutex_unlock(&cl_te_lock);
08207          return help;
08208       }
08209    }
08210    ast_mutex_unlock(&cl_te_lock);
08211    chan_misdn_log(6, bc->port,
08212       "$$$ find_hold_call: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08213       bc->dialed.number,
08214       bc->caller.name,
08215       bc->caller.number);
08216 
08217    return NULL;
08218 }

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

Returns a reference to the found chan_list.

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

08223 {
08224    struct chan_list *help;
08225 
08226    ast_mutex_lock(&cl_te_lock);
08227    for (help = cl_te; help; help = help->next) {
08228       if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
08229          chan_list_ref(help, "Found chan_list hold call l3");
08230          ast_mutex_unlock(&cl_te_lock);
08231          return help;
08232       }
08233    }
08234    ast_mutex_unlock(&cl_te_lock);
08235 
08236    return NULL;
08237 }

static void free_robin_list ( void   )  [static]

Definition at line 599 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

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

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

Returns a reference to the found chan_list.

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

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

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

Returns a reference to the found chan_list.

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

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

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

Definition at line 611 of file chan_misdn.c.

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

Referenced by misdn_request().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

08353 {
08354    int port;
08355 
08356    if (!ch) {
08357       cb_log(1, 0, "Cannot hangup chan, no ch\n");
08358       return;
08359    }
08360 
08361    port = bc->port;
08362    cb_log(5, port, "hangup_chan called\n");
08363 
08364    if (ch->need_hangup) {
08365       cb_log(2, port, " --> hangup\n");
08366       ch->need_hangup = 0;
08367       ch->need_queue_hangup = 0;
08368       if (ch->ast) {
08369          send_cause2ast(ch->ast, bc, ch);
08370          ast_hangup(ch->ast);
08371       }
08372       return;
08373    }
08374 
08375    if (!ch->need_queue_hangup) {
08376       cb_log(2, port, " --> No need to queue hangup\n");
08377    }
08378 
08379    ch->need_queue_hangup = 0;
08380    if (ch->ast) {
08381       send_cause2ast(ch->ast, bc, ch);
08382       ast_queue_hangup_with_cause(ch->ast, bc->cause);
08383       cb_log(2, port, " --> queue_hangup\n");
08384    } else {
08385       cb_log(1, port, "Cannot hangup chan, no ast\n");
08386    }
08387 }

static void hanguptone_indicate ( struct chan_list cl  )  [static]

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

07643 {
07644    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
07645 }

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

08717 {
08718    const char *tmp;
08719 
08720    ast_channel_lock(chan);
08721    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
08722    if (tmp && (atoi(tmp) == 1)) {
08723       bc->sending_complete = 1;
08724    }
08725 
08726    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
08727    if (tmp) {
08728       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
08729       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
08730       bc->uulen = strlen(bc->uu);
08731    }
08732 
08733    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
08734    if (tmp) {
08735       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
08736    }
08737    ast_channel_unlock(chan);
08738 }

static int load_module ( void   )  [static]

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

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

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

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

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

static int misdn_answer ( struct ast_channel ast  )  [static]

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

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

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

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

08525 {
08526    int retval;
08527    struct ast_channel *target;
08528    struct ast_channel *transferee;
08529    struct ast_party_connected_line target_colp;
08530    struct ast_party_connected_line transferee_colp;
08531 
08532    switch (active_ch->state) {
08533    case MISDN_PROCEEDING:
08534    case MISDN_PROGRESS:
08535    case MISDN_ALERTING:
08536    case MISDN_CONNECTED:
08537       break;
08538    default:
08539       return -1;
08540    }
08541 
08542    ast_channel_lock(held_ch->ast);
08543    while (ast_channel_trylock(active_ch->ast)) {
08544       CHANNEL_DEADLOCK_AVOIDANCE(held_ch->ast);
08545    }
08546 
08547    transferee = ast_bridged_channel(held_ch->ast);
08548    if (!transferee) {
08549       /*
08550        * Could not transfer.  Held channel is not bridged anymore.
08551        * Held party probably got tired of waiting and hung up.
08552        */
08553       ast_channel_unlock(held_ch->ast);
08554       ast_channel_unlock(active_ch->ast);
08555       return -1;
08556    }
08557 
08558    target = active_ch->ast;
08559    chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
08560       held_ch->ast->name, target->name);
08561 
08562    ast_party_connected_line_init(&target_colp);
08563    ast_party_connected_line_copy(&target_colp, &target->connected);
08564    ast_party_connected_line_init(&transferee_colp);
08565    ast_party_connected_line_copy(&transferee_colp, &held_ch->ast->connected);
08566    held_ch->hold.state = MISDN_HOLD_TRANSFER;
08567 
08568    /*
08569     * Before starting a masquerade, all channel and pvt locks must
08570     * be unlocked.  Any recursive channel locks held before
08571     * ast_channel_transfer_masquerade() invalidates deadlock
08572     * avoidance.  Since we are unlocking both the pvt and its owner
08573     * channel it is possible for "target" and "transferee" to be
08574     * destroyed by their pbx threads.  To prevent this we must give
08575     * "target" and "transferee" a reference before any unlocking
08576     * takes place.
08577     */
08578    ao2_ref(target, +1);
08579    ao2_ref(transferee, +1);
08580    ast_channel_unlock(held_ch->ast);
08581    ast_channel_unlock(active_ch->ast);
08582 
08583    /* Setup transfer masquerade. */
08584    retval = ast_channel_transfer_masquerade(target, &target_colp, 0,
08585       transferee, &transferee_colp, 1);
08586 
08587    ast_party_connected_line_free(&target_colp);
08588    ast_party_connected_line_free(&transferee_colp);
08589    ao2_ref(target, -1);
08590    ao2_ref(transferee, -1);
08591    return retval;
08592 }

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 7498 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.

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

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

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

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

static int misdn_chan_is_valid ( struct chan_list ch  )  [static]

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

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

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

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

12123 {
12124    char *parse;
12125    char group[BUFFERSIZE + 1];
12126    char *port_str;
12127    int port = 0;
12128    int timeout;
12129    int dowait = 0;
12130    int port_up;
12131 
12132    AST_DECLARE_APP_ARGS(args,
12133       AST_APP_ARG(grouppar);
12134       AST_APP_ARG(timeout);
12135    );
12136 
12137    if (ast_strlen_zero((char *) data)) {
12138       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
12139       return -1;
12140    }
12141 
12142    parse = ast_strdupa(data);
12143    AST_STANDARD_APP_ARGS(args, parse);
12144 
12145    if (args.argc != 2) {
12146       ast_log(LOG_WARNING, "Wrong argument count\n");
12147       return 0;
12148    }
12149 
12150    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
12151    timeout = atoi(args.timeout);
12152    port_str = args.grouppar;
12153 
12154    if (port_str[0] == 'g' && port_str[1] == ':') {
12155       /* We make a group call lets checkout which ports are in my group */
12156       port_str += 2;
12157       ast_copy_string(group, port_str, sizeof(group));
12158       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
12159 
12160       for (port = misdn_cfg_get_next_port(port);
12161          port > 0;
12162          port = misdn_cfg_get_next_port(port)) {
12163          char cfg_group[BUFFERSIZE + 1];
12164 
12165          chan_misdn_log(2, 0, "trying port %d\n", port);
12166 
12167          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
12168 
12169          if (!strcasecmp(cfg_group, group)) {
12170             port_up = misdn_lib_port_up(port, 1);
12171             if (!port_up) {
12172                chan_misdn_log(2, 0, " --> port '%d'\n", port);
12173                misdn_lib_get_port_up(port);
12174                dowait = 1;
12175             }
12176          }
12177       }
12178    } else {
12179       port = atoi(port_str);
12180       chan_misdn_log(2, 0, "Checking Port: %d\n", port);
12181       port_up = misdn_lib_port_up(port, 1);
12182       if (!port_up) {
12183          misdn_lib_get_port_up(port);
12184          dowait = 1;
12185       }
12186    }
12187 
12188    if (dowait) {
12189       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
12190       ast_safe_sleep(chan, timeout * 1000);
12191    }
12192 
12193    return 0;
12194 }

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

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

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

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

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

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

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

Definition at line 6837 of file chan_misdn.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int misdn_hangup ( struct ast_channel ast  )  [static]

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

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

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

Definition at line 6903 of file chan_misdn.c.

References chan_list::ast, 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_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, misdn_bchannel::pid, misdn_bchannel::port, start_bc_tones(), chan_list::state, hold_info::state, and stop_indicate().

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

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

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

09819 {
09820    char number[sizeof(dialed->number)];
09821 
09822    ast_copy_string(number, dialed->number, sizeof(number));
09823    misdn_add_number_prefix(port, dialed->number_type, number, sizeof(number));
09824    return misdn_cfg_is_msn_valid(port, number);
09825 }

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

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

12476 {
12477    ast_mutex_destroy(&jb->mutexjb);
12478 
12479    ast_free(jb->ok);
12480    ast_free(jb->samples);
12481    ast_free(jb);
12482 }

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

12553 {
12554    int i;
12555    int wp;
12556    int rp;
12557    int read = 0;
12558 
12559    ast_mutex_lock(&jb->mutexjb);
12560 
12561    rp = jb->rp;
12562    wp = jb->wp;
12563 
12564    if (jb->state_empty) {
12565       for (i = 0; i < len; i++) {
12566          if (wp == rp) {
12567             jb->rp = rp;
12568             jb->state_empty = 0;
12569 
12570             ast_mutex_unlock(&jb->mutexjb);
12571 
12572             return read;
12573          } else {
12574             if (jb->ok[rp] == 1) {
12575                data[i] = jb->samples[rp];
12576                jb->ok[rp] = 0;
12577                rp = (rp != jb->size - 1) ? rp + 1 : 0;
12578                read += 1;
12579             }
12580          }
12581       }
12582 
12583       if (wp >= rp) {
12584          jb->state_buffer = wp - rp;
12585       } else {
12586          jb->state_buffer = jb->size - rp + wp;
12587       }
12588       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12589 
12590       jb->rp = rp;
12591    } else {
12592       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
12593    }
12594 
12595    ast_mutex_unlock(&jb->mutexjb);
12596 
12597    return read;
12598 }

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 12486 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.

12487 {
12488    int i;
12489    int j;
12490    int rp;
12491    int wp;
12492 
12493    if (!jb || ! data) {
12494       return 0;
12495    }
12496 
12497    ast_mutex_lock(&jb->mutexjb);
12498 
12499    wp = jb->wp;
12500    rp = jb->rp;
12501 
12502    for (i = 0; i < len; i++) {
12503       jb->samples[wp] = data[i];
12504       jb->ok[wp] = 1;
12505       wp = (wp != jb->size - 1) ? wp + 1 : 0;
12506 
12507       if (wp == jb->rp) {
12508          jb->state_full = 1;
12509       }
12510    }
12511 
12512    if (wp >= rp) {
12513       jb->state_buffer = wp - rp;
12514    } else {
12515       jb->state_buffer = jb->size - rp + wp;
12516    }
12517    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12518 
12519    if (jb->state_full) {
12520       jb->wp = wp;
12521 
12522       rp = wp;
12523       for (j = 0; j < jb->upper_threshold; j++) {
12524          rp = (rp != 0) ? rp - 1 : jb->size - 1;
12525       }
12526       jb->rp = rp;
12527       jb->state_full = 0;
12528       jb->state_empty = 1;
12529 
12530       ast_mutex_unlock(&jb->mutexjb);
12531 
12532       return -1;
12533    }
12534 
12535    if (!jb->state_empty) {
12536       jb->bytes_wrote += len;
12537       if (jb->bytes_wrote >= jb->upper_threshold) {
12538          jb->state_empty = 1;
12539          jb->bytes_wrote = 0;
12540       }
12541    }
12542    jb->wp = wp;
12543 
12544    ast_mutex_unlock(&jb->mutexjb);
12545 
12546    return 0;
12547 }

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

Definition at line 12433 of file chan_misdn.c.

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

Referenced by config_jitterbuffer().

12434 {
12435    int i;
12436    struct misdn_jb *jb;
12437 
12438    jb = ast_malloc(sizeof(*jb));
12439    if (!jb) {
12440        chan_misdn_log(-1, 0, "No free Mem for jb\n");
12441        return NULL;
12442    }
12443    jb->size = size;
12444    jb->upper_threshold = upper_threshold;
12445    jb->wp = 0;
12446    jb->rp = 0;
12447    jb->state_full = 0;
12448    jb->state_empty = 0;
12449    jb->bytes_wrote = 0;
12450    jb->samples = ast_malloc(size * sizeof(char));
12451    if (!jb->samples) {
12452       ast_free(jb);
12453       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
12454       return NULL;
12455    }
12456 
12457    jb->ok = ast_malloc(size * sizeof(char));
12458    if (!jb->ok) {
12459       ast_free(jb->samples);
12460       ast_free(jb);
12461       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
12462       return NULL;
12463    }
12464 
12465    for (i = 0; i < size; i++) {
12466       jb->ok[i] = 0;
12467    }
12468 
12469    ast_mutex_init(&jb->mutexjb);
12470 
12471    return jb;
12472 }

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

Definition at line 3586 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

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

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 8089 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(), and misdn_request().

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

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

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

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

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

Definition at line 3351 of file chan_misdn.c.

Referenced by misdn_add_number_prefix().

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

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

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

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

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

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

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

References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, AST_STATE_RESERVED, ast_strdupa, ast_strlen_zero(), chan_list::bc, BUFFERSIZE, chan_list_init(), chan_list_unref, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, cl_queue_chan(), misdn_bchannel::dec, ext, get_robin_position(), ast_channel::linkedid, LOG_ERROR, LOG_WARNING, METHOD_ROUND_ROBIN, METHOD_STANDARD_DEC, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_next_port_spin(), MISDN_CFG_GROUPNAME, misdn_cfg_is_group_method(), MISDN_CFG_PMP_L1_CHECK, misdn_lib_get_free_bc(), misdn_lib_get_maxchans(), misdn_lib_port_up(), misdn_new(), misdn_type, chan_list::need_hangup, ORG_AST, misdn_bchannel::port, robin_list::port, and read_config().

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

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

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

08011 {
08012    struct chan_list *tmp = MISDN_ASTERISK_TECH_PVT(chan);
08013 
08014    if (tmp && tmp->bc) {
08015       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
08016       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
08017    } else {
08018       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
08019       return -1;
08020    }
08021 
08022    return 0;
08023 }

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

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

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

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

Definition at line 3571 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

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

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

Definition at line 3576 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

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

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 3541 of file chan_misdn.c.

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

Referenced by unload_module().

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

static void misdn_tasks_init ( void   )  [static]

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

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

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 3581 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by chan_list_destructor().

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

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

Definition at line 3495 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 3553 of file chan_misdn.c.

References misdn_tasks_thread.

Referenced by _misdn_tasks_add_variable().

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

static int misdn_to_ast_plan ( enum mISDN_NUMBER_PLAN  number_plan  )  [static]

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

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

static int misdn_to_ast_pres ( int  presentation  )  [static]

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

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

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

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

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

static int misdn_to_ast_screen ( int  screening  )  [static]

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

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

static int misdn_to_ast_ton ( enum mISDN_NUMBER_TYPE  number_type  )  [static]

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

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

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

Definition at line 1928 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Definition at line 2054 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

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

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

Definition at line 2143 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

08344 {
08345    int ret = ast_pbx_start(ch->ast);
08346 
08347    ch->need_hangup = (ret >= 0) ? 0 : 1;
08348 
08349    return ret;
08350 }

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

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

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

static void print_bearer ( struct misdn_bchannel bc  )  [static]

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

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

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

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

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

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

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

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

static int read_config ( struct chan_list ch  )  [static]

Definition at line 5890 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(), and misdn_request().

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

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

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

08401 {
08402    struct ast_channel *ast;
08403 
08404    chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
08405 
08406    ast_mutex_lock(&release_lock);
08407    for (;;) {
08408       ast = ch->ast;
08409       if (!ast || !ast_channel_trylock(ast)) {
08410          break;
08411       }
08412       DEADLOCK_AVOIDANCE(&release_lock);
08413    }
08414    if (!cl_dequeue_chan(ch)) {
08415       /* Someone already released it. */
08416       if (ast) {
08417          ast_channel_unlock(ast);
08418       }
08419       ast_mutex_unlock(&release_lock);
08420       return;
08421    }
08422    ch->state = MISDN_CLEANING;
08423    ch->ast = NULL;
08424    if (ast) {
08425       struct chan_list *ast_ch;
08426 
08427       ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
08428       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
08429       chan_misdn_log(1, bc->port,
08430          "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
08431          bc->pid,
08432          ast->context,
08433          ast->exten,
08434          S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
08435          S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""));
08436 
08437       if (ast->_state != AST_STATE_RESERVED) {
08438          chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
08439          ast_setstate(ast, AST_STATE_DOWN);
08440       }
08441       ast_channel_unlock(ast);
08442       if (ast_ch) {
08443          chan_list_unref(ast_ch, "Release ast_channel reference.");
08444       }
08445    }
08446 
08447    if (ch->originator == ORG_AST) {
08448       --misdn_out_calls[bc->port];
08449    } else {
08450       --misdn_in_calls[bc->port];
08451    }
08452 
08453    ast_mutex_unlock(&release_lock);
08454 }

static void release_chan_early ( struct chan_list ch  )  [static]

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

08467 {
08468    struct ast_channel *ast;
08469 
08470    ast_mutex_lock(&release_lock);
08471    for (;;) {
08472       ast = ch->ast;
08473       if (!ast || !ast_channel_trylock(ast)) {
08474          break;
08475       }
08476       DEADLOCK_AVOIDANCE(&release_lock);
08477    }
08478    if (!cl_dequeue_chan(ch)) {
08479       /* Someone already released it. */
08480       if (ast) {
08481          ast_channel_unlock(ast);
08482       }
08483       ast_mutex_unlock(&release_lock);
08484       return;
08485    }
08486    ch->state = MISDN_CLEANING;
08487    ch->ast = NULL;
08488    if (ast) {
08489       struct chan_list *ast_ch;
08490 
08491       ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
08492       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
08493 
08494       if (ast->_state != AST_STATE_RESERVED) {
08495          ast_setstate(ast, AST_STATE_DOWN);
08496       }
08497       ast_channel_unlock(ast);
08498       if (ast_ch) {
08499          chan_list_unref(ast_ch, "Release ast_channel reference.");
08500       }
08501    }
08502 
08503    if (ch->hold.state != MISDN_HOLD_IDLE) {
08504       if (ch->originator == ORG_AST) {
08505          --misdn_out_calls[ch->hold.port];
08506       } else {
08507          --misdn_in_calls[ch->hold.port];
08508       }
08509    }
08510 
08511    ast_mutex_unlock(&release_lock);
08512 }

static int reload ( void   )  [static]

Definition at line 11369 of file chan_misdn.c.

References reload_config().

11370 {
11371    reload_config();
11372 
11373    return 0;
11374 }

static void reload_config ( void   )  [static]

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

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

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

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

08659                                                                                                      {
08660    if (!ast) {
08661       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
08662       return;
08663    }
08664    if (!bc) {
08665       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
08666       return;
08667    }
08668    if (!ch) {
08669       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
08670       return;
08671    }
08672 
08673    ast->hangupcause = bc->cause;
08674 
08675    switch (bc->cause) {
08676 
08677    case AST_CAUSE_UNALLOCATED:
08678    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
08679    case AST_CAUSE_NO_ROUTE_DESTINATION:
08680    case 4:  /* Send special information tone */
08681    case AST_CAUSE_NUMBER_CHANGED:
08682    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
08683       /* Congestion Cases */
08684       /*
08685        * Not Queueing the Congestion anymore, since we want to hear
08686        * the inband message
08687        *
08688       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
08689       ch->state = MISDN_BUSY;
08690 
08691       ast_queue_control(ast, AST_CONTROL_CONGESTION);
08692       */
08693       break;
08694 
08695    case AST_CAUSE_CALL_REJECTED:
08696    case AST_CAUSE_USER_BUSY:
08697       ch->state = MISDN_BUSY;
08698 
08699       if (!ch->need_busy) {
08700          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
08701          break;
08702       }
08703 
08704       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
08705 
08706       ast_queue_control(ast, AST_CONTROL_BUSY);
08707 
08708       ch->need_busy = 0;
08709 
08710       break;
08711    }
08712 }

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

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

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

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

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

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

static void sighandler ( int  sig  )  [static]

Definition at line 3491 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

03492 {
03493 }

static int start_bc_tones ( struct chan_list cl  )  [static]

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

07669 {
07670    misdn_lib_tone_generator_stop(cl->bc);
07671    cl->notxtone = 0;
07672    cl->norxtone = 0;
07673    return 0;
07674 }

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

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

08806 {
08807    if (pbx_start_chan(ch) < 0) {
08808       hangup_chan(ch, bc);
08809       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
08810       if (bc->nt) {
08811          hanguptone_indicate(ch);
08812          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
08813       } else {
08814          misdn_lib_send_event(bc, EVENT_RELEASE);
08815       }
08816    }
08817 }

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 7676 of file chan_misdn.c.

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

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

07677 {
07678    if (!cl) {
07679       return -1;
07680    }
07681 
07682    cl->notxtone = 1;
07683    cl->norxtone = 1;
07684 
07685    return 0;
07686 }

static int stop_indicate ( struct chan_list cl  )  [static]

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

07648 {
07649    struct ast_channel *ast = cl->ast;
07650 
07651    if (!ast) {
07652       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
07653       return -1;
07654    }
07655 
07656    chan_misdn_log(3, cl->bc->port, " --> None\n");
07657    misdn_lib_tone_generator_stop(cl->bc);
07658    ast_playtones_stop(ast);
07659 
07660    if (cl->ts) {
07661       cl->ts = ast_tone_zone_sound_unref(cl->ts);
07662    }
07663 
07664    return 0;
07665 }

static int unload_module ( void   )  [static]

TE STUFF END

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

11112 {
11113    /* First, take us out of the channel loop */
11114    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
11115 
11116    misdn_tasks_destroy();
11117 
11118    if (!g_config_initialized) {
11119       return 0;
11120    }
11121 
11122    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11123 
11124    /* ast_unregister_application("misdn_crypt"); */
11125    ast_unregister_application("misdn_set_opt");
11126    ast_unregister_application("misdn_facility");
11127    ast_unregister_application("misdn_check_l2l1");
11128 #if defined(AST_MISDN_ENHANCEMENTS)
11129    ast_unregister_application(misdn_command_name);
11130    ast_custom_function_unregister(&misdn_cc_function);
11131 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11132 
11133    ast_channel_unregister(&misdn_tech);
11134 
11135    free_robin_list();
11136    misdn_cfg_destroy();
11137    misdn_lib_destroy();
11138 
11139    ast_free(misdn_out_calls);
11140    ast_free(misdn_in_calls);
11141    ast_free(misdn_debug_only);
11142    ast_free(misdn_ports);
11143    ast_free(misdn_debug);
11144 
11145 #if defined(AST_MISDN_ENHANCEMENTS)
11146    misdn_cc_destroy();
11147 #endif   /* defined(AST_MISDN_ENHANCEMENTS) */
11148 
11149    return 0;
11150 }

static void update_config ( struct chan_list ch  )  [static]

Updates caller ID information from config.

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

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

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

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

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

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

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

08066 {
08067    int chan_offset = 0;
08068    int tmp_port = misdn_cfg_get_next_port(0);
08069    char newname[255];
08070 
08071    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
08072       if (tmp_port == port) {
08073          break;
08074       }
08075       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
08076    }
08077    if (c < 0) {
08078       c = 0;
08079    }
08080 
08081    snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
08082    if (strncmp(tmp->name, newname, strlen(newname))) {
08083       snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
08084       ast_change_name(tmp, newname);
08085       chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
08086    }
08087 }

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

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

08820 {
08821    ch->state = MISDN_WAITING4DIGS;
08822    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08823    if (bc->nt && !bc->dialed.number[0]) {
08824       dialtone_indicate(ch);
08825    }
08826 }


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 12679 of file chan_misdn.c.

struct allowed_bearers allowed_bearers_array[] [static]

Definition at line 2332 of file chan_misdn.c.

Referenced by bearer2str(), and cb_events().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 12679 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

Definition at line 5702 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 676 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 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(), load_module(), and misdn_chan_is_valid().

int g_config_initialized = 0 [static]

Definition at line 99 of file chan_misdn.c.

int glob_channel = 0 [static]

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

int max_ports [static]

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

int* misdn_debug [static]

Definition at line 666 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 667 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 670 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 671 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 643 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 640 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 641 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 8025 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 8044 of file chan_misdn.c.

Referenced by misdn_new().

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

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

Referenced by misdn_new(), and misdn_write().

ast_mutex_t release_lock [static]

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

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 4050 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 661 of file chan_misdn.c.

Referenced by load_module().


Generated on Wed Apr 6 11:29:57 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7