Ignore some files generated from 1.6.x/trunk build
[asterisk-bristuff.git] / channels / chan_misdn.c
blobc4dc1c88c9dac79bf720efb004a93ff67c221933
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
25 * \author Christian Richter <crich@beronet.com>
27 * \extref MISDN http://www.misdn.org/
29 * \ingroup channel_drivers
32 /*** MODULEINFO
33 <depend>isdnnet</depend>
34 <depend>misdn</depend>
35 <depend>suppserv</depend>
36 ***/
37 #include "asterisk.h"
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
41 #include <stdio.h>
42 #include <pthread.h>
43 #include <string.h>
44 #include <sys/socket.h>
45 #include <sys/time.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <stdlib.h>
49 #include <arpa/inet.h>
50 #include <fcntl.h>
51 #include <sys/ioctl.h>
52 #include <signal.h>
53 #include <sys/file.h>
54 #include <semaphore.h>
56 #include "asterisk/channel.h"
57 #include "asterisk/config.h"
58 #include "asterisk/logger.h"
59 #include "asterisk/module.h"
60 #include "asterisk/pbx.h"
61 #include "asterisk/options.h"
62 #include "asterisk/io.h"
63 #include "asterisk/frame.h"
64 #include "asterisk/translate.h"
65 #include "asterisk/cli.h"
66 #include "asterisk/musiconhold.h"
67 #include "asterisk/dsp.h"
68 #include "asterisk/translate.h"
69 #include "asterisk/config.h"
70 #include "asterisk/file.h"
71 #include "asterisk/callerid.h"
72 #include "asterisk/indications.h"
73 #include "asterisk/app.h"
74 #include "asterisk/features.h"
75 #include "asterisk/term.h"
76 #include "asterisk/sched.h"
77 #include "asterisk/stringfields.h"
78 #include "asterisk/causes.h"
80 #include "chan_misdn_config.h"
81 #include "isdn_lib.h"
83 char global_tracefile[BUFFERSIZE + 1];
85 static int g_config_initialized = 0;
87 struct misdn_jb{
88 int size;
89 int upper_threshold;
90 char *samples, *ok;
91 int wp,rp;
92 int state_empty;
93 int state_full;
94 int state_buffer;
95 int bytes_wrote;
96 ast_mutex_t mutexjb;
101 /*! \brief allocates the jb-structure and initialize the elements */
102 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
104 /*! \brief frees the data and destroys the given jitterbuffer struct */
105 void misdn_jb_destroy(struct misdn_jb *jb);
107 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
108 error (buffer overrun). */
109 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
111 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
112 available data is returned and the return value indicates the number
113 of data. */
114 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
117 /* BEGIN: chan_misdn.h */
119 ast_mutex_t release_lock;
121 enum misdn_chan_state {
122 MISDN_NOTHING=0, /*!< at beginning */
123 MISDN_WAITING4DIGS, /*!< when waiting for infos */
124 MISDN_EXTCANTMATCH, /*!< when asterisk couldn't match our ext */
125 MISDN_INCOMING_SETUP, /*!< for incoming setups*/
126 MISDN_DIALING, /*!< when pbx_start */
127 MISDN_PROGRESS, /*!< we got a progress */
128 MISDN_PROCEEDING, /*!< we got a progress */
129 MISDN_CALLING, /*!< when misdn_call is called */
130 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
131 MISDN_ALERTING, /*!< when Alerting */
132 MISDN_BUSY, /*!< when BUSY */
133 MISDN_CONNECTED, /*!< when connected */
134 MISDN_PRECONNECTED, /*!< when connected */
135 MISDN_DISCONNECTED, /*!< when connected */
136 MISDN_RELEASED, /*!< when connected */
137 MISDN_BRIDGED, /*!< when bridged */
138 MISDN_CLEANING, /*!< when hangup from * but we were connected before */
139 MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP came from misdn */
140 MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
141 MISDN_HOLDED, /*!< if this chan is holded */
142 MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */
146 #define ORG_AST 1
147 #define ORG_MISDN 2
149 struct hold_info {
150 int port;
151 int channel;
154 struct chan_list {
156 char allowed_bearers[BUFFERSIZE + 1];
158 enum misdn_chan_state state;
159 int need_queue_hangup;
160 int need_hangup;
161 int need_busy;
163 int originator;
164 int noautorespond_on_setup;
166 int norxtone;
167 int notxtone;
169 int toggle_ec;
171 int incoming_early_audio;
173 int ignore_dtmf;
175 int pipe[2];
176 char ast_rd_buf[4096];
177 struct ast_frame frame;
179 int faxdetect; /*!< 0:no 1:yes 2:yes+nojump */
180 int faxdetect_timeout;
181 struct timeval faxdetect_tv;
182 int faxhandled;
184 int ast_dsp;
186 int jb_len;
187 int jb_upper_threshold;
188 struct misdn_jb *jb;
190 struct ast_dsp *dsp;
191 struct ast_trans_pvt *trans;
193 struct ast_channel * ast;
195 int dummy;
197 struct misdn_bchannel *bc;
199 struct hold_info hold_info;
201 unsigned int l3id;
202 int addr;
204 char context[BUFFERSIZE];
206 int zero_read_cnt;
207 int dropped_frame_cnt;
209 int far_alerting;
211 int nttimeout;
213 int other_pid;
214 struct chan_list *other_ch;
216 const struct ind_tone_zone_sound *ts;
218 int overlap_dial;
219 int overlap_dial_task;
220 ast_mutex_t overlap_tv_lock;
221 struct timeval overlap_tv;
223 struct chan_list *peer;
224 struct chan_list *next;
225 struct chan_list *prev;
226 struct chan_list *first;
231 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
232 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
234 struct robin_list {
235 char *group;
236 int port;
237 int channel;
238 struct robin_list *next;
239 struct robin_list *prev;
241 static struct robin_list *robin = NULL;
245 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
249 static inline void free_robin_list_r (struct robin_list *r)
251 if (r) {
252 if (r->next)
253 free_robin_list_r(r->next);
254 if (r->group)
255 free(r->group);
256 free(r);
260 static void free_robin_list ( void )
262 free_robin_list_r(robin);
263 robin = NULL;
266 static struct robin_list* get_robin_position (char *group)
268 struct robin_list *new;
269 struct robin_list *iter = robin;
270 for (; iter; iter = iter->next) {
271 if (!strcasecmp(iter->group, group))
272 return iter;
274 new = (struct robin_list *) calloc(1, sizeof(struct robin_list));
275 new->group = strndup(group, strlen(group));
276 new->port = 0;
277 new->channel = 0;
278 if (robin) {
279 new->next = robin;
280 robin->prev = new;
282 robin = new;
283 return robin;
287 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
288 static struct sched_context *misdn_tasks = NULL;
289 static pthread_t misdn_tasks_thread;
291 static int *misdn_ports;
293 static void chan_misdn_log(int level, int port, char *tmpl, ...)
294 __attribute__ ((format (printf, 3, 4)));
296 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
297 static void send_digit_to_chan(struct chan_list *cl, char digit );
299 static void hangup_chan(struct chan_list *ch);
300 static int pbx_start_chan(struct chan_list *ch);
302 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
303 #define MISDN_ASTERISK_PVT(ast) 1
305 #include "asterisk/strings.h"
307 /* #define MISDN_DEBUG 1 */
309 static const char misdn_type[] = "mISDN";
311 static int tracing = 0 ;
313 /*! \brief Only alaw and mulaw is allowed for now */
314 static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
316 static int *misdn_debug;
317 static int *misdn_debug_only;
318 static int max_ports;
320 static int *misdn_in_calls;
321 static int *misdn_out_calls;
324 struct chan_list dummy_cl;
326 struct chan_list *cl_te=NULL;
327 ast_mutex_t cl_te_lock;
329 static enum event_response_e
330 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
332 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
334 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
335 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
336 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
337 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
341 static int dialtone_indicate(struct chan_list *cl);
342 static int hanguptone_indicate(struct chan_list *cl);
343 static int stop_indicate(struct chan_list *cl);
345 static int start_bc_tones(struct chan_list *cl);
346 static int stop_bc_tones(struct chan_list *cl);
347 static void release_chan(struct misdn_bchannel *bc);
349 static int misdn_check_l2l1(struct ast_channel *chan, void *data);
350 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
351 static int misdn_facility_exec(struct ast_channel *chan, void *data);
353 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
356 void debug_numplan(int port, int numplan, char *type);
359 int add_out_calls(int port);
360 int add_in_calls(int port);
363 #ifdef MISDN_1_2
364 static int update_pipeline_config(struct misdn_bchannel *bc);
365 #else
366 static int update_ec_config(struct misdn_bchannel *bc);
367 #endif
371 /*************** Helpers *****************/
373 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
375 struct chan_list *tmp;
377 for (tmp=cl_te; tmp; tmp = tmp->next) {
378 if ( tmp->ast == ast ) return tmp;
381 return NULL;
384 static struct chan_list * get_chan_by_ast_name(char *name)
386 struct chan_list *tmp;
388 for (tmp=cl_te; tmp; tmp = tmp->next) {
389 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp;
392 return NULL;
397 struct allowed_bearers {
398 char *name; /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
399 char *display; /*!< Bearer capability displayable name */
400 int cap; /*!< SETUP message bearer capability field code value */
401 int deprecated; /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
404 /* *INDENT-OFF* */
405 static const struct allowed_bearers allowed_bearers_array[]= {
406 /* Name, Displayable Name Bearer Capability, Deprecated */
407 { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
408 { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
409 { "digital_unrestricted", "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
410 { "digital_restricted", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 0 },
411 { "digital_restriced", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 1 }, /* Allow misspelling for backwards compatibility */
412 { "video", "Video", INFO_CAPABILITY_VIDEO, 0 }
414 /* *INDENT-ON* */
416 static const char *bearer2str(int cap)
418 unsigned index;
420 for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
421 if (allowed_bearers_array[index].cap == cap) {
422 return allowed_bearers_array[index].display;
424 } /* end for */
426 return "Unknown Bearer";
430 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc)
432 switch (fac->Function) {
433 case Fac_CD:
434 chan_misdn_log(1,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber,
435 fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
436 break;
437 case Fac_AOCDCurrency:
438 if (fac->u.AOCDcur.chargeNotAvailable)
439 chan_misdn_log(1,bc->port," --> AOCD currency: charge not available\n");
440 else if (fac->u.AOCDcur.freeOfCharge)
441 chan_misdn_log(1,bc->port," --> AOCD currency: free of charge\n");
442 else if (fac->u.AOCDchu.billingId >= 0)
443 chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
444 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
445 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
446 else
447 chan_misdn_log(1,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
448 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
449 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
450 break;
451 case Fac_AOCDChargingUnit:
452 if (fac->u.AOCDchu.chargeNotAvailable)
453 chan_misdn_log(1,bc->port," --> AOCD charging unit: charge not available\n");
454 else if (fac->u.AOCDchu.freeOfCharge)
455 chan_misdn_log(1,bc->port," --> AOCD charging unit: free of charge\n");
456 else if (fac->u.AOCDchu.billingId >= 0)
457 chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
458 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
459 else
460 chan_misdn_log(1,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
461 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
462 break;
463 default:
464 chan_misdn_log(1,bc->port," --> unknown facility\n");
465 break;
469 static void print_bearer(struct misdn_bchannel *bc)
472 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
474 switch(bc->law) {
475 case INFO_CODEC_ALAW:
476 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
477 break;
478 case INFO_CODEC_ULAW:
479 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
480 break;
484 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
486 char buf[128];
488 if (!ast)
489 return;
491 if (originator == ORG_AST) {
492 ast = ast_bridged_channel(ast);
493 if (!ast)
494 return;
497 switch (bc->AOCDtype) {
498 case Fac_AOCDCurrency:
499 pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
500 if (bc->AOCD.currency.chargeNotAvailable)
501 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
502 else {
503 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
504 if (bc->AOCD.currency.freeOfCharge)
505 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
506 else {
507 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
508 if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
509 pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
510 if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf))
511 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
515 break;
516 case Fac_AOCDChargingUnit:
517 pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
518 if (bc->AOCD.chargingUnit.chargeNotAvailable)
519 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
520 else {
521 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
522 if (bc->AOCD.chargingUnit.freeOfCharge)
523 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
524 else {
525 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
526 if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
527 pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
528 if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf))
529 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
533 break;
534 default:
535 break;
539 /*************** Helpers END *************/
541 static void sighandler(int sig)
544 static void* misdn_tasks_thread_func (void *data)
546 int wait;
547 struct sigaction sa;
549 sa.sa_handler = sighandler;
550 sa.sa_flags = SA_NODEFER;
551 sigemptyset(&sa.sa_mask);
552 sigaddset(&sa.sa_mask, SIGUSR1);
553 sigaction(SIGUSR1, &sa, NULL);
555 sem_post((sem_t *)data);
557 while (1) {
558 wait = ast_sched_wait(misdn_tasks);
559 if (wait < 0)
560 wait = 8000;
561 if (poll(NULL, 0, wait) < 0)
562 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
563 ast_sched_runq(misdn_tasks);
565 return NULL;
568 static void misdn_tasks_init (void)
570 sem_t blocker;
571 int i = 5;
573 if (sem_init(&blocker, 0, 0)) {
574 perror("chan_misdn: Failed to initialize semaphore!");
575 exit(1);
578 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
580 misdn_tasks = sched_context_create();
581 pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
583 while (sem_wait(&blocker) && --i);
584 sem_destroy(&blocker);
587 static void misdn_tasks_destroy (void)
589 if (misdn_tasks) {
590 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
591 if ( pthread_cancel(misdn_tasks_thread) == 0 ) {
592 cb_log(4, 0, "Joining misdn_tasks thread\n");
593 pthread_join(misdn_tasks_thread, NULL);
595 sched_context_destroy(misdn_tasks);
599 static inline void misdn_tasks_wakeup (void)
601 pthread_kill(misdn_tasks_thread, SIGUSR1);
604 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data, int variable)
606 int task_id;
608 if (!misdn_tasks) {
609 misdn_tasks_init();
611 task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
612 misdn_tasks_wakeup();
614 return task_id;
617 static int misdn_tasks_add (int timeout, ast_sched_cb callback, const void *data)
619 return _misdn_tasks_add_variable(timeout, callback, data, 0);
622 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, const void *data)
624 return _misdn_tasks_add_variable(timeout, callback, data, 1);
627 static void misdn_tasks_remove (int task_id)
629 AST_SCHED_DEL(misdn_tasks, task_id);
632 static int misdn_l1_task (const void *data)
634 misdn_lib_isdn_l1watcher(*(int *)data);
635 chan_misdn_log(5, *(int *)data, "L1watcher timeout\n");
636 return 1;
639 static int misdn_overlap_dial_task (const void *data)
641 struct timeval tv_end, tv_now;
642 int diff;
643 struct chan_list *ch = (struct chan_list *)data;
645 chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
647 if (ch->state != MISDN_WAITING4DIGS) {
648 ch->overlap_dial_task = -1;
649 return 0;
652 ast_mutex_lock(&ch->overlap_tv_lock);
653 tv_end = ch->overlap_tv;
654 ast_mutex_unlock(&ch->overlap_tv_lock);
656 tv_end.tv_sec += ch->overlap_dial;
657 tv_now = ast_tvnow();
659 diff = ast_tvdiff_ms(tv_end, tv_now);
661 if (diff <= 100) {
662 char *dad=ch->bc->dad, sexten[]="s";
663 /* if we are 100ms near the timeout, we are satisfied.. */
664 stop_indicate(ch);
666 if (ast_strlen_zero(ch->bc->dad)) {
667 dad=sexten;
668 strcpy(ch->ast->exten, sexten);
671 if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->oad)) {
672 ch->state=MISDN_DIALING;
673 if (pbx_start_chan(ch) < 0) {
674 chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
675 goto misdn_overlap_dial_task_disconnect;
677 } else {
678 misdn_overlap_dial_task_disconnect:
679 hanguptone_indicate(ch);
680 ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
681 ch->state=MISDN_CLEANING;
682 misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
684 ch->overlap_dial_task = -1;
685 return 0;
686 } else
687 return diff;
690 static void send_digit_to_chan(struct chan_list *cl, char digit )
692 static const char* dtmf_tones[] = {
693 "!941+1336/100,!0/100", /* 0 */
694 "!697+1209/100,!0/100", /* 1 */
695 "!697+1336/100,!0/100", /* 2 */
696 "!697+1477/100,!0/100", /* 3 */
697 "!770+1209/100,!0/100", /* 4 */
698 "!770+1336/100,!0/100", /* 5 */
699 "!770+1477/100,!0/100", /* 6 */
700 "!852+1209/100,!0/100", /* 7 */
701 "!852+1336/100,!0/100", /* 8 */
702 "!852+1477/100,!0/100", /* 9 */
703 "!697+1633/100,!0/100", /* A */
704 "!770+1633/100,!0/100", /* B */
705 "!852+1633/100,!0/100", /* C */
706 "!941+1633/100,!0/100", /* D */
707 "!941+1209/100,!0/100", /* * */
708 "!941+1477/100,!0/100" }; /* # */
709 struct ast_channel *chan=cl->ast;
711 if (digit >= '0' && digit <='9')
712 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
713 else if (digit >= 'A' && digit <= 'D')
714 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
715 else if (digit == '*')
716 ast_playtones_start(chan,0,dtmf_tones[14], 0);
717 else if (digit == '#')
718 ast_playtones_start(chan,0,dtmf_tones[15], 0);
719 else {
720 /* not handled */
721 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
725 /*** CLI HANDLING ***/
726 static int misdn_set_debug(int fd, int argc, char *argv[])
728 int level;
730 if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
731 return RESULT_SHOWUSAGE;
733 level = atoi(argv[3]);
735 switch (argc) {
736 case 4:
737 case 5:
739 int i;
740 int only = 0;
741 if (argc == 5) {
742 if (strncasecmp(argv[4], "only", strlen(argv[4])))
743 return RESULT_SHOWUSAGE;
744 else
745 only = 1;
748 for (i = 0; i <= max_ports; i++) {
749 misdn_debug[i] = level;
750 misdn_debug_only[i] = only;
752 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
754 break;
755 case 6:
756 case 7:
758 int port;
759 if (strncasecmp(argv[4], "port", strlen(argv[4])))
760 return RESULT_SHOWUSAGE;
761 port = atoi(argv[5]);
762 if (port <= 0 || port > max_ports) {
763 switch (max_ports) {
764 case 0:
765 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
766 break;
767 case 1:
768 ast_cli(fd, "port number not valid! only port 1 is available.\n");
769 break;
770 default:
771 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
773 return 0;
775 if (argc == 7) {
776 if (strncasecmp(argv[6], "only", strlen(argv[6])))
777 return RESULT_SHOWUSAGE;
778 else
779 misdn_debug_only[port] = 1;
780 } else
781 misdn_debug_only[port] = 0;
782 misdn_debug[port] = level;
783 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
786 return 0;
789 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
791 if (argc != 5) return RESULT_SHOWUSAGE;
793 return 0;
796 static int misdn_port_block(int fd, int argc, char *argv[])
798 int port;
800 if (argc != 4)
801 return RESULT_SHOWUSAGE;
803 port = atoi(argv[3]);
805 misdn_lib_port_block(port);
807 return 0;
810 static int misdn_port_unblock(int fd, int argc, char *argv[])
812 int port;
814 if (argc != 4)
815 return RESULT_SHOWUSAGE;
817 port = atoi(argv[3]);
819 misdn_lib_port_unblock(port);
821 return 0;
825 static int misdn_restart_port (int fd, int argc, char *argv[])
827 int port;
829 if (argc != 4)
830 return RESULT_SHOWUSAGE;
832 port = atoi(argv[3]);
834 misdn_lib_port_restart(port);
836 return 0;
839 static int misdn_restart_pid (int fd, int argc, char *argv[])
841 int pid;
843 if (argc != 4)
844 return RESULT_SHOWUSAGE;
846 pid = atoi(argv[3]);
848 misdn_lib_pid_restart(pid);
850 return 0;
853 static int misdn_port_up (int fd, int argc, char *argv[])
855 int port;
857 if (argc != 4)
858 return RESULT_SHOWUSAGE;
860 port = atoi(argv[3]);
862 misdn_lib_get_port_up(port);
864 return 0;
867 static int misdn_port_down (int fd, int argc, char *argv[])
869 int port;
871 if (argc != 4)
872 return RESULT_SHOWUSAGE;
874 port = atoi(argv[3]);
876 misdn_lib_get_port_down(port);
878 return 0;
881 static inline void show_config_description (int fd, enum misdn_cfg_elements elem)
883 char section[BUFFERSIZE];
884 char name[BUFFERSIZE];
885 char desc[BUFFERSIZE];
886 char def[BUFFERSIZE];
887 char tmp[BUFFERSIZE];
889 misdn_cfg_get_name(elem, tmp, sizeof(tmp));
890 term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
891 misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
893 if (elem < MISDN_CFG_LAST)
894 term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
895 else
896 term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
898 if (*def)
899 ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
900 else
901 ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
904 static int misdn_show_config (int fd, int argc, char *argv[])
906 char buffer[BUFFERSIZE];
907 enum misdn_cfg_elements elem;
908 int linebreak;
909 int onlyport = -1;
910 int ok = 0;
912 if (argc >= 4) {
913 if (!strcmp(argv[3], "description")) {
914 if (argc == 5) {
915 enum misdn_cfg_elements elem = misdn_cfg_get_elem(argv[4]);
916 if (elem == MISDN_CFG_FIRST)
917 ast_cli(fd, "Unknown element: %s\n", argv[4]);
918 else
919 show_config_description(fd, elem);
920 return 0;
922 return RESULT_SHOWUSAGE;
924 if (!strcmp(argv[3], "descriptions")) {
925 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
926 for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
927 show_config_description(fd, elem);
928 ast_cli(fd, "\n");
930 ok = 1;
932 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
933 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) {
934 show_config_description(fd, elem);
935 ast_cli(fd, "\n");
937 ok = 1;
939 return ok ? 0 : RESULT_SHOWUSAGE;
941 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
942 ast_cli(fd, "Unknown option: %s\n", argv[3]);
943 return RESULT_SHOWUSAGE;
947 if (argc == 3 || onlyport == 0) {
948 ast_cli(fd, "Misdn General-Config:\n");
949 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
950 misdn_cfg_get_config_string(0, elem, buffer, BUFFERSIZE);
951 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
953 ast_cli(fd, "\n");
956 if (onlyport < 0) {
957 int port = misdn_cfg_get_next_port(0);
958 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
959 ast_cli(fd, "\n[PORT %d]\n", port);
960 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
961 misdn_cfg_get_config_string(port, elem, buffer, BUFFERSIZE);
962 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
964 ast_cli(fd, "\n");
968 if (onlyport > 0) {
969 if (misdn_cfg_is_port_valid(onlyport)) {
970 ast_cli(fd, "[PORT %d]\n", onlyport);
971 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
972 misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
973 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
975 ast_cli(fd, "\n");
976 } else {
977 ast_cli(fd, "Port %d is not active!\n", onlyport);
981 return 0;
984 struct state_struct {
985 enum misdn_chan_state state;
986 char txt[255];
989 static struct state_struct state_array[] = {
990 {MISDN_NOTHING,"NOTHING"}, /* at beginning */
991 {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */
992 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldn't match our ext */
993 {MISDN_INCOMING_SETUP,"INCOMING SETUP"}, /* when pbx_start */
994 {MISDN_DIALING,"DIALING"}, /* when pbx_start */
995 {MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */
996 {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */
997 {MISDN_CALLING,"CALLING"}, /* when misdn_call is called */
998 {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
999 {MISDN_ALERTING,"ALERTING"}, /* when Alerting */
1000 {MISDN_BUSY,"BUSY"}, /* when BUSY */
1001 {MISDN_CONNECTED,"CONNECTED"}, /* when connected */
1002 {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */
1003 {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
1004 {MISDN_RELEASED,"RELEASED"}, /* when connected */
1005 {MISDN_BRIDGED,"BRIDGED"}, /* when bridged */
1006 {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
1007 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1008 {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1009 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP came from misdn */
1010 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of misdn_hangup */
1013 static const char *misdn_get_ch_state(struct chan_list *p)
1015 int i;
1016 static char state[8];
1018 if( !p) return NULL;
1020 for (i = 0; i < sizeof(state_array) / sizeof(struct state_struct); i++) {
1021 if (state_array[i].state == p->state)
1022 return state_array[i].txt;
1025 snprintf(state, sizeof(state), "%d", p->state) ;
1027 return state;
1032 static void reload_config(void)
1034 int i, cfg_debug;
1036 if (!g_config_initialized) {
1037 ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
1038 return ;
1041 free_robin_list();
1042 misdn_cfg_reload();
1043 misdn_cfg_update_ptp();
1044 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
1045 misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
1047 for (i = 0; i <= max_ports; i++) {
1048 misdn_debug[i] = cfg_debug;
1049 misdn_debug_only[i] = 0;
1053 static int misdn_reload (int fd, int argc, char *argv[])
1055 ast_cli(fd, "Reloading mISDN configuration\n");
1056 reload_config();
1057 return 0;
1060 static void print_bc_info (int fd, struct chan_list *help, struct misdn_bchannel *bc)
1062 struct ast_channel *ast = help->ast;
1063 ast_cli(fd,
1064 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
1066 bc->pid, bc->port, bc->channel,
1067 bc->nt ? "NT" : "TE",
1068 help->originator == ORG_AST ? "*" : "I",
1069 ast ? ast->exten : NULL,
1070 ast ? ast->cid.cid_num : NULL,
1071 bc->rad,
1072 ast ? ast->context : NULL,
1073 misdn_get_ch_state(help)
1075 if (misdn_debug[bc->port] > 0)
1076 ast_cli(fd,
1077 " --> astname: %s\n"
1078 " --> ch_l3id: %x\n"
1079 " --> ch_addr: %x\n"
1080 " --> bc_addr: %x\n"
1081 " --> bc_l3id: %x\n"
1082 " --> display: %s\n"
1083 " --> activated: %d\n"
1084 " --> state: %s\n"
1085 " --> capability: %s\n"
1086 #ifdef MISDN_1_2
1087 " --> pipeline: %s\n"
1088 #else
1089 " --> echo_cancel: %d\n"
1090 #endif
1091 " --> notone : rx %d tx:%d\n"
1092 " --> bc_hold: %d\n",
1093 help->ast->name,
1094 help->l3id,
1095 help->addr,
1096 bc->addr,
1097 bc ? bc->l3_id : -1,
1098 bc->display,
1100 bc->active,
1101 bc_state2str(bc->bc_state),
1102 bearer2str(bc->capability),
1103 #ifdef MISDN_1_2
1104 bc->pipeline,
1105 #else
1106 bc->ec_enable,
1107 #endif
1109 help->norxtone, help->notxtone,
1110 bc->holded
1115 static int misdn_show_cls (int fd, int argc, char *argv[])
1117 struct chan_list *help;
1119 help = cl_te;
1121 ast_cli(fd, "Channel List: %p\n", cl_te);
1123 for (; help; help = help->next) {
1124 struct misdn_bchannel *bc = help->bc;
1125 struct ast_channel *ast = help->ast;
1126 if (!ast) {
1127 if (!bc) {
1128 ast_cli(fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
1129 continue;
1131 ast_cli(fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
1132 continue;
1135 if (misdn_debug[0] > 2)
1136 ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
1137 if (bc) {
1138 print_bc_info(fd, help, bc);
1139 } else {
1140 if (help->state == MISDN_HOLDED) {
1141 ast_cli(fd, "ITS A HOLDED BC:\n");
1142 ast_cli(fd, " --> l3_id: %x\n"
1143 " --> dad:%s oad:%s\n"
1144 " --> hold_port: %d\n"
1145 " --> hold_channel: %d\n",
1146 help->l3id,
1147 ast->exten,
1148 ast->cid.cid_num,
1149 help->hold_info.port,
1150 help->hold_info.channel
1152 } else {
1153 ast_cli(fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
1158 misdn_dump_chanlist();
1160 return 0;
1163 static int misdn_show_cl (int fd, int argc, char *argv[])
1165 struct chan_list *help;
1167 if (argc != 4)
1168 return RESULT_SHOWUSAGE;
1170 help = cl_te;
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;
1184 return 0;
1187 ast_mutex_t lock;
1188 int MAXTICS = 8;
1190 static int misdn_set_tics (int fd, int argc, char *argv[])
1192 if (argc != 4)
1193 return RESULT_SHOWUSAGE;
1195 MAXTICS = atoi(argv[3]);
1197 return 0;
1200 static int misdn_show_stacks (int fd, int argc, char *argv[])
1202 int port;
1204 ast_cli(fd, "BEGIN STACK_LIST:\n");
1205 for (port = misdn_cfg_get_next_port(0); port > 0;
1206 port = misdn_cfg_get_next_port(port)) {
1207 char buf[128];
1208 get_show_stack_details(port, buf);
1209 ast_cli(fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
1212 return 0;
1215 static int misdn_show_ports_stats (int fd, int argc, char *argv[])
1217 int port;
1219 ast_cli(fd, "Port\tin_calls\tout_calls\n");
1220 for (port = misdn_cfg_get_next_port(0); port > 0;
1221 port = misdn_cfg_get_next_port(port)) {
1222 ast_cli(fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
1224 ast_cli(fd, "\n");
1226 return 0;
1229 static int misdn_show_port (int fd, int argc, char *argv[])
1231 int port;
1232 char buf[128];
1234 if (argc != 4)
1235 return RESULT_SHOWUSAGE;
1237 port = atoi(argv[3]);
1239 ast_cli(fd, "BEGIN STACK_LIST:\n");
1240 get_show_stack_details(port, buf);
1241 ast_cli(fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
1243 return 0;
1246 static int misdn_send_cd (int fd, int argc, char *argv[])
1248 char *channame;
1249 char *nr;
1250 struct chan_list *tmp;
1252 if (argc != 5)
1253 return RESULT_SHOWUSAGE;
1257 channame = argv[3];
1258 nr = argv[4];
1260 ast_cli(fd, "Sending Calldeflection (%s) to %s\n", nr, channame);
1261 tmp = get_chan_by_ast_name(channame);
1262 if (!tmp) {
1263 ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame);
1264 return 0;
1267 if (strlen(nr) >= 15) {
1268 ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame);
1269 return 0;
1271 tmp->bc->fac_out.Function = Fac_CD;
1272 ast_copy_string((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber));
1273 misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
1276 return 0;
1279 static int misdn_send_restart(int fd, int argc, char *argv[])
1281 int port;
1282 int channel;
1284 if (argc < 4 || argc > 5)
1285 return RESULT_SHOWUSAGE;
1287 port = atoi(argv[3]);
1289 if (argc == 5) {
1290 channel = atoi(argv[4]);
1291 misdn_lib_send_restart(port, channel);
1292 } else {
1293 misdn_lib_send_restart(port, -1);
1296 return 0;
1299 static int misdn_send_digit (int fd, int argc, char *argv[])
1301 char *channame;
1302 char *msg;
1303 struct chan_list *tmp;
1304 int i, msglen;
1306 if (argc != 5)
1307 return RESULT_SHOWUSAGE;
1309 channame = argv[3];
1310 msg = argv[4];
1311 msglen = strlen(msg);
1313 ast_cli(fd, "Sending %s to %s\n", msg, channame);
1315 tmp = get_chan_by_ast_name(channame);
1316 if (!tmp) {
1317 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
1318 return 0;
1320 #if 1
1321 for (i = 0; i < msglen; i++) {
1322 ast_cli(fd, "Sending: %c\n", msg[i]);
1323 send_digit_to_chan(tmp, msg[i]);
1324 /* res = ast_safe_sleep(tmp->ast, 250); */
1325 usleep(250000);
1326 /* res = ast_waitfor(tmp->ast,100); */
1328 #else
1329 ast_dtmf_stream(tmp->ast, NULL, msg, 250);
1330 #endif
1332 return 0;
1335 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
1337 char *channame;
1338 struct chan_list *tmp;
1340 if (argc != 4)
1341 return RESULT_SHOWUSAGE;
1343 channame = argv[3];
1345 ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
1347 tmp = get_chan_by_ast_name(channame);
1348 if (!tmp) {
1349 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
1350 return 0;
1353 tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
1355 if (tmp->toggle_ec) {
1356 #ifdef MISDN_1_2
1357 update_pipeline_config(tmp->bc);
1358 #else
1359 update_ec_config(tmp->bc);
1360 #endif
1361 manager_ec_enable(tmp->bc);
1362 } else {
1363 manager_ec_disable(tmp->bc);
1366 return 0;
1369 static int misdn_send_display (int fd, int argc, char *argv[])
1371 char *channame;
1372 char *msg;
1373 struct chan_list *tmp;
1375 if (argc != 5)
1376 return RESULT_SHOWUSAGE;
1378 channame = argv[3];
1379 msg = argv[4];
1381 ast_cli(fd, "Sending %s to %s\n", msg, channame);
1382 tmp = get_chan_by_ast_name(channame);
1384 if (tmp && tmp->bc) {
1385 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
1386 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
1387 } else {
1388 ast_cli(fd, "No such channel %s\n", channame);
1389 return RESULT_FAILURE;
1392 return RESULT_SUCCESS;
1395 static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
1397 struct ast_channel *c;
1398 int which=0;
1399 char *ret;
1400 if (pos != rpos)
1401 return NULL;
1402 c = ast_channel_walk_locked(NULL);
1403 while(c) {
1404 if (!strncasecmp(word, c->name, strlen(word))) {
1405 if (++which > state)
1406 break;
1408 ast_mutex_unlock(&c->lock);
1409 c = ast_channel_walk_locked(c);
1411 if (c) {
1412 ret = strdup(c->name);
1413 ast_mutex_unlock(&c->lock);
1414 } else
1415 ret = NULL;
1416 return ret;
1419 static char *complete_ch(const char *line, const char *word, int pos, int state)
1421 return complete_ch_helper(line, word, pos, state, 3);
1424 static char *complete_debug_port (const char *line, const char *word, int pos, int state)
1426 if (state)
1427 return NULL;
1429 switch (pos) {
1430 case 4:
1431 if (*word == 'p')
1432 return strdup("port");
1433 else if (*word == 'o')
1434 return strdup("only");
1435 break;
1436 case 6:
1437 if (*word == 'o')
1438 return strdup("only");
1439 break;
1441 return NULL;
1444 static char *complete_show_config (const char *line, const char *word, int pos, int state)
1446 char buffer[BUFFERSIZE];
1447 enum misdn_cfg_elements elem;
1448 int wordlen = strlen(word);
1449 int which = 0;
1450 int port = 0;
1452 switch (pos) {
1453 case 3:
1454 if ((!strncmp(word, "description", wordlen)) && (++which > state))
1455 return strdup("description");
1456 if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
1457 return strdup("descriptions");
1458 if ((!strncmp(word, "0", wordlen)) && (++which > state))
1459 return strdup("0");
1460 while ((port = misdn_cfg_get_next_port(port)) != -1) {
1461 snprintf(buffer, sizeof(buffer), "%d", port);
1462 if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
1463 return strdup(buffer);
1466 break;
1467 case 4:
1468 if (strstr(line, "description ")) {
1469 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
1470 if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
1471 continue;
1472 misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
1473 if (!wordlen || !strncmp(word, buffer, wordlen)) {
1474 if (++which > state)
1475 return strdup(buffer);
1478 } else if (strstr(line, "descriptions ")) {
1479 if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
1480 return strdup("general");
1481 if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
1482 return strdup("ports");
1484 break;
1486 return NULL;
1489 static struct ast_cli_entry chan_misdn_clis[] = {
1490 { {"misdn","send","calldeflect", NULL}, misdn_send_cd, "Sends CallDeflection to mISDN Channel",
1491 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch },
1492 { {"misdn","send","digit", NULL}, misdn_send_digit, "Sends DTMF Digit to mISDN Channel",
1493 "Usage: misdn send digit <channel> \"<msg>\" \n"
1494 " Send <digit> to <channel> as DTMF Tone\n"
1495 " when channel is a mISDN channel\n", complete_ch },
1496 { {"misdn","toggle","echocancel", NULL}, misdn_toggle_echocancel, "Toggles EchoCancel on mISDN Channel",
1497 "Usage: misdn toggle echocancel <channel>\n", complete_ch },
1498 { {"misdn","send","display", NULL}, misdn_send_display, "Sends Text to mISDN Channel",
1499 "Usage: misdn send display <channel> \"<msg>\" \n"
1500 " Send <msg> to <channel> as Display Message\n"
1501 " when channel is a mISDN channel\n", complete_ch },
1502 { {"misdn","show","config", NULL}, misdn_show_config, "Shows internal mISDN config, read from cfg-file",
1503 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1504 " Use 0 for <port> to only print the general config.\n", complete_show_config },
1505 { {"misdn","reload", NULL}, misdn_reload, "Reloads internal mISDN config, read from cfg-file",
1506 "Usage: misdn reload\n" },
1507 { {"misdn","set","tics", NULL}, misdn_set_tics, "",
1508 "\n" },
1509 { {"misdn","show","channels", NULL}, misdn_show_cls, "Shows internal mISDN chan_list",
1510 "Usage: misdn show channels\n" },
1511 { {"misdn","show","channel", NULL}, misdn_show_cl, "Shows internal mISDN chan_list",
1512 "Usage: misdn show channels\n", complete_ch },
1513 { {"misdn","port","block", NULL}, misdn_port_block, "Blocks the given port",
1514 "Usage: misdn port block\n" },
1515 { {"misdn","port","unblock", NULL}, misdn_port_unblock, "Unblocks the given port",
1516 "Usage: misdn port unblock\n" },
1517 { {"misdn","restart","port", NULL}, misdn_restart_port, "Restarts the given port",
1518 "Usage: misdn restart port\n" },
1519 { {"misdn","restart","pid", NULL}, misdn_restart_pid, "Restarts the given pid",
1520 "Usage: misdn restart pid\n" },
1521 { {"misdn","send","restart", NULL}, misdn_send_restart,
1522 "Sends a restart for every bchannel on the given port",
1523 "Usage: misdn send restart <port>\n"},
1524 { {"misdn","port","up", NULL}, misdn_port_up, "Tries to establish L1 on the given port",
1525 "Usage: misdn port up <port>\n" },
1526 { {"misdn","port","down", NULL}, misdn_port_down, "Tries to deactivate the L1 on the given port",
1527 "Usage: misdn port down <port>\n" },
1528 { {"misdn","show","stacks", NULL}, misdn_show_stacks, "Shows internal mISDN stack_list",
1529 "Usage: misdn show stacks\n" },
1530 { {"misdn","show","ports","stats", NULL}, misdn_show_ports_stats, "Shows chan_misdns call statistics per port",
1531 "Usage: misdn show port stats\n" },
1532 { {"misdn","show","port", NULL}, misdn_show_port, "Shows detailed information for given port",
1533 "Usage: misdn show port <port>\n" },
1534 { {"misdn","set","debug", NULL}, misdn_set_debug, "Sets Debuglevel of chan_misdn",
1535 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port },
1536 { {"misdn","set","crypt","debug", NULL}, misdn_set_crypt_debug, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1537 "Usage: misdn set crypt debug <level>\n" }
1540 static int update_config(struct chan_list *ch, int orig)
1542 struct ast_channel *ast;
1543 struct misdn_bchannel *bc;
1544 int port, hdlc = 0;
1545 int pres, screen;
1547 if (!ch) {
1548 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1549 return -1;
1552 ast = ch->ast;
1553 bc = ch->bc;
1554 if (! ast || ! bc) {
1555 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1556 return -1;
1559 port = bc->port;
1561 chan_misdn_log(7, port, "update_config: Getting Config\n");
1563 misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1565 if (hdlc) {
1566 switch (bc->capability) {
1567 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1568 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1569 chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
1570 bc->hdlc = 1;
1571 break;
1576 misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
1577 misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
1578 chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
1580 if (pres < 0 || screen < 0) {
1581 chan_misdn_log(2, port, " --> pres: %x\n", ast->cid.cid_pres);
1583 switch (ast->cid.cid_pres & 0x60) {
1584 case AST_PRES_RESTRICTED:
1585 bc->pres = 1;
1586 chan_misdn_log(2, port, " --> PRES: Restricted (1)\n");
1587 break;
1588 case AST_PRES_UNAVAILABLE:
1589 bc->pres = 2;
1590 chan_misdn_log(2, port, " --> PRES: Unavailable (2)\n");
1591 break;
1592 default:
1593 bc->pres = 0;
1594 chan_misdn_log(2, port, " --> PRES: Allowed (0)\n");
1595 break;
1598 switch (ast->cid.cid_pres & 0x3) {
1599 default:
1600 case AST_PRES_USER_NUMBER_UNSCREENED:
1601 bc->screen = 0;
1602 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0)\n");
1603 break;
1604 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
1605 bc->screen = 1;
1606 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (1)\n");
1607 break;
1608 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
1609 bc->screen = 2;
1610 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (2)\n");
1611 break;
1612 case AST_PRES_NETWORK_NUMBER:
1613 bc->screen = 3;
1614 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (3)\n");
1615 break;
1617 } else {
1618 bc->screen = screen;
1619 bc->pres = pres;
1622 return 0;
1626 static void config_jitterbuffer(struct chan_list *ch)
1628 struct misdn_bchannel *bc = ch->bc;
1629 int len = ch->jb_len, threshold = ch->jb_upper_threshold;
1631 chan_misdn_log(5, bc->port, "config_jb: Called\n");
1633 if (! len) {
1634 chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
1635 bc->nojitter=1;
1636 } else {
1637 if (len <= 100 || len > 8000) {
1638 chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1639 len = 1000;
1642 if ( threshold > len ) {
1643 chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1646 if ( ch->jb) {
1647 cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
1648 misdn_jb_destroy(ch->jb);
1649 ch->jb = NULL;
1652 ch->jb=misdn_jb_init(len, threshold);
1654 if (!ch->jb )
1655 bc->nojitter = 1;
1660 void debug_numplan(int port, int numplan, char *type)
1662 switch (numplan) {
1663 case NUMPLAN_INTERNATIONAL:
1664 chan_misdn_log(2, port, " --> %s: International\n", type);
1665 break;
1666 case NUMPLAN_NATIONAL:
1667 chan_misdn_log(2, port, " --> %s: National\n", type);
1668 break;
1669 case NUMPLAN_SUBSCRIBER:
1670 chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
1671 break;
1672 case NUMPLAN_UNKNOWN:
1673 chan_misdn_log(2, port, " --> %s: Unknown\n", type);
1674 break;
1675 /* Maybe we should cut off the prefix if present ? */
1676 default:
1677 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1678 break;
1683 #ifdef MISDN_1_2
1684 static int update_pipeline_config(struct misdn_bchannel *bc)
1686 int ec;
1688 misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
1690 if (*bc->pipeline)
1691 return 0;
1693 misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1694 if (ec == 1)
1695 ast_copy_string(bc->pipeline, "mg2ec", sizeof(bc->pipeline));
1696 else if (ec > 1)
1697 snprintf(bc->pipeline, sizeof(bc->pipeline), "mg2ec(deftaps=%d)", ec);
1699 return 0;
1701 #else
1702 static int update_ec_config(struct misdn_bchannel *bc)
1704 int ec;
1705 int port = bc->port;
1707 misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1709 if (ec == 1) {
1710 bc->ec_enable = 1;
1711 } else if (ec > 1) {
1712 bc->ec_enable = 1;
1713 bc->ec_deftaps = ec;
1716 return 0;
1718 #endif
1721 static int read_config(struct chan_list *ch, int orig)
1723 struct ast_channel *ast;
1724 struct misdn_bchannel *bc;
1725 int port;
1726 int hdlc = 0;
1727 char lang[BUFFERSIZE + 1];
1728 char localmusicclass[BUFFERSIZE + 1];
1729 char faxdetect[BUFFERSIZE + 1];
1730 char buf[256];
1731 char buf2[256];
1732 ast_group_t pg;
1733 ast_group_t cg;
1735 if (!ch) {
1736 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1737 return -1;
1740 ast = ch->ast;
1741 bc = ch->bc;
1742 if (! ast || ! bc) {
1743 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1744 return -1;
1747 port = bc->port;
1748 chan_misdn_log(1, port, "read_config: Getting Config\n");
1750 misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
1751 ast_string_field_set(ast, language, lang);
1753 misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
1754 ast_string_field_set(ast, musicclass, localmusicclass);
1756 misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
1757 misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
1759 misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
1761 misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
1763 misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
1765 if (ch->ast_dsp) {
1766 ch->ignore_dtmf = 1;
1769 misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
1770 misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int));
1772 misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(int));
1774 misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
1776 misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
1778 misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE);
1780 misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1782 if (hdlc) {
1783 switch (bc->capability) {
1784 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1785 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1786 chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
1787 bc->hdlc = 1;
1788 break;
1792 /*Initialize new Jitterbuffer*/
1793 misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
1794 misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
1796 config_jitterbuffer(ch);
1798 misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
1800 ast_copy_string(ast->context, ch->context, sizeof(ast->context));
1802 #ifdef MISDN_1_2
1803 update_pipeline_config(bc);
1804 #else
1805 update_ec_config(bc);
1806 #endif
1809 int eb3;
1811 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
1812 bc->early_bconnect=eb3;
1815 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
1816 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
1818 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
1819 ast->pickupgroup = pg;
1820 ast->callgroup = cg;
1822 if (orig == ORG_AST) {
1823 char callerid[BUFFERSIZE + 1];
1825 misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
1827 if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
1828 if (strstr(faxdetect, "nojump"))
1829 ch->faxdetect = 2;
1830 else
1831 ch->faxdetect = 1;
1834 misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1835 if ( ! ast_strlen_zero(callerid) ) {
1836 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1837 ast_copy_string(bc->oad, callerid, sizeof(bc->oad));
1840 misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
1841 misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
1842 misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1843 debug_numplan(port, bc->dnumplan, "TON");
1844 debug_numplan(port, bc->onumplan, "LTON");
1845 debug_numplan(port, bc->cpnnumplan, "CTON");
1847 ch->overlap_dial = 0;
1848 } else { /** ORIGINATOR MISDN **/
1849 char prefix[BUFFERSIZE + 1] = "";
1851 if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
1852 if (strstr(faxdetect, "nojump"))
1853 ch->faxdetect = 2;
1854 else
1855 ch->faxdetect = 1;
1858 misdn_cfg_get(port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1859 debug_numplan(port, bc->cpnnumplan, "CTON");
1861 switch (bc->onumplan) {
1862 case NUMPLAN_INTERNATIONAL:
1863 misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1864 break;
1866 case NUMPLAN_NATIONAL:
1867 misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1868 break;
1869 default:
1870 break;
1873 ast_copy_string(buf, bc->oad, sizeof(buf));
1874 snprintf(bc->oad, sizeof(bc->oad), "%s%s", prefix, buf);
1876 if (!ast_strlen_zero(bc->dad)) {
1877 ast_copy_string(bc->orig_dad, bc->dad, sizeof(bc->orig_dad));
1880 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
1881 ast_copy_string(bc->dad, bc->keypad, sizeof(bc->dad));
1884 prefix[0] = 0;
1886 switch (bc->dnumplan) {
1887 case NUMPLAN_INTERNATIONAL:
1888 misdn_cfg_get(bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1889 break;
1890 case NUMPLAN_NATIONAL:
1891 misdn_cfg_get(bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1892 break;
1893 default:
1894 break;
1897 ast_copy_string(buf, bc->dad, sizeof(buf));
1898 snprintf(bc->dad, sizeof(bc->dad), "%s%s", prefix, buf);
1900 if (strcmp(bc->dad, ast->exten)) {
1901 ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
1904 ast_set_callerid(ast, bc->oad, NULL, bc->oad);
1906 if ( !ast_strlen_zero(bc->rad) ) {
1907 if (ast->cid.cid_rdnis)
1908 free(ast->cid.cid_rdnis);
1909 ast->cid.cid_rdnis = strdup(bc->rad);
1912 misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
1913 ast_mutex_init(&ch->overlap_tv_lock);
1914 } /* ORIG MISDN END */
1916 ch->overlap_dial_task = -1;
1918 if (ch->faxdetect || ch->ast_dsp) {
1919 misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
1920 if (!ch->dsp)
1921 ch->dsp = ast_dsp_new();
1922 if (ch->dsp) {
1923 if (ch->faxdetect)
1924 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
1925 else
1926 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT );
1928 if (!ch->trans)
1929 ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
1932 /* AOCD initialization */
1933 bc->AOCDtype = Fac_None;
1935 return 0;
1939 /*****************************/
1940 /*** AST Indications Start ***/
1941 /*****************************/
1943 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
1945 int port = 0;
1946 int r;
1947 int exceed;
1948 int bridging;
1949 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(ast);
1950 struct misdn_bchannel *newbc;
1951 char *opts = NULL, *ext, *tokb;
1952 char *dest_cp = ast_strdupa(dest);
1954 ext = strtok_r(dest_cp, "/", &tokb);
1956 if (ext) {
1957 ext = strtok_r(NULL, "/", &tokb);
1958 if (ext) {
1959 opts = strtok_r(NULL, "/", &tokb);
1960 } else {
1961 chan_misdn_log(0, 0, "misdn_call: No Extension given!\n");
1962 return -1;
1966 if (!ast) {
1967 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1968 return -1;
1971 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) {
1972 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1973 ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
1974 ast_setstate(ast, AST_STATE_DOWN);
1975 return -1;
1978 if (!ch) {
1979 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1980 ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
1981 ast_setstate(ast, AST_STATE_DOWN);
1982 return -1;
1985 newbc = ch->bc;
1987 if (!newbc) {
1988 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1989 ast->hangupcause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
1990 ast_setstate(ast, AST_STATE_DOWN);
1991 return -1;
1994 port = newbc->port;
1996 if ((exceed = add_out_calls(port))) {
1997 char tmp[16];
1998 snprintf(tmp, sizeof(tmp), "%d", exceed);
1999 pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
2000 return -1;
2003 chan_misdn_log(1, port, "* CALL: %s\n", dest);
2005 chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n", ast->exten, ast->name, ast->context);
2007 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n", ast->exten);
2008 if (ast->exten) {
2009 ast_copy_string(ast->exten, ext, sizeof(ast->exten));
2010 ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
2013 ast_copy_string(newbc->rad, S_OR(ast->cid.cid_rdnis, ""), sizeof(newbc->rad));
2015 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n", ast->cid.cid_num);
2016 if (ast_strlen_zero(newbc->oad) && !ast_strlen_zero(ast->cid.cid_num)) {
2017 ast_copy_string(newbc->oad, ast->cid.cid_num, sizeof(newbc->oad));
2020 newbc->capability = ast->transfercapability;
2021 pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
2022 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
2023 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
2026 /* update screening and presentation */
2027 update_config(ch, ORG_AST);
2029 /* fill in some ies from channel vary*/
2030 import_ch(ast, newbc, ch);
2032 /* Finally The Options Override Everything */
2033 if (opts)
2034 misdn_set_opt_exec(ast, opts);
2035 else
2036 chan_misdn_log(2, port, "NO OPTS GIVEN\n");
2038 /*check for bridging*/
2039 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
2040 if (bridging && ch->other_ch) {
2041 #ifdef MISDN_1_2
2042 chan_misdn_log(1, port, "Disabling EC (aka Pipeline) on both Sides\n");
2043 *ch->bc->pipeline = 0;
2044 *ch->other_ch->bc->pipeline = 0;
2045 #else
2046 chan_misdn_log(1, port, "Disabling EC on both Sides\n");
2047 ch->bc->ec_enable = 0;
2048 ch->other_ch->bc->ec_enable = 0;
2049 #endif
2052 r = misdn_lib_send_event( newbc, EVENT_SETUP );
2054 /** we should have l3id after sending setup **/
2055 ch->l3id = newbc->l3_id;
2057 if ( r == -ENOCHAN ) {
2058 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
2059 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
2060 ast->hangupcause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
2061 ast_setstate(ast, AST_STATE_DOWN);
2062 return -1;
2065 chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
2067 ast_setstate(ast, AST_STATE_DIALING);
2068 ast->hangupcause = AST_CAUSE_NORMAL_CLEARING;
2070 if (newbc->nt)
2071 stop_bc_tones(ch);
2073 ch->state = MISDN_CALLING;
2075 return 0;
2079 static int misdn_answer(struct ast_channel *ast)
2081 struct chan_list *p;
2082 const char *tmp;
2084 if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
2086 chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
2088 if (!p) {
2089 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
2090 ast_queue_hangup(ast);
2093 if (!p->bc) {
2094 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
2096 ast_queue_hangup(ast);
2099 tmp = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
2100 if (!ast_strlen_zero(tmp)) {
2101 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
2102 ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
2103 } else {
2104 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
2107 tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
2108 if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
2109 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
2110 p->bc->nodsp = 1;
2111 p->bc->hdlc = 0;
2112 p->bc->nojitter = 1;
2115 p->state = MISDN_CONNECTED;
2116 stop_indicate(p);
2118 if ( ast_strlen_zero(p->bc->cad) ) {
2119 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
2120 ast_copy_string(p->bc->cad, p->bc->dad, sizeof(p->bc->cad));
2123 misdn_lib_send_event( p->bc, EVENT_CONNECT);
2124 start_bc_tones(p);
2126 return 0;
2129 static int misdn_digit_begin(struct ast_channel *chan, char digit)
2131 /* XXX Modify this callback to support Asterisk controlling the length of DTMF */
2132 return 0;
2135 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
2137 struct chan_list *p;
2138 struct misdn_bchannel *bc;
2140 if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) return -1;
2142 bc = p->bc;
2143 chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
2145 if (!bc) {
2146 ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
2147 return -1;
2150 switch (p->state ) {
2151 case MISDN_CALLING:
2153 int l;
2154 char buf[8];
2155 buf[0]=digit;
2156 buf[1]=0;
2158 l = sizeof(bc->infos_pending);
2159 strncat(bc->infos_pending, buf, l - strlen(bc->infos_pending) - 1);
2161 break;
2162 case MISDN_CALLING_ACKNOWLEDGE:
2164 bc->info_dad[0]=digit;
2165 bc->info_dad[1]=0;
2168 int l = sizeof(bc->dad);
2169 strncat(bc->dad, bc->info_dad, l - strlen(bc->dad) - 1);
2172 int l = sizeof(p->ast->exten);
2173 strncpy(p->ast->exten, bc->dad, l);
2174 p->ast->exten[l-1] = 0;
2177 misdn_lib_send_event( bc, EVENT_INFORMATION);
2179 break;
2180 default:
2181 /* Do not send Digits in CONNECTED State, when
2182 * the other side is too mISDN. */
2183 if (p->other_ch )
2184 return 0;
2186 if ( bc->send_dtmf )
2187 send_digit_to_chan(p,digit);
2188 break;
2191 return 0;
2195 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
2197 struct chan_list *p;
2199 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
2201 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);
2203 p->ast = ast;
2205 return 0;
2210 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
2212 struct chan_list *p;
2214 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
2215 ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
2216 return -1;
2219 if (!p->bc ) {
2220 chan_misdn_log(1, 0, "* IND : Indication from %s\n", ast->exten);
2221 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
2222 return -1;
2225 chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n", cond, ast->exten);
2227 switch (cond) {
2228 case AST_CONTROL_BUSY:
2229 chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc ? p->bc->pid : -1);
2230 ast_setstate(ast, AST_STATE_BUSY);
2232 p->bc->out_cause = AST_CAUSE_USER_BUSY;
2233 if (p->state != MISDN_CONNECTED) {
2234 start_bc_tones(p);
2235 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2236 } else {
2237 chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
2239 return -1;
2240 case AST_CONTROL_RING:
2241 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
2242 return -1;
2243 case AST_CONTROL_RINGING:
2244 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
2245 switch (p->state) {
2246 case MISDN_ALERTING:
2247 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);
2248 break;
2249 case MISDN_CONNECTED:
2250 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);
2251 return -1;
2252 default:
2253 p->state = MISDN_ALERTING;
2254 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
2255 misdn_lib_send_event( p->bc, EVENT_ALERTING);
2257 if (p->other_ch && p->other_ch->bc) {
2258 if (misdn_inband_avail(p->other_ch->bc)) {
2259 chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
2260 break;
2263 if (!p->other_ch->bc->nt) {
2264 chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
2265 break;
2269 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
2270 ast_setstate(ast, AST_STATE_RINGING);
2272 if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio)
2273 chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
2274 else
2275 return -1;
2277 break;
2278 case AST_CONTROL_ANSWER:
2279 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
2280 start_bc_tones(p);
2281 break;
2282 case AST_CONTROL_TAKEOFFHOOK:
2283 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
2284 return -1;
2285 case AST_CONTROL_OFFHOOK:
2286 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
2287 return -1;
2288 case AST_CONTROL_FLASH:
2289 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
2290 break;
2291 case AST_CONTROL_PROGRESS:
2292 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
2293 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
2294 break;
2295 case AST_CONTROL_PROCEEDING:
2296 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
2297 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
2298 break;
2299 case AST_CONTROL_CONGESTION:
2300 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
2302 p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
2303 start_bc_tones(p);
2304 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2306 if (p->bc->nt) {
2307 hanguptone_indicate(p);
2309 break;
2310 case -1 :
2311 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
2313 stop_indicate(p);
2315 if (p->state == MISDN_CONNECTED)
2316 start_bc_tones(p);
2317 break;
2318 case AST_CONTROL_HOLD:
2319 ast_moh_start(ast,data,ast->musicclass);
2320 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
2321 break;
2322 case AST_CONTROL_UNHOLD:
2323 ast_moh_stop(ast);
2324 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
2325 break;
2326 default:
2327 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
2330 return 0;
2333 static int misdn_hangup(struct ast_channel *ast)
2335 struct chan_list *p;
2336 struct misdn_bchannel *bc = NULL;
2337 const char *varcause = NULL;
2339 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
2341 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
2343 if (!p) {
2344 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2345 return 0 ;
2348 bc = p->bc;
2350 if (bc) {
2351 const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
2352 if (tmp) {
2353 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
2354 strcpy(bc->uu, tmp);
2355 bc->uulen=strlen(bc->uu);
2359 MISDN_ASTERISK_TECH_PVT(ast) = NULL;
2360 p->ast = NULL;
2362 if (ast->_state == AST_STATE_RESERVED ||
2363 p->state == MISDN_NOTHING ||
2364 p->state == MISDN_HOLDED ||
2365 p->state == MISDN_HOLD_DISCONNECT ) {
2367 CLEAN_CH:
2368 /* between request and call */
2369 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
2370 MISDN_ASTERISK_TECH_PVT(ast) = NULL;
2372 ast_mutex_lock(&release_lock);
2373 cl_dequeue_chan(&cl_te, p);
2374 close(p->pipe[0]);
2375 close(p->pipe[1]);
2376 free(p);
2377 ast_mutex_unlock(&release_lock);
2379 if (bc)
2380 misdn_lib_release(bc);
2382 return 0;
2385 if (!bc) {
2386 ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
2387 goto CLEAN_CH;
2391 p->need_hangup = 0;
2392 p->need_queue_hangup = 0;
2393 p->need_busy = 0;
2396 if (!p->bc->nt)
2397 stop_bc_tones(p);
2399 bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
2401 if ((varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
2402 (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
2403 int tmpcause = atoi(varcause);
2404 bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
2407 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));
2408 chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
2409 chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
2410 chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
2411 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
2413 switch (p->state) {
2414 case MISDN_INCOMING_SETUP:
2415 case MISDN_CALLING:
2416 /* This is the only place in misdn_hangup, where we
2417 * can call release_chan, else it might create lot's of trouble
2418 * */
2419 ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
2420 release_chan(bc);
2422 p->state = MISDN_CLEANING;
2423 if (bc->need_release_complete)
2424 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
2425 break;
2426 case MISDN_HOLDED:
2427 case MISDN_DIALING:
2428 start_bc_tones(p);
2429 hanguptone_indicate(p);
2431 if (bc->need_disconnect)
2432 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2433 break;
2434 case MISDN_CALLING_ACKNOWLEDGE:
2435 start_bc_tones(p);
2436 hanguptone_indicate(p);
2438 if (bc->need_disconnect)
2439 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2440 break;
2442 case MISDN_ALERTING:
2443 case MISDN_PROGRESS:
2444 case MISDN_PROCEEDING:
2445 if (p->originator != ORG_AST)
2446 hanguptone_indicate(p);
2448 /*p->state=MISDN_CLEANING;*/
2449 if (bc->need_disconnect)
2450 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2451 break;
2452 case MISDN_CONNECTED:
2453 case MISDN_PRECONNECTED:
2454 /* Alerting or Disconnect */
2455 if (p->bc->nt) {
2456 start_bc_tones(p);
2457 hanguptone_indicate(p);
2458 p->bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
2460 if (bc->need_disconnect)
2461 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2463 /*p->state=MISDN_CLEANING;*/
2464 break;
2465 case MISDN_DISCONNECTED:
2466 if (bc->need_release)
2467 misdn_lib_send_event( bc, EVENT_RELEASE);
2468 p->state = MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
2469 break;
2471 case MISDN_RELEASED:
2472 case MISDN_CLEANING:
2473 p->state = MISDN_CLEANING;
2474 break;
2476 case MISDN_BUSY:
2477 break;
2479 case MISDN_HOLD_DISCONNECT:
2480 /* need to send release here */
2481 chan_misdn_log(1, bc->port, " --> cause %d\n", bc->cause);
2482 chan_misdn_log(1, bc->port, " --> out_cause %d\n", bc->out_cause);
2484 bc->out_cause = -1;
2485 if (bc->need_release)
2486 misdn_lib_send_event(bc, EVENT_RELEASE);
2487 p->state = MISDN_CLEANING;
2488 break;
2489 default:
2490 if (bc->nt) {
2491 bc->out_cause = -1;
2492 if (bc->need_release)
2493 misdn_lib_send_event(bc, EVENT_RELEASE);
2494 p->state = MISDN_CLEANING;
2495 } else {
2496 if (bc->need_disconnect)
2497 misdn_lib_send_event(bc, EVENT_DISCONNECT);
2501 p->state = MISDN_CLEANING;
2503 chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
2505 return 0;
2509 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
2511 struct ast_frame *f,*f2;
2513 if (tmp->trans) {
2514 f2 = ast_translate(tmp->trans, frame, 0);
2515 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2516 } else {
2517 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2518 return NULL;
2521 if (!f || (f->frametype != AST_FRAME_DTMF))
2522 return frame;
2524 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
2526 if (tmp->faxdetect && (f->subclass == 'f')) {
2527 /* Fax tone -- Handle and return NULL */
2528 if (!tmp->faxhandled) {
2529 struct ast_channel *ast = tmp->ast;
2530 tmp->faxhandled++;
2531 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
2532 tmp->bc->rxgain = 0;
2533 isdn_lib_update_rxgain(tmp->bc);
2534 tmp->bc->txgain = 0;
2535 isdn_lib_update_txgain(tmp->bc);
2536 #ifdef MISDN_1_2
2537 *tmp->bc->pipeline = 0;
2538 #else
2539 tmp->bc->ec_enable = 0;
2540 #endif
2541 isdn_lib_update_ec(tmp->bc);
2542 isdn_lib_stop_dtmf(tmp->bc);
2543 switch (tmp->faxdetect) {
2544 case 1:
2545 if (strcmp(ast->exten, "fax")) {
2546 char *context;
2547 char context_tmp[BUFFERSIZE];
2548 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
2549 context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
2550 if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
2551 if (option_verbose > 2)
2552 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
2553 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2554 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2555 if (ast_async_goto(ast, context, "fax", 1))
2556 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
2557 } else
2558 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
2559 } else {
2560 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2562 break;
2563 case 2:
2564 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
2565 break;
2567 } else {
2568 ast_log(LOG_DEBUG, "Fax already handled\n");
2572 if (tmp->ast_dsp && (f->subclass != 'f')) {
2573 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
2576 return f;
2580 static struct ast_frame *misdn_read(struct ast_channel *ast)
2582 struct chan_list *tmp;
2583 fd_set rrfs;
2584 struct timeval tv;
2585 int len, t;
2587 if (!ast) {
2588 chan_misdn_log(1, 0, "misdn_read called without ast\n");
2589 return NULL;
2591 if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
2592 chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
2593 return NULL;
2596 if (!tmp->bc && !(tmp->state == MISDN_HOLDED)) {
2597 chan_misdn_log(1, 0, "misdn_read called without bc\n");
2598 return NULL;
2601 tv.tv_sec=0;
2602 tv.tv_usec=20000;
2604 FD_ZERO(&rrfs);
2605 FD_SET(tmp->pipe[0],&rrfs);
2607 t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
2609 if (!t) {
2610 chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
2611 len=160;
2614 if (t<0) {
2615 chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
2616 return NULL;
2619 if (FD_ISSET(tmp->pipe[0],&rrfs)) {
2620 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
2622 if (len<=0) {
2623 /* we hangup here, since our pipe is closed */
2624 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
2625 return NULL;
2628 } else {
2629 return NULL;
2632 tmp->frame.frametype = AST_FRAME_VOICE;
2633 tmp->frame.subclass = AST_FORMAT_ALAW;
2634 tmp->frame.datalen = len;
2635 tmp->frame.samples = len;
2636 tmp->frame.mallocd = 0;
2637 tmp->frame.offset = 0;
2638 tmp->frame.delivery = ast_tv(0,0);
2639 tmp->frame.src = NULL;
2640 tmp->frame.data = tmp->ast_rd_buf;
2642 if (tmp->faxdetect && !tmp->faxhandled) {
2643 if (tmp->faxdetect_timeout) {
2644 if (ast_tvzero(tmp->faxdetect_tv)) {
2645 tmp->faxdetect_tv = ast_tvnow();
2646 chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
2647 return process_ast_dsp(tmp, &tmp->frame);
2648 } else {
2649 struct timeval tv_now = ast_tvnow();
2650 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
2651 if (diff <= (tmp->faxdetect_timeout * 1000)) {
2652 chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
2653 return process_ast_dsp(tmp, &tmp->frame);
2654 } else {
2655 chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
2656 tmp->faxdetect = 0;
2657 return &tmp->frame;
2660 } else {
2661 chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
2662 return process_ast_dsp(tmp, &tmp->frame);
2664 } else {
2665 if (tmp->ast_dsp)
2666 return process_ast_dsp(tmp, &tmp->frame);
2667 else
2668 return &tmp->frame;
2673 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
2675 struct chan_list *ch;
2676 int i = 0;
2678 if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2680 if (ch->state == MISDN_HOLDED) {
2681 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
2682 return 0;
2685 if (!ch->bc ) {
2686 ast_log(LOG_WARNING, "private but no bc\n");
2687 return -1;
2690 if (ch->notxtone) {
2691 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
2692 return 0;
2696 if (!frame->subclass) {
2697 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
2698 return 0;
2701 if (!(frame->subclass & prefformat)) {
2703 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
2704 return 0;
2708 if (!frame->samples ) {
2709 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
2711 if (!strcmp(frame->src,"ast_prod")) {
2712 chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
2714 if (ch->ts) {
2715 chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
2716 misdn_lib_tone_generator_start(ch->bc);
2718 return 0;
2721 return -1;
2724 if ( ! ch->bc->addr ) {
2725 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
2726 return 0;
2729 #if MISDN_DEBUG
2731 int i, max = 5 > frame->samples ? frame->samples : 5;
2733 printf("write2mISDN %p %d bytes: ", p, frame->samples);
2735 for (i = 0; i < max; i++)
2736 printf("%2.2x ", ((char*) frame->data)[i]);
2737 printf ("\n");
2739 #endif
2741 switch (ch->bc->bc_state) {
2742 case BCHAN_ACTIVATED:
2743 case BCHAN_BRIDGED:
2744 break;
2745 default:
2746 if (!ch->dropped_frame_cnt)
2747 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);
2749 ch->dropped_frame_cnt++;
2750 if (ch->dropped_frame_cnt > 100) {
2751 ch->dropped_frame_cnt = 0;
2752 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);
2755 return 0;
2758 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
2759 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
2760 /* Buffered Transmit (triggered by read from isdn side)*/
2761 if (misdn_jb_fill(ch->jb, frame->data, frame->samples) < 0) {
2762 if (ch->bc->active)
2763 cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
2766 } else {
2767 /*transmit without jitterbuffer*/
2768 i = misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
2771 return 0;
2777 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
2778 struct ast_channel *c1, int flags,
2779 struct ast_frame **fo,
2780 struct ast_channel **rc,
2781 int timeoutms)
2784 struct chan_list *ch1, *ch2;
2785 struct ast_channel *carr[2], *who;
2786 int to = -1;
2787 struct ast_frame *f;
2788 int p1_b, p2_b;
2789 int bridging;
2791 ch1 = get_chan_by_ast(c0);
2792 ch2 = get_chan_by_ast(c1);
2794 carr[0] = c0;
2795 carr[1] = c1;
2797 if (!(ch1 && ch2))
2798 return -1;
2800 misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(int));
2801 misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(int));
2803 if (! p1_b || ! p2_b) {
2804 ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
2805 return AST_BRIDGE_FAILED;
2808 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2809 if (bridging) {
2810 /* trying to make a mISDN_dsp conference */
2811 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
2812 misdn_lib_bridge(ch1->bc, ch2->bc);
2815 if (option_verbose > 2)
2816 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
2818 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
2820 if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
2821 ch1->ignore_dtmf = 1;
2823 if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
2824 ch2->ignore_dtmf = 1;
2826 for (;/*ever*/;) {
2827 to = -1;
2828 who = ast_waitfor_n(carr, 2, &to);
2830 if (!who) {
2831 ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
2832 break;
2834 f = ast_read(who);
2836 if (!f || f->frametype == AST_FRAME_CONTROL) {
2837 /* got hangup .. */
2839 if (!f)
2840 chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
2841 else
2842 chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
2844 *fo = f;
2845 *rc = who;
2846 break;
2849 if ( f->frametype == AST_FRAME_DTMF ) {
2850 chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
2852 *fo = f;
2853 *rc = who;
2854 break;
2857 #if 0
2858 if (f->frametype == AST_FRAME_VOICE) {
2859 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2861 continue;
2863 #endif
2865 if (who == c0) {
2866 ast_write(c1, f);
2868 else {
2869 ast_write(c0, f);
2873 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
2875 misdn_lib_split_bridge(ch1->bc, ch2->bc);
2877 return AST_BRIDGE_COMPLETE;
2880 /** AST INDICATIONS END **/
2882 static int dialtone_indicate(struct chan_list *cl)
2884 const struct ind_tone_zone_sound *ts = NULL;
2885 struct ast_channel *ast = cl->ast;
2886 int nd = 0;
2888 if (!ast) {
2889 chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
2890 return -1;
2893 misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
2895 if (nd) {
2896 chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
2897 return 0;
2900 chan_misdn_log(3, cl->bc->port, " --> Dial\n");
2901 ts = ast_get_indication_tone(ast->zone, "dial");
2902 cl->ts = ts;
2904 if (ts) {
2905 cl->notxtone = 0;
2906 cl->norxtone = 0;
2907 /* This prods us in misdn_write */
2908 ast_playtones_start(ast, 0, ts->data, 0);
2911 return 0;
2914 static int hanguptone_indicate(struct chan_list *cl)
2916 misdn_lib_send_tone(cl->bc, TONE_HANGUP);
2917 return 0;
2920 static int stop_indicate(struct chan_list *cl)
2922 struct ast_channel *ast = cl->ast;
2924 if (!ast) {
2925 chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
2926 return -1;
2929 chan_misdn_log(3, cl->bc->port, " --> None\n");
2930 misdn_lib_tone_generator_stop(cl->bc);
2931 ast_playtones_stop(ast);
2933 cl->ts = NULL;
2934 /*ast_deactivate_generator(ast);*/
2936 return 0;
2940 static int start_bc_tones(struct chan_list* cl)
2942 misdn_lib_tone_generator_stop(cl->bc);
2943 cl->notxtone = 0;
2944 cl->norxtone = 0;
2945 return 0;
2948 static int stop_bc_tones(struct chan_list *cl)
2950 if (!cl) return -1;
2952 cl->notxtone = 1;
2953 cl->norxtone = 1;
2955 return 0;
2959 static struct chan_list *init_chan_list(int orig)
2961 struct chan_list *cl;
2963 cl = calloc(1, sizeof(struct chan_list));
2964 if (!cl) {
2965 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
2966 return NULL;
2969 cl->originator = orig;
2970 cl->need_queue_hangup = 1;
2971 cl->need_hangup = 1;
2972 cl->need_busy = 1;
2973 cl->overlap_dial_task = -1;
2975 return cl;
2978 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
2980 struct ast_channel *tmp = NULL;
2981 char group[BUFFERSIZE + 1] = "";
2982 char buf[128];
2983 char buf2[128], *ext = NULL, *port_str;
2984 char *tokb = NULL, *p = NULL;
2985 int channel = 0, port = 0;
2986 struct misdn_bchannel *newbc = NULL;
2987 int dec = 0;
2989 struct chan_list *cl = init_chan_list(ORG_AST);
2991 snprintf(buf, sizeof(buf), "%s/%s", misdn_type, (char*)data);
2992 ast_copy_string(buf2, data, 128);
2994 port_str = strtok_r(buf2, "/", &tokb);
2996 ext = strtok_r(NULL, "/", &tokb);
2998 if (port_str) {
2999 if (port_str[0] == 'g' && port_str[1] == ':' ) {
3000 /* We make a group call lets checkout which ports are in my group */
3001 port_str += 2;
3002 ast_copy_string(group, port_str, sizeof(group));
3003 chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
3004 } else if ((p = strchr(port_str, ':'))) {
3005 /* we have a preselected channel */
3006 *p = 0;
3007 channel = atoi(++p);
3008 port = atoi(port_str);
3009 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
3010 } else {
3011 port = atoi(port_str);
3013 } else {
3014 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extensions.conf\n", ext);
3015 return NULL;
3018 if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
3019 chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
3020 dec = 1;
3023 if (!ast_strlen_zero(group)) {
3024 char cfg_group[BUFFERSIZE + 1];
3025 struct robin_list *rr = NULL;
3027 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
3028 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
3029 rr = get_robin_position(group);
3032 if (rr) {
3033 int port_start = 0;
3034 int port_bak = rr->port;
3035 int chan_bak = rr->channel;
3037 if (!rr->port)
3038 rr->port = misdn_cfg_get_next_port_spin(rr->port);
3040 for (; rr->port > 0; rr->port = misdn_cfg_get_next_port_spin(rr->port)) {
3041 int port_up;
3042 int check;
3043 int max_chan;
3044 int last_chance = 0;
3046 misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
3047 if (strcasecmp(cfg_group, group))
3048 continue;
3050 misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
3051 port_up = misdn_lib_port_up(rr->port, check);
3053 if (check && !port_up)
3054 chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
3056 if (check && port_up < 0)
3057 ast_log(LOG_WARNING,"This port (%d) is blocked\n", rr->port);
3059 if ((port_start == rr->port) && (port_up <= 0))
3060 break;
3062 if (!port_start)
3063 port_start = rr->port;
3065 if (port_up <= 0)
3066 continue;
3068 max_chan = misdn_lib_get_maxchans(rr->port);
3070 for (++rr->channel; !last_chance && rr->channel <= max_chan; ++rr->channel) {
3071 if (rr->port == port_bak && rr->channel == chan_bak)
3072 last_chance = 1;
3074 chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr->port, rr->channel);
3075 newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0);
3076 if (newbc) {
3077 chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
3078 if (port_up)
3079 chan_misdn_log(4, rr->port, "portup:%d\n", port_up);
3080 port = rr->port;
3081 break;
3085 if (newbc || last_chance)
3086 break;
3088 rr->channel = 0;
3090 if (!newbc) {
3091 rr->port = port_bak;
3092 rr->channel = chan_bak;
3094 } else {
3095 for (port = misdn_cfg_get_next_port(0); port > 0;
3096 port = misdn_cfg_get_next_port(port)) {
3098 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
3100 chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
3101 if (!strcasecmp(cfg_group, group)) {
3102 int port_up;
3103 int check;
3104 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
3105 port_up = misdn_lib_port_up(port, check);
3107 chan_misdn_log(4, port, "portup:%d\n", port_up);
3109 if (port_up > 0) {
3110 newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
3111 if (newbc)
3112 break;
3118 /* Group dial failed ?*/
3119 if (!newbc) {
3120 ast_log(LOG_WARNING,
3121 "Could not Dial out on group '%s'.\n"
3122 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
3123 "\tOr there was no free channel on none of the ports\n\n"
3124 , group);
3125 return NULL;
3127 } else { /* 'Normal' Port dial * Port dial */
3128 if (channel)
3129 chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
3130 newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
3132 if (!newbc) {
3133 ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
3134 return NULL;
3139 /* create ast_channel and link all the objects together */
3140 cl->bc = newbc;
3142 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
3143 if (!tmp) {
3144 ast_log(LOG_ERROR,"Could not create Asterisk object\n");
3145 return NULL;
3148 cl->ast=tmp;
3150 /* register chan in local list */
3151 cl_queue_chan(&cl_te, cl) ;
3153 /* fill in the config into the objects */
3154 read_config(cl, ORG_AST);
3156 /* important */
3157 cl->need_hangup = 0;
3159 return tmp;
3163 static int misdn_send_text(struct ast_channel *chan, const char *text)
3165 struct chan_list *tmp = chan->tech_pvt;
3167 if (tmp && tmp->bc) {
3168 ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
3169 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
3170 } else {
3171 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
3172 return -1;
3175 return 0;
3178 static struct ast_channel_tech misdn_tech = {
3179 .type = "mISDN",
3180 .description = "Channel driver for mISDN Support (Bri/Pri)",
3181 .capabilities = AST_FORMAT_ALAW ,
3182 .requester = misdn_request,
3183 .send_digit_begin = misdn_digit_begin,
3184 .send_digit_end = misdn_digit_end,
3185 .call = misdn_call,
3186 .bridge = misdn_bridge,
3187 .hangup = misdn_hangup,
3188 .answer = misdn_answer,
3189 .read = misdn_read,
3190 .write = misdn_write,
3191 .indicate = misdn_indication,
3192 .fixup = misdn_fixup,
3193 .send_text = misdn_send_text,
3194 .properties = 0
3197 static struct ast_channel_tech misdn_tech_wo_bridge = {
3198 .type = "mISDN",
3199 .description = "Channel driver for mISDN Support (Bri/Pri)",
3200 .capabilities = AST_FORMAT_ALAW ,
3201 .requester = misdn_request,
3202 .send_digit_begin = misdn_digit_begin,
3203 .send_digit_end = misdn_digit_end,
3204 .call = misdn_call,
3205 .hangup = misdn_hangup,
3206 .answer = misdn_answer,
3207 .read = misdn_read,
3208 .write = misdn_write,
3209 .indicate = misdn_indication,
3210 .fixup = misdn_fixup,
3211 .send_text = misdn_send_text,
3212 .properties = 0
3216 static int glob_channel = 0;
3218 static void update_name(struct ast_channel *tmp, int port, int c)
3220 int chan_offset = 0;
3221 int tmp_port = misdn_cfg_get_next_port(0);
3222 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
3223 if (tmp_port == port)
3224 break;
3225 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
3227 if (c < 0)
3228 c = 0;
3230 ast_string_field_build(tmp, name, "%s/%d-u%d",
3231 misdn_type, chan_offset + c, glob_channel++);
3233 chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
3236 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
3238 struct ast_channel *tmp;
3239 char *cid_name = 0, *cid_num = 0;
3240 int chan_offset = 0;
3241 int tmp_port = misdn_cfg_get_next_port(0);
3242 int bridging;
3244 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
3245 if (tmp_port == port)
3246 break;
3247 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
3249 if (c < 0)
3250 c = 0;
3252 if (callerid) {
3253 ast_callerid_parse(callerid, &cid_name, &cid_num);
3256 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
3257 if (tmp) {
3258 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
3260 tmp->nativeformats = prefformat;
3262 tmp->readformat = format;
3263 tmp->rawreadformat = format;
3264 tmp->writeformat = format;
3265 tmp->rawwriteformat = format;
3267 tmp->tech_pvt = chlist;
3269 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
3271 if (bridging)
3272 tmp->tech = &misdn_tech;
3273 else
3274 tmp->tech = &misdn_tech_wo_bridge;
3276 tmp->writeformat = format;
3277 tmp->readformat = format;
3278 tmp->priority=1;
3280 if (exten)
3281 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
3282 else
3283 chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
3285 if (callerid)
3286 /* Don't use ast_set_callerid() here because it will
3287 * generate a needless NewCallerID event */
3288 tmp->cid.cid_ani = ast_strdup(cid_num);
3290 if (pipe(chlist->pipe) < 0)
3291 perror("Pipe failed\n");
3292 tmp->fds[0] = chlist->pipe[0];
3294 if (state == AST_STATE_RING)
3295 tmp->rings = 1;
3296 else
3297 tmp->rings = 0;
3299 } else {
3300 chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
3303 return tmp;
3306 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
3308 struct chan_list *help = list;
3309 for (; help; help = help->next) {
3310 if (help->bc == bc) return help;
3313 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
3315 return NULL;
3318 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
3320 struct chan_list *help = list;
3321 for (; help; help = help->next) {
3322 if ( help->bc && (help->bc->pid == pid) ) return help;
3325 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
3327 return NULL;
3330 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
3332 struct chan_list *help = list;
3334 if (bc->pri) return NULL;
3336 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
3337 for (;help; help = help->next) {
3338 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state == MISDN_HOLDED, help->hold_info.channel);
3339 if ((help->state == MISDN_HOLDED) &&
3340 (help->hold_info.port == bc->port))
3341 return help;
3343 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
3345 return NULL;
3349 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
3351 struct chan_list *help = list;
3353 for (; help; help = help->next) {
3354 if ( (help->state == MISDN_HOLDED) &&
3355 (help->l3id == l3_id)
3357 return help;
3360 return NULL;
3363 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
3365 chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
3367 ast_mutex_lock(&cl_te_lock);
3368 if (!*list) {
3369 *list = chan;
3370 } else {
3371 struct chan_list *help = *list;
3372 for (; help->next; help = help->next);
3373 help->next = chan;
3375 chan->next = NULL;
3376 ast_mutex_unlock(&cl_te_lock);
3379 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
3381 struct chan_list *help;
3383 if (chan->dsp)
3384 ast_dsp_free(chan->dsp);
3385 if (chan->trans)
3386 ast_translator_free_path(chan->trans);
3388 ast_mutex_lock(&cl_te_lock);
3389 if (!*list) {
3390 ast_mutex_unlock(&cl_te_lock);
3391 return;
3394 if (*list == chan) {
3395 *list = (*list)->next;
3396 ast_mutex_unlock(&cl_te_lock);
3397 return;
3400 for (help = *list; help->next; help = help->next) {
3401 if (help->next == chan) {
3402 help->next = help->next->next;
3403 ast_mutex_unlock(&cl_te_lock);
3404 return;
3408 ast_mutex_unlock(&cl_te_lock);
3411 /** Channel Queue End **/
3414 static int pbx_start_chan(struct chan_list *ch)
3416 int ret = ast_pbx_start(ch->ast);
3418 if (ret >= 0)
3419 ch->need_hangup = 0;
3420 else
3421 ch->need_hangup = 1;
3423 return ret;
3426 static void hangup_chan(struct chan_list *ch)
3428 int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
3429 if (!ch) {
3430 cb_log(1, 0, "Cannot hangup chan, no ch\n");
3431 return;
3434 cb_log(5, port, "hangup_chan called\n");
3436 if (ch->need_hangup) {
3437 cb_log(2, port, " --> hangup\n");
3438 send_cause2ast(ch->ast, ch->bc, ch);
3439 ch->need_hangup = 0;
3440 ch->need_queue_hangup = 0;
3441 if (ch->ast)
3442 ast_hangup(ch->ast);
3443 return;
3446 if (!ch->need_queue_hangup) {
3447 cb_log(2, port, " --> No need to queue hangup\n");
3450 ch->need_queue_hangup = 0;
3451 if (ch->ast) {
3452 send_cause2ast(ch->ast, ch->bc, ch);
3454 if (ch->ast)
3455 ast_queue_hangup(ch->ast);
3456 cb_log(2, port, " --> queue_hangup\n");
3457 } else {
3458 cb_log(1, port, "Cannot hangup chan, no ast\n");
3462 /** Isdn asks us to release channel, pendant to misdn_hangup **/
3463 static void release_chan(struct misdn_bchannel *bc) {
3464 struct ast_channel *ast = NULL;
3466 ast_mutex_lock(&release_lock);
3468 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
3469 if (!ch) {
3470 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
3471 ast_mutex_unlock(&release_lock);
3472 return;
3475 if (ch->ast) {
3476 ast = ch->ast;
3479 chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
3481 /*releasing jitterbuffer*/
3482 if (ch->jb ) {
3483 misdn_jb_destroy(ch->jb);
3484 ch->jb = NULL;
3485 } else {
3486 if (!bc->nojitter)
3487 chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
3490 if (ch->overlap_dial) {
3491 if (ch->overlap_dial_task != -1) {
3492 misdn_tasks_remove(ch->overlap_dial_task);
3493 ch->overlap_dial_task = -1;
3495 ast_mutex_destroy(&ch->overlap_tv_lock);
3498 if (ch->originator == ORG_AST) {
3499 misdn_out_calls[bc->port]--;
3500 } else {
3501 misdn_in_calls[bc->port]--;
3504 if (ch) {
3505 close(ch->pipe[0]);
3506 close(ch->pipe[1]);
3508 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
3509 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));
3510 chan_misdn_log(3, bc->port, " --> * State Down\n");
3511 MISDN_ASTERISK_TECH_PVT(ast) = NULL;
3513 if (ast->_state != AST_STATE_RESERVED) {
3514 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
3515 ast_setstate(ast, AST_STATE_DOWN);
3519 ch->state = MISDN_CLEANING;
3520 cl_dequeue_chan(&cl_te, ch);
3522 free(ch);
3523 } else {
3524 /* chan is already cleaned, so exiting */
3527 ast_mutex_unlock(&release_lock);
3528 /*** release end **/
3531 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
3533 chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
3535 tmp_ch->state = MISDN_HOLD_DISCONNECT;
3537 ast_moh_stop(ast_bridged_channel(holded_chan->ast));
3539 holded_chan->state=MISDN_CONNECTED;
3540 /* misdn_lib_transfer(holded_chan->bc); */
3541 ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
3545 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
3547 char predial[256]="";
3548 char *p = predial;
3550 struct ast_frame fr;
3552 strncpy(predial, ast->exten, sizeof(predial) -1 );
3554 ch->state = MISDN_DIALING;
3556 if (!ch->noautorespond_on_setup) {
3557 if (bc->nt) {
3558 int ret;
3559 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3560 } else {
3561 int ret;
3562 if ( misdn_lib_is_ptp(bc->port)) {
3563 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3564 } else {
3565 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
3568 } else {
3569 ch->state = MISDN_INCOMING_SETUP;
3572 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);
3574 strncpy(ast->exten, "s", 2);
3576 if (pbx_start_chan(ch) < 0) {
3577 ast = NULL;
3578 hangup_chan(ch);
3579 hanguptone_indicate(ch);
3581 if (bc->nt)
3582 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
3583 else
3584 misdn_lib_send_event(bc, EVENT_DISCONNECT );
3588 while (!ast_strlen_zero(p) ) {
3589 fr.frametype = AST_FRAME_DTMF;
3590 fr.subclass = *p;
3591 fr.src = NULL;
3592 fr.data = NULL;
3593 fr.datalen = 0;
3594 fr.samples = 0;
3595 fr.mallocd = 0;
3596 fr.offset = 0;
3597 fr.delivery = ast_tv(0,0);
3599 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
3600 ast_queue_frame(ch->ast, &fr);
3602 p++;
3608 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) {
3609 if (!ast) {
3610 chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
3611 return;
3613 if (!bc) {
3614 chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
3615 return;
3617 if (!ch) {
3618 chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
3619 return;
3622 ast->hangupcause = bc->cause;
3624 switch (bc->cause) {
3626 case AST_CAUSE_UNALLOCATED:
3627 case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
3628 case AST_CAUSE_NO_ROUTE_DESTINATION:
3629 case 4: /* Send special information tone */
3630 case AST_CAUSE_NUMBER_CHANGED:
3631 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
3632 /* Congestion Cases */
3634 * Not Queueing the Congestion anymore, since we want to hear
3635 * the inband message
3637 chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
3638 ch->state = MISDN_BUSY;
3640 ast_queue_control(ast, AST_CONTROL_CONGESTION);
3642 break;
3644 case AST_CAUSE_CALL_REJECTED:
3645 case AST_CAUSE_USER_BUSY:
3646 ch->state = MISDN_BUSY;
3648 if (!ch->need_busy) {
3649 chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
3650 break;
3653 chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
3655 ast_queue_control(ast, AST_CONTROL_BUSY);
3657 ch->need_busy = 0;
3659 break;
3664 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
3666 const char *tmp;
3668 tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
3669 if (tmp) {
3670 ch->other_pid = atoi(tmp);
3671 chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
3672 if (ch->other_pid > 0) {
3673 ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
3674 if (ch->other_ch)
3675 ch->other_ch->other_ch = ch;
3679 tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
3680 if (tmp && (atoi(tmp) == 1)) {
3681 bc->sending_complete = 1;
3684 tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
3685 if (tmp) {
3686 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
3687 ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
3688 bc->uulen = strlen(bc->uu);
3691 tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
3692 if (tmp) {
3693 ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
3697 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
3699 char tmp[32];
3700 chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
3701 snprintf(tmp, sizeof(tmp), "%d", bc->pid);
3702 pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
3704 if (bc->sending_complete) {
3705 snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
3706 pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
3709 if (bc->urate) {
3710 snprintf(tmp, sizeof(tmp), "%d", bc->urate);
3711 pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
3714 if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
3715 bc->uu[bc->uulen] = 0;
3716 pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
3719 if (!ast_strlen_zero(bc->keypad))
3720 pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
3723 int add_in_calls(int port)
3725 int max_in_calls;
3727 misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
3728 misdn_in_calls[port]++;
3730 if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
3731 ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
3732 return misdn_in_calls[port] - max_in_calls;
3735 return 0;
3738 int add_out_calls(int port)
3740 int max_out_calls;
3742 misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
3744 if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
3745 ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
3746 return (misdn_out_calls[port] + 1) - max_out_calls;
3749 misdn_out_calls[port]++;
3751 return 0;
3754 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
3755 if (pbx_start_chan(ch) < 0) {
3756 hangup_chan(ch);
3757 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
3758 if (bc->nt) {
3759 hanguptone_indicate(ch);
3760 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
3761 } else
3762 misdn_lib_send_event(bc, EVENT_RELEASE);
3766 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
3767 ch->state=MISDN_WAITING4DIGS;
3768 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3769 if (bc->nt && !bc->dad[0])
3770 dialtone_indicate(ch);
3774 /************************************************************/
3775 /* Receive Events from isdn_lib here */
3776 /************************************************************/
3777 static enum event_response_e
3778 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
3780 int msn_valid;
3781 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
3783 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */
3784 int debuglevel = 1;
3785 if ( event == EVENT_CLEANUP && !user_data)
3786 debuglevel = 5;
3788 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");
3789 if (debuglevel == 1) {
3790 misdn_lib_log_ies(bc);
3791 chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
3795 if (!ch) {
3796 switch(event) {
3797 case EVENT_SETUP:
3798 case EVENT_DISCONNECT:
3799 case EVENT_PORT_ALARM:
3800 case EVENT_RETRIEVE:
3801 case EVENT_NEW_BC:
3802 case EVENT_FACILITY:
3803 break;
3804 case EVENT_RELEASE_COMPLETE:
3805 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
3806 break;
3807 case EVENT_CLEANUP:
3808 case EVENT_TONE_GENERATE:
3809 case EVENT_BCHAN_DATA:
3810 return -1;
3811 default:
3812 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);
3813 return -1;
3817 if (ch) {
3818 switch (event) {
3819 case EVENT_TONE_GENERATE:
3820 break;
3821 case EVENT_DISCONNECT:
3822 case EVENT_RELEASE:
3823 case EVENT_RELEASE_COMPLETE:
3824 case EVENT_CLEANUP:
3825 case EVENT_TIMEOUT:
3826 if (!ch->ast)
3827 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));
3828 break;
3829 default:
3830 if (!ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
3831 if (event != EVENT_BCHAN_DATA)
3832 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
3833 return -1;
3839 switch (event) {
3840 case EVENT_PORT_ALARM:
3842 int boa = 0;
3843 misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
3844 if (boa) {
3845 cb_log(1, bc->port, " --> blocking\n");
3846 misdn_lib_port_block(bc->port);
3849 break;
3850 case EVENT_BCHAN_ACTIVATED:
3851 break;
3853 case EVENT_NEW_CHANNEL:
3854 update_name(ch->ast,bc->port,bc->channel);
3855 break;
3857 case EVENT_NEW_L3ID:
3858 ch->l3id=bc->l3_id;
3859 ch->addr=bc->addr;
3860 break;
3862 case EVENT_NEW_BC:
3863 if (!ch) {
3864 ch = find_holded(cl_te,bc);
3867 if (!ch) {
3868 ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
3869 break;
3872 if (bc)
3873 ch->bc = (struct misdn_bchannel *)user_data;
3874 break;
3876 case EVENT_DTMF_TONE:
3878 /* sending INFOS as DTMF-Frames :) */
3879 struct ast_frame fr;
3881 memset(&fr, 0, sizeof(fr));
3882 fr.frametype = AST_FRAME_DTMF;
3883 fr.subclass = bc->dtmf ;
3884 fr.src = NULL;
3885 fr.data = NULL;
3886 fr.datalen = 0;
3887 fr.samples = 0;
3888 fr.mallocd = 0;
3889 fr.offset = 0;
3890 fr.delivery = ast_tv(0,0);
3892 if (!ch->ignore_dtmf) {
3893 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
3894 ast_queue_frame(ch->ast, &fr);
3895 } else {
3896 chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
3899 break;
3900 case EVENT_STATUS:
3901 break;
3903 case EVENT_INFORMATION:
3905 if ( ch->state != MISDN_CONNECTED )
3906 stop_indicate(ch);
3908 if (!ch->ast)
3909 break;
3911 if (ch->state == MISDN_WAITING4DIGS ) {
3912 /* Ok, incomplete Setup, waiting till extension exists */
3913 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
3914 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
3915 ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
3918 strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
3919 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
3921 /* Check for Pickup Request first */
3922 if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
3923 if (ast_pickup_call(ch->ast)) {
3924 hangup_chan(ch);
3925 } else {
3926 struct ast_channel *chan = ch->ast;
3927 ch->state = MISDN_CALLING_ACKNOWLEDGE;
3928 ast_setstate(chan, AST_STATE_DOWN);
3929 hangup_chan(ch);
3930 ch->ast = NULL;
3931 break;
3935 if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
3936 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
3937 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
3938 strcpy(ch->ast->exten, "i");
3940 ch->state = MISDN_DIALING;
3941 start_pbx(ch, bc, ch->ast);
3942 break;
3945 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d).\n"
3946 "\tMaybe you want to add an 'i' extension to catch this case.\n",
3947 bc->port);
3949 if (bc->nt)
3950 hanguptone_indicate(ch);
3951 ch->state = MISDN_EXTCANTMATCH;
3952 bc->out_cause = AST_CAUSE_UNALLOCATED;
3954 misdn_lib_send_event(bc, EVENT_DISCONNECT);
3955 break;
3958 if (ch->overlap_dial) {
3959 ast_mutex_lock(&ch->overlap_tv_lock);
3960 ch->overlap_tv = ast_tvnow();
3961 ast_mutex_unlock(&ch->overlap_tv_lock);
3962 if (ch->overlap_dial_task == -1) {
3963 ch->overlap_dial_task =
3964 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
3966 break;
3969 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
3971 ch->state = MISDN_DIALING;
3972 start_pbx(ch, bc, ch->ast);
3974 } else {
3975 /* sending INFOS as DTMF-Frames :) */
3976 struct ast_frame fr;
3977 int digits;
3979 memset(&fr, 0, sizeof(fr));
3980 fr.frametype = AST_FRAME_DTMF;
3981 fr.subclass = bc->info_dad[0] ;
3982 fr.src = NULL;
3983 fr.data = NULL;
3984 fr.datalen = 0;
3985 fr.samples = 0;
3986 fr.mallocd = 0;
3987 fr.offset = 0;
3988 fr.delivery = ast_tv(0,0);
3990 misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
3991 if (ch->state != MISDN_CONNECTED ) {
3992 if (digits) {
3993 strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
3994 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
3995 ast_cdr_update(ch->ast);
3998 ast_queue_frame(ch->ast, &fr);
4002 break;
4003 case EVENT_SETUP:
4005 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
4006 struct ast_channel *chan;
4007 int exceed;
4008 int pres, screen;
4009 int ai;
4010 int im;
4012 if (ch) {
4013 switch (ch->state) {
4014 case MISDN_NOTHING:
4015 ch = NULL;
4016 break;
4017 default:
4018 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
4019 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */
4023 msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
4024 if (!bc->nt && ! msn_valid) {
4025 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
4026 return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */
4029 if (bc->cw) {
4030 int cause;
4031 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
4032 misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
4033 bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
4034 return RESPONSE_RELEASE_SETUP;
4037 print_bearer(bc);
4039 ch = init_chan_list(ORG_MISDN);
4041 if (!ch) {
4042 chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
4043 return 0;
4046 ch->bc = bc;
4047 ch->l3id = bc->l3_id;
4048 ch->addr = bc->addr;
4049 ch->originator = ORG_MISDN;
4051 chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
4053 if (!chan) {
4054 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
4055 ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
4056 return 0;
4059 ch->ast = chan;
4061 if ((exceed = add_in_calls(bc->port))) {
4062 char tmp[16];
4063 snprintf(tmp, sizeof(tmp), "%d", exceed);
4064 pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
4067 read_config(ch, ORG_MISDN);
4069 export_ch(chan, bc, ch);
4071 ch->ast->rings = 1;
4072 ast_setstate(ch->ast, AST_STATE_RINGING);
4074 switch (bc->pres) {
4075 case 1:
4076 pres = AST_PRES_RESTRICTED;
4077 chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
4078 break;
4079 case 2:
4080 pres = AST_PRES_UNAVAILABLE;
4081 chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
4082 break;
4083 default:
4084 pres = AST_PRES_ALLOWED;
4085 chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
4086 break;
4089 switch (bc->screen) {
4090 default:
4091 case 0:
4092 screen = AST_PRES_USER_NUMBER_UNSCREENED;
4093 chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
4094 break;
4095 case 1:
4096 screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
4097 chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
4098 break;
4099 case 2:
4100 screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
4101 chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
4102 break;
4103 case 3:
4104 screen = AST_PRES_NETWORK_NUMBER;
4105 chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
4106 break;
4109 chan->cid.cid_pres = pres | screen;
4111 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
4112 chan->transfercapability = bc->capability;
4114 switch (bc->capability) {
4115 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
4116 pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
4117 break;
4118 default:
4119 pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
4122 /** queue new chan **/
4123 cl_queue_chan(&cl_te, ch);
4125 if (!strstr(ch->allowed_bearers, "all")) {
4126 int i;
4128 for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
4129 if (allowed_bearers_array[i].cap == bc->capability) {
4130 if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
4131 /* The bearer capability is allowed */
4132 if (allowed_bearers_array[i].deprecated) {
4133 chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
4134 allowed_bearers_array[i].name);
4136 break;
4139 } /* end for */
4140 if (i == ARRAY_LEN(allowed_bearers_array)) {
4141 /* We did not find the bearer capability */
4142 chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
4143 bearer2str(bc->capability), bc->capability);
4144 bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
4146 ch->state = MISDN_EXTCANTMATCH;
4147 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
4148 return RESPONSE_OK;
4152 /* Check for Pickup Request first */
4153 if (!strcmp(chan->exten, ast_pickup_ext())) {
4154 if (!ch->noautorespond_on_setup) {
4155 int ret;/** Sending SETUP_ACK**/
4156 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
4157 } else {
4158 ch->state = MISDN_INCOMING_SETUP;
4160 if (ast_pickup_call(chan)) {
4161 hangup_chan(ch);
4162 } else {
4163 ch->state = MISDN_CALLING_ACKNOWLEDGE;
4164 ast_setstate(chan, AST_STATE_DOWN);
4165 hangup_chan(ch);
4166 ch->ast = NULL;
4167 break;
4172 added support for s extension hope it will help those poor cretains
4173 which haven't overlap dial.
4175 misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
4176 if (ai) {
4177 do_immediate_setup(bc, ch, chan);
4178 break;
4181 /* check if we should jump into s when we have no dad */
4182 misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
4183 if (im && ast_strlen_zero(bc->dad)) {
4184 do_immediate_setup(bc, ch, chan);
4185 break;
4188 chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
4189 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4190 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
4191 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n", bc->port);
4192 strcpy(ch->ast->exten, "i");
4193 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
4194 ch->state = MISDN_DIALING;
4195 start_pbx(ch, bc, chan);
4196 break;
4199 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d).\n"
4200 "\tMaybe you want to add an 'i' extension to catch this case.\n",
4201 bc->port);
4202 if (bc->nt)
4203 hanguptone_indicate(ch);
4205 ch->state = MISDN_EXTCANTMATCH;
4206 bc->out_cause = AST_CAUSE_UNALLOCATED;
4208 if (bc->nt)
4209 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
4210 else
4211 misdn_lib_send_event(bc, EVENT_RELEASE );
4213 break;
4216 /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely
4217 * jump into the dialplan, when the dialed extension does not exist, the 's' extension
4218 * will be used by Asterisk automatically. */
4219 if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
4220 if (!ch->noautorespond_on_setup) {
4221 ch->state=MISDN_DIALING;
4222 misdn_lib_send_event(bc, EVENT_PROCEEDING );
4223 } else {
4224 ch->state = MISDN_INCOMING_SETUP;
4226 start_pbx(ch, bc, chan);
4227 break;
4232 * When we are NT and overlapdial is set and if
4233 * the number is empty, we wait for the ISDN timeout
4234 * instead of our own timer.
4236 if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
4237 wait_for_digits(ch, bc, chan);
4238 break;
4242 * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more
4243 * Infos with a Interdigit Timeout.
4244 * */
4245 if (ch->overlap_dial) {
4246 ast_mutex_lock(&ch->overlap_tv_lock);
4247 ch->overlap_tv = ast_tvnow();
4248 ast_mutex_unlock(&ch->overlap_tv_lock);
4250 wait_for_digits(ch, bc, chan);
4251 if (ch->overlap_dial_task == -1)
4252 ch->overlap_dial_task =
4253 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
4255 break;
4258 /* If the extension does not exist and we're not TE_PTMP we wait for more digits
4259 * without interdigit timeout.
4260 * */
4261 if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4262 wait_for_digits(ch, bc, chan);
4263 break;
4267 * If the extension exists let's just jump into it.
4268 * */
4269 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
4270 if (bc->need_more_infos)
4271 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
4272 else
4273 misdn_lib_send_event(bc, EVENT_PROCEEDING);
4275 ch->state = MISDN_DIALING;
4276 start_pbx(ch, bc, chan);
4277 break;
4280 break;
4282 case EVENT_SETUP_ACKNOWLEDGE:
4284 ch->state = MISDN_CALLING_ACKNOWLEDGE;
4286 if (bc->channel)
4287 update_name(ch->ast,bc->port,bc->channel);
4289 if (!ast_strlen_zero(bc->infos_pending)) {
4290 /* TX Pending Infos */
4291 strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
4293 if (!ch->ast)
4294 break;
4295 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
4296 ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
4297 ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
4299 misdn_lib_send_event(bc, EVENT_INFORMATION);
4302 break;
4303 case EVENT_PROCEEDING:
4305 if (bc->channel)
4306 update_name(ch->ast, bc->port, bc->channel);
4308 if (misdn_cap_is_speech(bc->capability) &&
4309 misdn_inband_avail(bc) ) {
4310 start_bc_tones(ch);
4313 ch->state = MISDN_PROCEEDING;
4315 if (!ch->ast)
4316 break;
4318 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
4320 break;
4321 case EVENT_PROGRESS:
4322 if (bc->channel)
4323 update_name(ch->ast, bc->port, bc->channel);
4325 if (!bc->nt ) {
4326 if ( misdn_cap_is_speech(bc->capability) &&
4327 misdn_inband_avail(bc)
4329 start_bc_tones(ch);
4332 ch->state = MISDN_PROGRESS;
4334 if (!ch->ast)
4335 break;
4336 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
4338 break;
4341 case EVENT_ALERTING:
4343 if (bc->channel)
4344 update_name(ch->ast, bc->port, bc->channel);
4346 ch->state = MISDN_ALERTING;
4348 if (!ch->ast)
4349 break;
4351 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
4352 ast_setstate(ch->ast, AST_STATE_RINGING);
4354 cb_log(7, bc->port, " --> Set State Ringing\n");
4356 if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
4357 cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
4358 start_bc_tones(ch);
4359 } else {
4360 cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
4361 if (ch->far_alerting) {
4362 cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
4363 start_bc_tones(ch);
4364 /*tone_indicate(ch, TONE_FAR_ALERTING);*/
4368 break;
4369 case EVENT_CONNECT:
4371 struct ast_channel *bridged;
4373 /*we answer when we've got our very new L3 ID from the NT stack */
4374 misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
4376 if (!ch->ast)
4377 break;
4379 bridged = ast_bridged_channel(ch->ast);
4380 stop_indicate(ch);
4382 if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
4383 struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
4385 chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
4386 if (bridged_ch) {
4387 bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
4388 ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
4392 ch->l3id=bc->l3_id;
4393 ch->addr=bc->addr;
4395 start_bc_tones(ch);
4397 ch->state = MISDN_CONNECTED;
4399 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
4400 break;
4401 case EVENT_CONNECT_ACKNOWLEDGE:
4403 ch->l3id = bc->l3_id;
4404 ch->addr = bc->addr;
4406 start_bc_tones(ch);
4408 ch->state = MISDN_CONNECTED;
4410 break;
4411 case EVENT_DISCONNECT:
4412 /*we might not have an ch->ast ptr here anymore*/
4413 if (ch) {
4414 struct chan_list *holded_ch = find_holded(cl_te, bc);
4416 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);
4417 if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
4418 /* If there's inband information available (e.g. a
4419 recorded message saying what was wrong with the
4420 dialled number, or perhaps even giving an
4421 alternative number, then play it instead of
4422 immediately releasing the call */
4423 chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
4425 ch->state = MISDN_DISCONNECTED;
4426 start_bc_tones(ch);
4428 if (ch->ast) {
4429 ch->ast->hangupcause = bc->cause;
4430 if (bc->cause == AST_CAUSE_USER_BUSY)
4431 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
4433 ch->need_busy = 0;
4434 break;
4437 /*Check for holded channel, to implement transfer*/
4438 if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
4439 cb_log(1, bc->port, " --> found holded ch\n");
4440 misdn_transfer_bc(ch, holded_ch) ;
4443 bc->need_disconnect = 0;
4445 stop_bc_tones(ch);
4446 hangup_chan(ch);
4447 #if 0
4448 } else {
4449 ch = find_holded_l3(cl_te, bc->l3_id,1);
4450 if (ch) {
4451 hangup_chan(ch);
4453 #endif
4455 bc->out_cause = -1;
4456 if (bc->need_release)
4457 misdn_lib_send_event(bc, EVENT_RELEASE);
4458 break;
4460 case EVENT_RELEASE:
4462 bc->need_disconnect = 0;
4463 bc->need_release = 0;
4465 hangup_chan(ch);
4466 release_chan(bc);
4468 break;
4469 case EVENT_RELEASE_COMPLETE:
4471 bc->need_disconnect = 0;
4472 bc->need_release = 0;
4473 bc->need_release_complete = 0;
4475 stop_bc_tones(ch);
4476 hangup_chan(ch);
4478 if (ch)
4479 ch->state = MISDN_CLEANING;
4481 release_chan(bc);
4483 break;
4484 case EVENT_BCHAN_ERROR:
4485 case EVENT_CLEANUP:
4487 stop_bc_tones(ch);
4489 switch (ch->state) {
4490 case MISDN_CALLING:
4491 bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
4492 break;
4493 default:
4494 break;
4497 hangup_chan(ch);
4498 release_chan(bc);
4500 break;
4502 case EVENT_TONE_GENERATE:
4504 int tone_len = bc->tone_cnt;
4505 struct ast_channel *ast = ch->ast;
4506 void *tmp;
4507 int res;
4508 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
4510 chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
4512 if (!ast)
4513 break;
4515 if (!ast->generator)
4516 break;
4518 tmp = ast->generatordata;
4519 ast->generatordata = NULL;
4520 generate = ast->generator->generate;
4522 if (tone_len < 0 || tone_len > 512 ) {
4523 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
4524 tone_len = 128;
4527 res = generate(ast, tmp, tone_len, tone_len);
4528 ast->generatordata = tmp;
4530 if (res) {
4531 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
4532 ast_deactivate_generator(ast);
4533 } else {
4534 bc->tone_cnt = 0;
4537 break;
4539 case EVENT_BCHAN_DATA:
4541 if (!misdn_cap_is_speech(ch->bc->capability)) {
4542 struct ast_frame frame;
4543 /*In Data Modes we queue frames*/
4544 frame.frametype = AST_FRAME_VOICE; /*we have no data frames yet*/
4545 frame.subclass = AST_FORMAT_ALAW;
4546 frame.datalen = bc->bframe_len;
4547 frame.samples = bc->bframe_len;
4548 frame.mallocd = 0;
4549 frame.offset = 0;
4550 frame.delivery = ast_tv(0,0);
4551 frame.src = NULL;
4552 frame.data = bc->bframe;
4554 if (ch->ast)
4555 ast_queue_frame(ch->ast, &frame);
4556 } else {
4557 fd_set wrfs;
4558 struct timeval tv = { 0, 0 };
4559 int t;
4561 FD_ZERO(&wrfs);
4562 FD_SET(ch->pipe[1], &wrfs);
4564 t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
4566 if (!t) {
4567 chan_misdn_log(9, bc->port, "Select Timed out\n");
4568 break;
4571 if (t < 0) {
4572 chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
4573 break;
4576 if (FD_ISSET(ch->pipe[1], &wrfs)) {
4577 chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
4578 if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
4579 chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
4581 stop_bc_tones(ch);
4582 hangup_chan(ch);
4583 release_chan(bc);
4585 } else {
4586 chan_misdn_log(1, bc->port, "Write Pipe full!\n");
4590 break;
4591 case EVENT_TIMEOUT:
4593 if (ch && bc)
4594 chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
4596 switch (ch->state) {
4597 case MISDN_DIALING:
4598 case MISDN_PROGRESS:
4599 if (bc->nt && !ch->nttimeout)
4600 break;
4602 case MISDN_CALLING:
4603 case MISDN_ALERTING:
4604 case MISDN_PROCEEDING:
4605 case MISDN_CALLING_ACKNOWLEDGE:
4606 if (bc->nt) {
4607 bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
4608 hanguptone_indicate(ch);
4611 bc->out_cause = AST_CAUSE_UNALLOCATED;
4612 misdn_lib_send_event(bc, EVENT_DISCONNECT);
4613 break;
4615 case MISDN_WAITING4DIGS:
4616 if (bc->nt) {
4617 bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
4618 bc->out_cause = AST_CAUSE_UNALLOCATED;
4619 hanguptone_indicate(ch);
4620 misdn_lib_send_event(bc, EVENT_DISCONNECT);
4621 } else {
4622 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
4623 misdn_lib_send_event(bc, EVENT_RELEASE);
4626 break;
4628 case MISDN_CLEANING:
4629 chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
4630 break;
4632 default:
4633 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
4636 break;
4639 /****************************/
4640 /** Supplementary Services **/
4641 /****************************/
4642 case EVENT_RETRIEVE:
4644 struct ast_channel *hold_ast;
4646 if (!ch) {
4647 chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
4648 ch = find_holded_l3(cl_te, bc->l3_id, 1);
4651 if (!ch) {
4652 ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
4653 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
4654 break;
4657 /*remember the channel again*/
4658 ch->bc = bc;
4659 ch->state = MISDN_CONNECTED;
4661 ch->hold_info.port = 0;
4662 ch->hold_info.channel = 0;
4664 hold_ast = ast_bridged_channel(ch->ast);
4666 if (hold_ast) {
4667 ast_moh_stop(hold_ast);
4670 if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
4671 chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
4672 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
4675 break;
4677 case EVENT_HOLD:
4679 int hold_allowed;
4680 struct ast_channel *bridged;
4682 misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
4684 if (!hold_allowed) {
4686 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
4687 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
4688 break;
4691 bridged = ast_bridged_channel(ch->ast);
4692 if (bridged) {
4693 chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
4694 ch->state = MISDN_HOLDED;
4695 ch->l3id = bc->l3_id;
4697 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
4699 /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
4700 * instead of starting moh on the bridged channel directly */
4701 ast_moh_start(bridged, NULL, NULL);
4703 /*forget the channel now*/
4704 ch->bc = NULL;
4705 ch->hold_info.port = bc->port;
4706 ch->hold_info.channel = bc->channel;
4708 } else {
4709 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
4710 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
4713 break;
4715 case EVENT_FACILITY:
4716 if (!ch) {
4717 /* This may come from a call we don't know nothing about, so we ignore it. */
4718 chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
4719 break;
4722 print_facility(&(bc->fac_in), bc);
4724 switch (bc->fac_in.Function) {
4725 case Fac_CD:
4727 struct ast_channel *bridged = ast_bridged_channel(ch->ast);
4728 struct chan_list *ch_br;
4729 if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
4730 ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
4731 /*ch->state = MISDN_FACILITY_DEFLECTED;*/
4732 if (ch_br->bc) {
4733 if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
4734 ch_br->state = MISDN_DIALING;
4735 if (pbx_start_chan(ch_br) < 0) {
4736 chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
4741 misdn_lib_send_event(bc, EVENT_DISCONNECT);
4743 break;
4744 case Fac_AOCDCurrency:
4746 bc->AOCDtype = Fac_AOCDCurrency;
4747 memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
4748 export_aoc_vars(ch->originator, ch->ast, bc);
4750 break;
4751 case Fac_AOCDChargingUnit:
4753 bc->AOCDtype = Fac_AOCDChargingUnit;
4754 memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
4755 export_aoc_vars(ch->originator, ch->ast, bc);
4757 break;
4758 default:
4759 chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
4762 break;
4764 case EVENT_RESTART:
4766 if (!bc->dummy) {
4767 stop_bc_tones(ch);
4768 release_chan(bc);
4770 break;
4772 default:
4773 chan_misdn_log(1, 0, "Got Unknown Event\n");
4774 break;
4777 return RESPONSE_OK;
4780 /** TE STUFF END **/
4782 /******************************************
4784 * Asterisk Channel Endpoint END
4787 *******************************************/
4791 static int unload_module(void)
4793 /* First, take us out of the channel loop */
4794 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
4796 misdn_tasks_destroy();
4798 if (!g_config_initialized)
4799 return 0;
4801 ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
4803 /* ast_unregister_application("misdn_crypt"); */
4804 ast_unregister_application("misdn_set_opt");
4805 ast_unregister_application("misdn_facility");
4806 ast_unregister_application("misdn_check_l2l1");
4808 ast_channel_unregister(&misdn_tech);
4810 free_robin_list();
4811 misdn_cfg_destroy();
4812 misdn_lib_destroy();
4814 if (misdn_debug)
4815 free(misdn_debug);
4816 if (misdn_debug_only)
4817 free(misdn_debug_only);
4818 free(misdn_ports);
4820 return 0;
4823 static int load_module(void)
4825 int i, port;
4826 int ntflags = 0, ntkc = 0;
4827 char ports[256] = "";
4828 char tempbuf[BUFFERSIZE + 1];
4829 char ntfile[BUFFERSIZE + 1];
4830 struct misdn_lib_iface iface = {
4831 .cb_event = cb_events,
4832 .cb_log = chan_misdn_log,
4833 .cb_jb_empty = chan_misdn_jb_empty,
4836 max_ports = misdn_lib_maxports_get();
4838 if (max_ports <= 0) {
4839 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
4840 return AST_MODULE_LOAD_DECLINE;
4843 if (misdn_cfg_init(max_ports)) {
4844 ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
4845 return AST_MODULE_LOAD_DECLINE;
4847 g_config_initialized = 1;
4849 misdn_debug = (int *) malloc(sizeof(int) * (max_ports + 1));
4850 if (!misdn_debug) {
4851 ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
4852 return AST_MODULE_LOAD_DECLINE;
4854 misdn_ports = (int *) malloc(sizeof(int) * (max_ports + 1));
4855 if (!misdn_ports) {
4856 ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
4857 return AST_MODULE_LOAD_DECLINE;
4859 misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
4860 for (i = 1; i <= max_ports; i++) {
4861 misdn_debug[i] = misdn_debug[0];
4862 misdn_ports[i] = i;
4864 *misdn_ports = 0;
4865 misdn_debug_only = (int *) calloc(max_ports + 1, sizeof(int));
4867 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
4868 if (!ast_strlen_zero(tempbuf))
4869 tracing = 1;
4871 misdn_in_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
4872 misdn_out_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
4874 for (i = 1; i <= max_ports; i++) {
4875 misdn_in_calls[i] = 0;
4876 misdn_out_calls[i] = 0;
4879 ast_mutex_init(&cl_te_lock);
4880 ast_mutex_init(&release_lock);
4882 misdn_cfg_update_ptp();
4883 misdn_cfg_get_ports_string(ports);
4885 if (!ast_strlen_zero(ports))
4886 chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
4887 if (misdn_lib_init(ports, &iface, NULL))
4888 chan_misdn_log(0, 0, "No te ports initialized\n");
4890 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
4891 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
4892 misdn_lib_nt_debug_init(ntflags, ntfile);
4894 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(int));
4895 misdn_lib_nt_keepcalls(ntkc);
4897 if (ast_channel_register(&misdn_tech)) {
4898 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
4899 unload_module();
4900 return -1;
4903 ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
4905 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
4906 "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
4907 "Sets mISDN opts. and optargs\n"
4908 "\n"
4909 "The available options are:\n"
4910 " a - Have Asterisk detect DTMF tones on called channel\n"
4911 " c - Make crypted outgoing call, optarg is keyindex\n"
4912 " d - Send display text to called phone, text is the optarg\n"
4913 " e - Perform echo cancelation on this channel,\n"
4914 " takes taps as optarg (32,64,128,256)\n"
4915 " e! - Disable echo cancelation on this channel\n"
4916 " f - Enable fax detection\n"
4917 " h - Make digital outgoing call\n"
4918 " h1 - Make HDLC mode digital outgoing call\n"
4919 " i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
4920 " they will be transported inband.\n"
4921 " jb - Set jitter buffer length, optarg is length\n"
4922 " jt - Set jitter buffer upper threshold, optarg is threshold\n"
4923 " jn - Disable jitter buffer\n"
4924 " n - disable DSP on channel, disables: Echocancel, DTMF Detection and Volume Control.\n"
4925 " p - Caller ID presentation,\n"
4926 " optarg is either 'allowed' or 'restricted'\n"
4927 " s - Send Non-inband DTMF as inband\n"
4928 " vr - Rx gain control, optarg is gain\n"
4929 " vt - Tx gain control, optarg is gain\n"
4933 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
4934 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
4935 "Sends the Facility Message FACILITY_TYPE with \n"
4936 "the given Arguments to the current ISDN Channel\n"
4937 "Supported Facilities are:\n"
4938 "\n"
4939 "type=calldeflect args=Nr where to deflect\n"
4943 ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
4944 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
4945 "Checks if the L2 and L1 are up on either the given <port> or\n"
4946 "on the ports in the group with <groupname>\n"
4947 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
4948 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
4949 "\n"
4950 "This application, ensures the L1/L2 state of the Ports in a group\n"
4951 "it is intended to make the pmp_l1_check option redundant and to\n"
4952 "fix a buggy switch config from your provider\n"
4953 "\n"
4954 "a sample dialplan would look like:\n\n"
4955 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
4956 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
4957 "\n"
4961 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
4963 /* start the l1 watchers */
4965 for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
4966 int l1timeout;
4967 misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
4968 if (l1timeout) {
4969 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
4970 misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
4974 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
4976 return 0;
4981 static int reload(void)
4983 reload_config();
4985 return 0;
4988 /*** SOME APPS ;)***/
4990 static int misdn_facility_exec(struct ast_channel *chan, void *data)
4992 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
4993 char *tok, *tokb;
4995 chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
4997 if (strcasecmp(chan->tech->type, "mISDN")) {
4998 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
4999 return -1;
5002 if (ast_strlen_zero((char *)data)) {
5003 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
5004 return -1;
5007 tok = strtok_r((char*) data, "|", &tokb) ;
5009 if (!tok) {
5010 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
5011 return -1;
5014 if (!strcasecmp(tok, "calldeflect")) {
5015 tok = strtok_r(NULL, "|", &tokb) ;
5017 if (!tok) {
5018 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
5021 if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
5022 ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
5023 return 0;
5025 ch->bc->fac_out.Function = Fac_CD;
5026 ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
5027 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
5028 } else {
5029 chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
5032 return 0;
5035 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
5037 char group[BUFFERSIZE + 1];
5038 char *port_str;
5039 int port = 0;
5040 int timeout;
5041 int dowait = 0;
5042 int port_up;
5044 AST_DECLARE_APP_ARGS(args,
5045 AST_APP_ARG(grouppar);
5046 AST_APP_ARG(timeout);
5049 if (ast_strlen_zero((char *)data)) {
5050 ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
5051 return -1;
5054 AST_STANDARD_APP_ARGS(args, data);
5056 if (args.argc != 2) {
5057 ast_log(LOG_WARNING, "Wrong argument count\n");
5058 return 0;
5061 /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
5062 timeout = atoi(args.timeout);
5063 port_str = args.grouppar;
5065 if (port_str[0] == 'g' && port_str[1] == ':' ) {
5066 /* We make a group call lets checkout which ports are in my group */
5067 port_str += 2;
5068 ast_copy_string(group, port_str, sizeof(group));
5069 chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
5071 for ( port = misdn_cfg_get_next_port(port);
5072 port > 0;
5073 port = misdn_cfg_get_next_port(port)) {
5074 char cfg_group[BUFFERSIZE + 1];
5076 chan_misdn_log(2, 0, "trying port %d\n", port);
5078 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
5080 if (!strcasecmp(cfg_group, group)) {
5081 port_up = misdn_lib_port_up(port, 1);
5083 if (!port_up) {
5084 chan_misdn_log(2, 0, " --> port '%d'\n", port);
5085 misdn_lib_get_port_up(port);
5086 dowait = 1;
5091 } else {
5092 port = atoi(port_str);
5093 chan_misdn_log(2, 0, "Checking Port: %d\n",port);
5094 port_up = misdn_lib_port_up(port, 1);
5095 if (!port_up) {
5096 misdn_lib_get_port_up(port);
5097 dowait = 1;
5101 if (dowait) {
5102 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
5103 sleep(timeout);
5106 return 0;
5109 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
5111 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
5112 char *tok, *tokb;
5113 int keyidx = 0;
5114 int rxgain = 0;
5115 int txgain = 0;
5116 int change_jitter = 0;
5118 if (strcasecmp(chan->tech->type, "mISDN")) {
5119 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
5120 return -1;
5123 if (ast_strlen_zero((char *)data)) {
5124 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
5125 return -1;
5128 for (tok = strtok_r((char*) data, ":", &tokb);
5129 tok;
5130 tok = strtok_r(NULL, ":", &tokb) ) {
5131 int neglect = 0;
5133 if (tok[0] == '!' ) {
5134 neglect = 1;
5135 tok++;
5138 switch(tok[0]) {
5140 case 'd' :
5141 ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
5142 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
5143 break;
5145 case 'n':
5146 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
5147 ch->bc->nodsp = 1;
5148 break;
5150 case 'j':
5151 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
5152 tok++;
5153 change_jitter = 1;
5155 switch ( tok[0] ) {
5156 case 'b':
5157 ch->jb_len = atoi(++tok);
5158 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
5159 break;
5160 case 't' :
5161 ch->jb_upper_threshold = atoi(++tok);
5162 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
5163 break;
5164 case 'n':
5165 ch->bc->nojitter = 1;
5166 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
5167 break;
5168 default:
5169 ch->jb_len = 4000;
5170 ch->jb_upper_threshold = 0;
5171 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
5172 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
5174 break;
5175 case 'v':
5176 tok++;
5178 switch (tok[0]) {
5179 case 'r' :
5180 rxgain = atoi(++tok);
5181 if (rxgain < -8)
5182 rxgain = -8;
5183 if (rxgain > 8)
5184 rxgain = 8;
5185 ch->bc->rxgain = rxgain;
5186 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
5187 break;
5188 case 't':
5189 txgain = atoi(++tok);
5190 if (txgain < -8)
5191 txgain = -8;
5192 if (txgain > 8)
5193 txgain = 8;
5194 ch->bc->txgain = txgain;
5195 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
5196 break;
5198 break;
5200 case 'c':
5201 keyidx = atoi(++tok);
5203 char keys[4096];
5204 char *key = NULL, *tmp = keys;
5205 int i;
5206 misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
5208 for (i = 0; i < keyidx; i++) {
5209 key = strsep(&tmp, ",");
5212 if (key) {
5213 ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
5216 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
5217 break;
5219 case 'e':
5220 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
5222 if (neglect) {
5223 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
5224 #ifdef MISDN_1_2
5225 *ch->bc->pipeline = 0;
5226 #else
5227 ch->bc->ec_enable = 0;
5228 #endif
5229 } else {
5230 #ifdef MISDN_1_2
5231 update_pipeline_config(ch->bc);
5232 #else
5233 ch->bc->ec_enable = 1;
5234 ch->bc->orig = ch->originator;
5235 tok++;
5236 if (*tok) {
5237 ch->bc->ec_deftaps = atoi(tok);
5239 #endif
5242 break;
5243 case 'h':
5244 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
5246 if (strlen(tok) > 1 && tok[1] == '1') {
5247 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
5248 if (!ch->bc->hdlc) {
5249 ch->bc->hdlc = 1;
5252 ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
5253 break;
5255 case 's':
5256 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
5257 ch->bc->send_dtmf = 1;
5258 break;
5260 case 'f':
5261 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
5262 ch->faxdetect = 1;
5263 misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
5264 break;
5266 case 'a':
5267 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
5268 ch->ast_dsp = 1;
5269 break;
5271 case 'p':
5272 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
5273 /* CRICH: callingpres!!! */
5274 if (strstr(tok,"allowed")) {
5275 ch->bc->pres = 0;
5276 } else if (strstr(tok, "restricted")) {
5277 ch->bc->pres = 1;
5278 } else if (strstr(tok, "not_screened")) {
5279 chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
5280 ch->bc->pres = 1;
5282 break;
5283 case 'i' :
5284 chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
5285 ch->ignore_dtmf=1;
5286 break;
5287 default:
5288 break;
5292 if (change_jitter)
5293 config_jitterbuffer(ch);
5295 if (ch->faxdetect || ch->ast_dsp) {
5296 if (!ch->dsp)
5297 ch->dsp = ast_dsp_new();
5298 if (ch->dsp)
5299 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
5300 if (!ch->trans)
5301 ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
5304 if (ch->ast_dsp) {
5305 chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
5306 ch->bc->nodsp = 1;
5307 ch->bc->nojitter = 1;
5310 return 0;
5314 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
5316 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
5318 if (ch && ch->jb) {
5319 return misdn_jb_empty(ch->jb, buf, len);
5322 return -1;
5327 /*******************************************************/
5328 /***************** JITTERBUFFER ************************/
5329 /*******************************************************/
5332 /* allocates the jb-structure and initialize the elements*/
5333 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
5335 int i;
5336 struct misdn_jb *jb;
5338 jb = malloc(sizeof(struct misdn_jb));
5339 if (!jb) {
5340 chan_misdn_log(-1, 0, "No free Mem for jb\n");
5341 return NULL;
5343 jb->size = size;
5344 jb->upper_threshold = upper_threshold;
5345 jb->wp = 0;
5346 jb->rp = 0;
5347 jb->state_full = 0;
5348 jb->state_empty = 0;
5349 jb->bytes_wrote = 0;
5350 jb->samples = malloc(size * sizeof(char));
5351 if (!jb->samples) {
5352 free(jb);
5353 chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
5354 return NULL;
5357 jb->ok = malloc(size * sizeof(char));
5358 if (!jb->ok) {
5359 free(jb->samples);
5360 free(jb);
5361 chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
5362 return NULL;
5365 for (i = 0; i < size; i++)
5366 jb->ok[i] = 0;
5368 ast_mutex_init(&jb->mutexjb);
5370 return jb;
5373 /* frees the data and destroys the given jitterbuffer struct */
5374 void misdn_jb_destroy(struct misdn_jb *jb)
5376 ast_mutex_destroy(&jb->mutexjb);
5378 free(jb->samples);
5379 free(jb);
5382 /* fills the jitterbuffer with len data returns < 0 if there was an
5383 error (buffer overflow). */
5384 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
5386 int i, j, rp, wp;
5388 if (!jb || ! data)
5389 return 0;
5391 ast_mutex_lock(&jb->mutexjb);
5393 wp = jb->wp;
5394 rp = jb->rp;
5396 for (i = 0; i < len; i++) {
5397 jb->samples[wp] = data[i];
5398 jb->ok[wp] = 1;
5399 wp = (wp != jb->size - 1) ? wp + 1 : 0;
5401 if (wp == jb->rp)
5402 jb->state_full = 1;
5405 if (wp >= rp)
5406 jb->state_buffer = wp - rp;
5407 else
5408 jb->state_buffer = jb->size - rp + wp;
5409 chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
5411 if (jb->state_full) {
5412 jb->wp = wp;
5414 rp = wp;
5415 for (j = 0; j < jb->upper_threshold; j++)
5416 rp = (rp != 0) ? rp - 1 : jb->size - 1;
5417 jb->rp = rp;
5418 jb->state_full = 0;
5419 jb->state_empty = 1;
5421 ast_mutex_unlock(&jb->mutexjb);
5423 return -1;
5426 if (!jb->state_empty) {
5427 jb->bytes_wrote += len;
5428 if (jb->bytes_wrote >= jb->upper_threshold) {
5429 jb->state_empty = 1;
5430 jb->bytes_wrote = 0;
5433 jb->wp = wp;
5435 ast_mutex_unlock(&jb->mutexjb);
5437 return 0;
5440 /* gets len bytes out of the jitterbuffer if available, else only the
5441 available data is returned and the return value indicates the number
5442 of data. */
5443 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
5445 int i, wp, rp, read = 0;
5447 ast_mutex_lock(&jb->mutexjb);
5449 rp = jb->rp;
5450 wp = jb->wp;
5452 if (jb->state_empty) {
5453 for (i = 0; i < len; i++) {
5454 if (wp == rp) {
5455 jb->rp = rp;
5456 jb->state_empty = 0;
5458 ast_mutex_unlock(&jb->mutexjb);
5460 return read;
5461 } else {
5462 if (jb->ok[rp] == 1) {
5463 data[i] = jb->samples[rp];
5464 jb->ok[rp] = 0;
5465 rp = (rp != jb->size - 1) ? rp + 1 : 0;
5466 read += 1;
5471 if (wp >= rp)
5472 jb->state_buffer = wp - rp;
5473 else
5474 jb->state_buffer = jb->size - rp + wp;
5475 chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
5477 jb->rp = rp;
5478 } else
5479 chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
5481 ast_mutex_unlock(&jb->mutexjb);
5483 return read;
5489 /*******************************************************/
5490 /*************** JITTERBUFFER END *********************/
5491 /*******************************************************/
5496 static void chan_misdn_log(int level, int port, char *tmpl, ...)
5498 va_list ap;
5499 char buf[1024];
5500 char port_buf[8];
5502 if (! ((0 <= port) && (port <= max_ports))) {
5503 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
5504 port = 0;
5505 level = -1;
5508 snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
5510 va_start(ap, tmpl);
5511 vsnprintf(buf, sizeof(buf), tmpl, ap);
5512 va_end(ap);
5514 if (level == -1)
5515 ast_log(LOG_WARNING, "%s", buf);
5517 else if (misdn_debug_only[port] ?
5518 (level == 1 && misdn_debug[port]) || (level == misdn_debug[port])
5519 : level <= misdn_debug[port]) {
5521 ast_console_puts(port_buf);
5522 ast_console_puts(buf);
5525 if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
5526 time_t tm = time(NULL);
5527 char *tmp = ctime(&tm), *p;
5529 FILE *fp = fopen(global_tracefile, "a+");
5531 p = strchr(tmp, '\n');
5532 if (p)
5533 *p = ':';
5535 if (!fp) {
5536 ast_console_puts("Error opening Tracefile: [ ");
5537 ast_console_puts(global_tracefile);
5538 ast_console_puts(" ] ");
5540 ast_console_puts(strerror(errno));
5541 ast_console_puts("\n");
5542 return ;
5545 fputs(tmp, fp);
5546 fputs(" ", fp);
5547 fputs(port_buf, fp);
5548 fputs(" ", fp);
5549 fputs(buf, fp);
5551 fclose(fp);
5555 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
5556 .load = load_module,
5557 .unload = unload_module,
5558 .reload = reload,