Mon Oct 8 12:39:15 2012

Asterisk developer's documentation


chan_misdn.c File Reference

the chan_misdn channel driver for Asterisk More...

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

Go to the source code of this file.

Data Structures

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

Defines

#define chan_list_ref(obj, debug)   (ao2_t_ref((obj), +1, (debug)), (obj))
#define chan_list_unref(obj, debug)   (ao2_t_ref((obj), -1, (debug)), NULL)
#define MISDN_ASTERISK_TECH_PVT(ast)   ast->tech_pvt
#define ORG_AST   1
#define ORG_MISDN   2
#define TRANSFER_ON_HELD_CALL_HANGUP   1

Enumerations

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
int add_in_calls (int port)
int add_out_calls (int port)
static enum mISDN_NUMBER_PLAN ast_to_misdn_plan (unsigned ast_number_plan)
static int ast_to_misdn_pres (int presentation)
static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason (const enum AST_REDIRECTING_REASON ast)
static int ast_to_misdn_screen (int screening)
static enum mISDN_NUMBER_TYPE ast_to_misdn_ton (unsigned ast_number_type)
static const char * bearer2str (int cap)
static enum event_response_e cb_events (enum event_e event, struct misdn_bchannel *bc, void *user_data)
static void chan_list_destructor (void *obj)
static struct chan_listchan_list_init (int orig)
int chan_misdn_jb_empty (struct misdn_bchannel *bc, char *buf, int len)
static void chan_misdn_log (int level, int port, char *tmpl,...)
static int cl_dequeue_chan (struct chan_list *chan)
static void cl_queue_chan (struct chan_list *chan)
static char * complete_ch (struct ast_cli_args *a)
static char * complete_debug_port (struct ast_cli_args *a)
static char * complete_show_config (struct ast_cli_args *a)
static void config_jitterbuffer (struct chan_list *ch)
void debug_numtype (int port, int numtype, char *type)
static int dialtone_indicate (struct chan_list *cl)
static void do_immediate_setup (struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
static void export_aoc_vars (int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
void export_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 Export parameters to the dialplan environment variables.
static struct chan_listfind_chan_by_bc (struct misdn_bchannel *bc)
static struct chan_listfind_hold_active_call (struct misdn_bchannel *bc)
static struct chan_listfind_hold_call (struct misdn_bchannel *bc)
static struct chan_listfind_hold_call_l3 (unsigned long l3_id)
static void free_robin_list (void)
static struct chan_listget_chan_by_ast (struct ast_channel *ast)
static struct chan_listget_chan_by_ast_name (const char *name)
static struct robin_listget_robin_position (char *group)
static char * handle_cli_misdn_port_block (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_down (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_unblock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_port_up (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_restart_pid (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_restart_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_digit (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_display (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_facility (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_send_restart (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_crypt_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_set_tics (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_config (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_port (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_ports_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_show_stacks (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_misdn_toggle_echocancel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void hangup_chan (struct chan_list *ch, struct misdn_bchannel *bc)
static void hanguptone_indicate (struct chan_list *cl)
void import_ch (struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
 Import parameters from the dialplan environment variables.
static int load_module (void)
static void misdn_add_number_prefix (int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
static int misdn_answer (struct ast_channel *ast)
static int misdn_attempt_transfer (struct chan_list *active_ch, struct chan_list *held_ch)
static enum ast_bridge_result misdn_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int misdn_call (struct ast_channel *ast, char *dest, int timeout)
static int misdn_chan_is_valid (struct chan_list *ch)
static int misdn_check_l2l1 (struct ast_channel *chan, const char *data)
static void misdn_copy_redirecting_from_ast (struct misdn_bchannel *bc, struct ast_channel *ast)
static void misdn_copy_redirecting_to_ast (struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag)
static int misdn_digit_begin (struct ast_channel *chan, char digit)
static int misdn_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static int misdn_facility_exec (struct ast_channel *chan, const char *data)
static void misdn_facility_ie_handler (enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch)
static int misdn_fixup (struct ast_channel *oldast, struct ast_channel *ast)
static const char * misdn_get_ch_state (struct chan_list *p)
static void misdn_get_connected_line (struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
static int misdn_hangup (struct ast_channel *ast)
static int misdn_indication (struct ast_channel *ast, int cond, const void *data, size_t datalen)
static int misdn_is_msn_valid (int port, const struct misdn_party_dialing *dialed)
void misdn_jb_destroy (struct misdn_jb *jb)
 frees the data and destroys the given jitterbuffer struct
int misdn_jb_empty (struct misdn_jb *jb, char *data, int len)
 gets len bytes out of the jitterbuffer if available, else only the available data is returned and the return value indicates the number of data.
int misdn_jb_fill (struct misdn_jb *jb, const char *data, int len)
 fills the jitterbuffer with len data returns < 0 if there was an error (buffer overrun).
misdn_jbmisdn_jb_init (int size, int upper_threshold)
 allocates the jb-structure and initialize the elements
static int misdn_l1_task (const void *vdata)
static struct ast_channelmisdn_new (struct chan_list *cl, int state, char *exten, char *callerid, int format, const char *linkedid, int port, int c)
static int misdn_overlap_dial_task (const void *data)
static void misdn_prefix_string (const char *str_prefix, char *str_main, size_t size)
static void misdn_queue_connected_line_update (struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
static struct ast_framemisdn_read (struct ast_channel *ast)
static struct ast_channelmisdn_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static int misdn_send_text (struct ast_channel *chan, const char *text)
static int misdn_set_opt_exec (struct ast_channel *chan, const char *data)
static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data)
static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data)
static void misdn_tasks_destroy (void)
static void misdn_tasks_init (void)
static void misdn_tasks_remove (int task_id)
static void * misdn_tasks_thread_func (void *data)
static void misdn_tasks_wakeup (void)
static int misdn_to_ast_plan (enum mISDN_NUMBER_PLAN number_plan)
static int misdn_to_ast_pres (int presentation)
static enum AST_REDIRECTING_REASON misdn_to_ast_reason (const enum mISDN_REDIRECTING_REASON q931)
static int misdn_to_ast_screen (int screening)
static int misdn_to_ast_ton (enum mISDN_NUMBER_TYPE number_type)
static const char * misdn_to_str_plan (enum mISDN_NUMBER_PLAN number_plan)
static const char * misdn_to_str_pres (int presentation)
static const char * misdn_to_str_screen (int screening)
static const char * misdn_to_str_ton (enum mISDN_NUMBER_TYPE number_type)
static void misdn_update_caller_id (struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
static void misdn_update_connected_line (struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
static void misdn_update_redirecting (struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
static void misdn_update_remote_party (struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
static int misdn_write (struct ast_channel *ast, struct ast_frame *frame)
static int pbx_start_chan (struct chan_list *ch)
static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
static void print_bearer (struct misdn_bchannel *bc)
static void print_facility (const struct FacParm *fac, const const struct misdn_bchannel *bc)
static struct ast_frameprocess_ast_dsp (struct chan_list *tmp, struct ast_frame *frame)
static int read_config (struct chan_list *ch)
static void release_chan (struct chan_list *ch, struct misdn_bchannel *bc)
static void release_chan_early (struct chan_list *ch)
static int reload (void)
static void reload_config (void)
static int send_cause2ast (struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
static void send_digit_to_chan (struct chan_list *cl, char digit)
static void show_config_description (int fd, enum misdn_cfg_elements elem)
static void sighandler (int sig)
static int start_bc_tones (struct chan_list *cl)
static void start_pbx (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
static int stop_bc_tones (struct chan_list *cl)
static int stop_indicate (struct chan_list *cl)
static int unload_module (void)
static void update_config (struct chan_list *ch)
 Updates caller ID information from config.
static int update_ec_config (struct misdn_bchannel *bc)
static void update_name (struct ast_channel *tmp, int port, int c)
static void wait_for_digits (struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)

Variables

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

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

#define MISDN_ASTERISK_TECH_PVT ( ast   )     ast->tech_pvt

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

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

#define ORG_MISDN   2

mISDN created the channel (incoming call)

Definition at line 317 of file chan_misdn.c.

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

#define TRANSFER_ON_HELD_CALL_HANGUP   1

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

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

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

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 12704 of file chan_misdn.c.

static void __unreg_module ( void   )  [static]

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

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

int add_in_calls ( int  port  ) 

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

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

int add_out_calls ( int  port  ) 

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

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

static enum mISDN_NUMBER_PLAN ast_to_misdn_plan ( unsigned  ast_number_plan  )  [static]

Definition at line 2014 of file chan_misdn.c.

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

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

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

static int ast_to_misdn_pres ( int  presentation  )  [static]

Definition at line 2117 of file chan_misdn.c.

References AST_PRES_ALLOWED, AST_PRES_RESTRICTED, AST_PRES_RESTRICTION, and AST_PRES_UNAVAILABLE.

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

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

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

Definition at line 2246 of file chan_misdn.c.

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

Referenced by misdn_copy_redirecting_from_ast().

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

static int ast_to_misdn_screen ( int  screening  )  [static]

Definition at line 2214 of file chan_misdn.c.

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

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

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

static enum mISDN_NUMBER_TYPE ast_to_misdn_ton ( unsigned  ast_number_type  )  [static]

Definition at line 1888 of file chan_misdn.c.

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

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

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

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

Definition at line 2345 of file chan_misdn.c.

References allowed_bearers_array, ARRAY_LEN, and allowed_bearers::display.

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

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

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

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

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

static void chan_list_destructor ( void *  obj  )  [static]

Definition at line 7710 of file chan_misdn.c.

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

Referenced by chan_list_init().

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

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

Returns a reference to the new chan_list.

Definition at line 7749 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

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

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

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

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

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

static int cl_dequeue_chan ( struct chan_list chan  )  [static]

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

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

static void cl_queue_chan ( struct chan_list chan  )  [static]

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

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

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

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

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

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

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

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

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

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

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

static void config_jitterbuffer ( struct chan_list ch  )  [static]

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

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

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

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

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

static int dialtone_indicate ( struct chan_list cl  )  [static]

AST INDICATIONS END

Definition at line 7625 of file chan_misdn.c.

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

Referenced by wait_for_digits().

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

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

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

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

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

Definition at line 3430 of file chan_misdn.c.

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

Referenced by cb_events(), and misdn_facility_ie_handler().

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

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

Export parameters to the dialplan environment variables.

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

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

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

Returns a reference to the found chan_list.

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

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

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

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

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

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

Returns a reference to the found chan_list.

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

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

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

Returns a reference to the found chan_list.

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

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

static void free_robin_list ( void   )  [static]

Definition at line 601 of file chan_misdn.c.

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

Referenced by reload_config(), and unload_module().

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

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

Returns a reference to the found chan_list.

Definition at line 740 of file chan_misdn.c.

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

Referenced by misdn_bridge().

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

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

Returns a reference to the found chan_list.

Definition at line 758 of file chan_misdn.c.

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

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

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

Definition at line 613 of file chan_misdn.c.

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

Referenced by misdn_request().

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

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

Definition at line 3799 of file chan_misdn.c.

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

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

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

Definition at line 3909 of file chan_misdn.c.

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

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

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

Definition at line 3821 of file chan_misdn.c.

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

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

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

Definition at line 3887 of file chan_misdn.c.

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

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

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

Definition at line 4113 of file chan_misdn.c.

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

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

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

Definition at line 3865 of file chan_misdn.c.

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

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

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

Definition at line 3843 of file chan_misdn.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3776 of file chan_misdn.c.

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

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

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

Definition at line 3689 of file chan_misdn.c.

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

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

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

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

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

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

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

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

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

Definition at line 4199 of file chan_misdn.c.

References ast_cli_args::argc, chan_list::ast, ast_cli(), ast_mutex_lock, ast_mutex_unlock, chan_list::bc, ast_channel::caller, hold_info::channel, 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.

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

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

Definition at line 3956 of file chan_misdn.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 8375 of file chan_misdn.c.

References chan_list::ast, ast_hangup(), ast_queue_hangup_with_cause(), chan_list::bc, misdn_bchannel::cause, cb_log, chan_list::need_hangup, chan_list::need_queue_hangup, misdn_bchannel::port, and send_cause2ast().

Referenced by cb_events(), do_immediate_setup(), local_hangup(), and start_pbx().

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

static void hanguptone_indicate ( struct chan_list cl  )  [static]

Definition at line 7656 of file chan_misdn.c.

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

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

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

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

Import parameters from the dialplan environment variables.

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

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

static int load_module ( void   )  [static]

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

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

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

Definition at line 3396 of file chan_misdn.c.

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

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

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

static int misdn_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

static enum ast_bridge_result misdn_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
) [static]

Definition at line 7512 of file chan_misdn.c.

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

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

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

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

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

static int misdn_chan_is_valid ( struct chan_list ch  )  [static]

Definition at line 723 of file chan_misdn.c.

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

Referenced by misdn_hangup().

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

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

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

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

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

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

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

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

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

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

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

Definition at line 6839 of file chan_misdn.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4071 of file chan_misdn.c.

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

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

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

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

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

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

static int misdn_hangup ( struct ast_channel ast  )  [static]

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

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

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

Definition at line 6905 of file chan_misdn.c.

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

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

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

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

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

void misdn_jb_destroy ( struct misdn_jb jb  ) 

frees the data and destroys the given jitterbuffer struct

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

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

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

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

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

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

struct misdn_jb * misdn_jb_init ( int  size,
int  upper_threshold 
)

allocates the jb-structure and initialize the elements

Definition at line 12463 of file chan_misdn.c.

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

Referenced by config_jitterbuffer().

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

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

Definition at line 3588 of file chan_misdn.c.

References chan_misdn_log(), and misdn_lib_isdn_l1watcher().

Referenced by load_module().

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

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

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

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

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

Definition at line 3597 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Definition at line 3353 of file chan_misdn.c.

Referenced by misdn_add_number_prefix().

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

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

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

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

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

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

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

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

Definition at line 7773 of file chan_misdn.c.

References args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), BUFFERSIZE, chan_misdn_log(), misdn_bchannel::channel, robin_list::channel, misdn_bchannel::dec, ext, get_robin_position(), LOG_WARNING, METHOD_ROUND_ROBIN, METHOD_STANDARD_DEC, misdn_cfg_get(), misdn_cfg_get_next_port(), misdn_cfg_get_next_port_spin(), MISDN_CFG_GROUPNAME, misdn_cfg_is_group_method(), MISDN_CFG_PMP_L1_CHECK, misdn_lib_get_free_bc(), misdn_lib_get_maxchans(), misdn_lib_port_up(), misdn_type, misdn_bchannel::port, and robin_list::port.

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

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

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

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

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

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

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

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

Definition at line 3573 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by load_module().

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

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

Definition at line 3578 of file chan_misdn.c.

References _misdn_tasks_add_variable().

Referenced by cb_events().

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

static void misdn_tasks_destroy ( void   )  [static]

Definition at line 3543 of file chan_misdn.c.

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

Referenced by unload_module().

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

static void misdn_tasks_init ( void   )  [static]

Definition at line 3523 of file chan_misdn.c.

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

Referenced by _misdn_tasks_add_variable().

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

static void misdn_tasks_remove ( int  task_id  )  [static]

Definition at line 3583 of file chan_misdn.c.

References AST_SCHED_DEL, and misdn_tasks.

Referenced by chan_list_destructor().

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

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

Definition at line 3497 of file chan_misdn.c.

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

Referenced by misdn_tasks_init().

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

static void misdn_tasks_wakeup ( void   )  [inline, static]

Definition at line 3555 of file chan_misdn.c.

References misdn_tasks_thread.

Referenced by _misdn_tasks_add_variable().

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

static int misdn_to_ast_plan ( enum mISDN_NUMBER_PLAN  number_plan  )  [static]

Definition at line 1972 of file chan_misdn.c.

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

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

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

static int misdn_to_ast_pres ( int  presentation  )  [static]

Definition at line 2089 of file chan_misdn.c.

References AST_PRES_ALLOWED, AST_PRES_RESTRICTED, and AST_PRES_UNAVAILABLE.

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

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

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

Definition at line 2286 of file chan_misdn.c.

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

Referenced by misdn_copy_redirecting_to_ast().

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

static int misdn_to_ast_screen ( int  screening  )  [static]

Definition at line 2182 of file chan_misdn.c.

References AST_PRES_NETWORK_NUMBER, AST_PRES_USER_NUMBER_FAILED_SCREEN, AST_PRES_USER_NUMBER_PASSED_SCREEN, and AST_PRES_USER_NUMBER_UNSCREENED.

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

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

static int misdn_to_ast_ton ( enum mISDN_NUMBER_TYPE  number_type  )  [static]

Definition at line 1846 of file chan_misdn.c.

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

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

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

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

Definition at line 1930 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Definition at line 2056 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

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

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

Definition at line 2145 of file chan_misdn.c.

References str.

Referenced by cb_events(), and update_config().

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

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

Definition at line 1804 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int pbx_start_chan ( struct chan_list ch  )  [static]

Channel Queue End

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

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

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

Definition at line 4136 of file chan_misdn.c.

References misdn_bchannel::active, misdn_bchannel::addr, chan_list::addr, chan_list::ast, ast_cli(), misdn_bchannel::bc_state, bc_state2str(), bearer2str(), ast_channel::caller, misdn_bchannel::capability, misdn_bchannel::channel, ast_channel::context, misdn_bchannel::display, misdn_bchannel::ec_enable, ast_channel::exten, misdn_party_redirecting::from, misdn_bchannel::holded, ast_party_caller::id, misdn_bchannel::l3_id, chan_list::l3id, misdn_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().

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

static void print_bearer ( struct misdn_bchannel bc  )  [static]

Definition at line 3327 of file chan_misdn.c.

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

Referenced by cb_events().

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

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

Definition at line 2734 of file chan_misdn.c.

References chan_misdn_log(), and misdn_bchannel::port.

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

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

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

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

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

static int read_config ( struct chan_list ch  )  [static]

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

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

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

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

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

static void release_chan_early ( struct chan_list ch  )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 11399 of file chan_misdn.c.

References reload_config().

11400 {
11401    reload_config();
11402 
11403    return 0;
11404 }

static void reload_config ( void   )  [static]

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

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

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

Return values:
-1 if can hangup after calling.
0 if cannot hangup after calling.

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

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

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

Definition at line 3650 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_send_digit(), and misdn_digit_end().

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

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

Definition at line 3931 of file chan_misdn.c.

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

Referenced by handle_cli_misdn_show_config().

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

static void sighandler ( int  sig  )  [static]

Definition at line 3493 of file chan_misdn.c.

Referenced by misdn_tasks_thread_func().

03494 {
03495 }

static int start_bc_tones ( struct chan_list cl  )  [static]

Definition at line 7682 of file chan_misdn.c.

References chan_list::bc, misdn_lib_tone_generator_stop(), chan_list::norxtone, and chan_list::notxtone.

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

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

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

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

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

static int stop_bc_tones ( struct chan_list cl  )  [static]

Definition at line 7690 of file chan_misdn.c.

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

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

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

static int stop_indicate ( struct chan_list cl  )  [static]

Definition at line 7661 of file chan_misdn.c.

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

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

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

static int unload_module ( void   )  [static]

TE STUFF END

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

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

static void update_config ( struct chan_list ch  )  [static]

Updates caller ID information from config.

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

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

static int update_ec_config ( struct misdn_bchannel bc  )  [static]

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

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

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

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

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

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

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

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


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

Definition at line 12704 of file chan_misdn.c.

struct allowed_bearers allowed_bearers_array[] [static]

Definition at line 2334 of file chan_misdn.c.

Referenced by bearer2str(), and cb_events().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 12704 of file chan_misdn.c.

struct ast_cli_entry chan_misdn_clis[] [static]

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

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

ast_mutex_t cl_te_lock [static]

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

int glob_channel = 0 [static]

Definition at line 8086 of file chan_misdn.c.

char global_tracefile[BUFFERSIZE+1] [static]

Note:
To use the CCBS/CCNR supplementary service feature and other supplementary services using FACILITY messages requires a modified version of mISDN.

The latest modified mISDN v1.1.x based version is available at: http://svn.digium.com/svn/thirdparty/mISDN/trunk http://svn.digium.com/svn/thirdparty/mISDNuser/trunk

Taged versions of the modified mISDN code are available under: http://svn.digium.com/svn/thirdparty/mISDN/tags http://svn.digium.com/svn/thirdparty/mISDNuser/tags

Definition at line 99 of file chan_misdn.c.

int max_ports [static]

Definition at line 670 of file chan_misdn.c.

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

int* misdn_debug [static]

Definition at line 668 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 669 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 672 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 673 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 645 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 642 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 643 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 8048 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 8067 of file chan_misdn.c.

Referenced by misdn_new().

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

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

Referenced by misdn_new(), and misdn_write().

ast_mutex_t release_lock [static]

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

Referenced by free_robin_list(), and get_robin_position().

struct state_struct state_array[] [static]

Definition at line 4052 of file chan_misdn.c.

Referenced by misdn_get_ch_state().

int tracing = 0 [static]

Definition at line 663 of file chan_misdn.c.

Referenced by load_module().


Generated on Mon Oct 8 12:39:15 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7