Creating tag for the release of asterisk-1.4.22-rc5
[asterisk-bristuff.git] / channels / chan_misdn.c
blobb304cf6e29736565c02223b06aec191737a9fab3
1 /*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2004 - 2006, Christian Richter
6 * Christian Richter <crich@beronet.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
20 /*!
21 * \file
23 * \brief the chan_misdn channel driver for Asterisk
24 * \author Christian Richter <crich@beronet.com>
26 * \ingroup channel_drivers
29 /*** MODULEINFO
30 <depend>isdnnet</depend>
31 <depend>misdn</depend>
32 <depend>suppserv</depend>
33 ***/
34 #include "asterisk.h"
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
38 #include <stdio.h>
39 #include <pthread.h>
40 #include <string.h>
41 #include <sys/socket.h>
42 #include <sys/time.h>
43 #include <errno.h>
44 #include <unistd.h>
45 #include <stdlib.h>
46 #include <arpa/inet.h>
47 #include <fcntl.h>
48 #include <sys/ioctl.h>
49 #include <signal.h>
50 #include <sys/file.h>
51 #include <semaphore.h>
53 #include "asterisk/channel.h"
54 #include "asterisk/config.h"
55 #include "asterisk/logger.h"
56 #include "asterisk/module.h"
57 #include "asterisk/pbx.h"
58 #include "asterisk/options.h"
59 #include "asterisk/io.h"
60 #include "asterisk/frame.h"
61 #include "asterisk/translate.h"
62 #include "asterisk/cli.h"
63 #include "asterisk/musiconhold.h"
64 #include "asterisk/dsp.h"
65 #include "asterisk/translate.h"
66 #include "asterisk/config.h"
67 #include "asterisk/file.h"
68 #include "asterisk/callerid.h"
69 #include "asterisk/indications.h"
70 #include "asterisk/app.h"
71 #include "asterisk/features.h"
72 #include "asterisk/term.h"
73 #include "asterisk/sched.h"
74 #include "asterisk/stringfields.h"
76 #include "chan_misdn_config.h"
77 #include "isdn_lib.h"
79 char global_tracefile[BUFFERSIZE+1];
81 static int g_config_initialized=0;
83 struct misdn_jb{
84 int size;
85 int upper_threshold;
86 char *samples, *ok;
87 int wp,rp;
88 int state_empty;
89 int state_full;
90 int state_buffer;
91 int bytes_wrote;
92 ast_mutex_t mutexjb;
97 /* allocates the jb-structure and initialize the elements*/
98 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
100 /* frees the data and destroys the given jitterbuffer struct */
101 void misdn_jb_destroy(struct misdn_jb *jb);
103 /* fills the jitterbuffer with len data returns < 0 if there was an
104 error (buffer overrun). */
105 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
107 /* gets len bytes out of the jitterbuffer if available, else only the
108 available data is returned and the return value indicates the number
109 of data. */
110 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
113 /* BEGIN: chan_misdn.h */
115 ast_mutex_t release_lock;
117 enum misdn_chan_state {
118 MISDN_NOTHING=0, /*!< at beginning */
119 MISDN_WAITING4DIGS, /*!< when waiting for infos */
120 MISDN_EXTCANTMATCH, /*!< when asterisk couldn't match our ext */
121 MISDN_INCOMING_SETUP, /*!< for incoming setups*/
122 MISDN_DIALING, /*!< when pbx_start */
123 MISDN_PROGRESS, /*!< we got a progress */
124 MISDN_PROCEEDING, /*!< we got a progress */
125 MISDN_CALLING, /*!< when misdn_call is called */
126 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
127 MISDN_ALERTING, /*!< when Alerting */
128 MISDN_BUSY, /*!< when BUSY */
129 MISDN_CONNECTED, /*!< when connected */
130 MISDN_PRECONNECTED, /*!< when connected */
131 MISDN_DISCONNECTED, /*!< when connected */
132 MISDN_RELEASED, /*!< when connected */
133 MISDN_BRIDGED, /*!< when bridged */
134 MISDN_CLEANING, /*!< when hangup from * but we were connected before */
135 MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */
136 MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
137 /* misdn_hangup */
138 MISDN_HOLDED, /*!< if this chan is holded */
139 MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
143 #define ORG_AST 1
144 #define ORG_MISDN 2
146 struct hold_info {
147 int port;
148 int channel;
151 struct chan_list {
153 char allowed_bearers[BUFFERSIZE+1];
155 enum misdn_chan_state state;
156 int need_queue_hangup;
157 int need_hangup;
158 int need_busy;
160 int noautorespond_on_setup;
162 int originator;
164 int norxtone;
165 int notxtone;
167 int toggle_ec;
169 int incoming_early_audio;
171 int ignore_dtmf;
173 int pipe[2];
174 char ast_rd_buf[4096];
175 struct ast_frame frame;
177 int faxdetect; /* 0:no 1:yes 2:yes+nojump */
178 int faxdetect_timeout;
179 struct timeval faxdetect_tv;
180 int faxhandled;
182 int ast_dsp;
184 int jb_len;
185 int jb_upper_threshold;
186 struct misdn_jb *jb;
188 struct ast_dsp *dsp;
189 struct ast_trans_pvt *trans;
191 struct ast_channel * ast;
193 int dummy;
195 struct misdn_bchannel *bc;
197 struct hold_info hold_info;
199 unsigned int l3id;
200 int addr;
202 char context[BUFFERSIZE];
204 int zero_read_cnt;
205 int dropped_frame_cnt;
207 int far_alerting;
209 int nttimeout;
211 int other_pid;
212 struct chan_list *other_ch;
214 const struct ind_tone_zone_sound *ts;
216 int overlap_dial;
217 int overlap_dial_task;
218 ast_mutex_t overlap_tv_lock;
219 struct timeval overlap_tv;
221 struct chan_list *peer;
222 struct chan_list *next;
223 struct chan_list *prev;
224 struct chan_list *first;
229 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
230 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
232 struct robin_list {
233 char *group;
234 int port;
235 int channel;
236 struct robin_list *next;
237 struct robin_list *prev;
239 static struct robin_list *robin = NULL;
243 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
247 static inline void free_robin_list_r (struct robin_list *r)
249 if (r) {
250 if (r->next) free_robin_list_r(r->next);
251 if (r->group) free(r->group);
252 free(r);
256 static void free_robin_list ( void )
258 free_robin_list_r(robin);
259 robin = NULL;
262 static struct robin_list* get_robin_position (char *group)
264 struct robin_list *new;
265 struct robin_list *iter = robin;
266 for (; iter; iter = iter->next) {
267 if (!strcasecmp(iter->group, group))
268 return iter;
270 new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
271 new->group = strndup(group, strlen(group));
272 new->port = 0;
273 new->channel = 0;
274 if (robin) {
275 new->next = robin;
276 robin->prev = new;
278 robin = new;
279 return robin;
283 /* the main schedule context for stuff like l1 watcher, overlap dial, ... */
284 static struct sched_context *misdn_tasks = NULL;
285 static pthread_t misdn_tasks_thread;
287 static int *misdn_ports;
289 static void chan_misdn_log(int level, int port, char *tmpl, ...);
291 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
292 static void send_digit_to_chan(struct chan_list *cl, char digit );
294 static void hangup_chan(struct chan_list *ch);
295 static int pbx_start_chan(struct chan_list *ch);
297 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
298 #define MISDN_ASTERISK_PVT(ast) 1
300 #include <asterisk/strings.h>
302 /* #define MISDN_DEBUG 1 */
304 static const char misdn_type[] = "mISDN";
306 static int tracing = 0 ;
308 /* Only alaw and mulaw is allowed for now */
309 static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
311 static int *misdn_debug;
312 static int *misdn_debug_only;
313 static int max_ports;
315 static int *misdn_in_calls;
316 static int *misdn_out_calls;
319 struct chan_list dummy_cl;
321 struct chan_list *cl_te=NULL;
322 ast_mutex_t cl_te_lock;
324 static enum event_response_e
325 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
327 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
329 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
330 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
331 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
332 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
336 static int dialtone_indicate(struct chan_list *cl);
337 static int hanguptone_indicate(struct chan_list *cl);
338 static int stop_indicate(struct chan_list *cl);
340 static int start_bc_tones(struct chan_list *cl);
341 static int stop_bc_tones(struct chan_list *cl);
342 static void release_chan(struct misdn_bchannel *bc);
344 static int misdn_check_l2l1(struct ast_channel *chan, void *data);
345 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
346 static int misdn_facility_exec(struct ast_channel *chan, void *data);
348 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
351 void debug_numplan(int port, int numplan, char *type);
354 int add_out_calls(int port);
355 int add_in_calls(int port);
358 #ifdef MISDN_1_2
359 static int update_pipeline_config(struct misdn_bchannel *bc);
360 #else
361 static int update_ec_config(struct misdn_bchannel *bc);
362 #endif
366 /*************** Helpers *****************/
368 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
370 struct chan_list *tmp;
372 for (tmp=cl_te; tmp; tmp = tmp->next) {
373 if ( tmp->ast == ast ) return tmp;
376 return NULL;
379 static struct chan_list * get_chan_by_ast_name(char *name)
381 struct chan_list *tmp;
383 for (tmp=cl_te; tmp; tmp = tmp->next) {
384 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp;
387 return NULL;
392 struct allowed_bearers {
393 int cap;
394 int val;
395 char *name;
396 int deprecated;
399 static struct allowed_bearers allowed_bearers_array[]= {
400 {INFO_CAPABILITY_SPEECH,1,"speech"},
401 {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
402 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
403 {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restricted"},
404 {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced", 1}, /* Allow misspelling for backwards compatibility */
405 {INFO_CAPABILITY_VIDEO,16,"video"}
408 static char *bearer2str(int cap) {
409 static char *bearers[]={
410 "Speech",
411 "Audio 3.1k",
412 "Unres Digital",
413 "Res Digital",
414 "Video",
415 "Unknown Bearer"
418 switch (cap) {
419 case INFO_CAPABILITY_SPEECH:
420 return bearers[0];
421 break;
422 case INFO_CAPABILITY_AUDIO_3_1K:
423 return bearers[1];
424 break;
425 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
426 return bearers[2];
427 break;
428 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
429 return bearers[3];
430 break;
431 case INFO_CAPABILITY_VIDEO:
432 return bearers[4];
433 break;
434 default:
435 return bearers[5];
436 break;
441 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
443 switch (fac->Function) {
444 case Fac_CD:
445 chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
446 fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
447 break;
448 case Fac_AOCDCurrency:
449 if (fac->u.AOCDcur.chargeNotAvailable)
450 chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
451 else if (fac->u.AOCDcur.freeOfCharge)
452 chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
453 else if (fac->u.AOCDchu.billingId >= 0)
454 chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n",
455 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
456 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
457 else
458 chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n",
459 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
460 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
461 break;
462 case Fac_AOCDChargingUnit:
463 if (fac->u.AOCDchu.chargeNotAvailable)
464 chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
465 else if (fac->u.AOCDchu.freeOfCharge)
466 chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
467 else if (fac->u.AOCDchu.billingId >= 0)
468 chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
469 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
470 else
471 chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
472 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
473 break;
474 default:
475 chan_misdn_log(1,bc->port," --> unknown\n");
479 static void print_bearer(struct misdn_bchannel *bc)
482 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
484 switch(bc->law) {
485 case INFO_CODEC_ALAW:
486 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
487 break;
488 case INFO_CODEC_ULAW:
489 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
490 break;
494 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
496 char buf[128];
498 if (!ast)
499 return;
501 if (originator == ORG_AST) {
502 ast = ast_bridged_channel(ast);
503 if (!ast)
504 return;
507 switch (bc->AOCDtype) {
508 case Fac_AOCDCurrency:
509 pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
510 if (bc->AOCD.currency.chargeNotAvailable)
511 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
512 else {
513 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
514 if (bc->AOCD.currency.freeOfCharge)
515 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
516 else {
517 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
518 if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
519 pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
520 if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
521 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
525 break;
526 case Fac_AOCDChargingUnit:
527 pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
528 if (bc->AOCD.chargingUnit.chargeNotAvailable)
529 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
530 else {
531 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
532 if (bc->AOCD.chargingUnit.freeOfCharge)
533 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
534 else {
535 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
536 if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
537 pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
538 if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
539 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
543 break;
544 default:
545 break;
549 /*************** Helpers END *************/
551 static void sighandler(int sig)
554 static void* misdn_tasks_thread_func (void *data)
556 int wait;
557 struct sigaction sa;
559 sa.sa_handler = sighandler;
560 sa.sa_flags = SA_NODEFER;
561 sigemptyset(&sa.sa_mask);
562 sigaddset(&sa.sa_mask, SIGUSR1);
563 sigaction(SIGUSR1, &sa, NULL);
565 sem_post((sem_t *)data);
567 while (1) {
568 wait = ast_sched_wait(misdn_tasks);
569 if (wait < 0)
570 wait = 8000;
571 if (poll(NULL, 0, wait) < 0)
572 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
573 ast_sched_runq(misdn_tasks);
575 return NULL;
578 static void misdn_tasks_init (void)
580 sem_t blocker;
581 int i = 5;
583 if (sem_init(&blocker, 0, 0)) {
584 perror("chan_misdn: Failed to initialize semaphore!");
585 exit(1);
588 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
590 misdn_tasks = sched_context_create();
591 pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
593 while (sem_wait(&blocker) && --i);
594 sem_destroy(&blocker);
597 static void misdn_tasks_destroy (void)
599 if (misdn_tasks) {
600 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
601 if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
602 cb_log(4, 0, "Joining misdn_tasks thread\n");
603 pthread_join(misdn_tasks_thread, NULL);
605 sched_context_destroy(misdn_tasks);
609 static inline void misdn_tasks_wakeup (void)
611 pthread_kill(misdn_tasks_thread, SIGUSR1);
614 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
616 int task_id;
618 if (!misdn_tasks) {
619 misdn_tasks_init();
621 task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
622 misdn_tasks_wakeup();
624 return task_id;
627 static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data)
629 return _misdn_tasks_add_variable(timeout, callback, data, 0);
632 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data)
634 return _misdn_tasks_add_variable(timeout, callback, data, 1);
637 static void misdn_tasks_remove (int task_id)
639 AST_SCHED_DEL(misdn_tasks, task_id);
642 static int misdn_l1_task (const void *data)
644 misdn_lib_isdn_l1watcher(*(int *)data);
645 chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
646 return 1;
649 static int misdn_overlap_dial_task (const void *data)
651 struct timeval tv_end, tv_now;
652 int diff;
653 struct chan_list *ch = (struct chan_list *)data;
655 chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
657 if (ch->state != MISDN_WAITING4DIGS) {
658 ch->overlap_dial_task = -1;
659 return 0;
662 ast_mutex_lock(&ch->overlap_tv_lock);
663 tv_end = ch->overlap_tv;
664 ast_mutex_unlock(&ch->overlap_tv_lock);
666 tv_end.tv_sec += ch->overlap_dial;
667 tv_now = ast_tvnow();
669 diff = ast_tvdiff_ms(tv_end, tv_now);
671 if (diff <= 100) {
672 char *dad=ch->bc->dad, sexten[]="s";
673 /* if we are 100ms near the timeout, we are satisfied.. */
674 stop_indicate(ch);
676 if (ast_strlen_zero(ch->bc->dad)) {
677 dad=sexten;
678 strcpy(ch->ast->exten, sexten);
681 if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
682 ch->state=MISDN_DIALING;
683 if (pbx_start_chan(ch) < 0) {
684 chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
685 goto misdn_overlap_dial_task_disconnect;
687 } else {
688 misdn_overlap_dial_task_disconnect:
689 hanguptone_indicate(ch);
690 ch->bc->out_cause=1;
691 ch->state=MISDN_CLEANING;
692 misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
694 ch->overlap_dial_task = -1;
695 return 0;
696 } else
697 return diff;
700 static void send_digit_to_chan(struct chan_list *cl, char digit )
702 static const char* dtmf_tones[] = {
703 "!941+1336/100,!0/100", /* 0 */
704 "!697+1209/100,!0/100", /* 1 */
705 "!697+1336/100,!0/100", /* 2 */
706 "!697+1477/100,!0/100", /* 3 */
707 "!770+1209/100,!0/100", /* 4 */
708 "!770+1336/100,!0/100", /* 5 */
709 "!770+1477/100,!0/100", /* 6 */
710 "!852+1209/100,!0/100", /* 7 */
711 "!852+1336/100,!0/100", /* 8 */
712 "!852+1477/100,!0/100", /* 9 */
713 "!697+1633/100,!0/100", /* A */
714 "!770+1633/100,!0/100", /* B */
715 "!852+1633/100,!0/100", /* C */
716 "!941+1633/100,!0/100", /* D */
717 "!941+1209/100,!0/100", /* * */
718 "!941+1477/100,!0/100" }; /* # */
719 struct ast_channel *chan=cl->ast;
721 if (digit >= '0' && digit <='9')
722 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
723 else if (digit >= 'A' && digit <= 'D')
724 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
725 else if (digit == '*')
726 ast_playtones_start(chan,0,dtmf_tones[14], 0);
727 else if (digit == '#')
728 ast_playtones_start(chan,0,dtmf_tones[15], 0);
729 else {
730 /* not handled */
731 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
736 /*** CLI HANDLING ***/
737 static int misdn_set_debug(int fd, int argc, char *argv[])
739 int level;
741 if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
742 return RESULT_SHOWUSAGE;
744 level = atoi(argv[3]);
746 switch (argc) {
747 case 4:
748 case 5: {
749 int i;
750 int only = 0;
751 if (argc == 5) {
752 if (strncasecmp(argv[4], "only", strlen(argv[4])))
753 return RESULT_SHOWUSAGE;
754 else
755 only = 1;
757 for (i=0; i<=max_ports; i++) {
758 misdn_debug[i] = level;
759 misdn_debug_only[i] = only;
761 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
763 break;
764 case 6:
765 case 7: {
766 int port;
767 if (strncasecmp(argv[4], "port", strlen(argv[4])))
768 return RESULT_SHOWUSAGE;
769 port = atoi(argv[5]);
770 if (port <= 0 || port > max_ports) {
771 switch (max_ports) {
772 case 0:
773 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
774 break;
775 case 1:
776 ast_cli(fd, "port number not valid! only port 1 is available.\n");
777 break;
778 default:
779 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
781 return 0;
783 if (argc == 7) {
784 if (strncasecmp(argv[6], "only", strlen(argv[6])))
785 return RESULT_SHOWUSAGE;
786 else
787 misdn_debug_only[port] = 1;
788 } else
789 misdn_debug_only[port] = 0;
790 misdn_debug[port] = level;
791 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
794 return 0;
797 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
799 if (argc != 5) return RESULT_SHOWUSAGE;
801 return 0;
804 static int misdn_port_block(int fd, int argc, char *argv[])
806 int port;
808 if (argc != 4)
809 return RESULT_SHOWUSAGE;
811 port = atoi(argv[3]);
813 misdn_lib_port_block(port);
815 return 0;
818 static int misdn_port_unblock(int fd, int argc, char *argv[])
820 int port;
822 if (argc != 4)
823 return RESULT_SHOWUSAGE;
825 port = atoi(argv[3]);
827 misdn_lib_port_unblock(port);
829 return 0;
833 static int misdn_restart_port (int fd, int argc, char *argv[])
835 int port;
837 if (argc != 4)
838 return RESULT_SHOWUSAGE;
840 port = atoi(argv[3]);
842 misdn_lib_port_restart(port);
844 return 0;
847 static int misdn_restart_pid (int fd, int argc, char *argv[])
849 int pid;
851 if (argc != 4)
852 return RESULT_SHOWUSAGE;
854 pid = atoi(argv[3]);
856 misdn_lib_pid_restart(pid);
858 return 0;
861 static int misdn_port_up (int fd, int argc, char *argv[])
863 int port;
865 if (argc != 4)
866 return RESULT_SHOWUSAGE;
868 port = atoi(argv[3]);
870 misdn_lib_get_port_up(port);
872 return 0;
875 static int misdn_port_down (int fd, int argc, char *argv[])
877 int port;
879 if (argc != 4)
880 return RESULT_SHOWUSAGE;
882 port = atoi(argv[3]);
884 misdn_lib_get_port_down(port);
886 return 0;
889 static inline void show_config_description (int fd, enum misdn_cfg_elements elem)
891 char section[BUFFERSIZE];
892 char name[BUFFERSIZE];
893 char desc[BUFFERSIZE];
894 char def[BUFFERSIZE];
895 char tmp[BUFFERSIZE];
897 misdn_cfg_get_name(elem, tmp, sizeof(tmp));
898 term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
899 misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
901 if (elem < MISDN_CFG_LAST)
902 term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
903 else
904 term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
906 if (*def)
907 ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
908 else
909 ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
912 static int misdn_show_config (int fd, int argc, char *argv[])
914 char buffer[BUFFERSIZE];
915 enum misdn_cfg_elements elem;
916 int linebreak;
917 int onlyport = -1;
918 int ok = 0;
920 if (argc >= 4) {
921 if (!strcmp(argv[3], "description")) {
922 if (argc == 5) {
923 enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]);
924 if (elem == MISDN_CFG_FIRST)
925 ast_cli(fd, "Unknown element: %s\n", argv[4]);
926 else
927 show_config_description(fd, elem);
928 return 0;
930 return RESULT_SHOWUSAGE;
932 if (!strcmp(argv[3], "descriptions")) {
933 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
934 for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
935 show_config_description(fd, elem);
936 ast_cli(fd, "\n");
938 ok = 1;
940 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
941 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
942 show_config_description(fd, elem);
943 ast_cli(fd, "\n");
945 ok = 1;
947 return ok ? 0 : RESULT_SHOWUSAGE;
949 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
950 ast_cli(fd, "Unknown option: %s\n", argv[3]);
951 return RESULT_SHOWUSAGE;
955 if (argc == 3 || onlyport == 0) {
956 ast_cli(fd,"Misdn General-Config: \n");
957 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
958 misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
959 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
961 ast_cli(fd, "\n");
964 if (onlyport < 0) {
965 int port = misdn_cfg_get_next_port(0);
966 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
967 ast_cli(fd, "\n[PORT %d]\n", port);
968 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
969 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
970 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
972 ast_cli(fd, "\n");
976 if (onlyport > 0) {
977 if (misdn_cfg_is_port_valid(onlyport)) {
978 ast_cli(fd, "[PORT %d]\n", onlyport);
979 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
980 misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
981 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
983 ast_cli(fd, "\n");
984 } else {
985 ast_cli(fd, "Port %d is not active!\n", onlyport);
988 return 0;
991 struct state_struct {
992 enum misdn_chan_state state;
993 char txt[255] ;
996 static struct state_struct state_array[] = {
997 {MISDN_NOTHING,"NOTHING"}, /* at beginning */
998 {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */
999 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldn't match our ext */
1000 {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /* when pbx_start */
1001 {MISDN_DIALING,"DIALING"}, /* when pbx_start */
1002 {MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */
1003 {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */
1004 {MISDN_CALLING,"CALLING"}, /* when misdn_call is called */
1005 {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
1006 {MISDN_ALERTING,"ALERTING"}, /* when Alerting */
1007 {MISDN_BUSY,"BUSY"}, /* when BUSY */
1008 {MISDN_CONNECTED,"CONNECTED"}, /* when connected */
1009 {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */
1010 {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
1011 {MISDN_RELEASED,"RELEASED"}, /* when connected */
1012 {MISDN_BRIDGED,"BRIDGED"}, /* when bridged */
1013 {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
1014 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1015 {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1016 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1017 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
1020 static char *misdn_get_ch_state(struct chan_list *p)
1022 int i;
1023 static char state[8];
1025 if( !p) return NULL;
1027 for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
1028 if ( state_array[i].state == p->state) return state_array[i].txt;
1031 sprintf(state,"%d",p->state) ;
1033 return state;
1038 static void reload_config(void)
1040 int i, cfg_debug;
1042 if (!g_config_initialized) {
1043 ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
1044 return ;
1047 free_robin_list();
1048 misdn_cfg_reload();
1049 misdn_cfg_update_ptp();
1050 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1051 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
1053 for (i = 0; i <= max_ports; i++) {
1054 misdn_debug[i] = cfg_debug;
1055 misdn_debug_only[i] = 0;
1059 static int misdn_reload (int fd, int argc, char *argv[])
1061 ast_cli(fd, "Reloading mISDN Config\n");
1062 reload_config();
1063 return 0;
1066 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
1068 struct ast_channel *ast=help->ast;
1069 ast_cli(fd,
1070 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1072 bc->pid, bc->port, bc->channel,
1073 bc->nt?"NT":"TE",
1074 help->originator == ORG_AST?"*":"I",
1075 ast?ast->exten:NULL,
1076 ast?ast->cid.cid_num:NULL,
1077 bc->rad,
1078 ast?ast->context:NULL,
1079 misdn_get_ch_state(help)
1081 if (misdn_debug[bc->port] > 0)
1082 ast_cli(fd,
1083 " --> astname: %s\n"
1084 " --> ch_l3id: %x\n"
1085 " --> ch_addr: %x\n"
1086 " --> bc_addr: %x\n"
1087 " --> bc_l3id: %x\n"
1088 " --> display: %s\n"
1089 " --> activated: %d\n"
1090 " --> state: %s\n"
1091 " --> capability: %s\n"
1092 #ifdef MISDN_1_2
1093 " --> pipeline: %s\n"
1094 #else
1095 " --> echo_cancel: %d\n"
1096 #endif
1097 " --> notone : rx %d tx:%d\n"
1098 " --> bc_hold: %d\n",
1099 help->ast->name,
1100 help->l3id,
1101 help->addr,
1102 bc->addr,
1103 bc?bc->l3_id:-1,
1104 bc->display,
1106 bc->active,
1107 bc_state2str(bc->bc_state),
1108 bearer2str(bc->capability),
1109 #ifdef MISDN_1_2
1110 bc->pipeline,
1111 #else
1112 bc->ec_enable,
1113 #endif
1115 help->norxtone,help->notxtone,
1116 bc->holded
1121 static int misdn_show_cls (int fd, int argc, char *argv[])
1123 struct chan_list *help=cl_te;
1125 ast_cli(fd,"Chan List: %p\n",cl_te);
1127 for (;help; help=help->next) {
1128 struct misdn_bchannel *bc=help->bc;
1129 struct ast_channel *ast=help->ast;
1130 if (!ast) {
1131 if (!bc) {
1132 ast_cli(fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
1133 continue;
1135 ast_cli(fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
1136 continue;
1138 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
1139 if (bc) {
1140 print_bc_info(fd, help, bc);
1141 } else {
1142 if (help->state == MISDN_HOLDED) {
1143 ast_cli(fd, "ITS A HOLDED BC:\n");
1144 ast_cli(fd, " --> l3_id: %x\n"
1145 " --> dad:%s oad:%s\n"
1146 " --> hold_port: %d\n"
1147 " --> hold_channel: %d\n"
1149 ,help->l3id
1150 ,ast->exten
1151 ,ast->cid.cid_num
1152 ,help->hold_info.port
1153 ,help->hold_info.channel
1155 } else {
1156 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
1161 misdn_dump_chanlist();
1162 return 0;
1165 static int misdn_show_cl (int fd, int argc, char *argv[])
1167 struct chan_list *help=cl_te;
1169 if (argc != 4)
1170 return RESULT_SHOWUSAGE;
1172 for (;help; help=help->next) {
1173 struct misdn_bchannel *bc=help->bc;
1174 struct ast_channel *ast=help->ast;
1176 if (bc && ast) {
1177 if (!strcasecmp(ast->name,argv[3])) {
1178 print_bc_info(fd, help, bc);
1179 break;
1185 return 0;
1188 ast_mutex_t lock;
1189 int MAXTICS=8;
1191 static int misdn_set_tics (int fd, int argc, char *argv[])
1193 if (argc != 4)
1194 return RESULT_SHOWUSAGE;
1196 MAXTICS=atoi(argv[3]);
1198 return 0;
1201 static int misdn_show_stacks (int fd, int argc, char *argv[])
1203 int port;
1205 ast_cli(fd, "BEGIN STACK_LIST:\n");
1207 for (port=misdn_cfg_get_next_port(0); port > 0;
1208 port=misdn_cfg_get_next_port(port)) {
1209 char buf[128];
1210 get_show_stack_details(port,buf);
1211 ast_cli(fd," %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1214 return 0;
1218 static int misdn_show_ports_stats (int fd, int argc, char *argv[])
1220 int port;
1222 ast_cli(fd, "Port\tin_calls\tout_calls\n");
1224 for (port=misdn_cfg_get_next_port(0); port > 0;
1225 port=misdn_cfg_get_next_port(port)) {
1226 ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]);
1228 ast_cli(fd,"\n");
1230 return 0;
1235 static int misdn_show_port (int fd, int argc, char *argv[])
1237 int port;
1238 char buf[128];
1240 if (argc != 4)
1241 return RESULT_SHOWUSAGE;
1243 port = atoi(argv[3]);
1245 ast_cli(fd, "BEGIN STACK_LIST:\n");
1247 get_show_stack_details(port,buf);
1248 ast_cli(fd," %s Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
1251 return 0;
1254 static int misdn_send_cd (int fd, int argc, char *argv[])
1256 char *channame;
1257 char *nr;
1259 if (argc != 5)
1260 return RESULT_SHOWUSAGE;
1262 channame = argv[3];
1263 nr = argv[4];
1265 ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
1268 struct chan_list *tmp=get_chan_by_ast_name(channame);
1270 if (!tmp) {
1271 ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
1272 return 0;
1273 } else {
1274 if (strlen(nr) >= 15) {
1275 ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
1276 return 0;
1278 tmp->bc->fac_out.Function = Fac_CD;
1279 strncpy((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
1280 misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
1284 return 0;
1287 static int misdn_send_restart(int fd, int argc, char *argv[])
1289 int port;
1290 int channel;
1292 if ( (argc < 4) || (argc > 5) )
1293 return RESULT_SHOWUSAGE;
1295 port = atoi(argv[3]);
1297 if (argc==5) {
1298 channel = atoi(argv[4]);
1299 misdn_lib_send_restart(port, channel);
1300 } else
1301 misdn_lib_send_restart(port, -1 );
1303 return 0;
1306 static int misdn_send_digit (int fd, int argc, char *argv[])
1308 char *channame;
1309 char *msg;
1311 if (argc != 5)
1312 return RESULT_SHOWUSAGE;
1314 channame = argv[3];
1315 msg = argv[4];
1317 ast_cli(fd, "Sending %s to %s\n",msg, channame);
1320 struct chan_list *tmp=get_chan_by_ast_name(channame);
1322 if (!tmp) {
1323 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
1324 return 0;
1325 } else {
1326 #if 1
1327 int i;
1328 int msglen = strlen(msg);
1329 for (i=0; i<msglen; i++) {
1330 ast_cli(fd, "Sending: %c\n",msg[i]);
1331 send_digit_to_chan(tmp, msg[i]);
1332 /* res = ast_safe_sleep(tmp->ast, 250); */
1333 usleep(250000);
1334 /* res = ast_waitfor(tmp->ast,100); */
1336 #else
1337 int res;
1338 res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
1339 #endif
1343 return 0;
1346 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
1348 char *channame;
1350 if (argc != 4)
1351 return RESULT_SHOWUSAGE;
1353 channame = argv[3];
1355 ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
1358 struct chan_list *tmp=get_chan_by_ast_name(channame);
1360 if (!tmp) {
1361 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
1362 return 0;
1363 } else {
1365 tmp->toggle_ec=tmp->toggle_ec?0:1;
1367 if (tmp->toggle_ec) {
1368 #ifdef MISDN_1_2
1369 update_pipeline_config(tmp->bc);
1370 #else
1371 update_ec_config(tmp->bc);
1372 #endif
1373 manager_ec_enable(tmp->bc);
1374 } else {
1375 manager_ec_disable(tmp->bc);
1380 return 0;
1383 static int misdn_send_display (int fd, int argc, char *argv[])
1385 char *channame;
1386 char *msg;
1388 if (argc != 5)
1389 return RESULT_SHOWUSAGE;
1391 channame = argv[3];
1392 msg = argv[4];
1394 ast_cli(fd, "Sending %s to %s\n",msg, channame);
1396 struct chan_list *tmp;
1397 tmp=get_chan_by_ast_name(channame);
1399 if (tmp && tmp->bc) {
1400 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
1401 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
1402 } else {
1403 ast_cli(fd,"No such channel %s\n",channame);
1404 return RESULT_FAILURE;
1408 return RESULT_SUCCESS ;
1411 static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
1413 struct ast_channel *c;
1414 int which=0;
1415 char *ret;
1416 if (pos != rpos)
1417 return NULL;
1418 c = ast_channel_walk_locked(NULL);
1419 while(c) {
1420 if (!strncasecmp(word, c->name, strlen(word))) {
1421 if (++which > state)
1422 break;
1424 ast_mutex_unlock(&c->lock);
1425 c = ast_channel_walk_locked(c);
1427 if (c) {
1428 ret = strdup(c->name);
1429 ast_mutex_unlock(&c->lock);
1430 } else
1431 ret = NULL;
1432 return ret;
1435 static char *complete_ch(const char *line, const char *word, int pos, int state)
1437 return complete_ch_helper(line, word, pos, state, 3);
1440 static char *complete_debug_port (const char *line, const char *word, int pos, int state)
1442 if (state)
1443 return NULL;
1445 switch (pos) {
1446 case 4: if (*word == 'p')
1447 return strdup("port");
1448 else if (*word == 'o')
1449 return strdup("only");
1450 break;
1451 case 6: if (*word == 'o')
1452 return strdup("only");
1453 break;
1455 return NULL;
1458 static char *complete_show_config (const char *line, const char *word, int pos, int state)
1460 char buffer[BUFFERSIZE];
1461 enum misdn_cfg_elements elem;
1462 int wordlen = strlen(word);
1463 int which = 0;
1464 int port = 0;
1466 switch (pos) {
1467 case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
1468 return strdup("description");
1469 if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
1470 return strdup("descriptions");
1471 if ((!strncmp(word, "0", wordlen)) && (++which > state))
1472 return strdup("0");
1473 while ((port = misdn_cfg_get_next_port(port)) != -1) {
1474 snprintf(buffer, sizeof(buffer), "%d", port);
1475 if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
1476 return strdup(buffer);
1479 break;
1480 case 4:
1481 if (strstr(line, "description ")) {
1482 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
1483 if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
1484 continue;
1485 misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
1486 if (!wordlen || !strncmp(word, buffer, wordlen)) {
1487 if (++which > state)
1488 return strdup(buffer);
1491 } else if (strstr(line, "descriptions ")) {
1492 if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
1493 return strdup("general");
1494 if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
1495 return strdup("ports");
1497 break;
1499 return NULL;
1502 static struct ast_cli_entry chan_misdn_clis[] = {
1503 { {"misdn","send","calldeflect", NULL}, misdn_send_cd, "Sends CallDeflection to mISDN Channel",
1504 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch },
1505 { {"misdn","send","digit", NULL}, misdn_send_digit, "Sends DTMF Digit to mISDN Channel",
1506 "Usage: misdn send digit <channel> \"<msg>\" \n"
1507 " Send <digit> to <channel> as DTMF Tone\n"
1508 " when channel is a mISDN channel\n", complete_ch },
1509 { {"misdn","toggle","echocancel", NULL}, misdn_toggle_echocancel, "Toggles EchoCancel on mISDN Channel",
1510 "Usage: misdn toggle echocancel <channel>\n", complete_ch },
1511 { {"misdn","send","display", NULL}, misdn_send_display, "Sends Text to mISDN Channel",
1512 "Usage: misdn send display <channel> \"<msg>\" \n"
1513 " Send <msg> to <channel> as Display Message\n"
1514 " when channel is a mISDN channel\n", complete_ch },
1515 { {"misdn","show","config", NULL}, misdn_show_config, "Shows internal mISDN config, read from cfg-file",
1516 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1517 " Use 0 for <port> to only print the general config.\n", complete_show_config },
1518 { {"misdn","reload", NULL}, misdn_reload, "Reloads internal mISDN config, read from cfg-file",
1519 "Usage: misdn reload\n" },
1520 { {"misdn","set","tics", NULL}, misdn_set_tics, "",
1521 "\n" },
1522 { {"misdn","show","channels", NULL}, misdn_show_cls, "Shows internal mISDN chan_list",
1523 "Usage: misdn show channels\n" },
1524 { {"misdn","show","channel", NULL}, misdn_show_cl, "Shows internal mISDN chan_list",
1525 "Usage: misdn show channels\n", complete_ch },
1526 { {"misdn","port","block", NULL}, misdn_port_block, "Blocks the given port",
1527 "Usage: misdn port block\n" },
1528 { {"misdn","port","unblock", NULL}, misdn_port_unblock, "Unblocks the given port",
1529 "Usage: misdn port unblock\n" },
1530 { {"misdn","restart","port", NULL}, misdn_restart_port, "Restarts the given port",
1531 "Usage: misdn restart port\n" },
1532 { {"misdn","restart","pid", NULL}, misdn_restart_pid, "Restarts the given pid",
1533 "Usage: misdn restart pid\n" },
1534 { {"misdn","send","restart", NULL}, misdn_send_restart,
1535 "Sends a restart for every bchannel on the given port",
1536 "Usage: misdn send restart <port>\n"},
1537 { {"misdn","port","up", NULL}, misdn_port_up, "Tries to establish L1 on the given port",
1538 "Usage: misdn port up <port>\n" },
1539 { {"misdn","port","down", NULL}, misdn_port_down, "Tries to deactivate the L1 on the given port",
1540 "Usage: misdn port down <port>\n" },
1541 { {"misdn","show","stacks", NULL}, misdn_show_stacks, "Shows internal mISDN stack_list",
1542 "Usage: misdn show stacks\n" },
1543 { {"misdn","show","ports","stats", NULL}, misdn_show_ports_stats, "Shows chan_misdns call statistics per port",
1544 "Usage: misdn show port stats\n" },
1545 { {"misdn","show","port", NULL}, misdn_show_port, "Shows detailed information for given port",
1546 "Usage: misdn show port <port>\n" },
1547 { {"misdn","set","debug", NULL}, misdn_set_debug, "Sets Debuglevel of chan_misdn",
1548 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port },
1549 { {"misdn","set","crypt","debug", NULL}, misdn_set_crypt_debug, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1550 "Usage: misdn set crypt debug <level>\n" }
1553 static int update_config (struct chan_list *ch, int orig)
1555 struct ast_channel *ast=ch->ast;
1556 struct misdn_bchannel *bc=ch->bc;
1557 int port;
1558 int pres, screen;
1559 int hdlc=0;
1561 if (!ch) {
1562 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1563 return -1;
1566 ast=ch->ast;
1567 bc=ch->bc;
1568 if (! ast || ! bc ) {
1569 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1570 return -1;
1573 port=bc->port;
1575 chan_misdn_log(7,port,"update_config: Getting Config\n");
1577 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1579 if (hdlc) {
1580 switch (bc->capability) {
1581 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1582 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1583 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1584 bc->hdlc=1;
1585 break;
1590 misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
1591 misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
1592 chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
1594 if ( (pres + screen) < 0 ) {
1596 chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
1598 switch (ast->cid.cid_pres & 0x60){
1600 case AST_PRES_RESTRICTED:
1601 bc->pres=1;
1602 chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
1603 break;
1606 case AST_PRES_UNAVAILABLE:
1607 bc->pres=2;
1608 chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
1609 break;
1611 default:
1612 bc->pres=0;
1613 chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
1616 switch (ast->cid.cid_pres & 0x3){
1618 case AST_PRES_USER_NUMBER_UNSCREENED:
1619 bc->screen=0;
1620 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1621 break;
1623 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
1624 bc->screen=1;
1625 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
1626 break;
1627 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
1628 bc->screen=2;
1629 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
1630 break;
1632 case AST_PRES_NETWORK_NUMBER:
1633 bc->screen=3;
1634 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
1635 break;
1637 default:
1638 bc->screen=0;
1639 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1643 } else {
1644 bc->screen=screen;
1645 bc->pres=pres;
1648 return 0;
1655 static void config_jitterbuffer(struct chan_list *ch)
1657 struct misdn_bchannel *bc=ch->bc;
1658 int len=ch->jb_len, threshold=ch->jb_upper_threshold;
1660 chan_misdn_log(5,bc->port, "config_jb: Called\n");
1662 if ( ! len ) {
1663 chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
1664 bc->nojitter=1;
1665 } else {
1667 if (len <=100 || len > 8000) {
1668 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1669 len=1000;
1672 if ( threshold > len ) {
1673 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1676 if ( ch->jb) {
1677 cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
1678 misdn_jb_destroy(ch->jb);
1679 ch->jb=NULL;
1682 ch->jb=misdn_jb_init(len, threshold);
1684 if (!ch->jb )
1685 bc->nojitter=1;
1690 void debug_numplan(int port, int numplan, char *type)
1692 switch (numplan) {
1693 case NUMPLAN_INTERNATIONAL:
1694 chan_misdn_log(2, port, " --> %s: International\n",type);
1695 break;
1696 case NUMPLAN_NATIONAL:
1697 chan_misdn_log(2, port, " --> %s: National\n",type);
1698 break;
1699 case NUMPLAN_SUBSCRIBER:
1700 chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
1701 break;
1702 case NUMPLAN_UNKNOWN:
1703 chan_misdn_log(2, port, " --> %s: Unknown\n",type);
1704 break;
1705 /* Maybe we should cut off the prefix if present ? */
1706 default:
1707 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1708 break;
1715 #ifdef MISDN_1_2
1716 static int update_pipeline_config(struct misdn_bchannel *bc)
1718 int ec;
1720 misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
1722 if (*bc->pipeline)
1723 return 0;
1725 misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1726 if (ec == 1)
1727 snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec");
1728 else if (ec > 1)
1729 snprintf(bc->pipeline, sizeof(bc->pipeline) - 1, "mg2ec(deftaps=%d)", ec);
1731 return 0;
1733 #else
1734 static int update_ec_config(struct misdn_bchannel *bc)
1736 int ec;
1737 int port=bc->port;
1739 misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1741 if (ec == 1 ) {
1742 bc->ec_enable=1;
1743 } else if ( ec > 1 ) {
1744 bc->ec_enable=1;
1745 bc->ec_deftaps=ec;
1748 return 0;
1750 #endif
1753 static int read_config(struct chan_list *ch, int orig)
1755 struct ast_channel *ast;
1756 struct misdn_bchannel *bc;
1757 int port;
1758 char lang[BUFFERSIZE+1];
1759 char localmusicclass[BUFFERSIZE+1];
1760 char faxdetect[BUFFERSIZE+1];
1761 int hdlc = 0;
1763 if (!ch) {
1764 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1765 return -1;
1768 ast=ch->ast;
1769 bc=ch->bc;
1770 if (! ast || ! bc ) {
1771 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1772 return -1;
1775 port=bc->port;
1778 chan_misdn_log(1,port,"read_config: Getting Config\n");
1780 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
1781 ast_string_field_set(ast, language, lang);
1783 misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
1784 ast_string_field_set(ast, musicclass, localmusicclass);
1787 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
1788 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
1790 misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
1792 misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
1794 misdn_cfg_get( port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
1796 if (ch->ast_dsp) {
1797 ch->ignore_dtmf=1;
1800 misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
1801 misdn_cfg_get( port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
1803 misdn_cfg_get( port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
1805 misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
1807 misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
1809 misdn_cfg_get( port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
1811 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1813 if (hdlc) {
1814 switch (bc->capability) {
1815 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1816 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1817 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1818 bc->hdlc=1;
1819 break;
1823 /*Initialize new Jitterbuffer*/
1825 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
1826 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
1828 config_jitterbuffer(ch);
1831 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
1833 ast_copy_string (ast->context,ch->context,sizeof(ast->context));
1835 #ifdef MISDN_1_2
1836 update_pipeline_config(bc);
1837 #else
1838 update_ec_config(bc);
1839 #endif
1842 int eb3;
1844 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
1845 bc->early_bconnect=eb3;
1848 port=bc->port;
1851 char buf[256];
1852 ast_group_t pg,cg;
1854 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
1855 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
1857 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
1858 ast->pickupgroup=pg;
1859 ast->callgroup=cg;
1862 if ( orig == ORG_AST) {
1863 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
1865 if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
1866 if (strstr(faxdetect, "nojump"))
1867 ch->faxdetect=2;
1868 else
1869 ch->faxdetect=1;
1873 char callerid[BUFFERSIZE+1];
1874 misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1875 if ( ! ast_strlen_zero(callerid) ) {
1876 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1878 int l = sizeof(bc->oad);
1879 strncpy(bc->oad,callerid, l);
1880 bc->oad[l-1] = 0;
1886 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
1887 misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
1888 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1889 debug_numplan(port, bc->dnumplan,"TON");
1890 debug_numplan(port, bc->onumplan,"LTON");
1891 debug_numplan(port, bc->cpnnumplan,"CTON");
1894 ch->overlap_dial = 0;
1895 } else { /** ORIGINATOR MISDN **/
1896 char prefix[BUFFERSIZE+1]="";
1897 if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
1898 if (strstr(faxdetect, "nojump"))
1899 ch->faxdetect=2;
1900 else
1901 ch->faxdetect=1;
1904 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1905 debug_numplan(port, bc->cpnnumplan,"CTON");
1907 switch( bc->onumplan ) {
1908 case NUMPLAN_INTERNATIONAL:
1909 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1910 break;
1912 case NUMPLAN_NATIONAL:
1913 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1914 break;
1915 default:
1916 break;
1920 int l = strlen(prefix) + strlen(bc->oad);
1921 char *tmp = alloca(l+1);
1922 strcpy(tmp,prefix);
1923 strcat(tmp,bc->oad);
1924 strcpy(bc->oad,tmp);
1927 if (!ast_strlen_zero(bc->dad)) {
1928 ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
1931 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
1932 ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
1935 prefix[0] = 0;
1937 switch( bc->dnumplan ) {
1938 case NUMPLAN_INTERNATIONAL:
1939 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1940 break;
1941 case NUMPLAN_NATIONAL:
1942 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1943 break;
1944 default:
1945 break;
1949 int l = strlen(prefix) + strlen(bc->dad);
1950 char *tmp = alloca(l+1);
1951 strcpy(tmp,prefix);
1952 strcat(tmp,bc->dad);
1953 strcpy(bc->dad,tmp);
1956 if ( strcmp(bc->dad,ast->exten)) {
1957 ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
1960 ast_set_callerid(ast, bc->oad, NULL, bc->oad);
1962 if ( !ast_strlen_zero(bc->rad) ) {
1963 if (ast->cid.cid_rdnis)
1964 free(ast->cid.cid_rdnis);
1965 ast->cid.cid_rdnis = strdup(bc->rad);
1968 misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
1969 ast_mutex_init(&ch->overlap_tv_lock);
1970 } /* ORIG MISDN END */
1972 ch->overlap_dial_task = -1;
1974 if (ch->faxdetect || ch->ast_dsp) {
1975 misdn_cfg_get( port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
1976 if (!ch->dsp)
1977 ch->dsp = ast_dsp_new();
1978 if (ch->dsp) {
1979 if (ch->faxdetect)
1980 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
1981 else
1982 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT );
1984 if (!ch->trans)
1985 ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
1988 /* AOCD initialization */
1989 bc->AOCDtype = Fac_None;
1991 return 0;
1995 /*****************************/
1996 /*** AST Indications Start ***/
1997 /*****************************/
1999 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
2001 int port=0;
2002 int r;
2003 int exceed;
2004 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
2005 struct misdn_bchannel *newbc;
2006 char *opts=NULL, *ext;
2009 ext = ast_strdupa(dest);
2010 strsep(&ext,"/");
2011 if (ext) {
2012 opts=ext;
2013 strsep(&opts,"/");
2014 } else {
2015 ast_log(LOG_WARNING, "Malformed dialstring\n");
2016 return -1;
2020 if (!ast) {
2021 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
2022 return -1;
2025 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) {
2026 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
2027 ast->hangupcause=41;
2028 ast_setstate(ast, AST_STATE_DOWN);
2029 return -1;
2032 if (!ch) {
2033 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
2034 ast->hangupcause=41;
2035 ast_setstate(ast, AST_STATE_DOWN);
2036 return -1;
2039 newbc=ch->bc;
2041 if (!newbc) {
2042 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
2043 ast->hangupcause=41;
2044 ast_setstate(ast, AST_STATE_DOWN);
2045 return -1;
2048 port=newbc->port;
2050 if ((exceed=add_out_calls(port))) {
2051 char tmp[16];
2052 sprintf(tmp,"%d",exceed);
2053 pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
2054 return -1;
2057 chan_misdn_log(1, port, "* CALL: %s\n",dest);
2059 chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
2061 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
2062 if (ast->exten) {
2063 int l = sizeof(newbc->dad);
2064 strncpy(ast->exten,ext,sizeof(ast->exten));
2066 strncpy(newbc->dad,ext,l);
2068 newbc->dad[l-1] = 0;
2071 if (ast->cid.cid_rdnis)
2072 strcpy(newbc->rad, ast->cid.cid_rdnis);
2073 else
2074 newbc->rad[0]=0;
2076 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",ast->cid.cid_num);
2077 if (ast_strlen_zero(newbc->oad) && ast->cid.cid_num ) {
2079 if (ast->cid.cid_num) {
2080 int l = sizeof(newbc->oad);
2081 strncpy(newbc->oad,ast->cid.cid_num, l);
2082 newbc->oad[l-1] = 0;
2087 int bridging;
2088 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
2089 if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
2091 newbc->capability=ast->transfercapability;
2092 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
2093 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
2094 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
2098 /* update screening and presentation */
2099 update_config(ch,ORG_AST);
2101 /* fill in some ies from channel vary*/
2102 import_ch(ast, newbc, ch);
2104 /* Finally The Options Override Everything */
2105 if (opts)
2106 misdn_set_opt_exec(ast,opts);
2107 else
2108 chan_misdn_log(2,port,"NO OPTS GIVEN\n");
2110 /*check for bridging*/
2111 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2112 if (bridging && ch->other_ch) {
2113 #ifdef MISDN_1_2
2114 chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
2115 *ch->bc->pipeline=0;
2116 *ch->other_ch->bc->pipeline=0;
2117 #else
2118 chan_misdn_log(1, port, "Disabling EC on both Sides\n");
2119 ch->bc->ec_enable=0;
2120 ch->other_ch->bc->ec_enable=0;
2121 #endif
2124 r=misdn_lib_send_event( newbc, EVENT_SETUP );
2126 /** we should have l3id after sending setup **/
2127 ch->l3id=newbc->l3_id;
2130 if ( r == -ENOCHAN ) {
2131 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
2132 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
2133 ast->hangupcause=34;
2134 ast_setstate(ast, AST_STATE_DOWN);
2135 return -1;
2138 chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
2140 ast_setstate(ast, AST_STATE_DIALING);
2141 ast->hangupcause=16;
2143 if (newbc->nt) stop_bc_tones(ch);
2145 ch->state=MISDN_CALLING;
2147 return 0;
2151 static int misdn_answer(struct ast_channel *ast)
2153 struct chan_list *p;
2156 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2158 chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
2160 if (!p) {
2161 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
2162 ast_queue_hangup(ast);
2165 if (!p->bc) {
2166 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
2168 ast_queue_hangup(ast);
2172 const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
2174 if (tmp_key ) {
2175 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
2177 int l = sizeof(p->bc->crypt_key);
2178 strncpy(p->bc->crypt_key,tmp_key, l);
2179 p->bc->crypt_key[l-1] = 0;
2181 } else {
2182 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
2188 const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
2189 if (nodsp) {
2190 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
2191 p->bc->nodsp=1;
2192 p->bc->hdlc=0;
2193 p->bc->nojitter=1;
2197 p->state = MISDN_CONNECTED;
2198 stop_indicate(p);
2200 if ( ast_strlen_zero(p->bc->cad) ) {
2201 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
2202 ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
2205 misdn_lib_send_event( p->bc, EVENT_CONNECT);
2206 start_bc_tones(p);
2208 return 0;
2211 static int misdn_digit_begin(struct ast_channel *chan, char digit)
2213 /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
2214 return 0;
2217 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
2219 struct chan_list *p;
2220 struct misdn_bchannel *bc;
2222 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
2224 bc=p->bc;
2225 chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
2227 if (!bc) {
2228 ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
2229 return -1;
2232 switch (p->state ) {
2233 case MISDN_CALLING:
2235 int l;
2236 char buf[8];
2237 buf[0]=digit;
2238 buf[1]=0;
2240 l = sizeof(bc->infos_pending);
2241 strncat(bc->infos_pending, buf, l - strlen(bc->infos_pending) - 1);
2243 break;
2244 case MISDN_CALLING_ACKNOWLEDGE:
2246 bc->info_dad[0]=digit;
2247 bc->info_dad[1]=0;
2250 int l = sizeof(bc->dad);
2251 strncat(bc->dad, bc->info_dad, l - strlen(bc->dad) - 1);
2254 int l = sizeof(p->ast->exten);
2255 strncpy(p->ast->exten, bc->dad, l);
2256 p->ast->exten[l-1] = 0;
2259 misdn_lib_send_event( bc, EVENT_INFORMATION);
2261 break;
2263 default:
2264 /* Do not send Digits in CONNECTED State, when
2265 * the other side is too mISDN. */
2266 if (p->other_ch )
2267 return 0;
2269 if ( bc->send_dtmf )
2270 send_digit_to_chan(p,digit);
2271 break;
2274 return 0;
2278 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
2280 struct chan_list *p;
2282 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
2284 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);
2286 p->ast = ast ;
2288 return 0;
2293 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
2295 struct chan_list *p;
2298 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
2299 ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
2300 return -1;
2303 if (!p->bc ) {
2304 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
2305 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
2306 return -1;
2309 chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
2311 switch (cond) {
2312 case AST_CONTROL_BUSY:
2313 chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1);
2314 ast_setstate(ast,AST_STATE_BUSY);
2316 p->bc->out_cause=17;
2317 if (p->state != MISDN_CONNECTED) {
2318 start_bc_tones(p);
2319 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2320 } else {
2321 chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
2323 return -1;
2324 break;
2325 case AST_CONTROL_RING:
2326 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
2327 return -1;
2328 break;
2330 case AST_CONTROL_RINGING:
2331 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2332 switch (p->state) {
2333 case MISDN_ALERTING:
2334 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n",p->bc?p->bc->pid:-1);
2335 break;
2336 case MISDN_CONNECTED:
2337 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
2338 return -1;
2339 break;
2340 default:
2341 p->state=MISDN_ALERTING;
2342 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
2343 misdn_lib_send_event( p->bc, EVENT_ALERTING);
2345 if (p->other_ch && p->other_ch->bc) {
2346 if (misdn_inband_avail(p->other_ch->bc)) {
2347 chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n");
2348 break;
2351 if (!p->other_ch->bc->nt) {
2352 chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2353 break;
2357 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
2358 ast_setstate(ast,AST_STATE_RINGING);
2360 if ( !p->bc->nt && (p->originator==ORG_MISDN) && !p->incoming_early_audio )
2361 chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n");
2362 else
2363 return -1;
2365 break;
2366 case AST_CONTROL_ANSWER:
2367 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
2368 start_bc_tones(p);
2369 break;
2370 case AST_CONTROL_TAKEOFFHOOK:
2371 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
2372 return -1;
2373 break;
2374 case AST_CONTROL_OFFHOOK:
2375 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
2376 return -1;
2377 break;
2378 case AST_CONTROL_FLASH:
2379 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
2380 break;
2381 case AST_CONTROL_PROGRESS:
2382 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
2383 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
2384 break;
2385 case AST_CONTROL_PROCEEDING:
2386 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
2387 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
2388 break;
2389 case AST_CONTROL_CONGESTION:
2390 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
2392 p->bc->out_cause=42;
2393 start_bc_tones(p);
2394 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2396 if (p->bc->nt) {
2397 hanguptone_indicate(p);
2399 break;
2400 case -1 :
2401 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
2403 stop_indicate(p);
2405 if (p->state == MISDN_CONNECTED)
2406 start_bc_tones(p);
2408 break;
2410 case AST_CONTROL_HOLD:
2411 ast_moh_start(ast,data,ast->musicclass);
2412 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2413 break;
2414 case AST_CONTROL_UNHOLD:
2415 ast_moh_stop(ast);
2416 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2417 break;
2418 default:
2419 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
2422 return 0;
2425 static int misdn_hangup(struct ast_channel *ast)
2427 struct chan_list *p;
2428 struct misdn_bchannel *bc=NULL;
2430 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
2432 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
2434 if (!p) {
2435 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2436 return 0 ;
2439 bc=p->bc;
2441 if (bc) {
2442 const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
2443 if (tmp) {
2444 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
2445 strcpy(bc->uu, tmp);
2446 bc->uulen=strlen(bc->uu);
2450 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2451 p->ast=NULL;
2453 if (ast->_state == AST_STATE_RESERVED ||
2454 p->state == MISDN_NOTHING ||
2455 p->state == MISDN_HOLDED ||
2456 p->state == MISDN_HOLD_DISCONNECT ) {
2458 CLEAN_CH:
2459 /* between request and call */
2460 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
2461 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2463 ast_mutex_lock(&release_lock);
2464 cl_dequeue_chan(&cl_te, p);
2465 close(p->pipe[0]);
2466 close(p->pipe[1]);
2467 free(p);
2468 ast_mutex_unlock(&release_lock);
2470 if (bc)
2471 misdn_lib_release(bc);
2473 return 0;
2476 if (!bc) {
2477 ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
2478 goto CLEAN_CH;
2482 p->need_hangup=0;
2483 p->need_queue_hangup=0;
2484 p->need_busy=0;
2487 if (!p->bc->nt)
2488 stop_bc_tones(p);
2492 const char *varcause=NULL;
2493 bc->out_cause=ast->hangupcause?ast->hangupcause:16;
2495 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
2496 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
2497 int tmpcause=atoi(varcause);
2498 bc->out_cause=tmpcause?tmpcause:16;
2501 chan_misdn_log(1, bc->port, "* IND : HANGUP\tpid:%d ctx:%s dad:%s oad:%s State:%s\n",p->bc?p->bc->pid:-1, ast->context, ast->exten, ast->cid.cid_num, misdn_get_ch_state(p));
2502 chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
2503 chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
2504 chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
2505 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
2507 switch (p->state) {
2508 case MISDN_CALLING:
2509 case MISDN_INCOMING_SETUP:
2510 /* This is the only place in misdn_hangup, where we
2511 * can call release_chan, else it might create lot's of trouble
2512 * */
2513 ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
2514 release_chan(bc);
2516 p->state=MISDN_CLEANING;
2517 if (bc->need_release_complete)
2518 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
2519 break;
2520 case MISDN_HOLDED:
2521 case MISDN_DIALING:
2522 start_bc_tones(p);
2523 hanguptone_indicate(p);
2525 if (bc->need_disconnect)
2526 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2527 break;
2529 case MISDN_CALLING_ACKNOWLEDGE:
2530 start_bc_tones(p);
2531 hanguptone_indicate(p);
2533 if (bc->need_disconnect)
2534 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2535 break;
2537 case MISDN_ALERTING:
2538 case MISDN_PROGRESS:
2539 case MISDN_PROCEEDING:
2540 if (p->originator != ORG_AST)
2541 hanguptone_indicate(p);
2543 /*p->state=MISDN_CLEANING;*/
2544 if (bc->need_disconnect)
2545 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2546 break;
2547 case MISDN_CONNECTED:
2548 case MISDN_PRECONNECTED:
2549 /* Alerting or Disconnect */
2550 if (p->bc->nt) {
2551 start_bc_tones(p);
2552 hanguptone_indicate(p);
2553 p->bc->progress_indicator=8;
2555 if (bc->need_disconnect)
2556 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2558 /*p->state=MISDN_CLEANING;*/
2559 break;
2560 case MISDN_DISCONNECTED:
2561 if (bc->need_release)
2562 misdn_lib_send_event( bc, EVENT_RELEASE);
2563 p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
2564 break;
2566 case MISDN_RELEASED:
2567 case MISDN_CLEANING:
2568 p->state=MISDN_CLEANING;
2569 break;
2571 case MISDN_BUSY:
2572 break;
2574 case MISDN_HOLD_DISCONNECT:
2575 /* need to send release here */
2576 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
2577 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
2579 bc->out_cause=-1;
2580 if (bc->need_release)
2581 misdn_lib_send_event(bc,EVENT_RELEASE);
2582 p->state=MISDN_CLEANING;
2583 break;
2584 default:
2585 if (bc->nt) {
2586 bc->out_cause=-1;
2587 if (bc->need_release)
2588 misdn_lib_send_event(bc, EVENT_RELEASE);
2589 p->state=MISDN_CLEANING;
2590 } else {
2591 if (bc->need_disconnect)
2592 misdn_lib_send_event(bc, EVENT_DISCONNECT);
2596 p->state=MISDN_CLEANING;
2601 chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
2603 return 0;
2607 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
2609 struct ast_frame *f,*f2;
2611 if (tmp->trans) {
2612 f2 = ast_translate(tmp->trans, frame, 0);
2613 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2614 } else {
2615 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2616 return NULL;
2620 if (!f || (f->frametype != AST_FRAME_DTMF))
2621 return frame;
2623 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
2625 if (tmp->faxdetect && (f->subclass == 'f')) {
2626 /* Fax tone -- Handle and return NULL */
2627 if (!tmp->faxhandled) {
2628 struct ast_channel *ast = tmp->ast;
2629 tmp->faxhandled++;
2630 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
2631 tmp->bc->rxgain = 0;
2632 isdn_lib_update_rxgain(tmp->bc);
2633 tmp->bc->txgain = 0;
2634 isdn_lib_update_txgain(tmp->bc);
2635 #ifdef MISDN_1_2
2636 *tmp->bc->pipeline = 0;
2637 #else
2638 tmp->bc->ec_enable = 0;
2639 #endif
2640 isdn_lib_update_ec(tmp->bc);
2641 isdn_lib_stop_dtmf(tmp->bc);
2642 switch (tmp->faxdetect) {
2643 case 1:
2644 if (strcmp(ast->exten, "fax")) {
2645 char *context;
2646 char context_tmp[BUFFERSIZE];
2647 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
2648 context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
2649 if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
2650 if (option_verbose > 2)
2651 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
2652 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2653 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2654 if (ast_async_goto(ast, context, "fax", 1))
2655 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
2656 } else
2657 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
2658 } else
2659 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2660 break;
2661 case 2:
2662 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
2663 break;
2665 } else
2666 ast_log(LOG_DEBUG, "Fax already handled\n");
2669 if (tmp->ast_dsp && (f->subclass != 'f')) {
2670 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
2673 return f;
2677 static struct ast_frame *misdn_read(struct ast_channel *ast)
2679 struct chan_list *tmp;
2680 fd_set rrfs;
2681 struct timeval tv;
2682 int len, t;
2684 if (!ast) {
2685 chan_misdn_log(1,0,"misdn_read called without ast\n");
2686 return NULL;
2688 if (!(tmp=MISDN_ASTERISK_TECH_PVT(ast))) {
2689 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
2690 return NULL;
2693 if (!tmp->bc && !(tmp->state==MISDN_HOLDED)) {
2694 chan_misdn_log(1,0,"misdn_read called without bc\n");
2695 return NULL;
2698 tv.tv_sec=0;
2699 tv.tv_usec=20000;
2701 FD_ZERO(&rrfs);
2702 FD_SET(tmp->pipe[0],&rrfs);
2704 t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
2706 if (!t) {
2707 chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
2708 len=160;
2711 if (t<0) {
2712 chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
2713 return NULL;
2716 if (FD_ISSET(tmp->pipe[0],&rrfs)) {
2717 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
2719 if (len<=0) {
2720 /* we hangup here, since our pipe is closed */
2721 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
2722 return NULL;
2725 } else {
2726 return NULL;
2729 tmp->frame.frametype = AST_FRAME_VOICE;
2730 tmp->frame.subclass = AST_FORMAT_ALAW;
2731 tmp->frame.datalen = len;
2732 tmp->frame.samples = len;
2733 tmp->frame.mallocd = 0;
2734 tmp->frame.offset = 0;
2735 tmp->frame.delivery= ast_tv(0,0) ;
2736 tmp->frame.src = NULL;
2737 tmp->frame.data = tmp->ast_rd_buf;
2739 if (tmp->faxdetect && !tmp->faxhandled) {
2740 if (tmp->faxdetect_timeout) {
2741 if (ast_tvzero(tmp->faxdetect_tv)) {
2742 tmp->faxdetect_tv = ast_tvnow();
2743 chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
2744 return process_ast_dsp(tmp, &tmp->frame);
2745 } else {
2746 struct timeval tv_now = ast_tvnow();
2747 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
2748 if (diff <= (tmp->faxdetect_timeout * 1000)) {
2749 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n");
2750 return process_ast_dsp(tmp, &tmp->frame);
2751 } else {
2752 chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n");
2753 tmp->faxdetect = 0;
2754 return &tmp->frame;
2757 } else {
2758 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n");
2759 return process_ast_dsp(tmp, &tmp->frame);
2761 } else {
2762 if (tmp->ast_dsp)
2763 return process_ast_dsp(tmp, &tmp->frame);
2764 else
2765 return &tmp->frame;
2770 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
2772 struct chan_list *ch;
2773 int i = 0;
2775 if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2777 if (ch->state == MISDN_HOLDED) {
2778 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2779 return 0;
2782 if (!ch->bc ) {
2783 ast_log(LOG_WARNING, "private but no bc\n");
2784 return -1;
2787 if (ch->notxtone) {
2788 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
2789 return 0;
2793 if ( !frame->subclass) {
2794 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
2795 return 0;
2798 if ( !(frame->subclass & prefformat)) {
2800 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
2801 return 0;
2805 if ( !frame->samples ) {
2806 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
2808 if (!strcmp(frame->src,"ast_prod")) {
2809 chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
2811 if (ch->ts) {
2812 chan_misdn_log(4,ch->bc->port,"Starting Playtones\n");
2813 misdn_lib_tone_generator_start(ch->bc);
2815 return 0;
2818 return -1;
2821 if ( ! ch->bc->addr ) {
2822 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
2823 return 0;
2826 #if MISDN_DEBUG
2828 int i, max=5>frame->samples?frame->samples:5;
2830 printf("write2mISDN %p %d bytes: ", p, frame->samples);
2832 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
2833 printf ("\n");
2835 #endif
2838 switch (ch->bc->bc_state) {
2839 case BCHAN_ACTIVATED:
2840 case BCHAN_BRIDGED:
2841 break;
2842 default:
2843 if (!ch->dropped_frame_cnt)
2844 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
2846 ch->dropped_frame_cnt++;
2847 if (ch->dropped_frame_cnt > 100) {
2848 ch->dropped_frame_cnt=0;
2849 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n",frame->samples,ch->bc->addr);
2853 return 0;
2856 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
2857 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
2858 /* Buffered Transmit (triggered by read from isdn side)*/
2859 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
2860 if (ch->bc->active)
2861 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
2864 } else {
2865 /*transmit without jitterbuffer*/
2866 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
2871 return 0;
2877 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
2878 struct ast_channel *c1, int flags,
2879 struct ast_frame **fo,
2880 struct ast_channel **rc,
2881 int timeoutms)
2884 struct chan_list *ch1,*ch2;
2885 struct ast_channel *carr[2], *who;
2886 int to=-1;
2887 struct ast_frame *f;
2888 int p1_b, p2_b;
2889 int bridging;
2891 ch1=get_chan_by_ast(c0);
2892 ch2=get_chan_by_ast(c1);
2894 carr[0]=c0;
2895 carr[1]=c1;
2897 if (ch1 && ch2 ) ;
2898 else
2899 return -1;
2901 misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(int));
2902 misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(int));
2904 if ( ! p1_b || ! p2_b) {
2905 ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
2906 return AST_BRIDGE_FAILED;
2909 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2910 if (bridging) {
2911 /* trying to make a mISDN_dsp conference */
2912 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
2913 misdn_lib_bridge(ch1->bc,ch2->bc);
2916 if (option_verbose > 2)
2917 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
2919 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
2921 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
2922 ch1->ignore_dtmf=1;
2924 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
2925 ch2->ignore_dtmf=1;
2927 while(1) {
2928 to=-1;
2929 who = ast_waitfor_n(carr, 2, &to);
2931 if (!who) {
2932 ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
2933 break;
2935 f = ast_read(who);
2937 if (!f || f->frametype == AST_FRAME_CONTROL) {
2938 /* got hangup .. */
2940 if (!f)
2941 chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
2942 else
2943 chan_misdn_log(4,ch1->bc->port,"Read Frame Control class:%d\n",f->subclass);
2945 *fo=f;
2946 *rc=who;
2948 break;
2951 if ( f->frametype == AST_FRAME_DTMF ) {
2952 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
2954 *fo=f;
2955 *rc=who;
2956 break;
2959 #if 0
2960 if (f->frametype == AST_FRAME_VOICE) {
2961 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2963 continue;
2965 #endif
2967 if (who == c0) {
2968 ast_write(c1,f);
2970 else {
2971 ast_write(c0,f);
2976 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2978 misdn_lib_split_bridge(ch1->bc,ch2->bc);
2981 return AST_BRIDGE_COMPLETE;
2984 /** AST INDICATIONS END **/
2986 static int dialtone_indicate(struct chan_list *cl)
2988 const struct ind_tone_zone_sound *ts= NULL;
2989 struct ast_channel *ast=cl->ast;
2990 int nd=0;
2992 if (!ast) {
2993 chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
2994 return -1;
2997 misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
2999 if (nd) {
3000 chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
3001 return 0;
3004 chan_misdn_log(3,cl->bc->port," --> Dial\n");
3005 ts=ast_get_indication_tone(ast->zone,"dial");
3006 cl->ts=ts;
3008 if (ts) {
3009 cl->notxtone=0;
3010 cl->norxtone=0;
3011 /* This prods us in misdn_write */
3012 ast_playtones_start(ast,0, ts->data, 0);
3015 return 0;
3018 static int hanguptone_indicate(struct chan_list *cl)
3020 misdn_lib_send_tone(cl->bc,TONE_HANGUP);
3021 return 0;
3024 static int stop_indicate(struct chan_list *cl)
3026 struct ast_channel *ast=cl->ast;
3028 if (!ast) {
3029 chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
3030 return -1;
3033 chan_misdn_log(3,cl->bc->port," --> None\n");
3034 misdn_lib_tone_generator_stop(cl->bc);
3035 ast_playtones_stop(ast);
3037 cl->ts=NULL;
3038 /*ast_deactivate_generator(ast);*/
3040 return 0;
3044 static int start_bc_tones(struct chan_list* cl)
3046 misdn_lib_tone_generator_stop(cl->bc);
3047 cl->notxtone=0;
3048 cl->norxtone=0;
3049 return 0;
3052 static int stop_bc_tones(struct chan_list *cl)
3054 if (!cl) return -1;
3056 cl->notxtone=1;
3057 cl->norxtone=1;
3059 return 0;
3063 static struct chan_list *init_chan_list(int orig)
3065 struct chan_list *cl=malloc(sizeof(struct chan_list));
3067 if (!cl) {
3068 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
3069 return NULL;
3072 memset(cl,0,sizeof(struct chan_list));
3074 cl->originator=orig;
3075 cl->need_queue_hangup=1;
3076 cl->need_hangup=1;
3077 cl->need_busy=1;
3078 cl->overlap_dial_task=-1;
3080 return cl;
3084 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
3087 struct ast_channel *tmp = NULL;
3088 char group[BUFFERSIZE+1]="";
3089 char buf[128];
3090 char buf2[128], *ext=NULL, *port_str;
3091 char *tokb=NULL, *p=NULL;
3092 int channel=0, port=0;
3093 struct misdn_bchannel *newbc = NULL;
3094 int dec=0;
3096 struct chan_list *cl=init_chan_list(ORG_AST);
3098 sprintf(buf,"%s/%s",misdn_type,(char*)data);
3099 ast_copy_string(buf2,data, 128);
3101 port_str=strtok_r(buf2,"/", &tokb);
3103 ext=strtok_r(NULL,"/", &tokb);
3105 if (port_str) {
3106 if (port_str[0]=='g' && port_str[1]==':' ) {
3107 /* We make a group call lets checkout which ports are in my group */
3108 port_str += 2;
3109 strncpy(group, port_str, BUFFERSIZE);
3110 group[127] = 0;
3111 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
3113 else if ((p = strchr(port_str, ':'))) {
3114 /* we have a preselected channel */
3115 *p = 0;
3116 channel = atoi(++p);
3117 port = atoi(port_str);
3118 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
3120 else {
3121 port = atoi(port_str);
3123 } else {
3124 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
3125 return NULL;
3128 if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
3129 chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
3130 dec=1;
3133 if (!ast_strlen_zero(group)) {
3135 char cfg_group[BUFFERSIZE+1];
3136 struct robin_list *rr = NULL;
3138 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
3139 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
3140 rr = get_robin_position(group);
3143 if (rr) {
3144 int port_start = 0;
3145 int port_bak = rr->port;
3146 int chan_bak = rr->channel;
3148 if (!rr->port)
3149 rr->port = misdn_cfg_get_next_port_spin(rr->port);
3151 for (; rr->port > 0; rr->port = misdn_cfg_get_next_port_spin(rr->port)) {
3152 int port_up;
3153 int check;
3154 int max_chan;
3155 int last_chance = 0;
3157 misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
3158 if (strcasecmp(cfg_group, group))
3159 continue;
3161 misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
3162 port_up = misdn_lib_port_up(rr->port, check);
3164 if (check && !port_up)
3165 chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
3167 if (check && port_up < 0)
3168 ast_log(LOG_WARNING,"This port (%d) is blocked\n", rr->port);
3170 if ((port_start == rr->port) && (port_up <= 0))
3171 break;
3173 if (!port_start)
3174 port_start = rr->port;
3176 if (port_up <= 0)
3177 continue;
3179 max_chan = misdn_lib_get_maxchans(rr->port);
3181 for (++rr->channel; !last_chance && rr->channel <= max_chan; ++rr->channel) {
3182 if (rr->port == port_bak && rr->channel == chan_bak)
3183 last_chance = 1;
3185 chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr->port, rr->channel);
3186 newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0);
3187 if (newbc) {
3188 chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
3189 if (port_up)
3190 chan_misdn_log(4, rr->port, "portup:%d\n", port_up);
3191 port = rr->port;
3192 break;
3196 if (newbc || last_chance)
3197 break;
3199 rr->channel = 0;
3201 if (!newbc) {
3202 rr->port = port_bak;
3203 rr->channel = chan_bak;
3205 } else {
3206 for (port=misdn_cfg_get_next_port(0); port > 0;
3207 port=misdn_cfg_get_next_port(port)) {
3209 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
3211 chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
3212 if (!strcasecmp(cfg_group, group)) {
3213 int port_up;
3214 int check;
3215 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
3216 port_up = misdn_lib_port_up(port, check);
3218 chan_misdn_log(4, port, "portup:%d\n", port_up);
3220 if ( port_up>0 ) {
3221 newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
3222 if (newbc)
3223 break;
3229 /* Group dial failed ?*/
3230 if (!newbc) {
3231 ast_log(LOG_WARNING,
3232 "Could not Dial out on group '%s'.\n"
3233 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
3234 "\tOr there was no free channel on none of the ports\n\n"
3235 , group);
3236 return NULL;
3238 } else { /* 'Normal' Port dial * Port dial */
3239 if (channel)
3240 chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
3241 newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
3243 if (!newbc) {
3244 ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n",port,ext);
3245 return NULL;
3250 /* create ast_channel and link all the objects together */
3251 cl->bc=newbc;
3253 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
3254 if (!tmp) {
3255 ast_log(LOG_ERROR,"Could not create Asterisk object\n");
3256 return NULL;
3259 cl->ast=tmp;
3261 /* register chan in local list */
3262 cl_queue_chan(&cl_te, cl) ;
3264 /* fill in the config into the objects */
3265 read_config(cl, ORG_AST);
3267 /* important */
3268 cl->need_hangup=0;
3270 return tmp;
3274 static int misdn_send_text (struct ast_channel *chan, const char *text)
3276 struct chan_list *tmp=chan->tech_pvt;
3278 if (tmp && tmp->bc) {
3279 ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
3280 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
3281 } else {
3282 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
3283 return -1;
3286 return 0;
3289 static struct ast_channel_tech misdn_tech = {
3290 .type="mISDN",
3291 .description="Channel driver for mISDN Support (Bri/Pri)",
3292 .capabilities= AST_FORMAT_ALAW ,
3293 .requester=misdn_request,
3294 .send_digit_begin=misdn_digit_begin,
3295 .send_digit_end=misdn_digit_end,
3296 .call=misdn_call,
3297 .bridge=misdn_bridge,
3298 .hangup=misdn_hangup,
3299 .answer=misdn_answer,
3300 .read=misdn_read,
3301 .write=misdn_write,
3302 .indicate=misdn_indication,
3303 .fixup=misdn_fixup,
3304 .send_text=misdn_send_text,
3305 .properties=0
3308 static struct ast_channel_tech misdn_tech_wo_bridge = {
3309 .type="mISDN",
3310 .description="Channel driver for mISDN Support (Bri/Pri)",
3311 .capabilities=AST_FORMAT_ALAW ,
3312 .requester=misdn_request,
3313 .send_digit_begin=misdn_digit_begin,
3314 .send_digit_end=misdn_digit_end,
3315 .call=misdn_call,
3316 .hangup=misdn_hangup,
3317 .answer=misdn_answer,
3318 .read=misdn_read,
3319 .write=misdn_write,
3320 .indicate=misdn_indication,
3321 .fixup=misdn_fixup,
3322 .send_text=misdn_send_text,
3323 .properties=0
3327 static int glob_channel=0;
3329 static void update_name(struct ast_channel *tmp, int port, int c)
3331 int chan_offset=0;
3332 int tmp_port = misdn_cfg_get_next_port(0);
3333 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
3334 if (tmp_port == port) break;
3335 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;
3337 if (c<0) c=0;
3339 ast_string_field_build(tmp, name, "%s/%d-u%d",
3340 misdn_type, chan_offset+c, glob_channel++);
3342 chan_misdn_log(3,port," --> updating channel name to [%s]\n",tmp->name);
3346 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
3348 struct ast_channel *tmp;
3349 char *cid_name = 0, *cid_num = 0;
3350 int chan_offset=0;
3351 int tmp_port = misdn_cfg_get_next_port(0);
3353 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
3354 if (tmp_port == port) break;
3355 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;
3357 if (c<0) c=0;
3360 if (callerid)
3361 ast_callerid_parse(callerid, &cid_name, &cid_num);
3363 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
3365 if (tmp) {
3366 int bridging;
3367 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
3369 tmp->nativeformats = prefformat;
3371 tmp->readformat = format;
3372 tmp->rawreadformat = format;
3373 tmp->writeformat = format;
3374 tmp->rawwriteformat = format;
3376 tmp->tech_pvt = chlist;
3378 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
3380 if (bridging)
3381 tmp->tech = &misdn_tech;
3382 else
3383 tmp->tech = &misdn_tech_wo_bridge;
3385 tmp->writeformat = format;
3386 tmp->readformat = format;
3387 tmp->priority=1;
3389 if (exten)
3390 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
3391 else
3392 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
3394 if (callerid)
3395 /* Don't use ast_set_callerid() here because it will
3396 * generate a needless NewCallerID event */
3397 tmp->cid.cid_ani = ast_strdup(cid_num);
3400 if (pipe(chlist->pipe)<0)
3401 perror("Pipe failed\n");
3403 tmp->fds[0]=chlist->pipe[0];
3407 if (state == AST_STATE_RING)
3408 tmp->rings = 1;
3409 else
3410 tmp->rings = 0;
3413 } else {
3414 chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
3417 return tmp;
3420 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
3422 struct chan_list *help=list;
3423 for (;help; help=help->next) {
3424 if (help->bc == bc) return help;
3427 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
3429 return NULL;
3432 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
3434 struct chan_list *help=list;
3435 for (;help; help=help->next) {
3436 if ( help->bc && (help->bc->pid == pid) ) return help;
3439 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
3441 return NULL;
3444 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
3446 struct chan_list *help=list;
3448 if (bc->pri) return NULL;
3450 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
3451 for (;help; help=help->next) {
3452 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel);
3453 if ( (help->state == MISDN_HOLDED) &&
3454 (help->hold_info.port == bc->port) )
3455 return help;
3457 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
3459 return NULL;
3463 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
3466 struct chan_list *help=list;
3468 for (;help; help=help->next) {
3469 if ( (help->state == MISDN_HOLDED) &&
3470 (help->l3id == l3_id)
3472 return help;
3475 return NULL;
3478 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
3480 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
3482 ast_mutex_lock(&cl_te_lock);
3483 if (!*list) {
3484 *list = chan;
3485 } else {
3486 struct chan_list *help=*list;
3487 for (;help->next; help=help->next);
3488 help->next=chan;
3490 chan->next=NULL;
3491 ast_mutex_unlock(&cl_te_lock);
3494 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
3496 if (chan->dsp)
3497 ast_dsp_free(chan->dsp);
3498 if (chan->trans)
3499 ast_translator_free_path(chan->trans);
3503 ast_mutex_lock(&cl_te_lock);
3504 if (!*list) {
3505 ast_mutex_unlock(&cl_te_lock);
3506 return;
3509 if (*list == chan) {
3510 *list=(*list)->next;
3511 ast_mutex_unlock(&cl_te_lock);
3512 return ;
3516 struct chan_list *help=*list;
3517 for (;help->next; help=help->next) {
3518 if (help->next == chan) {
3519 help->next=help->next->next;
3520 ast_mutex_unlock(&cl_te_lock);
3521 return;
3526 ast_mutex_unlock(&cl_te_lock);
3529 /** Channel Queue End **/
3532 static int pbx_start_chan(struct chan_list *ch)
3534 int ret=ast_pbx_start(ch->ast);
3536 if (ret>=0)
3537 ch->need_hangup=0;
3538 else
3539 ch->need_hangup=1;
3541 return ret;
3544 static void hangup_chan(struct chan_list *ch)
3546 int port=ch?ch->bc?ch->bc->port:0:0;
3547 if (!ch) {
3548 cb_log(1,0,"Cannot hangup chan, no ch\n");
3549 return;
3552 cb_log(5,port,"hangup_chan called\n");
3554 if (ch->need_hangup)
3556 cb_log(2,port," --> hangup\n");
3557 send_cause2ast(ch->ast,ch->bc,ch);
3558 ch->need_hangup=0;
3559 ch->need_queue_hangup=0;
3560 if (ch->ast)
3561 ast_hangup(ch->ast);
3562 return;
3565 if (!ch->need_queue_hangup) {
3566 cb_log(2,port," --> No need to queue hangup\n");
3569 ch->need_queue_hangup=0;
3570 if (ch->ast) {
3571 send_cause2ast(ch->ast,ch->bc,ch);
3573 if (ch->ast)
3574 ast_queue_hangup(ch->ast);
3575 cb_log(2,port," --> queue_hangup\n");
3576 } else {
3577 cb_log(1,port,"Cannot hangup chan, no ast\n");
3581 /** Isdn asks us to release channel, pendant to misdn_hangup **/
3582 static void release_chan(struct misdn_bchannel *bc) {
3583 struct ast_channel *ast=NULL;
3585 ast_mutex_lock(&release_lock);
3587 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
3588 if (!ch) {
3589 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
3590 ast_mutex_unlock(&release_lock);
3591 return;
3594 if (ch->ast) {
3595 ast=ch->ast;
3598 chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
3600 /*releasing jitterbuffer*/
3601 if (ch->jb ) {
3602 misdn_jb_destroy(ch->jb);
3603 ch->jb=NULL;
3604 } else {
3605 if (!bc->nojitter)
3606 chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
3609 if (ch->overlap_dial) {
3610 if (ch->overlap_dial_task != -1) {
3611 misdn_tasks_remove(ch->overlap_dial_task);
3612 ch->overlap_dial_task = -1;
3614 ast_mutex_destroy(&ch->overlap_tv_lock);
3617 if (ch->originator == ORG_AST) {
3618 misdn_out_calls[bc->port]--;
3619 } else {
3620 misdn_in_calls[bc->port]--;
3623 if (ch) {
3625 close(ch->pipe[0]);
3626 close(ch->pipe[1]);
3629 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
3630 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.cid_num,misdn_get_ch_state(ch));
3631 chan_misdn_log(3, bc->port, " --> * State Down\n");
3632 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
3635 if (ast->_state != AST_STATE_RESERVED) {
3636 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
3637 ast_setstate(ast, AST_STATE_DOWN);
3641 ch->state=MISDN_CLEANING;
3642 cl_dequeue_chan(&cl_te, ch);
3644 free(ch);
3645 } else {
3646 /* chan is already cleaned, so exiting */
3650 ast_mutex_unlock(&release_lock);
3652 /*** release end **/
3654 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
3656 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
3658 tmp_ch->state=MISDN_HOLD_DISCONNECT;
3660 ast_moh_stop(ast_bridged_channel(holded_chan->ast));
3662 holded_chan->state=MISDN_CONNECTED;
3663 //misdn_lib_transfer(holded_chan->bc);
3664 ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
3668 static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
3670 char predial[256]="";
3671 char *p = predial;
3673 struct ast_frame fr;
3675 strncpy(predial, ast->exten, sizeof(predial) -1 );
3677 ch->state=MISDN_DIALING;
3679 if (!ch->noautorespond_on_setup) {
3680 if (bc->nt) {
3681 int ret;
3682 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3683 } else {
3684 int ret;
3685 if ( misdn_lib_is_ptp(bc->port)) {
3686 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3687 } else {
3688 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
3691 } else {
3692 ch->state = MISDN_INCOMING_SETUP;
3695 chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, ast->cid.cid_num);
3697 strncpy(ast->exten,"s", 2);
3699 if (pbx_start_chan(ch)<0) {
3700 ast=NULL;
3701 hangup_chan(ch);
3702 hanguptone_indicate(ch);
3704 if (bc->nt)
3705 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
3706 else
3707 misdn_lib_send_event(bc, EVENT_DISCONNECT );
3711 while (!ast_strlen_zero(p) ) {
3712 fr.frametype = AST_FRAME_DTMF;
3713 fr.subclass = *p ;
3714 fr.src=NULL;
3715 fr.data = NULL ;
3716 fr.datalen = 0;
3717 fr.samples = 0 ;
3718 fr.mallocd =0 ;
3719 fr.offset= 0 ;
3720 fr.delivery= ast_tv(0,0) ;
3722 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
3723 ast_queue_frame(ch->ast, &fr);
3725 p++;
3731 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
3732 if (!ast) {
3733 chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
3734 return;
3736 if (!bc) {
3737 chan_misdn_log(1,0,"send_cause2ast: No BC\n");
3738 return;
3740 if (!ch) {
3741 chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
3742 return;
3745 ast->hangupcause=bc->cause;
3747 switch ( bc->cause) {
3749 case 1: /** Congestion Cases **/
3750 case 2:
3751 case 3:
3752 case 4:
3753 case 22:
3754 case 27:
3756 * Not Queueing the Congestion anymore, since we want to hear
3757 * the inband message
3759 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
3760 ch->state=MISDN_BUSY;
3762 ast_queue_control(ast, AST_CONTROL_CONGESTION);
3764 break;
3766 case 21:
3767 case 17: /* user busy */
3769 ch->state=MISDN_BUSY;
3771 if (!ch->need_busy) {
3772 chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
3773 break;
3776 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
3778 ast_queue_control(ast, AST_CONTROL_BUSY);
3780 ch->need_busy=0;
3782 break;
3789 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
3791 const char *tmp;
3792 tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
3793 if (tmp) {
3794 ch->other_pid=atoi(tmp);
3795 chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp);
3796 if (ch->other_pid >0) {
3797 ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
3798 if (ch->other_ch) ch->other_ch->other_ch=ch;
3802 tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
3803 if (tmp && (atoi(tmp) == 1)) {
3804 bc->sending_complete=1;
3807 tmp=pbx_builtin_getvar_helper(chan,"MISDN_USERUSER");
3808 if (tmp) {
3809 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
3810 strcpy(bc->uu, tmp);
3811 bc->uulen=strlen(bc->uu);
3814 tmp=pbx_builtin_getvar_helper(chan,"MISDN_KEYPAD");
3815 if (tmp) {
3816 strncpy(bc->keypad,tmp,sizeof(bc->keypad));
3817 bc->keypad[sizeof(bc->keypad)-1]=0;
3823 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
3825 char tmp[32];
3826 chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
3827 sprintf(tmp,"%d",bc->pid);
3828 pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
3830 if (bc->sending_complete) {
3831 sprintf(tmp,"%d",bc->sending_complete);
3832 pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
3835 if (bc->urate) {
3836 sprintf(tmp,"%d",bc->urate);
3837 pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp);
3840 if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
3841 bc->uu[bc->uulen]=0;
3842 pbx_builtin_setvar_helper(chan,"MISDN_USERUSER",bc->uu);
3845 if (bc->keypad[0])
3846 pbx_builtin_setvar_helper(chan,"MISDN_KEYPAD",bc->keypad);
3849 int add_in_calls(int port)
3851 int max_in_calls;
3853 misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
3854 misdn_in_calls[port]++;
3856 if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) {
3857 ast_log(LOG_NOTICE,"Marking Incoming Call on port[%d]\n",port);
3858 return misdn_in_calls[port]-max_in_calls;
3861 return 0;
3864 int add_out_calls(int port)
3866 int max_out_calls;
3868 misdn_cfg_get( port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
3871 if (max_out_calls >=0 && max_out_calls<=misdn_out_calls[port]) {
3872 ast_log(LOG_NOTICE,"Rejecting Outgoing Call on port[%d]\n",port);
3873 return (misdn_out_calls[port]+1)-max_out_calls;
3876 misdn_out_calls[port]++;
3878 return 0;
3881 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
3882 if (pbx_start_chan(ch)<0) {
3883 hangup_chan(ch);
3884 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
3885 if (bc->nt) {
3886 hanguptone_indicate(ch);
3887 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
3888 } else
3889 misdn_lib_send_event(bc, EVENT_RELEASE);
3893 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
3894 ch->state=MISDN_WAITING4DIGS;
3895 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3896 if (bc->nt && !bc->dad[0])
3897 dialtone_indicate(ch);
3901 /************************************************************/
3902 /* Receive Events from isdn_lib here */
3903 /************************************************************/
3904 static enum event_response_e
3905 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
3907 int msn_valid;
3908 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
3910 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */
3911 int debuglevel=1;
3912 if ( event==EVENT_CLEANUP && !user_data)
3913 debuglevel=5;
3915 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");
3916 if (debuglevel==1) {
3917 misdn_lib_log_ies(bc);
3918 chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
3922 if (!ch) {
3923 switch(event) {
3924 case EVENT_SETUP:
3925 case EVENT_DISCONNECT:
3926 case EVENT_PORT_ALARM:
3927 case EVENT_RETRIEVE:
3928 case EVENT_NEW_BC:
3929 case EVENT_FACILITY:
3930 break;
3931 case EVENT_RELEASE_COMPLETE:
3932 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
3933 break;
3934 case EVENT_CLEANUP:
3935 case EVENT_TONE_GENERATE:
3936 case EVENT_BCHAN_DATA:
3937 return -1;
3939 default:
3940 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);
3941 return -1;
3945 if (ch ) {
3946 switch (event) {
3947 case EVENT_TONE_GENERATE:
3948 break;
3949 case EVENT_DISCONNECT:
3950 case EVENT_RELEASE:
3951 case EVENT_RELEASE_COMPLETE:
3952 case EVENT_CLEANUP:
3953 case EVENT_TIMEOUT:
3954 if (!ch->ast)
3955 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));
3956 break;
3957 default:
3958 if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
3959 if (event!=EVENT_BCHAN_DATA)
3960 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
3961 return -1;
3967 switch (event) {
3968 case EVENT_PORT_ALARM:
3970 int boa=0;
3971 misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
3972 if (boa) {
3973 cb_log(1,bc->port," --> blocking\n");
3974 misdn_lib_port_block(bc->port);
3977 break;
3978 case EVENT_BCHAN_ACTIVATED:
3979 break;
3981 case EVENT_NEW_CHANNEL:
3982 update_name(ch->ast,bc->port,bc->channel);
3983 break;
3985 case EVENT_NEW_L3ID:
3986 ch->l3id=bc->l3_id;
3987 ch->addr=bc->addr;
3988 break;
3990 case EVENT_NEW_BC:
3991 if (!ch) {
3992 ch=find_holded(cl_te,bc);
3995 if (!ch) {
3996 ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
3997 break;
4000 if (bc)
4001 ch->bc=(struct misdn_bchannel*)user_data;
4002 break;
4004 case EVENT_DTMF_TONE:
4006 /* sending INFOS as DTMF-Frames :) */
4007 struct ast_frame fr;
4008 memset(&fr, 0 , sizeof(fr));
4009 fr.frametype = AST_FRAME_DTMF;
4010 fr.subclass = bc->dtmf ;
4011 fr.src=NULL;
4012 fr.data = NULL ;
4013 fr.datalen = 0;
4014 fr.samples = 0 ;
4015 fr.mallocd =0 ;
4016 fr.offset= 0 ;
4017 fr.delivery= ast_tv(0,0) ;
4019 if (!ch->ignore_dtmf) {
4020 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
4021 ast_queue_frame(ch->ast, &fr);
4022 } else {
4023 chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
4026 break;
4027 case EVENT_STATUS:
4028 break;
4030 case EVENT_INFORMATION:
4032 int l;
4034 if ( ch->state != MISDN_CONNECTED )
4035 stop_indicate(ch);
4037 if (!ch->ast) break;
4039 if (ch->state == MISDN_WAITING4DIGS ) {
4040 /* Ok, incomplete Setup, waiting till extension exists */
4041 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
4042 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
4043 strcpy(bc->info_dad,bc->keypad);
4046 l = sizeof(bc->dad);
4047 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad) - 1);
4049 l = sizeof(ch->ast->exten);
4050 strncpy(ch->ast->exten, bc->dad, l);
4051 ch->ast->exten[l-1] = 0;
4053 /* Check for Pickup Request first */
4054 if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
4055 if (ast_pickup_call(ch->ast)) {
4056 hangup_chan(ch);
4057 } else {
4058 struct ast_channel *chan=ch->ast;
4059 ch->state = MISDN_CALLING_ACKNOWLEDGE;
4060 ast_setstate(chan, AST_STATE_DOWN);
4061 hangup_chan(ch);
4062 ch->ast=NULL;
4063 break;
4067 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4068 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
4069 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
4070 strcpy(ch->ast->exten, "i");
4072 ch->state = MISDN_DIALING;
4073 start_pbx(ch, bc, ch->ast);
4074 break;
4077 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
4078 "maybe you want to add an 'i' extension to catch this case.\n",
4079 bc->port);
4081 if (bc->nt)
4082 hanguptone_indicate(ch);
4083 ch->state=MISDN_EXTCANTMATCH;
4084 bc->out_cause=1;
4086 misdn_lib_send_event(bc, EVENT_DISCONNECT );
4087 break;
4090 if (ch->overlap_dial) {
4091 ast_mutex_lock(&ch->overlap_tv_lock);
4092 ch->overlap_tv = ast_tvnow();
4093 ast_mutex_unlock(&ch->overlap_tv_lock);
4094 if (ch->overlap_dial_task == -1) {
4095 ch->overlap_dial_task =
4096 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
4098 break;
4101 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4103 ch->state = MISDN_DIALING;
4104 start_pbx(ch, bc, ch->ast);
4106 } else {
4107 /* sending INFOS as DTMF-Frames :) */
4108 int digits;
4109 struct ast_frame fr;
4110 memset(&fr, 0, sizeof(fr));
4111 fr.frametype = AST_FRAME_DTMF;
4112 fr.subclass = bc->info_dad[0] ;
4113 fr.src=NULL;
4114 fr.data = NULL ;
4115 fr.datalen = 0;
4116 fr.samples = 0 ;
4117 fr.mallocd =0 ;
4118 fr.offset= 0 ;
4119 fr.delivery= ast_tv(0,0) ;
4121 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
4122 if (ch->state != MISDN_CONNECTED ) {
4123 if (digits) {
4124 int l = sizeof(bc->dad);
4125 strncat(bc->dad, bc->info_dad, l - strlen(bc->dad) - 1);
4126 l = sizeof(ch->ast->exten);
4127 strncpy(ch->ast->exten, bc->dad, l);
4128 ch->ast->exten[l-1] = 0;
4130 ast_cdr_update(ch->ast);
4133 ast_queue_frame(ch->ast, &fr);
4137 break;
4138 case EVENT_SETUP:
4140 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
4141 if (ch) {
4142 switch (ch->state) {
4143 case MISDN_NOTHING:
4144 ch=NULL;
4145 break;
4146 default:
4147 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
4148 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */
4153 msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
4154 if (!bc->nt && ! msn_valid) {
4155 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
4156 return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */
4160 if (bc->cw) {
4161 int cause;
4162 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4163 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
4164 bc->out_cause=cause?cause:16;
4165 return RESPONSE_RELEASE_SETUP;
4168 print_bearer(bc);
4171 struct chan_list *ch;
4172 struct ast_channel *chan;
4173 int exceed;
4174 int pres,screen;
4175 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
4176 int ai, im;
4177 if (!bc->nt && ! msn_valid) {
4178 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
4179 return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */
4182 if (bc->cw) {
4183 int cause;
4184 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4185 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
4186 bc->out_cause=cause?cause:16;
4187 return RESPONSE_RELEASE_SETUP;
4190 print_bearer(bc);
4192 ch=init_chan_list(ORG_MISDN);
4194 if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
4196 ch->bc = bc;
4197 ch->l3id=bc->l3_id;
4198 ch->addr=bc->addr;
4199 ch->originator = ORG_MISDN;
4201 chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
4203 if (!chan) {
4204 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
4205 ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
4206 return 0;
4209 ch->ast = chan;
4211 if ((exceed=add_in_calls(bc->port))) {
4212 char tmp[16];
4213 sprintf(tmp,"%d",exceed);
4214 pbx_builtin_setvar_helper(chan,"MAX_OVERFLOW",tmp);
4217 read_config(ch, ORG_MISDN);
4219 export_ch(chan, bc, ch);
4221 ch->ast->rings=1;
4222 ast_setstate(ch->ast, AST_STATE_RINGING);
4224 switch (bc->pres) {
4225 case 1:
4226 pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
4227 break;
4228 case 2:
4229 pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
4230 break;
4231 default:
4232 pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
4235 switch (bc->screen) {
4236 case 0:
4237 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
4238 break;
4239 case 1:
4240 screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
4241 break;
4242 case 2:
4243 screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
4244 break;
4245 case 3:
4246 screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
4247 break;
4248 default:
4249 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
4252 chan->cid.cid_pres=pres+screen;
4254 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
4255 chan->transfercapability=bc->capability;
4257 switch (bc->capability) {
4258 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
4259 pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
4260 break;
4261 default:
4262 pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
4265 /** queue new chan **/
4266 cl_queue_chan(&cl_te, ch) ;
4268 if (!strstr(ch->allowed_bearers,"all")) {
4269 int i;
4271 for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
4272 if (allowed_bearers_array[i].cap == bc->capability) {
4273 if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
4274 /* The bearer capability is allowed */
4275 if (allowed_bearers_array[i].deprecated) {
4276 chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
4277 allowed_bearers_array[i].name);
4279 break;
4282 } /* end for */
4283 if (i == ARRAY_LEN(allowed_bearers_array)) {
4284 /* We did not find the bearer capability */
4285 chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
4286 bearer2str(bc->capability), bc->capability);
4287 bc->out_cause = 88;
4289 ch->state = MISDN_EXTCANTMATCH;
4290 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
4291 return RESPONSE_OK;
4295 /* Check for Pickup Request first */
4296 if (!strcmp(chan->exten, ast_pickup_ext())) {
4297 if (!ch->noautorespond_on_setup) {
4298 int ret;/** Sending SETUP_ACK**/
4299 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
4300 } else {
4301 ch->state = MISDN_INCOMING_SETUP;
4303 if (ast_pickup_call(chan)) {
4304 hangup_chan(ch);
4305 } else {
4306 ch->state = MISDN_CALLING_ACKNOWLEDGE;
4307 ast_setstate(chan, AST_STATE_DOWN);
4308 hangup_chan(ch);
4309 ch->ast=NULL;
4310 break;
4315 added support for s extension hope it will help those poor cretains
4316 which haven't overlap dial.
4318 misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
4319 if ( ai ) {
4320 do_immediate_setup(bc, ch , chan);
4321 break;
4324 /* check if we should jump into s when we have no dad */
4325 misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
4326 if ( im && ast_strlen_zero(bc->dad) ) {
4327 do_immediate_setup(bc, ch , chan);
4328 break;
4331 chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
4332 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4333 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
4334 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
4335 strcpy(ch->ast->exten, "i");
4336 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
4337 ch->state=MISDN_DIALING;
4338 start_pbx(ch, bc, chan);
4339 break;
4342 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
4343 "maybe you want to add an 'i' extension to catch this case.\n",
4344 bc->port);
4345 if (bc->nt)
4346 hanguptone_indicate(ch);
4348 ch->state=MISDN_EXTCANTMATCH;
4349 bc->out_cause=1;
4351 if (bc->nt)
4352 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
4353 else
4354 misdn_lib_send_event(bc, EVENT_RELEASE );
4356 break;
4359 /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
4360 * jump into the dialplan, when the dialed extension does not exist, the 's' extension
4361 * will be used by Asterisk automatically. */
4362 if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
4363 if (!ch->noautorespond_on_setup) {
4364 ch->state=MISDN_DIALING;
4365 misdn_lib_send_event(bc, EVENT_PROCEEDING );
4366 } else {
4367 ch->state = MISDN_INCOMING_SETUP;
4369 start_pbx(ch, bc, chan);
4370 break;
4375 * When we are NT and overlapdial is set and if
4376 * the number is empty, we wait for the ISDN timeout
4377 * instead of our own timer.
4379 if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
4380 wait_for_digits(ch, bc, chan);
4381 break;
4385 * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
4386 * Infos with a Interdigit Timeout.
4387 * */
4388 if (ch->overlap_dial) {
4389 ast_mutex_lock(&ch->overlap_tv_lock);
4390 ch->overlap_tv = ast_tvnow();
4391 ast_mutex_unlock(&ch->overlap_tv_lock);
4393 wait_for_digits(ch, bc, chan);
4394 if (ch->overlap_dial_task == -1)
4395 ch->overlap_dial_task =
4396 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
4398 break;
4401 /* If the extension does not exist and we're not TE_PTMP we wait for more digits
4402 * without interdigit timeout.
4403 * */
4404 if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4405 wait_for_digits(ch, bc, chan);
4406 break;
4410 * If the extension exists let's just jump into it.
4411 * */
4412 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4413 if (bc->need_more_infos)
4414 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
4415 else
4416 misdn_lib_send_event(bc, EVENT_PROCEEDING);
4418 ch->state=MISDN_DIALING;
4419 start_pbx(ch, bc, chan);
4420 break;
4423 break;
4425 case EVENT_SETUP_ACKNOWLEDGE:
4427 ch->state = MISDN_CALLING_ACKNOWLEDGE;
4429 if (bc->channel)
4430 update_name(ch->ast,bc->port,bc->channel);
4432 if (!ast_strlen_zero(bc->infos_pending)) {
4433 /* TX Pending Infos */
4436 int l = sizeof(bc->dad);
4437 strncat(bc->dad, bc->infos_pending, l - strlen(bc->dad) - 1);
4440 if (!ch->ast) break;
4442 int l = sizeof(ch->ast->exten);
4443 strncpy(ch->ast->exten, bc->dad, l);
4444 ch->ast->exten[l-1] = 0;
4447 int l = sizeof(bc->info_dad);
4448 strncpy(bc->info_dad, bc->infos_pending, l);
4449 bc->info_dad[l-1] = 0;
4451 strncpy(bc->infos_pending,"", 1);
4453 misdn_lib_send_event(bc, EVENT_INFORMATION);
4456 break;
4457 case EVENT_PROCEEDING:
4459 if (bc->channel)
4460 update_name(ch->ast,bc->port,bc->channel);
4462 if ( misdn_cap_is_speech(bc->capability) &&
4463 misdn_inband_avail(bc) ) {
4464 start_bc_tones(ch);
4467 ch->state = MISDN_PROCEEDING;
4469 if (!ch->ast) break;
4471 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
4473 break;
4474 case EVENT_PROGRESS:
4475 if (bc->channel)
4476 update_name(ch->ast,bc->port,bc->channel);
4478 if (!bc->nt ) {
4479 if ( misdn_cap_is_speech(bc->capability) &&
4480 misdn_inband_avail(bc)
4482 start_bc_tones(ch);
4485 ch->state=MISDN_PROGRESS;
4487 if (!ch->ast) break;
4488 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
4490 break;
4493 case EVENT_ALERTING:
4495 if (bc->channel)
4496 update_name(ch->ast,bc->port,bc->channel);
4498 ch->state = MISDN_ALERTING;
4500 if (!ch->ast) break;
4502 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
4503 ast_setstate(ch->ast, AST_STATE_RINGING);
4505 cb_log(7,bc->port," --> Set State Ringing\n");
4507 if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
4508 cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
4509 start_bc_tones(ch);
4510 } else {
4511 cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
4512 if (ch->far_alerting) {
4513 cb_log(1,bc->port," --> The other end can not do ringing eh ?.. we must do all ourself..");
4514 start_bc_tones(ch);
4515 /*tone_indicate(ch, TONE_FAR_ALERTING);*/
4519 break;
4520 case EVENT_CONNECT:
4522 struct ast_channel *bridged;
4523 /*we answer when we've got our very new L3 ID from the NT stack */
4524 misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
4526 if (!ch->ast) break;
4528 bridged=ast_bridged_channel(ch->ast);
4529 stop_indicate(ch);
4531 if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
4532 struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
4534 chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
4535 if (bridged_ch) {
4536 bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
4537 ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
4541 ch->l3id=bc->l3_id;
4542 ch->addr=bc->addr;
4544 start_bc_tones(ch);
4546 ch->state = MISDN_CONNECTED;
4548 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
4549 break;
4550 case EVENT_CONNECT_ACKNOWLEDGE:
4552 ch->l3id=bc->l3_id;
4553 ch->addr=bc->addr;
4555 start_bc_tones(ch);
4557 ch->state = MISDN_CONNECTED;
4559 break;
4560 case EVENT_DISCONNECT:
4561 /*we might not have an ch->ast ptr here anymore*/
4562 if (ch) {
4563 struct chan_list *holded_ch=find_holded(cl_te, bc);
4565 chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
4566 if ( ch->originator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
4567 /* If there's inband information available (e.g. a
4568 recorded message saying what was wrong with the
4569 dialled number, or perhaps even giving an
4570 alternative number, then play it instead of
4571 immediately releasing the call */
4572 chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
4574 ch->state=MISDN_DISCONNECTED;
4575 start_bc_tones(ch);
4577 if (ch->ast) {
4578 ch->ast->hangupcause=bc->cause;
4579 if (bc->cause == 17)
4580 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
4582 ch->need_busy=0;
4583 break;
4586 /*Check for holded channel, to implement transfer*/
4587 if ( holded_ch &&
4588 holded_ch != ch &&
4589 ch->ast &&
4590 ch->state == MISDN_CONNECTED ) {
4591 cb_log(1,bc->port," --> found holded ch\n");
4592 misdn_transfer_bc(ch, holded_ch) ;
4595 bc->need_disconnect=0;
4597 stop_bc_tones(ch);
4598 hangup_chan(ch);
4599 } else {
4600 /* ch=find_holded_l3(cl_te, bc->l3_id,1);
4601 if (ch) {
4602 hangup_chan(ch);
4606 bc->out_cause=-1;
4607 if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
4608 break;
4610 case EVENT_RELEASE:
4612 bc->need_disconnect=0;
4613 bc->need_release=0;
4615 hangup_chan(ch);
4616 release_chan(bc);
4618 break;
4619 case EVENT_RELEASE_COMPLETE:
4621 bc->need_disconnect=0;
4622 bc->need_release=0;
4623 bc->need_release_complete=0;
4625 stop_bc_tones(ch);
4626 hangup_chan(ch);
4628 if(ch)
4629 ch->state=MISDN_CLEANING;
4631 release_chan(bc);
4633 break;
4634 case EVENT_BCHAN_ERROR:
4635 case EVENT_CLEANUP:
4637 stop_bc_tones(ch);
4639 switch(ch->state) {
4640 case MISDN_CALLING:
4641 bc->cause=27; /* Destination out of order */
4642 break;
4643 default:
4644 break;
4647 hangup_chan(ch);
4648 release_chan(bc);
4650 break;
4652 case EVENT_TONE_GENERATE:
4654 int tone_len=bc->tone_cnt;
4655 struct ast_channel *ast=ch->ast;
4656 void *tmp;
4657 int res;
4658 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
4660 chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
4662 if (!ast) break;
4664 if (!ast->generator) break;
4668 tmp = ast->generatordata;
4669 ast->generatordata = NULL;
4670 generate = ast->generator->generate;
4672 if (tone_len <0 || tone_len > 512 ) {
4673 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
4674 tone_len=128;
4677 res = generate(ast, tmp, tone_len, tone_len);
4678 ast->generatordata = tmp;
4680 if (res) {
4681 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
4682 ast_deactivate_generator(ast);
4683 } else {
4684 bc->tone_cnt=0;
4687 break;
4689 case EVENT_BCHAN_DATA:
4691 if ( !misdn_cap_is_speech(ch->bc->capability) ) {
4692 struct ast_frame frame;
4693 /*In Data Modes we queue frames*/
4694 frame.frametype = AST_FRAME_VOICE; /*we have no data frames yet*/
4695 frame.subclass = AST_FORMAT_ALAW;
4696 frame.datalen = bc->bframe_len;
4697 frame.samples = bc->bframe_len ;
4698 frame.mallocd =0 ;
4699 frame.offset= 0 ;
4700 frame.delivery= ast_tv(0,0) ;
4701 frame.src = NULL;
4702 frame.data = bc->bframe ;
4704 if (ch->ast)
4705 ast_queue_frame(ch->ast,&frame);
4706 } else {
4707 int t;
4708 fd_set wrfs;
4709 struct timeval tv;
4710 tv.tv_sec=0;
4711 tv.tv_usec=0;
4714 FD_ZERO(&wrfs);
4715 FD_SET(ch->pipe[1],&wrfs);
4717 t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
4719 if (!t) {
4720 chan_misdn_log(9, bc->port, "Select Timed out\n");
4721 break;
4724 if (t<0) {
4725 chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
4726 break;
4729 if (FD_ISSET(ch->pipe[1],&wrfs)) {
4730 int ret;
4731 chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
4732 ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
4734 if (ret<=0) {
4735 chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno));
4737 stop_bc_tones(ch);
4738 hangup_chan(ch);
4739 release_chan(bc);
4741 } else {
4742 chan_misdn_log(1, bc->port, "Write Pipe full!\n");
4746 break;
4747 case EVENT_TIMEOUT:
4749 if (ch && bc)
4750 chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
4752 switch (ch->state) {
4753 case MISDN_DIALING:
4754 case MISDN_PROGRESS:
4755 if (bc->nt && !ch->nttimeout) break;
4757 case MISDN_CALLING:
4758 case MISDN_ALERTING:
4759 case MISDN_PROCEEDING:
4760 case MISDN_CALLING_ACKNOWLEDGE:
4761 if (bc->nt) {
4762 bc->progress_indicator=8;
4763 hanguptone_indicate(ch);
4766 bc->out_cause=1;
4767 misdn_lib_send_event(bc,EVENT_DISCONNECT);
4768 break;
4770 case MISDN_WAITING4DIGS:
4771 if (bc->nt) {
4772 bc->progress_indicator=8;
4773 bc->out_cause=1;
4774 hanguptone_indicate(ch);
4775 misdn_lib_send_event(bc,EVENT_DISCONNECT);
4776 } else {
4777 bc->out_cause=16;
4778 misdn_lib_send_event(bc,EVENT_RELEASE);
4781 break;
4784 case MISDN_CLEANING:
4785 chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
4786 break;
4788 default:
4789 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
4792 break;
4795 /****************************/
4796 /** Supplementary Services **/
4797 /****************************/
4798 case EVENT_RETRIEVE:
4800 struct ast_channel *hold_ast;
4801 if (!ch) {
4802 chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
4803 ch=find_holded_l3(cl_te, bc->l3_id,1);
4806 if (!ch) {
4807 ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
4808 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
4809 break;
4812 /*remember the channel again*/
4813 ch->bc=bc;
4814 ch->state = MISDN_CONNECTED;
4816 ch->hold_info.port=0;
4817 ch->hold_info.channel=0;
4819 hold_ast=ast_bridged_channel(ch->ast);
4821 if (hold_ast) {
4822 ast_moh_stop(hold_ast);
4825 if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
4826 chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
4827 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
4830 break;
4832 case EVENT_HOLD:
4834 int hold_allowed;
4835 struct ast_channel *bridged;
4836 misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
4838 if (!hold_allowed) {
4840 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
4841 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
4842 break;
4845 bridged=ast_bridged_channel(ch->ast);
4847 if (bridged) {
4848 chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
4849 ch->state = MISDN_HOLDED;
4850 ch->l3id = bc->l3_id;
4852 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
4854 /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
4855 * instead of starting moh on the bridged channel directly */
4856 ast_moh_start(bridged, NULL, NULL);
4858 /*forget the channel now*/
4859 ch->bc=NULL;
4860 ch->hold_info.port=bc->port;
4861 ch->hold_info.channel=bc->channel;
4863 } else {
4864 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
4865 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
4868 break;
4870 case EVENT_FACILITY:
4871 if (!ch) {
4872 /* This may come from a call we don't know nothing about, so we ignore it. */
4873 chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
4874 break;
4877 print_facility(&(bc->fac_in), bc);
4879 switch (bc->fac_in.Function) {
4880 case Fac_CD:
4882 struct ast_channel *bridged=ast_bridged_channel(ch->ast);
4883 struct chan_list *ch_br;
4884 if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
4885 ch_br=MISDN_ASTERISK_TECH_PVT(bridged);
4886 /*ch->state=MISDN_FACILITY_DEFLECTED;*/
4887 if (ch_br->bc) {
4888 if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
4889 ch_br->state=MISDN_DIALING;
4890 if (pbx_start_chan(ch_br) < 0) {
4891 chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
4897 misdn_lib_send_event(bc, EVENT_DISCONNECT);
4899 break;
4900 case Fac_AOCDCurrency:
4901 bc->AOCDtype = Fac_AOCDCurrency;
4902 memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
4903 export_aoc_vars(ch->originator, ch->ast, bc);
4904 break;
4905 case Fac_AOCDChargingUnit:
4906 bc->AOCDtype = Fac_AOCDChargingUnit;
4907 memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
4908 export_aoc_vars(ch->originator, ch->ast, bc);
4909 break;
4910 default:
4911 chan_misdn_log(0, bc->port," --> not yet handled: facility type:%p\n", bc->fac_in.Function);
4914 break;
4916 case EVENT_RESTART:
4918 if (!bc->dummy) {
4919 stop_bc_tones(ch);
4920 release_chan(bc);
4923 break;
4925 default:
4926 chan_misdn_log(1,0, "Got Unknown Event\n");
4927 break;
4930 return RESPONSE_OK;
4933 /** TE STUFF END **/
4935 /******************************************
4937 * Asterisk Channel Endpoint END
4940 *******************************************/
4944 static int unload_module(void)
4946 /* First, take us out of the channel loop */
4947 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
4949 misdn_tasks_destroy();
4951 if (!g_config_initialized) return 0;
4953 ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
4955 /* ast_unregister_application("misdn_crypt"); */
4956 ast_unregister_application("misdn_set_opt");
4957 ast_unregister_application("misdn_facility");
4958 ast_unregister_application("misdn_check_l2l1");
4960 ast_channel_unregister(&misdn_tech);
4963 free_robin_list();
4964 misdn_cfg_destroy();
4965 misdn_lib_destroy();
4967 if (misdn_debug)
4968 free(misdn_debug);
4969 if (misdn_debug_only)
4970 free(misdn_debug_only);
4971 free(misdn_ports);
4973 return 0;
4976 static int load_module(void)
4978 int i, port;
4980 char ports[256]="";
4982 max_ports=misdn_lib_maxports_get();
4984 if (max_ports<=0) {
4985 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
4986 return AST_MODULE_LOAD_DECLINE;
4989 if (misdn_cfg_init(max_ports)) {
4990 ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
4991 return AST_MODULE_LOAD_DECLINE;
4993 g_config_initialized=1;
4995 misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
4996 misdn_ports = (int *)malloc(sizeof(int) * (max_ports+1));
4997 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
4998 for (i = 1; i <= max_ports; i++) {
4999 misdn_debug[i] = misdn_debug[0];
5000 misdn_ports[i] = i;
5002 *misdn_ports = 0;
5003 misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
5006 char tempbuf[BUFFERSIZE+1];
5007 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
5008 if (strlen(tempbuf))
5009 tracing = 1;
5012 misdn_in_calls = (int *)malloc(sizeof(int) * (max_ports+1));
5013 misdn_out_calls = (int *)malloc(sizeof(int) * (max_ports+1));
5015 for (i=1; i <= max_ports; i++) {
5016 misdn_in_calls[i]=0;
5017 misdn_out_calls[i]=0;
5020 ast_mutex_init(&cl_te_lock);
5021 ast_mutex_init(&release_lock);
5023 misdn_cfg_update_ptp();
5024 misdn_cfg_get_ports_string(ports);
5026 if (strlen(ports))
5027 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
5030 int ntflags=0, ntkc=0;
5031 char ntfile[BUFFERSIZE+1];
5032 struct misdn_lib_iface iface = {
5033 .cb_event = cb_events,
5034 .cb_log = chan_misdn_log,
5035 .cb_jb_empty = chan_misdn_jb_empty,
5038 if (misdn_lib_init(ports, &iface, NULL))
5039 chan_misdn_log(0, 0, "No te ports initialized\n");
5041 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
5042 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
5043 misdn_lib_nt_debug_init(ntflags,ntfile);
5045 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(int));
5046 misdn_lib_nt_keepcalls(ntkc);
5050 if (ast_channel_register(&misdn_tech)) {
5051 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
5052 unload_module();
5053 return -1;
5057 ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
5059 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
5060 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
5061 "Sets mISDN opts. and optargs\n"
5062 "\n"
5063 "The available options are:\n"
5064 " d - Send display text on called phone, text is the optparam\n"
5065 " n - don't detect dtmf tones on called channel\n"
5066 " h - make digital outgoing call\n"
5067 " c - make crypted outgoing call, param is keyindex\n"
5068 " e - perform echo cancelation on this channel,\n"
5069 " takes taps as arguments (32,64,128,256)\n"
5070 " s - send Non Inband DTMF as inband\n"
5071 " vr - rxgain control\n"
5072 " vt - txgain control\n"
5073 " i - Ignore detected dtmf tones, don't signal them to asterisk, they will be transported inband.\n"
5077 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
5078 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
5079 "Sends the Facility Message FACILITY_TYPE with \n"
5080 "the given Arguments to the current ISDN Channel\n"
5081 "Supported Facilities are:\n"
5082 "\n"
5083 "type=calldeflect args=Nr where to deflect\n"
5087 ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
5088 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
5089 "Checks if the L2 and L1 are up on either the given <port> or\n"
5090 "on the ports in the group with <groupname>\n"
5091 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
5092 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
5093 "\n"
5094 "This application, ensures the L1/L2 state of the Ports in a group\n"
5095 "it is intended to make the pmp_l1_check option redundant and to\n"
5096 "fix a buggy switch config from your provider\n"
5097 "\n"
5098 "a sample dialplan would look like:\n\n"
5099 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
5100 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
5101 "\n"
5105 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
5107 /* start the l1 watchers */
5109 for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
5110 int l1timeout;
5111 misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
5112 if (l1timeout) {
5113 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
5114 misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
5118 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
5120 return 0;
5125 static int reload(void)
5127 reload_config();
5129 return 0;
5132 /*** SOME APPS ;)***/
5134 static int misdn_facility_exec(struct ast_channel *chan, void *data)
5136 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
5137 char *tok, *tokb;
5139 chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
5141 if (strcasecmp(chan->tech->type,"mISDN")) {
5142 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
5143 return -1;
5146 if (ast_strlen_zero((char *)data)) {
5147 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
5148 return -1;
5151 tok=strtok_r((char*)data,"|", &tokb) ;
5153 if (!tok) {
5154 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
5155 return -1;
5158 if (!strcasecmp(tok,"calldeflect")) {
5159 tok=strtok_r(NULL,"|", &tokb) ;
5161 if (!tok) {
5162 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
5165 if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
5166 ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
5167 return 0;
5169 ch->bc->fac_out.Function = Fac_CD;
5170 strncpy((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
5171 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
5172 } else {
5173 chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n",tok);
5176 return 0;
5180 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
5182 char group[BUFFERSIZE+1];
5183 char *port_str;
5184 int port_up;
5185 int timeout;
5186 int dowait=0;
5187 int port=0;
5189 AST_DECLARE_APP_ARGS(args,
5190 AST_APP_ARG(grouppar);
5191 AST_APP_ARG(timeout);
5194 if (ast_strlen_zero((char *)data)) {
5195 ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
5196 return -1;
5199 AST_STANDARD_APP_ARGS(args, data);
5201 if (args.argc != 2) {
5202 ast_log(LOG_WARNING, "Wrong argument count\n");
5203 return 0;
5206 /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
5207 timeout=atoi(args.timeout);
5208 port_str=args.grouppar;
5209 if (port_str[0]=='g' && port_str[1]==':' ) {
5210 /* We make a group call lets checkout which ports are in my group */
5211 port_str += 2;
5212 strncpy(group, port_str, BUFFERSIZE);
5213 group[BUFFERSIZE-1] = 0;
5214 chan_misdn_log(2, 0, "Checking Ports in group: %s\n",group);
5216 for ( port = misdn_cfg_get_next_port(port);
5217 port > 0;
5218 port = misdn_cfg_get_next_port(port))
5220 char cfg_group[BUFFERSIZE+1];
5222 chan_misdn_log(2,0,"trying port %d\n",port);
5224 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
5226 if (!strcasecmp(cfg_group, group)) {
5227 port_up = misdn_lib_port_up(port, 1);
5229 if (!port_up) {
5230 chan_misdn_log(2, 0, " --> port '%d'\n", port);
5231 misdn_lib_get_port_up(port);
5232 dowait=1;
5237 } else {
5238 port = atoi(port_str);
5239 chan_misdn_log(2, 0, "Checking Port: %d\n",port);
5240 port_up = misdn_lib_port_up(port, 1);
5241 if (!port_up) {
5242 misdn_lib_get_port_up(port);
5243 dowait=1;
5248 if (dowait) {
5249 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n",timeout);
5250 sleep(timeout);
5253 return 0;
5256 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
5258 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
5259 char *tok,*tokb;
5260 int keyidx=0;
5261 int rxgain=0;
5262 int txgain=0;
5263 int change_jitter=0;
5265 if (strcasecmp(chan->tech->type,"mISDN")) {
5266 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
5267 return -1;
5270 if (ast_strlen_zero((char *)data)) {
5271 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
5272 return -1;
5275 for (tok=strtok_r((char*)data, ":",&tokb);
5276 tok;
5277 tok=strtok_r(NULL,":",&tokb) ) {
5278 char keys[4096];
5279 char *key, *tmp;
5280 int i;
5281 int neglect=0;
5283 if (tok[0] == '!' ) {
5284 neglect=1;
5285 tok++;
5288 switch(tok[0]) {
5290 case 'd' :
5291 ast_copy_string(ch->bc->display,++tok,84);
5292 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
5293 break;
5295 case 'n':
5296 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
5297 ch->bc->nodsp=1;
5298 break;
5300 case 'j':
5301 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
5302 tok++;
5303 change_jitter=1;
5305 switch ( tok[0] ) {
5306 case 'b' :
5307 ch->jb_len=atoi(++tok);
5308 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
5309 break;
5310 case 't' :
5311 ch->jb_upper_threshold=atoi(++tok);
5312 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
5313 break;
5315 case 'n':
5316 ch->bc->nojitter=1;
5317 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
5318 break;
5320 default:
5321 ch->jb_len=4000;
5322 ch->jb_upper_threshold=0;
5323 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
5324 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
5327 break;
5329 case 'v':
5330 tok++;
5332 switch ( tok[0] ) {
5333 case 'r' :
5334 rxgain=atoi(++tok);
5335 if (rxgain<-8) rxgain=-8;
5336 if (rxgain>8) rxgain=8;
5337 ch->bc->rxgain=rxgain;
5338 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
5339 break;
5340 case 't':
5341 txgain=atoi(++tok);
5342 if (txgain<-8) txgain=-8;
5343 if (txgain>8) txgain=8;
5344 ch->bc->txgain=txgain;
5345 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
5346 break;
5348 break;
5350 case 'c':
5351 keyidx=atoi(++tok);
5352 key=NULL;
5353 misdn_cfg_get( 0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
5355 tmp=keys;
5357 for (i=0; i<keyidx; i++) {
5358 key=strsep(&tmp,",");
5361 if (key) {
5362 ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
5365 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",ch->bc->crypt_key);
5366 break;
5368 case 'e':
5369 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
5371 if (neglect) {
5372 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
5373 #ifdef MISDN_1_2
5374 *ch->bc->pipeline=0;
5375 #else
5376 ch->bc->ec_enable=0;
5377 #endif
5378 } else {
5379 #ifdef MISDN_1_2
5380 update_pipeline_config(ch->bc);
5381 #else
5382 ch->bc->ec_enable=1;
5383 ch->bc->orig=ch->originator;
5384 tok++;
5385 if (*tok) {
5386 ch->bc->ec_deftaps=atoi(tok);
5388 #endif
5391 break;
5393 case 'h':
5394 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
5396 if (strlen(tok) > 1 && tok[1]=='1') {
5397 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
5398 if (!ch->bc->hdlc) {
5399 ch->bc->hdlc=1;
5402 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
5403 break;
5405 case 's':
5406 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
5407 ch->bc->send_dtmf=1;
5408 break;
5410 case 'f':
5411 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
5412 ch->faxdetect=1;
5413 misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
5414 break;
5416 case 'a':
5417 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
5418 ch->ast_dsp=1;
5419 break;
5421 case 'p':
5422 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
5423 /* CRICH: callingpres!!! */
5424 if (strstr(tok,"allowed") ) {
5425 ch->bc->pres=0;
5426 } else if (strstr(tok,"not_screened")) {
5427 ch->bc->pres=1;
5429 break;
5430 case 'i' :
5431 chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
5432 ch->ignore_dtmf=1;
5433 break;
5434 default:
5435 break;
5439 if (change_jitter)
5440 config_jitterbuffer(ch);
5443 if (ch->faxdetect || ch->ast_dsp) {
5444 if (!ch->dsp) ch->dsp = ast_dsp_new();
5445 if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
5446 if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
5449 if (ch->ast_dsp) {
5450 chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
5451 ch->bc->nodsp=1;
5452 ch->bc->nojitter=1;
5455 return 0;
5459 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
5461 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
5463 if (ch && ch->jb) {
5464 return misdn_jb_empty(ch->jb, buf, len);
5467 return -1;
5472 /*******************************************************/
5473 /***************** JITTERBUFFER ************************/
5474 /*******************************************************/
5477 /* allocates the jb-structure and initialize the elements*/
5478 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
5480 int i;
5481 struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
5482 jb->size = size;
5483 jb->upper_threshold = upper_threshold;
5484 jb->wp = 0;
5485 jb->rp = 0;
5486 jb->state_full = 0;
5487 jb->state_empty = 0;
5488 jb->bytes_wrote = 0;
5489 jb->samples = (char *)malloc(size*sizeof(char));
5491 if (!jb->samples) {
5492 chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
5493 return NULL;
5496 jb->ok = (char *)malloc(size*sizeof(char));
5498 if (!jb->ok) {
5499 chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
5500 return NULL;
5503 for(i=0; i<size; i++)
5504 jb->ok[i]=0;
5506 ast_mutex_init(&jb->mutexjb);
5508 return jb;
5511 /* frees the data and destroys the given jitterbuffer struct */
5512 void misdn_jb_destroy(struct misdn_jb *jb)
5514 ast_mutex_destroy(&jb->mutexjb);
5516 free(jb->samples);
5517 free(jb);
5520 /* fills the jitterbuffer with len data returns < 0 if there was an
5521 error (buffer overflow). */
5522 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
5524 int i, j, rp, wp;
5526 if (!jb || ! data) return 0;
5528 ast_mutex_lock (&jb->mutexjb);
5530 wp=jb->wp;
5531 rp=jb->rp;
5533 for(i=0; i<len; i++)
5535 jb->samples[wp]=data[i];
5536 jb->ok[wp]=1;
5537 wp = (wp!=jb->size-1 ? wp+1 : 0);
5539 if(wp==jb->rp)
5540 jb->state_full=1;
5543 if(wp>=rp)
5544 jb->state_buffer=wp-rp;
5545 else
5546 jb->state_buffer= jb->size-rp+wp;
5547 chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Buffer status:%d p:%x\n",len,jb->state_buffer,jb);
5549 if(jb->state_full)
5551 jb->wp=wp;
5553 rp=wp;
5554 for(j=0; j<jb->upper_threshold; j++)
5555 rp = (rp!=0 ? rp-1 : jb->size-1);
5556 jb->rp=rp;
5557 jb->state_full=0;
5558 jb->state_empty=1;
5560 ast_mutex_unlock (&jb->mutexjb);
5562 return -1;
5565 if(!jb->state_empty)
5567 jb->bytes_wrote+=len;
5568 if(jb->bytes_wrote>=jb->upper_threshold)
5570 jb->state_empty=1;
5571 jb->bytes_wrote=0;
5574 jb->wp=wp;
5576 ast_mutex_unlock (&jb->mutexjb);
5578 return 0;
5581 /* gets len bytes out of the jitterbuffer if available, else only the
5582 available data is returned and the return value indicates the number
5583 of data. */
5584 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
5586 int i, wp, rp, read=0;
5588 ast_mutex_lock (&jb->mutexjb);
5590 rp=jb->rp;
5591 wp=jb->wp;
5593 if(jb->state_empty)
5595 for(i=0; i<len; i++)
5597 if(wp==rp)
5599 jb->rp=rp;
5600 jb->state_empty=0;
5602 ast_mutex_unlock (&jb->mutexjb);
5604 return read;
5606 else
5608 if(jb->ok[rp]==1)
5610 data[i]=jb->samples[rp];
5611 jb->ok[rp]=0;
5612 rp=(rp!=jb->size-1 ? rp+1 : 0);
5613 read+=1;
5618 if(wp >= rp)
5619 jb->state_buffer=wp-rp;
5620 else
5621 jb->state_buffer= jb->size-rp+wp;
5622 chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Buffer status:%d p:%x\n",len,jb->state_buffer,jb);
5624 jb->rp=rp;
5626 else
5627 chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
5629 ast_mutex_unlock (&jb->mutexjb);
5631 return read;
5637 /*******************************************************/
5638 /*************** JITTERBUFFER END *********************/
5639 /*******************************************************/
5644 static void chan_misdn_log(int level, int port, char *tmpl, ...)
5646 va_list ap;
5647 char buf[1024];
5648 char port_buf[8];
5650 if (! ((0 <= port) && (port <= max_ports))) {
5651 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
5652 port=0;
5653 level=-1;
5656 sprintf(port_buf,"P[%2d] ",port);
5658 va_start(ap, tmpl);
5659 vsnprintf( buf, 1023, tmpl, ap );
5660 va_end(ap);
5662 if (level == -1)
5663 ast_log(LOG_WARNING, buf);
5665 else if (misdn_debug_only[port] ?
5666 (level==1 && misdn_debug[port]) || (level==misdn_debug[port])
5667 : level <= misdn_debug[port]) {
5669 ast_console_puts(port_buf);
5670 ast_console_puts(buf);
5673 if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
5674 time_t tm = time(NULL);
5675 char *tmp=ctime(&tm),*p;
5677 FILE *fp= fopen(global_tracefile, "a+");
5679 p=strchr(tmp,'\n');
5680 if (p) *p=':';
5682 if (!fp) {
5683 ast_console_puts("Error opening Tracefile: [ ");
5684 ast_console_puts(global_tracefile);
5685 ast_console_puts(" ] ");
5687 ast_console_puts(strerror(errno));
5688 ast_console_puts("\n");
5689 return ;
5692 fputs(tmp,fp);
5693 fputs(" ", fp);
5694 fputs(port_buf,fp);
5695 fputs(" ", fp);
5696 fputs(buf, fp);
5698 fclose(fp);
5702 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
5703 .load = load_module,
5704 .unload = unload_module,
5705 .reload = reload,