aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_misdn.c
diff options
context:
space:
mode:
authorcrichter <crichter@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-17 21:57:19 +0000
committercrichter <crichter@f38db490-d61c-443f-a65b-d21fe96a405b>2006-08-17 21:57:19 +0000
commita16d56835cd72deab9e7fef2386536eb4420f0be (patch)
treec1a9895e91b73c87eca474c56f008d8791ee2367 /channels/chan_misdn.c
parent73270eca9183395525ff214e19e8e1aa9149c359 (diff)
This rather small ;-) commit merges the changes from my team branch 0.3.0 into t
he 1.2 branch. These changes include the new mISDN mqueue interface which makes it possible to compile chan_misdn against the current cvs version of mISDN/mISDNuser. These changes also contain various additions and numerous bugfixes to chan_misdn . Each change is documented in the commit logs in the team/crichter/0.3.0 branch. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2@40306 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_misdn.c')
-rw-r--r--channels/chan_misdn.c3227
1 files changed, 2056 insertions, 1171 deletions
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index a170105ff..5b322f6bf 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -59,28 +59,63 @@
#include <asterisk/app.h>
#include <asterisk/features.h>
-#include "chan_misdn_config.h"
-#include "isdn_lib.h"
+#include <chan_misdn_config.h>
+#include <isdn_lib.h>
+
+char global_tracefile[BUFFERSIZE+1];
+
+
+struct misdn_jb{
+ int size;
+ int upper_threshold;
+ char *samples, *ok;
+ int wp,rp;
+ int state_empty;
+ int state_full;
+ int state_buffer;
+ int bytes_wrote;
+ ast_mutex_t mutexjb;
+};
+
+
+
+/* allocates the jb-structure and initialise the elements*/
+struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
+
+/* frees the data and destroys the given jitterbuffer struct */
+void misdn_jb_destroy(struct misdn_jb *jb);
+
+/* fills the jitterbuffer with len data returns < 0 if there was an
+error (bufferoverun). */
+int misdn_jb_fill(struct misdn_jb *jb, const 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_empty(struct misdn_jb *jb, char *data, int len);
-ast_mutex_t release_lock_mutex;
-#define release_lock ast_mutex_lock(&release_lock_mutex)
-#define release_unlock ast_mutex_unlock(&release_lock_mutex)
/* BEGIN: chan_misdn.h */
+
+
enum misdn_chan_state {
MISDN_NOTHING, /*!< at beginning */
MISDN_WAITING4DIGS, /*!< when waiting for infos */
MISDN_EXTCANTMATCH, /*!< when asterisk couldnt match our ext */
MISDN_DIALING, /*!< when pbx_start */
MISDN_PROGRESS, /*!< we got a progress */
+ MISDN_PROCEEDING, /*!< we got a progress */
MISDN_CALLING, /*!< when misdn_call is called */
MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
MISDN_ALERTING, /*!< when Alerting */
MISDN_BUSY, /*!< when BUSY */
MISDN_CONNECTED, /*!< when connected */
+ MISDN_PRECONNECTED, /*!< when connected */
+ MISDN_DISCONNECTED, /*!< when connected */
+ MISDN_RELEASED, /*!< when connected */
MISDN_BRIDGED, /*!< when bridged */
MISDN_CLEANING, /*!< when hangup from * but we were connected before */
MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */
@@ -98,13 +133,24 @@ struct chan_list {
ast_mutex_t lock;
+ char allowed_bearers[BUFFERSIZE+1];
+
enum misdn_chan_state state;
- int holded;
+ int need_queue_hangup;
+ int need_hangup;
+ int need_busy;
+
int orginator;
int norxtone;
int notxtone;
+ int toggle_ec;
+
+ int incoming_early_audio;
+
+ int ignore_dtmf;
+
int pipe[2];
char ast_rd_buf[4096];
struct ast_frame frame;
@@ -113,17 +159,34 @@ struct chan_list {
int faxhandled;
int ast_dsp;
+
+ int jb_len;
+ int jb_upper_threshold;
+ struct misdn_jb *jb;
struct ast_dsp *dsp;
struct ast_trans_pvt *trans;
struct ast_channel * ast;
+
+ int dummy;
struct misdn_bchannel *bc;
struct misdn_bchannel *holded_bc;
unsigned int l3id;
int addr;
+
+ char context[BUFFERSIZE];
+
+ int zero_read_cnt;
+ int dropped_frame_cnt;
+
+ int far_alerting;
+ int other_pid;
+ struct chan_list *other_ch;
+
+ const struct tone_zone_sound *ts;
struct chan_list *peer;
struct chan_list *next;
@@ -131,6 +194,11 @@ struct chan_list {
struct chan_list *first;
};
+
+
+void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
+void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
+
struct robin_list {
char *group;
int port;
@@ -140,13 +208,19 @@ struct robin_list {
};
static struct robin_list *robin = NULL;
+
+
+struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
+
+
+
static inline void free_robin_list_r (struct robin_list *r)
{
- if (r) {
- if (r->next) free_robin_list_r(r->next);
- if (r->group) free(r->group);
- free(r);
- }
+ if (r) {
+ if (r->next) free_robin_list_r(r->next);
+ if (r->group) free(r->group);
+ free(r);
+ }
}
static void free_robin_list ( void )
@@ -155,7 +229,7 @@ static void free_robin_list ( void )
robin = NULL;
}
-struct robin_list* get_robin_position (char *group)
+static struct robin_list* get_robin_position (char *group)
{
struct robin_list *iter = robin;
for (; iter; iter = iter->next) {
@@ -173,8 +247,11 @@ struct robin_list* get_robin_position (char *group)
return robin;
}
-struct ast_channel *misdn_new(struct chan_list *cl, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c);
-void send_digit_to_chan(struct chan_list *cl, char digit );
+
+static void chan_misdn_log(int level, int port, char *tmpl, ...);
+
+static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
+static void send_digit_to_chan(struct chan_list *cl, char digit );
#define AST_CID_P(ast) ast->cid.cid_num
@@ -184,48 +261,50 @@ void send_digit_to_chan(struct chan_list *cl, char digit );
#define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
#define MISDN_ASTERISK_PVT(ast) 1
-#define MISDN_ASTERISK_TYPE(ast) ast->tech->type
-
-/* END: chan_misdn.h */
#include <asterisk/strings.h>
/* #define MISDN_DEBUG 1 */
-static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
-static char *type = "mISDN";
+static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
+static const char misdn_type[] = "mISDN";
-int tracing = 0 ;
+static int tracing = 0 ;
static int usecnt=0;
-char **misdn_key_vector=NULL;
-int misdn_key_vector_size=0;
+static char **misdn_key_vector=NULL;
+static int misdn_key_vector_size=0;
/* Only alaw and mulaw is allowed for now */
static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
static ast_mutex_t usecnt_lock;
-int *misdn_debug;
-int *misdn_debug_only;
-int max_ports;
+static int *misdn_debug;
+static int *misdn_debug_only;
+static int max_ports;
struct chan_list dummy_cl;
struct chan_list *cl_te=NULL;
ast_mutex_t cl_te_lock;
-enum event_response_e
+static enum event_response_e
cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
-void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc);
+static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
+
+static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
+static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
+static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
+static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
-void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
-void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
-struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
-void chan_misdn_log(int level, int port, char *tmpl, ...);
-void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...);
+
+
+static int dialtone_indicate(struct chan_list *cl);
+static int hanguptone_indicate(struct chan_list *cl);
+static int stop_indicate(struct chan_list *cl);
static int start_bc_tones(struct chan_list *cl);
static int stop_bc_tones(struct chan_list *cl);
@@ -234,6 +313,10 @@ static void release_chan(struct misdn_bchannel *bc);
static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
static int misdn_facility_exec(struct ast_channel *chan, void *data);
+int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
+
+static int update_ec_config(struct misdn_bchannel *bc);
+
/*************** Helpers *****************/
static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
@@ -258,25 +341,21 @@ static struct chan_list * get_chan_by_ast_name(char *name)
return NULL;
}
-static char* tone2str(struct misdn_bchannel *bc)
-{
- static struct {
- char name[16];
- enum tone_e tone;
- } *tone, tone_buf[] = {
- {"NOTONE",TONE_NONE},
- {"DIAL",TONE_DIAL},
- {"BUSY",TONE_BUSY},
- {"ALERT",TONE_ALERTING},
- {"",TONE_NONE}
- };
-
-
- for (tone=&tone_buf[0]; tone->name[0]; tone++) {
- if (tone->tone == bc->tone) return tone->name;
- }
- return NULL;
-}
+
+
+struct allowed_bearers {
+ int cap;
+ int val;
+ char *name;
+};
+
+struct allowed_bearers allowed_bearers_array[]={
+ {INFO_CAPABILITY_SPEECH,1,"speech"},
+ {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
+ {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
+ {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
+ {INFO_CAPABILITY_VIDEO,16,"video"}
+};
static char *bearer2str(int cap) {
static char *bearers[]={
@@ -284,6 +363,7 @@ static char *bearer2str(int cap) {
"Audio 3.1k",
"Unres Digital",
"Res Digital",
+ "Video",
"Unknown Bearer"
};
@@ -300,9 +380,30 @@ static char *bearer2str(int cap) {
case INFO_CAPABILITY_DIGITAL_RESTRICTED:
return bearers[3];
break;
- default:
+ case INFO_CAPABILITY_VIDEO:
return bearers[4];
break;
+ default:
+ return bearers[5];
+ break;
+ }
+}
+
+
+static void print_facility( struct misdn_bchannel *bc)
+{
+ switch (bc->fac_type) {
+ case FACILITY_CALLDEFLECT:
+ chan_misdn_log(2,bc->port," --> calldeflect: %s\n",
+ bc->fac.calldeflect_nr);
+ break;
+ case FACILITY_CENTREX:
+ chan_misdn_log(2,bc->port," --> centrex: %s\n",
+ bc->fac.cnip);
+ break;
+ default:
+ chan_misdn_log(2,bc->port," --> unknown\n");
+
}
}
@@ -322,7 +423,7 @@ static void print_bearer(struct misdn_bchannel *bc)
}
/*************** Helpers END *************/
-void send_digit_to_chan(struct chan_list *cl, char digit )
+static void send_digit_to_chan(struct chan_list *cl, char digit )
{
static const char* dtmf_tones[] = {
"!941+1336/100,!0/100", /* 0 */
@@ -416,10 +517,38 @@ static int misdn_set_debug(int fd, int argc, char *argv[])
return 0;
}
-
static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
{
- if (argc != 5 )return RESULT_SHOWUSAGE;
+ if (argc != 5) return RESULT_SHOWUSAGE;
+
+ return 0;
+}
+
+
+static int misdn_port_block(int fd, int argc, char *argv[])
+{
+ int port;
+
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+
+ port = atoi(argv[3]);
+
+ misdn_lib_port_block(port);
+
+ return 0;
+}
+
+static int misdn_port_unblock(int fd, int argc, char *argv[])
+{
+ int port;
+
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+
+ port = atoi(argv[3]);
+
+ misdn_lib_port_unblock(port);
return 0;
}
@@ -453,6 +582,20 @@ static int misdn_port_up (int fd, int argc, char *argv[])
return 0;
}
+static int misdn_port_down (int fd, int argc, char *argv[])
+{
+ int port;
+
+ if (argc != 4)
+ return RESULT_SHOWUSAGE;
+
+ port = atoi(argv[3]);
+
+ misdn_lib_get_port_down(port);
+
+ return 0;
+}
+
static int misdn_show_config (int fd, int argc, char *argv[])
{
@@ -470,12 +613,12 @@ static int misdn_show_config (int fd, int argc, char *argv[])
if (argc == 3 || onlyport == 0) {
ast_cli(fd,"Misdn General-Config: \n");
- ast_cli(fd," -> VERSION: " CHAN_MISDN_VERSION "\n");
-
+ ast_cli(fd," -> Version: chan_misdn-" CHAN_MISDN_VERSION "\n");
for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
}
+ ast_cli(fd, "\n");
}
if (onlyport < 0) {
@@ -505,23 +648,26 @@ static int misdn_show_config (int fd, int argc, char *argv[])
return 0;
}
-
-
struct state_struct {
enum misdn_chan_state state;
char txt[255] ;
} ;
-struct state_struct state_array[] = {
+static struct state_struct state_array[] = {
{MISDN_NOTHING,"NOTHING"}, /* at beginning */
{MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */
{MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldnt match our ext */
{MISDN_DIALING,"DIALING"}, /* when pbx_start */
{MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */
+ {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */
{MISDN_CALLING,"CALLING"}, /* when misdn_call is called */
+ {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
{MISDN_ALERTING,"ALERTING"}, /* when Alerting */
{MISDN_BUSY,"BUSY"}, /* when BUSY */
{MISDN_CONNECTED,"CONNECTED"}, /* when connected */
+ {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */
+ {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
+ {MISDN_RELEASED,"RELEASED"}, /* when connected */
{MISDN_BRIDGED,"BRIDGED"}, /* when bridged */
{MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
{MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
@@ -531,45 +677,44 @@ struct state_struct state_array[] = {
/* misdn_hangup */
};
-
-
-
-char *misdn_get_ch_state(struct chan_list *p)
+static char *misdn_get_ch_state(struct chan_list *p)
{
int i;
+ static char state[8];
+
if( !p) return NULL;
for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
if ( state_array[i].state == p->state) return state_array[i].txt;
}
-
- return NULL;
+
+ sprintf(state,"%d",p->state) ;
+
+ return state;
}
-static int misdn_reload (int fd, int argc, char *argv[])
+
+
+void reload_config(void)
{
int i, cfg_debug;
- ast_cli(fd, "Reloading mISDN Config\n");
- chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
-
free_robin_list();
-
misdn_cfg_reload();
-
- {
- char tempbuf[BUFFERSIZE];
- misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
- if (strlen(tempbuf))
- tracing = 1;
- }
-
+ misdn_cfg_update_ptp();
+ misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
+
for (i = 0; i <= max_ports; i++) {
misdn_debug[i] = cfg_debug;
misdn_debug_only[i] = 0;
}
-
+}
+
+static int misdn_reload (int fd, int argc, char *argv[])
+{
+ ast_cli(fd, "Reloading mISDN Config\n");
+ reload_config();
return 0;
}
@@ -577,12 +722,14 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
{
struct ast_channel *ast=help->ast;
ast_cli(fd,
- "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
+ "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
+
bc->pid, bc->port, bc->channel,
bc->nt?"NT":"TE",
help->orginator == ORG_AST?"*":"I",
ast?ast->exten:NULL,
ast?AST_CID_P(ast):NULL,
+ bc->rad,
ast?ast->context:NULL,
misdn_get_ch_state(help)
);
@@ -593,9 +740,9 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
" --> ch_addr: %x\n"
" --> bc_addr: %x\n"
" --> bc_l3id: %x\n"
- " --> tone: %s\n"
" --> display: %s\n"
" --> activated: %d\n"
+ " --> state: %s\n"
" --> capability: %s\n"
" --> echo_cancel: %d\n"
" --> notone : rx %d tx:%d\n"
@@ -605,19 +752,19 @@ static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel
help->addr,
bc->addr,
bc?bc->l3_id:-1,
- tone2str(bc),
bc->display,
bc->active,
+ bc_state2str(bc->bc_state),
bearer2str(bc->capability),
bc->ec_enable,
+
help->norxtone,help->notxtone,
bc->holded, help->holded_bc?1:0
);
}
-
static int misdn_show_cls (int fd, int argc, char *argv[])
{
struct chan_list *help=cl_te;
@@ -642,8 +789,6 @@ static int misdn_show_cls (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_show_cl (int fd, int argc, char *argv[])
{
struct chan_list *help=cl_te;
@@ -680,13 +825,12 @@ static int misdn_set_tics (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_show_stacks (int fd, int argc, char *argv[])
{
int port;
-
+
ast_cli(fd, "BEGIN STACK_LIST:\n");
+
for (port=misdn_cfg_get_next_port(0); port > 0;
port=misdn_cfg_get_next_port(port)) {
char buf[128];
@@ -746,8 +890,6 @@ static int misdn_send_cd (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_send_digit (int fd, int argc, char *argv[])
{
char *channame;
@@ -806,9 +948,11 @@ static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
return 0;
} else {
- tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
+
+ tmp->toggle_ec=tmp->toggle_ec?0:1;
- if (tmp->bc->ec_enable) {
+ if (tmp->toggle_ec) {
+ update_ec_config(tmp->bc);
manager_ec_enable(tmp->bc);
} else {
manager_ec_disable(tmp->bc);
@@ -819,8 +963,6 @@ static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
return 0;
}
-
-
static int misdn_send_display (int fd, int argc, char *argv[])
{
char *channame;
@@ -838,9 +980,7 @@ static int misdn_send_display (int fd, int argc, char *argv[])
tmp=get_chan_by_ast_name(channame);
if (tmp && tmp->bc) {
- int l = sizeof(tmp->bc->display);
- strncpy(tmp->bc->display, msg, l);
- tmp->bc->display[l-1] = 0;
+ ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
} else {
ast_cli(fd,"No such channel %s\n",channame);
@@ -851,9 +991,6 @@ static int misdn_send_display (int fd, int argc, char *argv[])
return RESULT_SUCCESS ;
}
-
-
-
static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
{
struct ast_channel *c;
@@ -909,7 +1046,6 @@ static struct ast_cli_entry cli_send_cd =
complete_ch
};
-
static struct ast_cli_entry cli_send_digit =
{ {"misdn","send","digit", NULL},
misdn_send_digit,
@@ -920,7 +1056,6 @@ static struct ast_cli_entry cli_send_digit =
complete_ch
};
-
static struct ast_cli_entry cli_toggle_echocancel =
{ {"misdn","toggle","echocancel", NULL},
misdn_toggle_echocancel,
@@ -929,8 +1064,6 @@ static struct ast_cli_entry cli_toggle_echocancel =
complete_ch
};
-
-
static struct ast_cli_entry cli_send_display =
{ {"misdn","send","display", NULL},
misdn_send_display,
@@ -941,7 +1074,6 @@ static struct ast_cli_entry cli_send_display =
complete_ch
};
-
static struct ast_cli_entry cli_show_config =
{ {"misdn","show","config", NULL},
misdn_show_config,
@@ -949,7 +1081,6 @@ static struct ast_cli_entry cli_show_config =
"Usage: misdn show config [port | 0]\n use 0 to only print the general config.\n"
};
-
static struct ast_cli_entry cli_reload =
{ {"misdn","reload", NULL},
misdn_reload,
@@ -964,7 +1095,6 @@ static struct ast_cli_entry cli_set_tics =
"\n"
};
-
static struct ast_cli_entry cli_show_cls =
{ {"misdn","show","channels", NULL},
misdn_show_cls,
@@ -980,6 +1110,19 @@ static struct ast_cli_entry cli_show_cl =
complete_ch
};
+static struct ast_cli_entry cli_port_block=
+{ {"misdn","port","block", NULL},
+ misdn_port_block,
+ "Blocks the given port",
+ "Usage: misdn port block\n"
+};
+
+static struct ast_cli_entry cli_port_unblock=
+{ {"misdn","port","unblock", NULL},
+ misdn_port_unblock,
+ "Unblocks the given port",
+ "Usage: misdn port unblock\n"
+};
static struct ast_cli_entry cli_restart_port =
@@ -989,7 +1132,6 @@ static struct ast_cli_entry cli_restart_port =
"Usage: misdn restart port\n"
};
-
static struct ast_cli_entry cli_port_up =
{ {"misdn","port","up", NULL},
misdn_port_up,
@@ -997,6 +1139,14 @@ static struct ast_cli_entry cli_port_up =
"Usage: misdn port up <port>\n"
};
+static struct ast_cli_entry cli_port_down =
+{ {"misdn","port","down", NULL},
+ misdn_port_down,
+ "Tries to deacivate the L1 on the given port",
+ "Usage: misdn port down <port>\n"
+};
+
+
static struct ast_cli_entry cli_show_stacks =
{ {"misdn","show","stacks", NULL},
@@ -1012,8 +1162,6 @@ static struct ast_cli_entry cli_show_port =
"Usage: misdn show port <port>\n"
};
-
-
static struct ast_cli_entry cli_set_debug =
{ {"misdn","set","debug", NULL},
misdn_set_debug,
@@ -1031,6 +1179,372 @@ static struct ast_cli_entry cli_set_crypt_debug =
/*** CLI END ***/
+static int update_config (struct chan_list *ch, int orig)
+{
+ if (!ch) {
+ ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
+ return -1;
+ }
+
+ struct ast_channel *ast=ch->ast;
+ struct misdn_bchannel *bc=ch->bc;
+ if (! ast || ! bc ) {
+ ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
+ return -1;
+ }
+
+ int port=bc->port;
+
+ chan_misdn_log(1,port,"update_config: Getting Config\n");
+
+
+ int hdlc=0;
+ misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+
+ if (hdlc) {
+ switch (bc->capability) {
+ case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+ case INFO_CAPABILITY_DIGITAL_RESTRICTED:
+ chan_misdn_log(1,bc->port," --> CONF HDLC\n");
+ bc->hdlc=1;
+ break;
+ }
+
+ }
+
+
+ int pres, screen;
+
+ misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
+ chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
+
+ if ( (pres + screen) < 0 ) {
+
+ chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
+
+ switch (ast->cid.cid_pres & 0x60){
+
+ case AST_PRES_RESTRICTED:
+ bc->pres=1;
+ chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
+ break;
+
+
+ case AST_PRES_UNAVAILABLE:
+ bc->pres=2;
+ chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
+ break;
+
+ default:
+ bc->pres=0;
+ chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
+ }
+
+ switch (ast->cid.cid_pres & 0x3){
+
+ case AST_PRES_USER_NUMBER_UNSCREENED:
+ bc->screen=0;
+ chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
+ break;
+
+ case AST_PRES_USER_NUMBER_PASSED_SCREEN:
+ bc->screen=1;
+ chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
+ break;
+ case AST_PRES_USER_NUMBER_FAILED_SCREEN:
+ bc->screen=2;
+ chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
+ break;
+
+ case AST_PRES_NETWORK_NUMBER:
+ bc->screen=3;
+ chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
+ break;
+
+ default:
+ bc->screen=0;
+ chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
+ }
+
+
+ } else {
+ bc->screen=screen;
+ bc->pres=pres;
+ }
+
+ return 0;
+
+}
+
+
+
+
+void config_jitterbuffer(struct chan_list *ch)
+{
+ struct misdn_bchannel *bc=ch->bc;
+ int len=ch->jb_len, threshold=ch->jb_upper_threshold;
+
+ chan_misdn_log(5,bc->port, "config_jb: Called\n");
+
+ if ( ! len ) {
+ chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
+ bc->nojitter=1;
+ } else {
+
+ if (len <=100 || len > 8000) {
+ chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
+ len=1000;
+ }
+
+ if ( threshold > len ) {
+ chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
+ }
+
+ if ( ch->jb) {
+ cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
+ misdn_jb_destroy(ch->jb);
+ ch->jb=NULL;
+ }
+
+ ch->jb=misdn_jb_init(len, threshold);
+
+ if (!ch->jb )
+ bc->nojitter=1;
+ }
+}
+
+
+void debug_numplan(int port, int numplan, char *type)
+{
+ switch (numplan) {
+ case NUMPLAN_INTERNATIONAL:
+ chan_misdn_log(2, port, " --> %s: International\n",type);
+ break;
+ case NUMPLAN_NATIONAL:
+ chan_misdn_log(2, port, " --> %s: National\n",type);
+ break;
+ case NUMPLAN_SUBSCRIBER:
+ chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
+ break;
+ case NUMPLAN_UNKNOWN:
+ chan_misdn_log(2, port, " --> %s: Unknown\n",type);
+ break;
+ /* Maybe we should cut off the prefix if present ? */
+ default:
+ chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
+ break;
+ }
+}
+
+
+
+
+static int update_ec_config(struct misdn_bchannel *bc)
+{
+ int ec;
+ int port=bc->port;
+
+ misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+
+ if (ec == 1 ) {
+ bc->ec_enable=1;
+ } else if ( ec > 1 ) {
+ bc->ec_enable=1;
+ bc->ec_deftaps=ec;
+ }
+
+ return 0;
+}
+
+
+static int read_config(struct chan_list *ch, int orig) {
+
+ if (!ch) {
+ ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
+ return -1;
+ }
+
+ struct ast_channel *ast=ch->ast;
+ struct misdn_bchannel *bc=ch->bc;
+ if (! ast || ! bc ) {
+ ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
+ return -1;
+ }
+
+ int port=bc->port;
+
+ chan_misdn_log(5,port,"read_config: Getting Config\n");
+
+ char lang[BUFFERSIZE+1];
+
+ misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
+ ast_copy_string(ast->language, lang, sizeof(ast->language));
+
+ char musicclass[BUFFERSIZE+1];
+
+ misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, musicclass, BUFFERSIZE);
+ ast_copy_string(ast->musicclass, musicclass, sizeof(ast->musicclass));
+
+ misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
+
+ misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
+
+
+ int hdlc=0;
+ misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
+
+ if (hdlc) {
+ switch (bc->capability) {
+ case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
+ case INFO_CAPABILITY_DIGITAL_RESTRICTED:
+ chan_misdn_log(1,bc->port," --> CONF HDLC\n");
+ bc->hdlc=1;
+ break;
+ }
+
+ }
+ /*Initialize new Jitterbuffer*/
+ {
+ misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
+
+ config_jitterbuffer(ch);
+ }
+
+ misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
+
+ ast_copy_string (ast->context,ch->context,sizeof(ast->context));
+
+ update_ec_config(bc);
+
+ {
+ int eb3;
+
+ misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
+ bc->early_bconnect=eb3;
+ }
+
+ port=bc->port;
+
+ {
+ char buf[256];
+ ast_group_t pg,cg;
+
+ misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
+ misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
+
+ chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
+ ast->pickupgroup=pg;
+ ast->callgroup=cg;
+ }
+
+ if ( orig == ORG_AST) {
+ misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
+
+ {
+ char callerid[BUFFERSIZE+1];
+ misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
+ if ( ! ast_strlen_zero(callerid) ) {
+ chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
+ {
+ int l = sizeof(bc->oad);
+ strncpy(bc->oad,callerid, l);
+ bc->oad[l-1] = 0;
+ }
+
+ }
+
+
+ misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
+ misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
+ debug_numplan(port, bc->dnumplan,"TON");
+ debug_numplan(port, bc->onumplan,"LTON");
+ debug_numplan(port, bc->cpnnumplan,"CTON");
+ }
+
+
+
+ } else { /** ORIGINATOR MISDN **/
+
+ misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
+ debug_numplan(port, bc->cpnnumplan,"CTON");
+
+ char prefix[BUFFERSIZE+1]="";
+ switch( bc->onumplan ) {
+ case NUMPLAN_INTERNATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+ break;
+
+ case NUMPLAN_NATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+ break;
+ default:
+ break;
+ }
+
+ {
+ int l = strlen(prefix) + strlen(bc->oad);
+ char tmp[l+1];
+ strcpy(tmp,prefix);
+ strcat(tmp,bc->oad);
+ strcpy(bc->oad,tmp);
+ }
+
+ if (!ast_strlen_zero(bc->dad)) {
+ ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
+ }
+
+ if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
+ ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
+ }
+
+ prefix[0] = 0;
+
+ switch( bc->dnumplan ) {
+ case NUMPLAN_INTERNATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
+ break;
+ case NUMPLAN_NATIONAL:
+ misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
+ break;
+ default:
+ break;
+ }
+
+ {
+ int l = strlen(prefix) + strlen(bc->dad);
+ char tmp[l+1];
+ strcpy(tmp,prefix);
+ strcat(tmp,bc->dad);
+ strcpy(bc->dad,tmp);
+ }
+
+ if ( strcmp(bc->dad,ast->exten)) {
+ ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
+ }
+
+ ast_set_callerid(ast, bc->oad, NULL, bc->oad);
+
+ if ( !ast_strlen_zero(bc->rad) )
+ ast->cid.cid_rdnis=strdup(bc->rad);
+
+ } /* ORIG MISDN END */
+
+ return 0;
+}
+
+
/*****************************/
/*** AST Indications Start ***/
/*****************************/
@@ -1041,9 +1555,8 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
int r;
struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
struct misdn_bchannel *newbc;
- char *opts=NULL, *ext=NULL;
+ char *opts=NULL, *ext,*tokb;
char dest_cp[256];
- char *tokb;
{
strncpy(dest_cp,dest,sizeof(dest_cp)-1);
@@ -1056,12 +1569,10 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
if (ext) {
opts=strtok_r(NULL,"/",&tokb);
} else {
- chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
+ chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
return -1;
}
}
-
-
}
if (!ast) {
@@ -1076,7 +1587,6 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
return -1;
}
-
if (!ch) {
ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
ast->hangupcause=41;
@@ -1092,183 +1602,15 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
ast_setstate(ast, AST_STATE_DOWN);
return -1;
}
-
+
port=newbc->port;
-
- ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
- ast_copy_string(ast->exten, ext, sizeof(ast->exten));
+ strncpy(newbc->dad,ext,sizeof( newbc->dad));
+ strncpy(ast->exten,ext,sizeof(ast->exten));
- chan_misdn_log(1, 0, "* CALL: %s\n",dest);
+ chan_misdn_log(1, port, "* CALL: %s\n",dest);
chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
- {
- char context[BUFFERSIZE];
-
- misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
- {
- int l = sizeof(ast->context);
- strncpy(ast->context,context, l);
- ast->context[l-1] = 0;
- }
- chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
- misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
-
- misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
- misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
-
- misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
-
-
- {
- char callerid[BUFFERSIZE];
- misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
- if ( ! ast_strlen_zero(callerid) ) {
- chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
- {
- int l = sizeof(newbc->oad);
- strncpy(newbc->oad,callerid, l);
- newbc->oad[l-1] = 0;
- }
- }
-
-
- misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
- switch (newbc->dnumplan) {
- case NUMPLAN_INTERNATIONAL:
- chan_misdn_log(2, port, " --> TON: International\n");
- break;
- case NUMPLAN_NATIONAL:
- chan_misdn_log(2, port, " --> TON: National\n");
- break;
- case NUMPLAN_SUBSCRIBER:
- chan_misdn_log(2, port, " --> TON: Subscriber\n");
- break;
- case NUMPLAN_UNKNOWN:
- chan_misdn_log(2, port, " --> TON: Unknown\n");
- break;
- /* Maybe we should cut off the prefix if present ? */
- default:
- chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
- break;
- }
-
-
- misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &newbc->onumplan, sizeof(int));
- switch (newbc->onumplan) {
- case NUMPLAN_INTERNATIONAL:
- chan_misdn_log(2, port, " --> TON: International\n");
- break;
- case NUMPLAN_NATIONAL:
- chan_misdn_log(2, port, " --> TON: National\n");
- break;
- case NUMPLAN_SUBSCRIBER:
- chan_misdn_log(2, port, " --> TON: Subscriber\n");
- break;
- case NUMPLAN_UNKNOWN:
- chan_misdn_log(2, port, " --> TON: Unknown\n");
- break;
- /* Maybe we should cut off the prefix if present ? */
- default:
- chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
- break;
- }
- }
-
-
-
-
- {
- int eb3;
-
- misdn_cfg_get( port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
- newbc->early_bconnect=eb3;
-
- }
-
-
-
- /* Will be overridden by asterisk in head! */
- {
- int pres;
-
- misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
- newbc->pres=pres?0:1;
-
- }
-
- int def_callingpres;
- misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
- if ( def_callingpres) {
-
- switch (ast->cid.cid_pres & 0x60){
-
- case AST_PRES_RESTRICTED:
- chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
- newbc->pres=1;
- break;
-
-
- case AST_PRES_UNAVAILABLE:
- chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
- newbc->pres=2;
- break;
-
- default:
- chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
- newbc->pres=0;
- }
-
- switch (ast->cid.cid_pres & 0x3){
-
- case AST_PRES_USER_NUMBER_UNSCREENED:
- chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
- newbc->screen=0;
- break;
-
- case AST_PRES_USER_NUMBER_PASSED_SCREEN:
- chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
- newbc->screen=1;
- break;
- case AST_PRES_USER_NUMBER_FAILED_SCREEN:
- chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
- newbc->screen=2;
- break;
-
- case AST_PRES_NETWORK_NUMBER:
- chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
- newbc->screen=3;
- break;
-
- default:
- chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
- newbc->screen=0;
- }
- }
-
-
- {
- int ec, ectr;
-
- misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
-
- misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
- if (ec == 1 ) {
- newbc->ec_enable=1;
- } else if ( ec > 1 ) {
- newbc->ec_enable=1;
- newbc->ec_deftaps=ec;
- }
-
-
- if (ectr>=0) {
- newbc->ec_training=ectr;
- }
-
- }
-
- }
-
chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
if (ast->exten) {
int l = sizeof(newbc->dad);
@@ -1278,6 +1620,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
newbc->rad[0]=0;
chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
+
if (AST_CID_P(ast)) {
int l = sizeof(newbc->oad);
strncpy(newbc->oad,AST_CID_P(ast), l);
@@ -1288,14 +1631,7 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
{
struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
- ch->bc = newbc;
- ch->orginator=ORG_AST;
- ch->ast = ast;
- MISDN_ASTERISK_TECH_PVT(ast) = ch ;
-
-
-
newbc->capability=ast->transfercapability;
pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
@@ -1303,17 +1639,19 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
}
+ /* update screening and presentation */
+ update_config(ch,ORG_AST);
+
+ /* fill in some ies from channel vary*/
+ import_ch(ast, newbc, ch);
+
/* Finally The Options Override Everything */
if (opts)
misdn_set_opt_exec(ast,opts);
else
- chan_misdn_log(1,0,"NO OPTS GIVEN\n");
-
+ chan_misdn_log(2,port,"NO OPTS GIVEN\n");
- cl_queue_chan(&cl_te, ch) ;
ch->state=MISDN_CALLING;
-
- chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
r=misdn_lib_send_event( newbc, EVENT_SETUP );
@@ -1332,21 +1670,20 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
ast_setstate(ast, AST_STATE_DIALING);
-
ast->hangupcause=16;
+
+ if (newbc->nt) stop_bc_tones(ch);
+
return 0;
}
-int misdn_answer(struct ast_channel *ast)
+static int misdn_answer(struct ast_channel *ast)
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
-
- chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
@@ -1362,7 +1699,7 @@ int misdn_answer(struct ast_channel *ast)
}
{
- char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
+ const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
if (tmp_key ) {
chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
@@ -1378,27 +1715,35 @@ int misdn_answer(struct ast_channel *ast)
}
{
- char *async=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
- if (async) {
+ const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
+ if (nodsp) {
chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
- p->bc->async=1;
+ p->bc->nodsp=1;
+ p->bc->hdlc=0;
+ p->bc->nojitter=1;
}
}
p->state = MISDN_CONNECTED;
+ misdn_lib_echo(p->bc,0);
+ stop_indicate(p);
+
+ if ( ast_strlen_zero(p->bc->cad) ) {
+ chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
+ ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
+ }
+
misdn_lib_send_event( p->bc, EVENT_CONNECT);
start_bc_tones(p);
return 0;
}
-int misdn_digit(struct ast_channel *ast, char digit )
+static int misdn_digit(struct ast_channel *ast, char digit )
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
-
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
struct misdn_bchannel *bc=p->bc;
chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
@@ -1452,14 +1797,13 @@ int misdn_digit(struct ast_channel *ast, char digit )
}
-int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
+static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
- chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s Holded:%d L3id:%x\n", misdn_get_ch_state(p), p->holded, p->l3id);
+ 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);
p->ast = ast ;
p->state=MISDN_CONNECTED;
@@ -1468,29 +1812,16 @@ int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
}
-int misdn_transfer (struct ast_channel *ast, char *dest)
-{
- struct chan_list *p;
-
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
-
- chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
- return 0;
-}
-
-
-int misdn_indication(struct ast_channel *ast, int cond)
+static int misdn_indication(struct ast_channel *ast, int cond)
{
struct chan_list *p;
- if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
+ if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
return -1;
}
- p = MISDN_ASTERISK_TECH_PVT(ast) ;
if (!p->bc ) {
chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
@@ -1498,56 +1829,85 @@ int misdn_indication(struct ast_channel *ast, int cond)
return -1;
}
- chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
+ chan_misdn_log(1, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
switch (cond) {
case AST_CONTROL_BUSY:
chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
ast_setstate(ast,AST_STATE_BUSY);
-
+
p->bc->out_cause=17;
if (p->state != MISDN_CONNECTED) {
+ start_bc_tones(p);
misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
- manager_send_tone(p->bc, TONE_BUSY);
} else {
- chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
- p->bc->port, ast->name);
+ chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
}
+ return -1;
break;
case AST_CONTROL_RING:
chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
+ return -1;
break;
+
case AST_CONTROL_RINGING:
- if ( p->state == MISDN_ALERTING) {
- chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I ws Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
- break;
+ switch (p->state) {
+ case MISDN_ALERTING:
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
+ break;
+ case MISDN_CONNECTED:
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
+ return -1;
+ break;
+ default:
+ p->state=MISDN_ALERTING;
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
+ misdn_lib_send_event( p->bc, EVENT_ALERTING);
+
+ if (p->other_ch && p->other_ch->bc) {
+ if (misdn_inband_avail(p->other_ch->bc)) {
+ chan_misdn_log(1,p->bc->port, " --> other End is mISDN and has inband info available\n");
+ break;
+ }
+
+ if (!p->other_ch->bc->nt) {
+ chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
+ break;
+ }
+ }
+
+ chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
+ ast_setstate(ast,AST_STATE_RINGING);
+
+ if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio )
+ chan_misdn_log(1,p->bc->port, " --> incoming_early_audio off\n");
+ else
+ return -1;
}
- p->state=MISDN_ALERTING;
-
- chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
-
- misdn_lib_send_event( p->bc, EVENT_ALERTING);
-
- manager_send_tone(p->bc, TONE_ALERTING);
- chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
- ast_setstate(ast,AST_STATE_RINGING);
break;
-
case AST_CONTROL_ANSWER:
chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
+ start_bc_tones(p);
break;
case AST_CONTROL_TAKEOFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
+ return -1;
break;
case AST_CONTROL_OFFHOOK:
chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
+ return -1;
break;
case AST_CONTROL_FLASH:
chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
break;
case AST_CONTROL_PROGRESS:
chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
+ misdn_lib_send_event( p->bc, EVENT_PROGRESS);
+ break;
+ case AST_CONTROL_PROCEEDING:
+ chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
+ misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
break;
case AST_CONTROL_CONGESTION:
chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
@@ -1555,18 +1915,25 @@ int misdn_indication(struct ast_channel *ast, int cond)
p->bc->out_cause=42;
if (p->state != MISDN_CONNECTED) {
start_bc_tones(p);
- //misdn_lib_send_event( p->bc, EVENT_RELEASE_COMPLETE);
misdn_lib_send_event( p->bc, EVENT_RELEASE);
} else {
misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
}
+
if (p->bc->nt) {
- manager_send_tone(p->bc, TONE_BUSY);
+ hanguptone_indicate(p);
}
break;
case -1 :
- chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
+ chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
+
+ stop_indicate(p);
+
+ if (p->state == MISDN_CONNECTED)
+ start_bc_tones(p);
+
break;
+
case AST_CONTROL_HOLD:
chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
break;
@@ -1574,35 +1941,29 @@ int misdn_indication(struct ast_channel *ast, int cond)
chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
break;
default:
- ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
+ ast_log(LOG_NOTICE, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
}
return 0;
}
-int misdn_hangup(struct ast_channel *ast)
+static int misdn_hangup(struct ast_channel *ast)
{
struct chan_list *p;
struct misdn_bchannel *bc=NULL;
if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
- release_lock;
-
- chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
-
ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
if (!p) {
chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
- release_unlock;
return 0 ;
}
bc=p->bc;
if (!bc) {
- release_unlock;
ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
return 0;
}
@@ -1611,31 +1972,32 @@ int misdn_hangup(struct ast_channel *ast)
MISDN_ASTERISK_TECH_PVT(ast)=NULL;
p->ast=NULL;
+ bc=p->bc;
+
if (ast->_state == AST_STATE_RESERVED) {
/* between request and call */
MISDN_ASTERISK_TECH_PVT(ast)=NULL;
- release_unlock;
cl_dequeue_chan(&cl_te, p);
free(p);
-
- misdn_lib_release(bc);
+
+ if (bc)
+ misdn_lib_release(bc);
return 0;
}
- stop_bc_tones(p);
-
- release_unlock;
-
-
-
-
-
+ p->need_hangup=0;
+ p->need_queue_hangup=0;
+
+
+ if (!p->bc->nt)
+ stop_bc_tones(p);
+
{
- char *varcause=NULL;
- bc->cause=ast->hangupcause?ast->hangupcause:16;
+ const char *varcause=NULL;
+ bc->out_cause=ast->hangupcause?ast->hangupcause:16;
if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
(varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
@@ -1647,6 +2009,7 @@ int misdn_hangup(struct ast_channel *ast)
chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
+ chan_misdn_log(1, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
switch (p->state) {
case MISDN_CALLING:
@@ -1656,81 +2019,112 @@ int misdn_hangup(struct ast_channel *ast)
case MISDN_HOLDED:
case MISDN_DIALING:
start_bc_tones(p);
- manager_send_tone(bc, TONE_BUSY);
- p->state=MISDN_CLEANING;
-
- misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
-
+ hanguptone_indicate(p);
+
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
+ break;
+
+ case MISDN_CALLING_ACKNOWLEDGE:
+ start_bc_tones(p);
+ hanguptone_indicate(p);
+
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
break;
case MISDN_ALERTING:
- chan_misdn_log(2, bc->port, " --> * State Alerting\n");
-
+ case MISDN_PROGRESS:
+ case MISDN_PROCEEDING:
if (p->orginator != ORG_AST)
- manager_send_tone(bc, TONE_BUSY);
+ hanguptone_indicate(p);
- p->state=MISDN_CLEANING;
- misdn_lib_send_event( bc, EVENT_DISCONNECT);
+ /*p->state=MISDN_CLEANING;*/
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
break;
case MISDN_CONNECTED:
+ case MISDN_PRECONNECTED:
/* Alerting or Disconect */
- chan_misdn_log(2, bc->port, " --> * State Connected\n");
- start_bc_tones(p);
- manager_send_tone(bc, TONE_BUSY);
- misdn_lib_send_event( bc, EVENT_DISCONNECT);
-
+ if (p->bc->nt) {
+ start_bc_tones(p);
+ hanguptone_indicate(p);
+ p->bc->progress_indicator=8;
+ }
+ if (bc->need_disconnect)
+ misdn_lib_send_event( bc, EVENT_DISCONNECT);
+
+ /*p->state=MISDN_CLEANING;*/
+ break;
+ case MISDN_DISCONNECTED:
+ misdn_lib_send_event( bc, EVENT_RELEASE);
p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
break;
+ case MISDN_RELEASED:
case MISDN_CLEANING:
+ p->state=MISDN_CLEANING;
+ break;
+
+ case MISDN_BUSY:
break;
case MISDN_HOLD_DISCONNECT:
/* need to send release here */
- chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
+ bc->out_cause=-1;
misdn_lib_send_event(bc,EVENT_RELEASE);
+ p->state=MISDN_CLEANING;
break;
default:
- /* Alerting or Disconect */
- if (bc->nt)
+ if (bc->nt) {
+ bc->out_cause=-1;
misdn_lib_send_event(bc, EVENT_RELEASE);
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT);
- p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
+ p->state=MISDN_CLEANING;
+ } else {
+ if (bc->need_disconnect)
+ misdn_lib_send_event(bc, EVENT_DISCONNECT);
+ }
}
+
+ p->state=MISDN_CLEANING;
}
- chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
+
+ chan_misdn_log(1, bc->port, "Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
return 0;
}
-struct ast_frame *misdn_read(struct ast_channel *ast)
+static struct ast_frame *misdn_read(struct ast_channel *ast)
{
struct chan_list *tmp;
+ int len;
- char blah[255];
- int len =0 ;
-
- if (!ast) return NULL;
- if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
- if (!tmp->bc) return NULL;
-
-
- read(tmp->pipe[0],blah,sizeof(blah));
-
-
- len = misdn_ibuf_usedcount(tmp->bc->astbuf);
+ if (!ast) {
+ chan_misdn_log(1,0,"misdn_read called without ast\n");
+ return NULL;
+ }
+ if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) {
+ chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
+ return NULL;
+ }
+ if (!tmp->bc) {
+ chan_misdn_log(1,0,"misdn_read called without bc\n");
+ return NULL;
+ }
- /*shrinken len if necessary, we transmit at maximum 4k*/
- len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
-
- misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
+ len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
+ if (len<=0) {
+ /* we hangup here, since our pipe is closed */
+ chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
+ return NULL;
+ }
+
tmp->frame.frametype = AST_FRAME_VOICE;
tmp->frame.subclass = AST_FORMAT_ALAW;
tmp->frame.datalen = len;
@@ -1739,41 +2133,59 @@ struct ast_frame *misdn_read(struct ast_channel *ast)
tmp->frame.offset= 0 ;
tmp->frame.src = NULL;
tmp->frame.data = tmp->ast_rd_buf ;
-
- chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
+
+ if (tmp->faxdetect || tmp->ast_dsp ) {
+ return process_ast_dsp(tmp, &tmp->frame);
+ }
+
return &tmp->frame;
}
-int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
+
+static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
{
- struct chan_list *p;
+ struct chan_list *ch;
int i = 0;
- if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
+ if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
- if (!p->bc ) {
+ if (!ch->bc ) {
ast_log(LOG_WARNING, "private but no bc\n");
return -1;
}
- if (p->bc->tone != TONE_NONE)
- manager_send_tone(p->bc,TONE_NONE);
-
-
- if (p->holded ) {
- chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
+ if (ch->state == MISDN_HOLDED) {
+ chan_misdn_log(8, ch->bc->port, "misdn_write: Returning because holded\n");
return 0;
}
- if (p->notxtone) {
- chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
+ if (ch->notxtone) {
+ chan_misdn_log(9, ch->bc->port, "misdn_write: Returning because notxone\n");
+ return 0;
+ }
+
+
+ if ( !frame->subclass) {
+ chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
return 0;
}
if ( !(frame->subclass & prefformat)) {
- chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
+
+ chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
+ return 0;
}
+
+ if ( !frame->samples ) {
+ chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
+ return 0;
+ }
+
+ if ( ! ch->bc->addr ) {
+ chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
+ return 0;
+ }
#if MISDN_DEBUG
{
@@ -1785,13 +2197,48 @@ int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
printf ("\n");
}
#endif
- chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
- i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
+
+
+ switch (ch->bc->bc_state) {
+ case BCHAN_ACTIVATED:
+ case BCHAN_BRIDGED:
+ break;
+ default:
+ if (!ch->dropped_frame_cnt)
+ chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state);
+
+ ch->dropped_frame_cnt++;
+ if (ch->dropped_frame_cnt > 100) {
+ ch->dropped_frame_cnt=0;
+ chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x dropped > 100 frames!\n",frame->samples,ch->bc->addr);
+
+ }
+
+ return 0;
+ }
+
+ chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
+
+ if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
+ /* Buffered Transmit (triggert by read from isdn side)*/
+ if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
+ if (ch->bc->active)
+ cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
+ }
+
+ } else {
+ /*transmit without jitterbuffer*/
+ i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
+ }
+
+
return 0;
}
+
+
enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
struct ast_channel *c1, int flags,
struct ast_frame **fo,
@@ -1819,47 +2266,69 @@ enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
int bridging;
misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
if (bridging) {
- int ecwb;
- misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
- if ( !ecwb ) {
- chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
+ int ec;
+ misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+ if ( ec ) {
+ chan_misdn_log(2, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
ch1->bc->ec_enable=0;
manager_ec_disable(ch1->bc);
}
- misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
- if ( !ecwb ) {
- chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
+ misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
+ if ( ec ) {
+ chan_misdn_log(2, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
ch2->bc->ec_enable=0;
- manager_ec_disable(ch2->bc);
+ manager_ec_disable(ch2->bc);
}
/* trying to make a mISDN_dsp conference */
- chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
-
+ chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
+
misdn_lib_bridge(ch1->bc,ch2->bc);
}
- chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
-
+ chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
+
+
+ if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
+ ch1->ignore_dtmf=1;
+
+ if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
+ ch2->ignore_dtmf=1;
+
+
while(1) {
to=-1;
who = ast_waitfor_n(carr, 2, &to);
if (!who) {
- ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
- continue;
+ ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
+ break;
}
f = ast_read(who);
if (!f || f->frametype == AST_FRAME_CONTROL) {
/* got hangup .. */
+
+ if (!f)
+ chan_misdn_log(1,ch1->bc->port,"Read Null Frame\n");
+ else
+ chan_misdn_log(1,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
+
*fo=f;
*rc=who;
break;
}
-
-
+
+ if ( f->frametype == AST_FRAME_DTMF ) {
+ chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
+
+ *fo=f;
+ *rc=who;
+ break;
+ }
+
+
if (who == c0) {
ast_write(c1,f);
}
@@ -1868,20 +2337,67 @@ enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
}
}
-
- if (bridging) {
- misdn_lib_split_bridge(ch1->bc,ch2->bc);
+
+ chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
+
+ misdn_lib_split_bridge(ch1->bc,ch2->bc);
+
+
+ return AST_BRIDGE_COMPLETE;
+}
+
+/** AST INDICATIONS END **/
+
+static int dialtone_indicate(struct chan_list *cl)
+{
+ const struct tone_zone_sound *ts= NULL;
+ struct ast_channel *ast=cl->ast;
+
+
+ int nd=0;
+ misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
+
+ if (nd) {
+ chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
+ return 0;
}
-
+
+ chan_misdn_log(3,cl->bc->port," --> Dial\n");
+ ts=ast_get_indication_tone(ast->zone,"dial");
+ cl->ts=ts;
+
+ if (ts) {
+ cl->notxtone=0;
+ cl->norxtone=0;
+ ast_playtones_start(ast,0, ts->data, 0);
+ chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
+ misdn_lib_tone_generator_start(cl->bc);
+ }
+
+ return 0;
+}
+
+static int hanguptone_indicate(struct chan_list *cl)
+{
+ misdn_lib_send_tone(cl->bc,TONE_HANGUP);
+ return 0;
+}
+
+static int stop_indicate(struct chan_list *cl)
+{
+ struct ast_channel *ast=cl->ast;
+ chan_misdn_log(3,cl->bc->port," --> None\n");
+ misdn_lib_tone_generator_stop(cl->bc);
+ ast_playtones_stop(ast);
+ /*ast_deactivate_generator(ast);*/
+
return 0;
}
-/** AST INDICATIONS END **/
static int start_bc_tones(struct chan_list* cl)
{
- manager_bchannel_activate(cl->bc);
- manager_send_tone(cl->bc ,TONE_NONE);
+ misdn_lib_tone_generator_stop(cl->bc);
cl->notxtone=0;
cl->norxtone=0;
return 0;
@@ -1889,9 +2405,8 @@ static int start_bc_tones(struct chan_list* cl)
static int stop_bc_tones(struct chan_list *cl)
{
- if (cl->bc) {
- manager_bchannel_deactivate(cl->bc);
- }
+ if (!cl) return -1;
+
cl->notxtone=1;
cl->norxtone=1;
@@ -1899,16 +2414,21 @@ static int stop_bc_tones(struct chan_list *cl)
}
-struct chan_list *init_chan_list(void)
+static struct chan_list *init_chan_list(int orig)
{
struct chan_list *cl=malloc(sizeof(struct chan_list));
if (!cl) {
- chan_misdn_log(0, 0, "misdn_request: malloc failed!");
+ chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
return NULL;
}
memset(cl,0,sizeof(struct chan_list));
+
+ cl->orginator=orig;
+ cl->need_queue_hangup=1;
+ cl->need_hangup=1;
+ cl->need_busy=1;
return cl;
@@ -1918,30 +2438,22 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
{
struct ast_channel *tmp = NULL;
- char group[BUFFERSIZE]="";
+ char group[BUFFERSIZE+1]="";
char buf[128];
char buf2[128], *ext=NULL, *port_str;
char *tokb=NULL, *p=NULL;
int channel=0, port=0;
struct misdn_bchannel *newbc = NULL;
- struct chan_list *cl=init_chan_list();
+ struct chan_list *cl=init_chan_list(ORG_AST);
+
+ sprintf(buf,"%s/%s",misdn_type,(char*)data);
+ ast_copy_string(buf2,data, 128);
- sprintf(buf,"%s/%s",type,(char*)data);
- strncpy(buf2,data, 128);
- buf2[127] = 0;
port_str=strtok_r(buf2,"/", &tokb);
ext=strtok_r(NULL,"/", &tokb);
- /*
- if (!ext) {
- ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITH WRONG ARGS, check extension.conf\n",ext);
-
- return NULL;
- }
- */
-
if (port_str) {
if (port_str[0]=='g' && port_str[1]==':' ) {
/* We make a group call lets checkout which ports are in my group */
@@ -1951,11 +2463,11 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
}
else if ((p = strchr(port_str, ':'))) {
- // we have a preselected channel
+ /* we have a preselected channel */
*p = 0;
channel = atoi(++p);
port = atoi(port_str);
- chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
+ chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
}
else {
port = atoi(port_str);
@@ -1969,7 +2481,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
if (!ast_strlen_zero(group)) {
- char cfg_group[BUFFERSIZE];
+ char cfg_group[BUFFERSIZE+1];
struct robin_list *rr = NULL;
if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
@@ -1993,8 +2505,9 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
if (port >= port_start)
next_chan = 1;
- if (port < port_start && next_chan) {
- if (++robin_channel >= MAX_BCHANS) {
+ if (port <= port_start && next_chan) {
+ int maxbchans=misdn_lib_get_maxchans(port);
+ if (++robin_channel >= maxbchans) {
robin_channel = 1;
}
next_chan = 0;
@@ -2003,17 +2516,25 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
if (!strcasecmp(cfg_group, group)) {
- int l1, port_up;
-
- misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
- port_up = misdn_lib_port_up(port);
+ int port_up;
+ int check;
+ misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+ port_up = misdn_lib_port_up(port, check);
+
+ if (check && !port_up)
+ chan_misdn_log(1,port,"L1 is not Up on this Port\n");
- if ((l1 && port_up) || !l1) {
+ if (check && port_up<0) {
+ ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
+ }
+
+
+ if ( port_up>0 ) {
newbc = misdn_lib_get_free_bc(port, robin_channel);
if (newbc) {
chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
if (port_up)
- chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
+ chan_misdn_log(4, port, "portup:%d\n", port_up);
rr->port = newbc->port;
rr->channel = newbc->channel;
break;
@@ -2024,7 +2545,7 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
} while (!newbc && robin_channel != rr->channel);
if (!newbc)
- chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
+ chan_misdn_log(-1, port, " Failed! No free channel in group %d!", group);
}
else {
@@ -2032,16 +2553,17 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
port=misdn_cfg_get_next_port(port)) {
misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
-
+
+ chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
if (!strcasecmp(cfg_group, group)) {
- int l1, port_up;
+ int port_up;
+ int check;
+ misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
+ port_up = misdn_lib_port_up(port, check);
- misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
- port_up = misdn_lib_port_up(port);
-
- chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
+ chan_misdn_log(4, port, "portup:%d\n", port_up);
- if ((l1 && port_up) || !l1) {
+ if ( port_up>0 ) {
newbc = misdn_lib_get_free_bc(port, 0);
if (newbc)
break;
@@ -2057,20 +2579,45 @@ static struct ast_channel *misdn_request(const char *type, int format, void *dat
}
if (!newbc) {
- chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
- chan_misdn_log(1, 0, " --> SEND: State Down\n");
+ chan_misdn_log(-1, 0, "Could not create channel on port:%d with extensions:%s\n",port,ext);
return NULL;
}
-
+
+ /* create ast_channel and link all the objects together */
cl->bc=newbc;
- tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
+ tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
+ cl->ast=tmp;
+
+ /* register chan in local list */
+ cl_queue_chan(&cl_te, cl) ;
+
+ /* fill in the config into the objects */
+ read_config(cl, ORG_AST);
+
+ /* important */
+ cl->need_hangup=0;
return tmp;
}
-struct ast_channel_tech misdn_tech = {
+int misdn_send_text (struct ast_channel *chan, const char *text)
+{
+ struct chan_list *tmp=chan->tech_pvt;
+
+ if (tmp && tmp->bc) {
+ ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
+ misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
+ } else {
+ ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct ast_channel_tech misdn_tech = {
.type="mISDN",
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities= AST_FORMAT_ALAW ,
@@ -2084,11 +2631,11 @@ struct ast_channel_tech misdn_tech = {
.write=misdn_write,
.indicate=misdn_indication,
.fixup=misdn_fixup,
+ .send_text=misdn_send_text,
.properties=0
- /* .transfer=misdn_transfer */
};
-struct ast_channel_tech misdn_tech_wo_bridge = {
+static struct ast_channel_tech misdn_tech_wo_bridge = {
.type="mISDN",
.description="Channel driver for mISDN Support (Bri/Pri)",
.capabilities=AST_FORMAT_ALAW ,
@@ -2101,69 +2648,64 @@ struct ast_channel_tech misdn_tech_wo_bridge = {
.write=misdn_write,
.indicate=misdn_indication,
.fixup=misdn_fixup,
+ .send_text=misdn_send_text,
.properties=0
- /* .transfer=misdn_transfer */
};
-unsigned long glob_channel=0;
+static unsigned long glob_channel=0;
-struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c)
+static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
{
struct ast_channel *tmp;
tmp = ast_channel_alloc(1);
if (tmp) {
- chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
+ chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
if (c<=0) {
c=glob_channel++;
snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
- type, port, c);
+ misdn_type, port, c);
} else {
snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
- type, port, c);
+ misdn_type, port, c);
}
- tmp->type = type;
-
+ tmp->type = misdn_type;
+
tmp->nativeformats = prefformat;
+
tmp->readformat = format;
+ tmp->rawreadformat = format;
tmp->writeformat = format;
+ tmp->rawwriteformat = format;
tmp->tech_pvt = chlist;
-
+
int bridging;
misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
if (bridging)
tmp->tech = &misdn_tech;
else
tmp->tech = &misdn_tech_wo_bridge;
-
-
+
tmp->writeformat = format;
tmp->readformat = format;
tmp->priority=1;
-
- if (context) {
- ast_copy_string(tmp->context, context, sizeof(tmp->context));
- } else {
- chan_misdn_log(1,0,"misdn_new: no context given.\n");
- }
-
- if (exten) {
+ if (exten)
ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
- } else {
+ else
chan_misdn_log(1,0,"misdn_new: no exten given.\n");
- }
if (callerid) {
char *cid_name, *cid_num;
ast_callerid_parse(callerid, &cid_name, &cid_num);
+
if (!ast_strlen_zero(cid_num)) {
tmp->cid.cid_num = strdup(cid_num);
tmp->cid.cid_ani = strdup(cid_num);
@@ -2180,193 +2722,107 @@ struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name,
}
- if (chlist->bc) {
- int port=chlist->bc->port;
- misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
-
- {
- char buf[256];
- ast_group_t pg,cg;
-
- misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
- misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
-
- chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
- tmp->pickupgroup=pg;
- tmp->callgroup=cg;
- }
- misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
- misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
- chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
-
- } else {
- chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
- }
-
ast_setstate(tmp, state);
if (state == AST_STATE_RING)
tmp->rings = 1;
else
tmp->rings = 0;
+
+
} else {
- ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
- chan_misdn_log(0,0,"Unable to allocate channel structure\n");
+ chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
}
return tmp;
}
-
-int misdn_tx2ast_frm(struct chan_list * tmp, char * buf, int len )
+struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
{
- struct ast_frame frame;
-
- /* If in hold state we drop frame .. */
- if (tmp->holded ) return 0;
-
- switch(tmp->state) {
- case MISDN_CLEANING:
- case MISDN_EXTCANTMATCH:
- case MISDN_WAITING4DIGS:
- return 0;
- default:
- break;
- }
-
- if (tmp->norxtone) {
- chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
- return 0;
+ struct ast_frame *f,*f2;
+ if (tmp->trans)
+ f2=ast_translate(tmp->trans, frame,0);
+ else {
+ chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
+ return NULL;
}
- frame.frametype = AST_FRAME_VOICE;
- frame.subclass = AST_FORMAT_ALAW;
- frame.datalen = len;
- frame.samples = len ;
- frame.mallocd =0 ;
- frame.offset= 0 ;
- frame.src = NULL;
- frame.data = buf ;
-
- if (tmp->faxdetect || tmp->ast_dsp ) {
- struct ast_frame *f,*f2;
- if (tmp->trans)
- f2=ast_translate(tmp->trans, &frame,0);
- else {
- chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
- return 0;
- }
-
- f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
- if (f && (f->frametype == AST_FRAME_DTMF)) {
- ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
- if (f->subclass == 'f' && tmp->faxdetect) {
- /* Fax tone -- Handle and return NULL */
- struct ast_channel *ast = tmp->ast;
- if (!tmp->faxhandled) {
- tmp->faxhandled++;
- if (strcmp(ast->exten, "fax")) {
- if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
- /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
- pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
- if (ast_async_goto(ast, ast->context, "fax", 1))
- ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
- } else
- ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
+ f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
+ if (f && (f->frametype == AST_FRAME_DTMF)) {
+ ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
+ if (f->subclass == 'f' && tmp->faxdetect) {
+ /* Fax tone -- Handle and return NULL */
+ struct ast_channel *ast = tmp->ast;
+ if (!tmp->faxhandled) {
+ tmp->faxhandled++;
+ if (strcmp(ast->exten, "fax")) {
+ if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
+ /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
+ pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
+ if (ast_async_goto(ast, ast->context, "fax", 1))
+ ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
} else
- ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+ ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
} else
- ast_log(LOG_DEBUG, "Fax already handled\n");
- frame.frametype = AST_FRAME_NULL;
- frame.subclass = 0;
- f = &frame;
- } else if ( tmp->ast_dsp) {
- struct ast_frame fr;
- memset(&fr, 0 , sizeof(fr));
- fr.frametype = AST_FRAME_DTMF;
- fr.subclass = f->subclass ;
- fr.src=NULL;
- fr.data = NULL ;
- fr.datalen = 0;
- fr.samples = 0 ;
- fr.mallocd =0 ;
- fr.offset= 0 ;
-
- chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
- ast_queue_frame(tmp->ast, &fr);
-
- frame.frametype = AST_FRAME_NULL;
- frame.subclass = 0;
- f = &frame;
- }
+ ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
+ } else
+ ast_log(LOG_DEBUG, "Fax already handled\n");
+
+ } else if ( tmp->ast_dsp) {
+ chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
+ return f;
}
}
-
- if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
-#if MISDN_DEBUG
- int i, max=5>len?len:5;
-
- printf("write2* %p %d bytes: ",tmp, len);
-
- for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
- printf ("\n");
-#endif
- chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
- ast_queue_frame(tmp->ast,&frame);
-
- } else {
- ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
- }
-
- return 0;
+
+ frame->frametype = AST_FRAME_NULL;
+ frame->subclass = 0;
+ return frame;
}
-/** Channel Queue ***/
-struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
+static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
{
struct chan_list *help=list;
for (;help; help=help->next) {
- if (help->l3id == l3id ) return help;
+ if (help->bc == bc) return help;
}
- chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
+ chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
return NULL;
}
-struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
+static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
{
struct chan_list *help=list;
for (;help; help=help->next) {
- if (help->bc == bc) return help;
+ if (help->bc->pid == pid) return help;
}
- chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
+ chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
return NULL;
}
-
-struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
+static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
{
struct chan_list *help=list;
- chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
+ chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
for (;help; help=help->next) {
chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
if (help->bc->port == bc->port
&& help->bc->holded ) return help;
}
- chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
+ chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
return NULL;
}
-void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
+static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
{
chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
@@ -2382,12 +2838,13 @@ void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
ast_mutex_unlock(&cl_te_lock);
}
-void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
+static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
{
if (chan->dsp)
ast_dsp_free(chan->dsp);
if (chan->trans)
ast_translator_free_path(chan->trans);
+
ast_mutex_lock(&cl_te_lock);
@@ -2419,35 +2876,88 @@ void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
/** Channel Queue End **/
+int pbx_start_chan(struct chan_list *ch)
+{
+ int ret=ast_pbx_start(ch->ast);
+
+ if (ret>=0)
+ ch->need_hangup=0;
+ else
+ ch->need_hangup=1;
+
+ return ret;
+}
+
+static void hangup_chan(struct chan_list *ch)
+{
+ if (!ch) {
+ cb_log(1,0,"Cannot hangup chan, no ch\n");
+ return;
+ }
+
+ cb_log(1,ch->bc?ch->bc->port:0,"hangup_chan\n");
+
+ if (ch->need_hangup)
+ {
+ cb_log(1,ch->bc->port,"-> hangup\n");
+ send_cause2ast(ch->ast,ch->bc,ch);
+ ch->need_hangup=0;
+ ch->need_queue_hangup=0;
+ if (ch->ast)
+ ast_hangup(ch->ast);
+ return;
+ }
+
+ if (!ch->need_queue_hangup) {
+ cb_log(1,ch->bc->port,"No need to queue hangup\n");
+ }
+
+ ch->need_queue_hangup=0;
+ if (ch->ast) {
+ send_cause2ast(ch->ast,ch->bc,ch);
+
+ if (ch->ast)
+ ast_queue_hangup(ch->ast);
+ cb_log(1,ch->bc->port,"-> queue_hangup\n");
+ } else {
+ cb_log(1,ch->bc->port,"Cannot hangup chan, no ast\n");
+ }
+}
/** Isdn asks us to release channel, pendant to misdn_hangup **/
static void release_chan(struct misdn_bchannel *bc) {
struct ast_channel *ast=NULL;
-
{
struct chan_list *ch=find_chan_by_bc(cl_te, bc);
- if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
+ if (!ch) {
+ chan_misdn_log(0, bc->port, "release_chan: Ch not found!\n");
+ return;
+ }
- release_lock;
if (ch->ast) {
ast=ch->ast;
}
- release_unlock;
- chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
+ chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
+
+ /*releaseing jitterbuffer*/
+ if (ch->jb ) {
+ misdn_jb_destroy(ch->jb);
+ ch->jb=NULL;
+ } else {
+ if (!bc->nojitter)
+ chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
+ }
+
if (ch) {
- if (ast)
- chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
close(ch->pipe[0]);
close(ch->pipe[1]);
+
- if (ast && MISDN_ASTERISK_PVT(ast)) {
+ if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
chan_misdn_log(3, bc->port, " --> * State Down\n");
- /* copy cause */
- send_cause2ast(ast,bc);
-
MISDN_ASTERISK_TECH_PVT(ast)=NULL;
@@ -2455,58 +2965,9 @@ static void release_chan(struct misdn_bchannel *bc) {
chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
ast_setstate(ast, AST_STATE_DOWN);
}
-
- switch(ch->state) {
- case MISDN_EXTCANTMATCH:
- case MISDN_WAITING4DIGS:
- {
- chan_misdn_log(3, bc->port, " --> * State Wait4dig | ExtCantMatch\n");
- ast_hangup(ast);
- }
- break;
-
- case MISDN_DIALING:
- case MISDN_CALLING_ACKNOWLEDGE:
- case MISDN_PROGRESS:
- chan_misdn_log(2, bc->port, "* --> In State Dialin\n");
- chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
-
-
- ast_queue_hangup(ast);
- break;
- case MISDN_CALLING:
-
- chan_misdn_log(2, bc->port, "* --> In State Callin\n");
-
- if (!bc->nt) {
- chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
- ast_queue_hangup(ast);
- } else {
- chan_misdn_log(2, bc->port, "* --> Hangup\n");
- ast_queue_hangup(ast);
- //ast_hangup(ast);
- }
- break;
-
- case MISDN_CLEANING:
- /* this state comes out of ast so we mustnt call a ast function ! */
- chan_misdn_log(2, bc->port, "* --> In StateCleaning\n");
- break;
- case MISDN_HOLD_DISCONNECT:
- chan_misdn_log(2, bc->port, "* --> In HOLD_DISC\n");
- break;
- default:
- chan_misdn_log(2, bc->port, "* --> In State Default\n");
- chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
-
-
- if (ast && MISDN_ASTERISK_PVT(ast)) {
- ast_queue_hangup(ast);
- } else {
- chan_misdn_log (0, bc->port, "!! Not really queued!\n");
- }
- }
}
+
+ ch->state=MISDN_CLEANING;
cl_dequeue_chan(&cl_te, ch);
free(ch);
@@ -2517,7 +2978,7 @@ static void release_chan(struct misdn_bchannel *bc) {
}
/*** release end **/
-void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
+static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
{
chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
@@ -2526,14 +2987,12 @@ void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
holded_chan->state=MISDN_CONNECTED;
- holded_chan->holded=0;
misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
-
ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
}
-void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
+static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
{
char predial[256]="";
char *p = predial;
@@ -2543,7 +3002,7 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
strncpy(predial, ast->exten, sizeof(predial) -1 );
ch->state=MISDN_DIALING;
-
+
if (bc->nt) {
int ret;
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
@@ -2556,15 +3015,20 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
}
}
- manager_send_tone(bc,TONE_DIAL);
+ if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio )
+ chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
+ else
+ dialtone_indicate(ch);
chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
strncpy(ast->exten,"s", 2);
- if (ast_pbx_start(ast)<0) {
+ if (pbx_start_chan(ch)<0) {
ast=NULL;
- manager_send_tone(bc,TONE_BUSY);
+ hangup_chan(ch);
+ hanguptone_indicate(ch);
+
if (bc->nt)
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
@@ -2591,7 +3055,19 @@ void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct
-void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
+static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
+ if (!ast) {
+ chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
+ return;
+ }
+ if (!bc) {
+ chan_misdn_log(1,0,"send_cause2ast: No BC\n");
+ return;
+ }
+ if (!ch) {
+ chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
+ return;
+ }
ast->hangupcause=bc->cause;
@@ -2603,55 +3079,122 @@ void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
case 4:
case 22:
case 27:
+ /*
+ * Not Queueing the Congestion anymore, since we want to hear
+ * the inband message
+ *
chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
+ ch->state=MISDN_BUSY;
ast_queue_control(ast, AST_CONTROL_CONGESTION);
+ */
break;
case 21:
case 17: /* user busy */
+
+ ch->state=MISDN_BUSY;
+
+ if (!ch->need_busy) {
+ chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
+ break;
+ }
+
chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
ast_queue_control(ast, AST_CONTROL_BUSY);
+ ch->need_busy=0;
+
break;
}
}
+void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
+{
+ char *tmp;
+ tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
+ if (tmp) {
+ ch->other_pid=atoi(tmp);
+ chan_misdn_log(1,bc->port,"IMPORT_PID: importing pid:%s\n",tmp);
+
+ if (ch->other_pid >0) {
+ ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
+ if (ch->other_ch) ch->other_ch->other_ch=ch;
+ }
+ }
+}
+
+void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
+{
+ char tmp[32];
+
+ chan_misdn_log(1,bc->port,"EXPORT_PID: pid:%d\n",bc->pid);
+ sprintf(tmp,"%d",bc->pid);
+ pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
+}
+
+
+
/************************************************************/
/* Receive Events from isdn_lib here */
/************************************************************/
-enum event_response_e
+static enum event_response_e
cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
{
struct chan_list *ch=find_chan_by_bc(cl_te, bc);
- if (!ch)
- ch=find_chan_by_l3id(cl_te, bc->l3_id);
+ if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */
+ int debuglevel=1;
- if (event != EVENT_BCHAN_DATA) { /* Debug Only Non-Bchan */
- chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s port:%d\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->port);
- misdn_lib_log_ies(bc);
+ if ( event==EVENT_CLEANUP && !user_data)
+ debuglevel=5;
+
+ chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch?misdn_get_ch_state(ch):"none");
+ if (debuglevel==1) {
+ misdn_lib_log_ies(bc);
+ chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
+ }
}
- if (event != EVENT_SETUP) {
- if (!ch) {
- if (event != EVENT_CLEANUP )
- ast_log(LOG_WARNING, "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);
- return -1;
+ if (!ch) {
+ switch(event) {
+ case EVENT_SETUP:
+ case EVENT_DISCONNECT:
+ case EVENT_PORT_ALARM:
+ case EVENT_RETRIEVE:
+ case EVENT_NEW_BC:
+ break;
+ case EVENT_RELEASE_COMPLETE:
+ chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
+ break;
+ case EVENT_CLEANUP:
+ case EVENT_TONE_GENERATE:
+ case EVENT_BCHAN_DATA:
+ return -1;
+
+ default:
+ 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);
+ return -1;
}
}
if (ch ) {
switch (event) {
+ case EVENT_TONE_GENERATE:
+ break;
+ case EVENT_DISCONNECT:
case EVENT_RELEASE:
case EVENT_RELEASE_COMPLETE:
case EVENT_CLEANUP:
+ case EVENT_TIMEOUT:
+ if (!ch->ast)
+ 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));
break;
default:
if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
if (event!=EVENT_BCHAN_DATA)
- ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
+ ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
return -1;
}
}
@@ -2659,13 +3202,38 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
switch (event) {
+ case EVENT_PORT_ALARM:
+ {
+ int boa=0;
+
+ misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
+ if (boa) {
+ cb_log(1,bc->port," --> blocking\n");
+ misdn_lib_port_block(bc->port);
+ }
+ }
+ break;
+
+ case EVENT_BCHAN_ACTIVATED:
+ break;
+
case EVENT_NEW_L3ID:
ch->l3id=bc->l3_id;
+ ch->addr=bc->addr;
break;
case EVENT_NEW_BC:
+ if (!ch) {
+ ch=find_holded(cl_te,bc);
+ }
+
+ if (!ch) {
+ ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
+ break;
+ }
+
if (bc)
- ch->bc=bc;
+ ch->bc=(struct misdn_bchannel*)user_data;
break;
case EVENT_DTMF_TONE:
@@ -2682,9 +3250,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
fr.mallocd =0 ;
fr.offset= 0 ;
- chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
-
- ast_queue_frame(ch->ast, &fr);
+ if (!ch->ignore_dtmf) {
+ chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
+ ast_queue_frame(ch->ast, &fr);
+ } else {
+ chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
+ }
}
break;
case EVENT_STATUS:
@@ -2694,8 +3265,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
{
int stop_tone;
misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
- if ( stop_tone && bc->tone != TONE_NONE) {
- manager_send_tone(bc,TONE_NONE);
+ if ( stop_tone ) {
+ stop_indicate(ch);
}
if (ch->state == MISDN_WAITING4DIGS ) {
@@ -2714,31 +3285,46 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
}
/* chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
- char bc_context[BUFFERSIZE];
- misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
- if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
- chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
- manager_send_tone(bc,TONE_BUSY);
+ /* Check for Pickup Request first */
+ if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
+ int ret;/** Sending SETUP_ACK**/
+ ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+ if (ast_pickup_call(ch->ast)) {
+ hangup_chan(ch);
+ } else {
+ struct ast_channel *chan=ch->ast;
+ ch->state = MISDN_CALLING_ACKNOWLEDGE;
+ ast_setstate(chan, AST_STATE_DOWN);
+ hangup_chan(ch);
+ ch->ast=NULL;
+ break;
+ }
+ }
+
+ if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+
+ chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
+ if (bc->nt)
+ hanguptone_indicate(ch);
ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1;
- if (bc->nt)
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+
+ misdn_lib_send_event(bc, EVENT_DISCONNECT );
+
break;
}
- if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
+ if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
ch->state=MISDN_DIALING;
- manager_send_tone(bc,TONE_NONE);
-/* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
- if (ast_pbx_start(ch->ast)<0) {
- chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
- manager_send_tone(bc,TONE_BUSY);
- if (bc->nt)
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+ stop_indicate(ch);
+/* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/
+ if (pbx_start_chan(ch)<0) {
+ hangup_chan(ch);
+
+ chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
+ if (bc->nt) hanguptone_indicate(ch);
+
+ misdn_lib_send_event(bc, EVENT_DISCONNECT );
}
}
@@ -2771,7 +3357,6 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ast_queue_frame(ch->ast, &fr);
}
-
}
}
break;
@@ -2784,6 +3369,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
}
}
+
int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
if (!bc->nt && ! msn_valid) {
chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
@@ -2793,119 +3379,61 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
print_bearer(bc);
{
- struct chan_list *ch=init_chan_list();
+ struct chan_list *ch=init_chan_list(ORG_MISDN);
struct ast_channel *chan;
- char name[128];
- if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
+
+ if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
ch->bc = bc;
ch->l3id=bc->l3_id;
ch->addr=bc->addr;
ch->orginator = ORG_MISDN;
+ chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
+ ch->ast = chan;
+
+ read_config(ch, ORG_MISDN);
- {
- char prefix[BUFFERSIZE]="";
- switch( bc->onumplan ) {
- case NUMPLAN_INTERNATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
- break;
-
- case NUMPLAN_NATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
- break;
-
-
- case NUMPLAN_SUBSCRIBER:
- /* dunno what to do here ? */
- break;
+ export_ch(chan, bc, ch);
- case NUMPLAN_UNKNOWN:
- break;
- default:
- break;
- }
+ ch->ast->rings=1;
+ ast_setstate(ch->ast, AST_STATE_RINGING);
- {
- int l = strlen(prefix) + strlen(bc->oad);
- char tmp[l+1];
- strcpy(tmp,prefix);
- strcat(tmp,bc->oad);
- strcpy(bc->oad,tmp);
- }
-
- if (!ast_strlen_zero(bc->oad))
- sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
- else
- sprintf(name,"mISDN/%d",bc->port);
+ int pres,screen;
+ switch (bc->pres) {
+ case 1:
+ pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
+ break;
+ case 2:
+ pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
+ break;
+ default:
+ pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
+ }
- if (!ast_strlen_zero(bc->dad)) {
- strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
- bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
- }
-
- if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
- strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
- bc->dad[sizeof(bc->dad)-1] = 0;
- }
- prefix[0] = 0;
-
- switch( bc->dnumplan ) {
- case NUMPLAN_INTERNATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
- break;
-
- case NUMPLAN_NATIONAL:
- misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
- break;
-
-
- case NUMPLAN_SUBSCRIBER:
- /* dunno what to do here ? */
- break;
-
- case NUMPLAN_UNKNOWN:
- break;
+ switch (bc->screen) {
+ case 0:
+ screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
+ break;
+ case 1:
+ screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
+ break;
+ case 2:
+ screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
+ break;
+ case 3:
+ screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
+ break;
default:
- break;
- }
-
- {
- int l = strlen(prefix) + strlen(bc->dad);
- char tmp[l+1];
- strcpy(tmp,prefix);
- strcat(tmp,bc->dad);
- strcpy(bc->dad,tmp);
- }
-
- char bc_context[BUFFERSIZE];
- misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
- chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
-
- if (!chan) {
- misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- return 0;
- }
-
- ch->ast = chan;
- pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
-
+ screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
}
-
+ chan->cid.cid_pres=pres+screen;
- chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
-
- if ( bc->pres ) {
- chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
- } else {
- chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
- }
-
pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
chan->transfercapability=bc->capability;
-
+
switch (bc->capability) {
case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
@@ -2917,113 +3445,88 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
/** queue new chan **/
cl_queue_chan(&cl_te, ch) ;
-
- /*
- added support for s extension hope it will help those poor cretains
- which haven't overlap dial.
- */
- {
-
- misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));
-
- }
-
- {
- int eb3;
-
- misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
- bc->early_bconnect=eb3;
-
- }
- {
- int ec, ectr;
-
- misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
-
- misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
- if (ec == 1 ) {
- bc->ec_enable=1;
- } else if ( ec > 1 ) {
- bc->ec_enable=1;
- bc->ec_deftaps=ec;
- }
-
- if ( ectr>=0 ) {
- bc->ec_training=ectr;
+ if (!strstr(ch->allowed_bearers,"all")) {
+ int i;
+ for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
+ if (allowed_bearers_array[i].cap == bc->capability) {
+ if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
+ chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
+ bc->out_cause=88;
+
+ ch->state=MISDN_EXTCANTMATCH;
+ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
+ return RESPONSE_OK;
+ }
+ }
+
}
}
-
- if (bc->urate>0) {
- char buf[16];
- snprintf(buf,16,"%d",bc->urate);
- pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
- }
-
-
-
- /**
- from here on we start the PBX, so no configuration should
- be considered anymore
- **/
-
- int ai;
- misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
- if ( ai ) {
- do_immediate_setup(bc, ch , chan);
- break;
- }
-
-
- int immediate;
- misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
-
- if (ast_strlen_zero(bc->orig_dad) && immediate ) {
- do_immediate_setup(bc, ch , chan);
- break;
- }
-
/* Check for Pickup Request first */
if (!strcmp(chan->exten, ast_pickup_ext())) {
int ret;/** Sending SETUP_ACK**/
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
-
if (ast_pickup_call(chan)) {
- ast_hangup(chan);
+ hangup_chan(ch);
} else {
ch->state = MISDN_CALLING_ACKNOWLEDGE;
-
- ch->ast=NULL;
-
ast_setstate(chan, AST_STATE_DOWN);
- ast_hangup(chan);
-
+ hangup_chan(ch);
+ ch->ast=NULL;
break;
}
}
- /** Now after we've finished configuring our channel object
- we'll jump into the dialplan **/
+ /*
+ added support for s extension hope it will help those poor cretains
+ which haven't overlap dial.
+ */
+ {
+ int ai;
+ misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
+ if ( ai ) {
+ do_immediate_setup(bc, ch , chan);
+ break;
+ }
+
+
+
+ }
+
+ /* check if we should jump into s when we have no dad */
+ {
+ int im;
+ misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
+ if ( im && ast_strlen_zero(bc->dad) ) {
+ do_immediate_setup(bc, ch , chan);
+ break;
+ }
+ }
+
- char bc_context[BUFFERSIZE];
- misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
- if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
- chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
- manager_send_tone(bc,TONE_BUSY);
+ chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
+ if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
+
+ chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
+
+ if (bc->nt)
+ hanguptone_indicate(ch);
ch->state=MISDN_EXTCANTMATCH;
bc->out_cause=1;
+
if (bc->nt)
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+ misdn_lib_send_event(bc, EVENT_RELEASE );
+
break;
}
- if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
+ if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
ch->state=MISDN_DIALING;
-
- if (bc->nt) {
+
+ if (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)) ) {
int ret;
ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
} else {
@@ -3031,31 +3534,53 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
}
- if (ast_pbx_start(chan)<0) {
- chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
+ if (pbx_start_chan(ch)<0) {
+ hangup_chan(ch);
+
+ chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
chan=NULL;
- manager_send_tone(bc,TONE_BUSY);
- if (bc->nt)
+
+ if (bc->nt) {
+ hanguptone_indicate(ch);
misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
- else
- misdn_lib_send_event(bc, EVENT_DISCONNECT );
+ } else
+ misdn_lib_send_event(bc, EVENT_RELEASE);
}
} else {
- int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
- if (ret == -ENOCHAN) {
- ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+
+ if (bc->sending_complete) {
+ ch->state=MISDN_EXTCANTMATCH;
+ bc->out_cause=1;
+
+ if (bc->nt) {
+ chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
+ misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
+ } else {
+ chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
+ misdn_lib_send_event(bc, EVENT_RELEASE);
+ }
+
+ } else {
+
+ int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
+ if (ret == -ENOCHAN) {
+ ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
+ misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
+ }
+ /* send tone to phone :) */
+
+ /** ADD IGNOREPAT **/
+
+ int stop_tone;
+ misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
+ if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
+ stop_indicate(ch);
+ else {
+ dialtone_indicate(ch);
+ }
+
+ ch->state=MISDN_WAITING4DIGS;
}
- /* send tone to phone :) */
-
- int stop_tone;
- misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
- if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
- manager_send_tone(bc,TONE_NONE);
- else
- manager_send_tone(bc,TONE_DIAL);
-
- ch->state=MISDN_WAITING4DIGS;
}
}
@@ -3094,6 +3619,10 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
misdn_inband_avail(bc) ) {
start_bc_tones(ch);
}
+
+ ch->state = MISDN_PROCEEDING;
+
+ ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
}
break;
case EVENT_PROGRESS:
@@ -3121,162 +3650,272 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
cb_log(1,bc->port,"Set State Ringing\n");
if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
- start_bc_tones(ch);
- }
+ cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
+ start_bc_tones(ch);
+ } else {
+ cb_log(1,bc->port,"We have no inband Data, the other end must create ringing\n");
+ if (ch->far_alerting) {
+ cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself..");
+ start_bc_tones(ch);
+ /*tone_indicate(ch, TONE_FAR_ALERTING);*/
+ }
+ }
}
break;
case EVENT_CONNECT:
+ {
+ /*we answer when we've got our very new L3 ID from the NT stack */
misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
+
+ struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
+
+ misdn_lib_echo(bc,0);
+ stop_indicate(ch);
+
+ if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
+ struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
+
+ chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
+ if (bridged_ch) {
+ bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
+ ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
+ }
+ }
+ }
+
+
+ /* notice that we don't break here!*/
+
case EVENT_CONNECT_ACKNOWLEDGE:
{
- bc->state=STATE_CONNECTED;
-
ch->l3id=bc->l3_id;
ch->addr=bc->addr;
start_bc_tones(ch);
- chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
ch->state = MISDN_CONNECTED;
ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
}
break;
case EVENT_DISCONNECT:
- {
-
+ /*we might not have an ch->ast ptr here anymore*/
+ if (ch) {
struct chan_list *holded_ch=find_holded(cl_te, bc);
-
-
- send_cause2ast(ch->ast,bc);
-
- if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
+
+ chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->orginator, bc->nt, misdn_inband_avail(bc), ch->state);
+ if ( ch->orginator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
/* If there's inband information available (e.g. a
recorded message saying what was wrong with the
dialled number, or perhaps even giving an
alternative number, then play it instead of
immediately releasing the call */
+ chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
+
+ ch->state=MISDN_DISCONNECTED;
start_bc_tones(ch);
break;
}
/*Check for holded channel, to implement transfer*/
- if (holded_ch ) {
+ if (holded_ch && ch->ast ) {
+ cb_log(1,bc->port," --> found holded ch\n");
if (ch->state == MISDN_CONNECTED ) {
misdn_transfer_bc(ch, holded_ch) ;
- misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
- break;
}
+ hangup_chan(ch);
+ release_chan(bc);
+ break;
}
stop_bc_tones(ch);
- bc->out_cause=16;
- misdn_lib_send_event(bc,EVENT_RELEASE);
-
+ hangup_chan(ch);
}
+ bc->out_cause=-1;
+ if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
break;
case EVENT_RELEASE:
{
-
- switch ( bc->cause) {
-
- case -1:
- /*
- OK, it really sucks, this is a RELEASE from NT-Stack So we take
- it and return easylie, It seems that we've send a DISCONNECT
- before, so we should RELEASE_COMPLETE after that Disconnect
- (looks like ALERTING State at misdn_hangup !!
- */
- return RESPONSE_OK;
- break;
- }
-
-
bc->out_cause=16;
- stop_bc_tones(ch);
+ hangup_chan(ch);
release_chan(bc);
+
+ if (bc->need_release_complete)
+ misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
}
break;
case EVENT_RELEASE_COMPLETE:
{
stop_bc_tones(ch);
+ hangup_chan(ch);
+ release_chan(bc);
+ if(ch)
+ ch->state=MISDN_CLEANING;
+ }
+ break;
+ case EVENT_CLEANUP:
+ {
+ stop_bc_tones(ch);
+
+ switch(ch->state) {
+ case MISDN_CALLING:
+ bc->cause=27; /* Destination out of order */
+ break;
+ default:
+ break;
+ }
+
+ hangup_chan(ch);
release_chan(bc);
}
break;
+
+ case EVENT_TONE_GENERATE:
+ {
+ int tone_len=bc->tone_cnt;
+ struct ast_channel *ast=ch->ast;
+ void *tmp;
+ int res;
+ int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
+
+ chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
+
+ if (!ast) break;
+
+ if (!ast->generator) break;
+
+
+ tmp = ast->generatordata;
+ ast->generatordata = NULL;
+ generate = ast->generator->generate;
+
+ if (tone_len <0 || tone_len > 512 ) {
+ ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
+ tone_len=128;
+ }
+
+ res = generate(ast, tmp, tone_len, tone_len);
+ ast->generatordata = tmp;
+
+ if (res) {
+ ast_log(LOG_WARNING, "Auto-deactivating generator\n");
+ ast_deactivate_generator(ast);
+ } else {
+ bc->tone_cnt=0;
+ }
+ }
+ break;
+
case EVENT_BCHAN_DATA:
{
- chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
-
- if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
- misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
+ if ( !misdn_cap_is_speech(ch->bc->capability) ) {
+ struct ast_frame frame;
+ /*In Data Modes we queue frames*/
+ frame.frametype = AST_FRAME_VOICE; /*we have no data frames yet*/
+ frame.subclass = AST_FORMAT_ALAW;
+ frame.datalen = bc->bframe_len;
+ frame.samples = bc->bframe_len ;
+ frame.mallocd =0 ;
+ frame.offset= 0 ;
+ frame.src = NULL;
+ frame.data = bc->bframe ;
+
+ ast_queue_frame(ch->ast,&frame);
} else {
- int len=bc->bframe_len;
- int free=misdn_ibuf_freecount(bc->astbuf);
+ fd_set wrfs;
+ struct timeval tv;
+ tv.tv_sec=0;
+ tv.tv_usec=0;
+
+ FD_ZERO(&wrfs);
+ FD_SET(ch->pipe[1],&wrfs);
- if (bc->bframe_len > free) {
- ast_log(LOG_DEBUG, "sbuf overflow!\n");
- len=misdn_ibuf_freecount(bc->astbuf);
+ int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
- if (len == 0) {
- ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
- }
+ if (!t) {
+ chan_misdn_log(9, bc->port, "Select Timed out\n");
+ break;
}
- misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
+ if (t<0) {
+ chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
+ break;
+ }
- {
- char blah[1]="\0";
-#ifdef FLATTEN_JITTER
- {
- struct timeval tv;
- gettimeofday(&tv,NULL);
-
- if (tv.tv_usec % 10000 > 0 ) {
- write(ch->pipe[1], blah,sizeof(blah));
- bc->time_usec=tv.tv_usec;
- }
- }
-#else
- write(ch->pipe[1], blah,sizeof(blah));
-#endif
-
+ if (FD_ISSET(ch->pipe[1],&wrfs)) {
+ chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
+ int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
+ if (ret<=0) {
+ chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s)\n",strerror(errno));
+ }
+ } else {
+ chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
}
}
-
}
break;
case EVENT_TIMEOUT:
- break; /* Ignore now .. */
{
- switch (ch->state) {
+ if (ch && bc)
+ chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
+
+ switch (ch->state) {
case MISDN_CALLING:
- chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
- break;
case MISDN_DIALING:
case MISDN_PROGRESS:
- break;
+ case MISDN_ALERTING:
+ case MISDN_PROCEEDING:
+ case MISDN_CALLING_ACKNOWLEDGE:
+ if (bc->nt) {
+ bc->progress_indicator=8;
+ hanguptone_indicate(ch);
+ }
+
+ bc->out_cause=1;
+ misdn_lib_send_event(bc,EVENT_DISCONNECT);
+ break;
+
+ case MISDN_WAITING4DIGS:
+ if (bc->nt) {
+ bc->progress_indicator=8;
+ bc->out_cause=1;
+ hanguptone_indicate(ch);
+ misdn_lib_send_event(bc,EVENT_DISCONNECT);
+ } else {
+ bc->out_cause=16;
+ misdn_lib_send_event(bc,EVENT_RELEASE);
+ }
+
+ break;
+
+
+ case MISDN_CLEANING:
+ chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
+ break;
+
default:
misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
}
}
break;
- case EVENT_CLEANUP:
- {
- stop_bc_tones(ch);
- release_chan(bc);
- }
- break;
+
/***************************/
/** Suplementary Services **/
/***************************/
case EVENT_RETRIEVE:
{
+ ch=find_holded(cl_te, bc);
+ if (!ch) {
+ ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
+ misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
+ break;
+ }
struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
ch->state = MISDN_CONNECTED;
@@ -3297,34 +3936,77 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
if (!hold_allowed) {
- chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
+
+ chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
break;
}
+#if 0
{
struct chan_list *holded_ch=find_holded(cl_te, bc);
if (holded_ch) {
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
- chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
+
+ chan_misdn_log(-1, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
break;
}
}
+#endif
+ struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
- if (AST_BRIDGED_P(ch->ast)){
+ if (bridged){
+ struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
ch->state = MISDN_HOLDED;
ch->l3id = bc->l3_id;
- ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
+ bc->holded_bc=bridged_ch->bc;
misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
+
+ ast_moh_start(bridged, NULL);
} else {
misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
}
}
break;
+
+ case EVENT_FACILITY:
+ print_facility(bc);
+
+ switch (bc->fac_type) {
+ case FACILITY_CALLDEFLECT:
+ {
+ struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
+ struct chan_list *ch;
+
+ if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
+ ch=MISDN_ASTERISK_TECH_PVT(bridged);
+ /*ch->state=MISDN_FACILITY_DEFLECTED;*/
+ if (ch->bc) {
+ /* todo */
+ }
+
+ }
+
+ }
+
+ break;
+ default:
+ chan_misdn_log(1, bc->port," --> not yet handled\n");
+ }
+
+ break;
+
+ case EVENT_RESTART:
+
+ stop_bc_tones(ch);
+ release_chan(bc);
+
+ break;
+
default:
- ast_log(LOG_WARNING, "Got Unknown Event\n");
+ ast_log(LOG_NOTICE, "Got Unknown Event\n");
break;
}
@@ -3341,13 +4023,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
*******************************************/
-int clearl3_true ( void ) {
- int default_clearl3;
- misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
- return default_clearl3;
-}
-
-int g_config_initialized=0;
+static int g_config_initialized=0;
int load_module(void)
{
@@ -3359,7 +4035,7 @@ int load_module(void)
if (max_ports<=0) {
ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
- return -1;
+ return 0;
}
@@ -3374,16 +4050,17 @@ int load_module(void)
{
- char tempbuf[BUFFERSIZE];
+ char tempbuf[BUFFERSIZE+1];
misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
if (strlen(tempbuf))
tracing = 1;
}
ast_mutex_init(&cl_te_lock);
- ast_mutex_init(&release_lock_mutex);
+ misdn_cfg_update_ptp();
misdn_cfg_get_ports_string(ports);
+
if (strlen(ports))
chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
@@ -3391,16 +4068,25 @@ int load_module(void)
struct misdn_lib_iface iface = {
.cb_event = cb_events,
.cb_log = chan_misdn_log,
- .cb_clearl3_true = clearl3_true
+ .cb_jb_empty = chan_misdn_jb_empty,
};
if (misdn_lib_init(ports, &iface, NULL))
chan_misdn_log(0, 0, "No te ports initialized\n");
+
+ int ntflags=0;
+ char ntfile[BUFFERSIZE+1];
+
+ misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
+ misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
+
+ misdn_lib_nt_debug_init(ntflags,ntfile);
+
}
{
if (ast_channel_register(&misdn_tech)) {
- ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
+ ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
unload_module();
return -1;
}
@@ -3418,17 +4104,30 @@ int load_module(void)
ast_cli_register(&cli_show_port);
ast_cli_register(&cli_show_stacks);
+ ast_cli_register(&cli_port_block);
+ ast_cli_register(&cli_port_unblock);
ast_cli_register(&cli_restart_port);
ast_cli_register(&cli_port_up);
+ ast_cli_register(&cli_port_down);
ast_cli_register(&cli_set_debug);
ast_cli_register(&cli_set_crypt_debug);
ast_cli_register(&cli_reload);
- ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
+ ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
"misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
"Sets mISDN opts. and optargs\n"
"\n"
+ "The available options are:\n"
+ " d - Send display text on called phone, text is the optparam\n"
+ " n - don't detect dtmf tones on called channel\n"
+ " h - make digital outgoing call\n"
+ " c - make crypted outgoing call, param is keyindex\n"
+ " e - perform echo cancelation on this channel,\n"
+ " takes taps as arguments (32,64,128,256)\n"
+ " s - send Non Inband DTMF as inband\n"
+ " vr - rxgain control\n"
+ " vt - txgain control\n"
);
@@ -3439,9 +4138,11 @@ int load_module(void)
"Supported Facilities are:\n"
"\n"
"type=calldeflect args=Nr where to deflect\n"
- "\n"
);
-
+
+
+ misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
+
chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
return 0;
@@ -3469,8 +4170,11 @@ int unload_module(void)
ast_cli_unregister(&cli_show_config);
ast_cli_unregister(&cli_show_port);
ast_cli_unregister(&cli_show_stacks);
+ ast_cli_unregister(&cli_port_block);
+ ast_cli_unregister(&cli_port_unblock);
ast_cli_unregister(&cli_restart_port);
ast_cli_unregister(&cli_port_up);
+ ast_cli_unregister(&cli_port_down);
ast_cli_unregister(&cli_set_debug);
ast_cli_unregister(&cli_set_crypt_debug);
ast_cli_unregister(&cli_reload);
@@ -3480,6 +4184,7 @@ int unload_module(void)
ast_channel_unregister(&misdn_tech);
+
free_robin_list();
misdn_cfg_destroy();
misdn_lib_destroy();
@@ -3492,6 +4197,13 @@ int unload_module(void)
return 0;
}
+int reload(void)
+{
+ reload_config();
+
+ return 0;
+}
+
int usecount(void)
{
int res;
@@ -3511,102 +4223,7 @@ char *key(void)
return ASTERISK_GPL_KEY;
}
-void chan_misdn_log(int level, int port, char *tmpl, ...)
-{
- if (! ((0 <= port) && (port <= max_ports))) {
- ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
- return;
- }
-
- va_list ap;
- char buf[1024];
-
- va_start(ap, tmpl);
- vsnprintf( buf, 1023, tmpl, ap );
- va_end(ap);
-
- if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
- ast_console_puts(buf);
- }
-
- if (level <= misdn_debug[0] && tracing) {
- time_t tm = time(NULL);
- char *tmp=ctime(&tm),*p;
- char file[BUFFERSIZE];
- misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
- FILE *fp= fopen(file, "a+");
-
- p=strchr(tmp,'\n');
- if (p) *p=':';
-
- if (!fp) {
- ast_console_puts("Error opening Tracefile: ");
- ast_console_puts(strerror(errno));
- ast_console_puts("\n");
- return ;
- }
-
- fputs(tmp,fp);
- fputs(" ", fp);
- fputs(buf, fp);
-
- fclose(fp);
- }
-}
-
-
-void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
-{
- va_list ap;
- char buf[1024];
- char name[1024];
-
- int trace;
- misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
- if (!trace) return ;
-
- if (misdn_debug[0] < debug) return ;
-
- char tracedir[BUFFERSIZE];
- misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
- sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
-
- va_start(ap, tmpl);
-
- vsprintf( buf, tmpl, ap );
-
- va_end(ap);
-
- time_t tm = time(NULL);
- char *tmp=ctime(&tm),*p;
- FILE *fp= fopen(name, "a");
- int fd;
-
- if (!fp) {
- ast_console_puts("Error opening Tracefile");
- ast_console_puts(strerror(errno));
- ast_console_puts("\n");
- return ;
- }
-
- fd=fileno(fp) ;
-
- flock(fd, LOCK_EX);
-
- p=strchr(tmp,'\n');
- if (p) *p=':';
-
-
-
- fputs(tmp,fp);
- fputs(" ", fp);
- fputs(buf, fp);
- flock(fd, LOCK_UN);
-
- fclose(fp);
-
-}
/*** SOME APPS ;)***/
@@ -3615,9 +4232,10 @@ static int misdn_facility_exec(struct ast_channel *chan, void *data)
{
struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
char *tok, *tokb;
-
- if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
+ chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
+
+ if (strcasecmp(chan->tech->type,"mISDN")) {
ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
return -1;
}
@@ -3659,8 +4277,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
int keyidx=0;
int rxgain=0;
int txgain=0;
-
- if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
+ int change_jitter=0;
+
+ if (strcasecmp(chan->tech->type,"mISDN")) {
ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
return -1;
}
@@ -3683,7 +4302,7 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
switch(tok[0]) {
case 'd' :
- strncpy(ch->bc->display,++tok,84);
+ ast_copy_string(ch->bc->display,++tok,84);
chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
break;
@@ -3693,8 +4312,32 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
break;
case 'j':
- chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
- ch->bc->nojitter=1;
+ chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
+ tok++;
+ change_jitter=1;
+
+ switch ( tok[0] ) {
+ case 'b' :
+ ch->jb_len=atoi(++tok);
+ chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
+ break;
+ case 't' :
+ ch->jb_upper_threshold=atoi(++tok);
+ chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
+ break;
+
+ case 'n':
+ ch->bc->nojitter=1;
+ chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
+ break;
+
+ default:
+ ch->jb_len=4000;
+ ch->jb_upper_threshold=0;
+ chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
+ chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
+ }
+
break;
case 'v':
@@ -3727,10 +4370,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
}
{
- int l = sizeof(ch->bc->crypt_key);
- strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
- ch->bc->crypt_key[l-1] = 0;
+ ast_copy_string(ch->bc->crypt_key, misdn_key_vector[keyidx], sizeof(ch->bc->crypt_key));
}
+
chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
break;
@@ -3738,7 +4380,9 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
if (neglect) {
+ chan_misdn_log(1, ch->bc->port, " --> disabled\n");
ch->bc->ec_enable=0;
+
} else {
ch->bc->ec_enable=1;
ch->bc->orig=ch->orginator;
@@ -3752,18 +4396,12 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
case 'h':
chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
+
if (strlen(tok) > 1 && tok[1]=='1') {
- chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
- ch->bc->async=1;
- ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
- /*ch->bc->state=STATE_CONNECTED;
- misdn_lib_setup_bc(ch->bc);*/
- } else {
- ch->bc->async=0;
- ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
- /*ch->bc->state=STATE_CONNECTED;
- misdn_lib_setup_bc(ch->bc);*/
- }
+ chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
+ ch->bc->hdlc=1;
+ }
+ ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
break;
case 's':
@@ -3798,6 +4436,10 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
break;
}
}
+
+ if (change_jitter)
+ config_jitterbuffer(ch);
+
if (ch->faxdetect || ch->ast_dsp) {
@@ -3816,3 +4458,246 @@ static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
}
+int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
+{
+ struct chan_list *ch=find_chan_by_bc(cl_te, bc);
+
+ if (ch && ch->jb) {
+ return misdn_jb_empty(ch->jb, buf, len);
+ }
+
+ return -1;
+}
+
+
+
+/*******************************************************/
+/***************** JITTERBUFFER ************************/
+/*******************************************************/
+
+
+/* allocates the jb-structure and initialise the elements*/
+struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
+{
+ int i;
+ struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
+ jb->size = size;
+ jb->upper_threshold = upper_threshold;
+ jb->wp = 0;
+ jb->rp = 0;
+ jb->state_full = 0;
+ jb->state_empty = 0;
+ jb->bytes_wrote = 0;
+ jb->samples = (char *)malloc(size*sizeof(char));
+
+ if (!jb->samples) {
+ chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
+ return NULL;
+ }
+
+ jb->ok = (char *)malloc(size*sizeof(char));
+
+ if (!jb->ok) {
+ chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
+ return NULL;
+ }
+
+ for(i=0; i<size; i++)
+ jb->ok[i]=0;
+
+ ast_mutex_init(&jb->mutexjb);
+
+ return jb;
+}
+
+/* frees the data and destroys the given jitterbuffer struct */
+void misdn_jb_destroy(struct misdn_jb *jb)
+{
+ ast_mutex_destroy(&jb->mutexjb);
+
+ free(jb->samples);
+ free(jb);
+}
+
+/* fills the jitterbuffer with len data returns < 0 if there was an
+ error (bufferoverflow). */
+int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
+{
+ int i, j, rp, wp;
+
+ if (!jb || ! data) return 0;
+
+ ast_mutex_lock (&jb->mutexjb);
+
+ wp=jb->wp;
+ rp=jb->rp;
+
+ for(i=0; i<len; i++)
+ {
+ jb->samples[wp]=data[i];
+ jb->ok[wp]=1;
+ wp = (wp!=jb->size-1 ? wp+1 : 0);
+
+ if(wp==jb->rp)
+ jb->state_full=1;
+ }
+
+ if(wp>=rp)
+ jb->state_buffer=wp-rp;
+ else
+ jb->state_buffer= jb->size-rp+wp;
+ chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
+
+ if(jb->state_full)
+ {
+ jb->wp=wp;
+
+ rp=wp;
+ for(j=0; j<jb->upper_threshold; j++)
+ rp = (rp!=0 ? rp-1 : jb->size-1);
+ jb->rp=rp;
+ jb->state_full=0;
+ jb->state_empty=1;
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return -1;
+ }
+
+ if(!jb->state_empty)
+ {
+ jb->bytes_wrote+=len;
+ if(jb->bytes_wrote>=jb->upper_threshold)
+ {
+ jb->state_empty=1;
+ jb->bytes_wrote=0;
+ }
+ }
+ jb->wp=wp;
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return 0;
+}
+
+/* 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_empty(struct misdn_jb *jb, char *data, int len)
+{
+ int i, wp, rp, read=0;
+
+ ast_mutex_lock (&jb->mutexjb);
+
+ rp=jb->rp;
+ wp=jb->wp;
+
+ if(jb->state_empty)
+ {
+ for(i=0; i<len; i++)
+ {
+ if(wp==rp)
+ {
+ jb->rp=rp;
+ jb->state_empty=0;
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return read;
+ }
+ else
+ {
+ if(jb->ok[rp]==1)
+ {
+ data[i]=jb->samples[rp];
+ jb->ok[rp]=0;
+ rp=(rp!=jb->size-1 ? rp+1 : 0);
+ read+=1;
+ }
+ }
+ }
+
+ if(wp >= rp)
+ jb->state_buffer=wp-rp;
+ else
+ jb->state_buffer= jb->size-rp+wp;
+ chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
+
+ jb->rp=rp;
+ }
+ else
+ chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
+
+ ast_mutex_unlock (&jb->mutexjb);
+
+ return read;
+}
+
+
+
+
+/*******************************************************/
+/*************** JITTERBUFFER END *********************/
+/*******************************************************/
+
+
+
+
+void chan_misdn_log(int level, int port, char *tmpl, ...)
+{
+ if (! ((0 <= port) && (port <= max_ports))) {
+ ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
+ port=0;
+ level=-1;
+ }
+
+ va_list ap;
+ char buf[1024];
+ char port_buf[8];
+ sprintf(port_buf,"P[%2d] ",port);
+
+ va_start(ap, tmpl);
+ vsnprintf( buf, 1023, tmpl, ap );
+ va_end(ap);
+
+ if (level == -1)
+ ast_log(LOG_WARNING, buf);
+
+ else if (misdn_debug_only[port] ?
+ (level==1 && misdn_debug[port]) || (level==misdn_debug[port])
+ : level <= misdn_debug[port]) {
+
+ ast_console_puts(port_buf);
+ ast_console_puts(buf);
+ }
+
+ if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
+ time_t tm = time(NULL);
+ char *tmp=ctime(&tm),*p;
+
+ FILE *fp= fopen(global_tracefile, "a+");
+
+ p=strchr(tmp,'\n');
+ if (p) *p=':';
+
+ if (!fp) {
+ ast_console_puts("Error opening Tracefile: [ ");
+ ast_console_puts(global_tracefile);
+ ast_console_puts(" ] ");
+
+ ast_console_puts(strerror(errno));
+ ast_console_puts("\n");
+ return ;
+ }
+
+ fputs(tmp,fp);
+ fputs(" ", fp);
+ fputs(port_buf,fp);
+ fputs(" ", fp);
+ fputs(buf, fp);
+
+ fclose(fp);
+ }
+}
+
+