2 * Asterisk -- An open source telephony toolkit.
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.
23 * \brief the chan_misdn channel driver for Asterisk
24 * \author Christian Richter <crich@beronet.com>
26 * \ingroup channel_drivers
31 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
36 #include <sys/socket.h>
41 #include <arpa/inet.h>
43 #include <sys/ioctl.h>
46 #include "asterisk/channel.h"
47 #include "asterisk/config.h"
48 #include "asterisk/logger.h"
49 #include "asterisk/module.h"
50 #include "asterisk/pbx.h"
51 #include "asterisk/options.h"
52 #include "asterisk/io.h"
53 #include "asterisk/frame.h"
54 #include "asterisk/translate.h"
55 #include "asterisk/cli.h"
56 #include "asterisk/musiconhold.h"
57 #include "asterisk/dsp.h"
58 #include "asterisk/translate.h"
59 #include "asterisk/config.h"
60 #include "asterisk/file.h"
61 #include "asterisk/callerid.h"
62 #include "asterisk/indications.h"
63 #include "asterisk/app.h"
64 #include "asterisk/features.h"
65 #include "asterisk/term.h"
66 #include "asterisk/stringfields.h"
68 #include "chan_misdn_config.h"
71 ast_mutex_t release_lock_mutex;
73 #define release_lock ast_mutex_lock(&release_lock_mutex)
74 #define release_unlock ast_mutex_unlock(&release_lock_mutex)
77 char global_tracefile[BUFFERSIZE+1];
94 /* allocates the jb-structure and initialise the elements*/
95 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
97 /* frees the data and destroys the given jitterbuffer struct */
98 void misdn_jb_destroy(struct misdn_jb *jb);
100 /* fills the jitterbuffer with len data returns < 0 if there was an
101 error (bufferoverun). */
102 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
104 /* gets len bytes out of the jitterbuffer if available, else only the
105 available data is returned and the return value indicates the number
107 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
112 /* BEGIN: chan_misdn.h */
116 enum misdn_chan_state {
117 MISDN_NOTHING, /*!< at beginning */
118 MISDN_WAITING4DIGS, /*!< when waiting for infos */
119 MISDN_EXTCANTMATCH, /*!< when asterisk couldnt match our ext */
120 MISDN_DIALING, /*!< when pbx_start */
121 MISDN_PROGRESS, /*!< we got a progress */
122 MISDN_PROCEEDING, /*!< we got a progress */
123 MISDN_CALLING, /*!< when misdn_call is called */
124 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
125 MISDN_ALERTING, /*!< when Alerting */
126 MISDN_BUSY, /*!< when BUSY */
127 MISDN_CONNECTED, /*!< when connected */
128 MISDN_PRECONNECTED, /*!< when connected */
129 MISDN_DISCONNECTED, /*!< when connected */
130 MISDN_RELEASED, /*!< when connected */
131 MISDN_BRIDGED, /*!< when bridged */
132 MISDN_CLEANING, /*!< when hangup from * but we were connected before */
133 MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */
134 MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
136 MISDN_HOLDED, /*!< if this chan is holded */
137 MISDN_HOLD_DISCONNECT /*!< if this chan is holded */
148 char allowed_bearers[BUFFERSIZE+1];
150 enum misdn_chan_state state;
151 int need_queue_hangup;
160 int incoming_early_audio;
165 char ast_rd_buf[4096];
166 struct ast_frame frame;
174 int jb_upper_threshold;
178 struct ast_trans_pvt *trans;
180 struct ast_channel * ast;
184 struct misdn_bchannel *bc;
185 struct misdn_bchannel *holded_bc;
190 char context[BUFFERSIZE];
193 int dropped_frame_cnt;
197 struct chan_list *other_ch;
199 const struct tone_zone_sound *ts;
201 struct chan_list *peer;
202 struct chan_list *next;
203 struct chan_list *prev;
204 struct chan_list *first;
209 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
210 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
216 struct robin_list *next;
217 struct robin_list *prev;
219 static struct robin_list *robin = NULL;
223 struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
227 static inline void free_robin_list_r (struct robin_list *r)
230 if (r->next) free_robin_list_r(r->next);
231 if (r->group) free(r->group);
236 static void free_robin_list ( void )
238 free_robin_list_r(robin);
242 static struct robin_list* get_robin_position (char *group)
244 struct robin_list *iter = robin;
245 for (; iter; iter = iter->next) {
246 if (!strcasecmp(iter->group, group))
249 struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
250 new->group = strndup(group, strlen(group));
261 static void chan_misdn_log(int level, int port, char *tmpl, ...);
263 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
264 static void send_digit_to_chan(struct chan_list *cl, char digit );
266 static void hangup_chan(struct chan_list *ch);
267 static int pbx_start_chan(struct chan_list *ch);
270 #define AST_CID_P(ast) ast->cid.cid_num
271 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast)
272 #define AST_LOAD_CFG ast_config_load
273 #define AST_DESTROY_CFG ast_config_destroy
275 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
276 #define MISDN_ASTERISK_PVT(ast) 1
278 #include <asterisk/strings.h>
280 /* #define MISDN_DEBUG 1 */
282 static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
283 static const char misdn_type[] = "mISDN";
285 static int tracing = 0 ;
287 static char **misdn_key_vector=NULL;
288 static int misdn_key_vector_size=0;
290 /* Only alaw and mulaw is allowed for now */
291 static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */
293 static int *misdn_debug;
294 static int *misdn_debug_only;
295 static int max_ports;
297 static int *misdn_in_calls;
298 static int *misdn_out_calls;
301 struct chan_list dummy_cl;
303 struct chan_list *cl_te=NULL;
304 ast_mutex_t cl_te_lock;
306 static enum event_response_e
307 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
309 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
311 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
312 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
313 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
314 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
318 static int dialtone_indicate(struct chan_list *cl);
319 static int hanguptone_indicate(struct chan_list *cl);
320 static int stop_indicate(struct chan_list *cl);
322 static int start_bc_tones(struct chan_list *cl);
323 static int stop_bc_tones(struct chan_list *cl);
324 static void release_chan(struct misdn_bchannel *bc);
326 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
327 static int misdn_facility_exec(struct ast_channel *chan, void *data);
329 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
332 void debug_numplan(int port, int numplan, char *type);
335 int add_out_calls(int port);
336 int add_in_calls(int port);
339 /*************** Helpers *****************/
341 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
343 struct chan_list *tmp;
345 for (tmp=cl_te; tmp; tmp = tmp->next) {
346 if ( tmp->ast == ast ) return tmp;
352 static struct chan_list * get_chan_by_ast_name(char *name)
354 struct chan_list *tmp;
356 for (tmp=cl_te; tmp; tmp = tmp->next) {
357 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp;
365 struct allowed_bearers {
371 struct allowed_bearers allowed_bearers_array[]={
372 {INFO_CAPABILITY_SPEECH,1,"speech"},
373 {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
374 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
375 {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
376 {INFO_CAPABILITY_VIDEO,16,"video"}
379 static char *bearer2str(int cap) {
380 static char *bearers[]={
390 case INFO_CAPABILITY_SPEECH:
393 case INFO_CAPABILITY_AUDIO_3_1K:
396 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
399 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
402 case INFO_CAPABILITY_VIDEO:
412 static void print_facility( struct misdn_bchannel *bc)
414 switch (bc->fac_type) {
415 case FACILITY_CALLDEFLECT:
416 chan_misdn_log(2,bc->port," --> calldeflect: %s\n",
417 bc->fac.calldeflect_nr);
419 case FACILITY_CENTREX:
420 chan_misdn_log(2,bc->port," --> centrex: %s\n",
424 chan_misdn_log(2,bc->port," --> unknown\n");
429 static void print_bearer(struct misdn_bchannel *bc)
432 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
435 case INFO_CODEC_ALAW:
436 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
438 case INFO_CODEC_ULAW:
439 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
443 /*************** Helpers END *************/
445 static void send_digit_to_chan(struct chan_list *cl, char digit )
447 static const char* dtmf_tones[] = {
448 "!941+1336/100,!0/100", /* 0 */
449 "!697+1209/100,!0/100", /* 1 */
450 "!697+1336/100,!0/100", /* 2 */
451 "!697+1477/100,!0/100", /* 3 */
452 "!770+1209/100,!0/100", /* 4 */
453 "!770+1336/100,!0/100", /* 5 */
454 "!770+1477/100,!0/100", /* 6 */
455 "!852+1209/100,!0/100", /* 7 */
456 "!852+1336/100,!0/100", /* 8 */
457 "!852+1477/100,!0/100", /* 9 */
458 "!697+1633/100,!0/100", /* A */
459 "!770+1633/100,!0/100", /* B */
460 "!852+1633/100,!0/100", /* C */
461 "!941+1633/100,!0/100", /* D */
462 "!941+1209/100,!0/100", /* * */
463 "!941+1477/100,!0/100" }; /* # */
464 struct ast_channel *chan=cl->ast;
466 if (digit >= '0' && digit <='9')
467 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
468 else if (digit >= 'A' && digit <= 'D')
469 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
470 else if (digit == '*')
471 ast_playtones_start(chan,0,dtmf_tones[14], 0);
472 else if (digit == '#')
473 ast_playtones_start(chan,0,dtmf_tones[15], 0);
476 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
481 /*** CLI HANDLING ***/
482 static int misdn_set_debug(int fd, int argc, char *argv[])
484 if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
485 return RESULT_SHOWUSAGE;
487 int level = atoi(argv[3]);
494 if (strncasecmp(argv[4], "only", strlen(argv[4])))
495 return RESULT_SHOWUSAGE;
500 for (i=0; i<=max_ports; i++) {
501 misdn_debug[i] = level;
502 misdn_debug_only[i] = only;
504 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
509 if (strncasecmp(argv[4], "port", strlen(argv[4])))
510 return RESULT_SHOWUSAGE;
511 int port = atoi(argv[5]);
512 if (port <= 0 || port > max_ports) {
515 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
518 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
521 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
526 if (strncasecmp(argv[6], "only", strlen(argv[6])))
527 return RESULT_SHOWUSAGE;
529 misdn_debug_only[port] = 1;
531 misdn_debug_only[port] = 0;
532 misdn_debug[port] = level;
533 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
539 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
541 if (argc != 5) return RESULT_SHOWUSAGE;
547 static int misdn_restart_port (int fd, int argc, char *argv[])
552 return RESULT_SHOWUSAGE;
554 port = atoi(argv[3]);
556 misdn_lib_port_restart(port);
561 static int misdn_port_up (int fd, int argc, char *argv[])
566 return RESULT_SHOWUSAGE;
568 port = atoi(argv[3]);
570 misdn_lib_get_port_up(port);
575 static int misdn_port_down (int fd, int argc, char *argv[])
580 return RESULT_SHOWUSAGE;
582 port = atoi(argv[3]);
584 misdn_lib_get_port_down(port);
589 static inline void show_config_description (int fd, enum misdn_cfg_elements elem)
591 char section[BUFFERSIZE];
592 char name[BUFFERSIZE];
593 char desc[BUFFERSIZE];
594 char def[BUFFERSIZE];
595 char tmp[BUFFERSIZE];
597 misdn_cfg_get_name(elem, tmp, sizeof(tmp));
598 term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
599 misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
601 if (elem < MISDN_CFG_LAST)
602 term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
604 term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
607 ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
609 ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
612 static int misdn_show_config (int fd, int argc, char *argv[])
614 char buffer[BUFFERSIZE];
615 enum misdn_cfg_elements elem;
621 if (!strcmp(argv[3], "description")) {
623 enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]);
624 if (elem == MISDN_CFG_FIRST)
625 ast_cli(fd, "Unknown element: %s\n", argv[4]);
627 show_config_description(fd, elem);
630 return RESULT_SHOWUSAGE;
632 if (!strcmp(argv[3], "descriptions")) {
633 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) {
634 for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
635 show_config_description(fd, elem);
640 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) {
641 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST; ++elem) {
642 show_config_description(fd, elem);
647 return ok ? 0 : RESULT_SHOWUSAGE;
649 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
650 ast_cli(fd, "Unknown option: %s\n", argv[3]);
651 return RESULT_SHOWUSAGE;
655 if (argc == 3 || onlyport == 0) {
656 ast_cli(fd,"Misdn General-Config: \n");
657 ast_cli(fd," -> Version: chan_misdn-" CHAN_MISDN_VERSION "\n");
658 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
659 misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
660 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
666 int port = misdn_cfg_get_next_port(0);
667 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
668 ast_cli(fd, "\n[PORT %d]\n", port);
669 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
670 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
671 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
678 if (misdn_cfg_is_port_valid(onlyport)) {
679 ast_cli(fd, "[PORT %d]\n", onlyport);
680 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
681 misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE);
682 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
686 ast_cli(fd, "Port %d is not active!\n", onlyport);
692 struct state_struct {
693 enum misdn_chan_state state;
697 static struct state_struct state_array[] = {
698 {MISDN_NOTHING,"NOTHING"}, /* at beginning */
699 {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */
700 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldnt match our ext */
701 {MISDN_DIALING,"DIALING"}, /* when pbx_start */
702 {MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */
703 {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */
704 {MISDN_CALLING,"CALLING"}, /* when misdn_call is called */
705 {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */
706 {MISDN_ALERTING,"ALERTING"}, /* when Alerting */
707 {MISDN_BUSY,"BUSY"}, /* when BUSY */
708 {MISDN_CONNECTED,"CONNECTED"}, /* when connected */
709 {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */
710 {MISDN_RELEASED,"RELEASED"}, /* when connected */
711 {MISDN_BRIDGED,"BRIDGED"}, /* when bridged */
712 {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
713 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
714 {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
715 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */
716 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
720 static char *misdn_get_ch_state(struct chan_list *p)
723 static char state[8];
727 for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
728 if ( state_array[i].state == p->state) return state_array[i].txt;
731 sprintf(state,"%d",p->state) ;
738 static void reload_config(void)
741 chan_misdn_log(-1, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
745 misdn_cfg_update_ptp();
746 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
747 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
749 for (i = 0; i <= max_ports; i++) {
750 misdn_debug[i] = cfg_debug;
751 misdn_debug_only[i] = 0;
755 static int misdn_reload (int fd, int argc, char *argv[])
757 ast_cli(fd, "Reloading mISDN Config\n");
762 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
764 struct ast_channel *ast=help->ast;
766 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
768 bc->pid, bc->port, bc->channel,
770 help->orginator == ORG_AST?"*":"I",
772 ast?AST_CID_P(ast):NULL,
774 ast?ast->context:NULL,
775 misdn_get_ch_state(help)
777 if (misdn_debug[bc->port] > 0)
785 " --> activated: %d\n"
787 " --> capability: %s\n"
788 " --> echo_cancel: %d\n"
789 " --> notone : rx %d tx:%d\n"
790 " --> bc_hold: %d holded_bc :%d\n",
799 bc_state2str(bc->bc_state),
800 bearer2str(bc->capability),
802 help->norxtone,help->notxtone,
803 bc->holded, help->holded_bc?1:0
808 static int misdn_show_cls (int fd, int argc, char *argv[])
810 struct chan_list *help=cl_te;
812 ast_cli(fd,"Chan List: %p\n",cl_te);
814 for (;help; help=help->next) {
815 struct misdn_bchannel *bc=help->bc;
816 struct ast_channel *ast=help->ast;
817 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
819 print_bc_info(fd, help, bc);
820 } else if ( (bc=help->holded_bc) ) {
821 chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
822 print_bc_info(fd, help, bc);
824 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
832 static int misdn_show_cl (int fd, int argc, char *argv[])
834 struct chan_list *help=cl_te;
837 return RESULT_SHOWUSAGE;
839 for (;help; help=help->next) {
840 struct misdn_bchannel *bc=help->bc;
841 struct ast_channel *ast=help->ast;
844 if (!strcasecmp(ast->name,argv[3])) {
845 print_bc_info(fd, help, bc);
858 static int misdn_set_tics (int fd, int argc, char *argv[])
861 return RESULT_SHOWUSAGE;
863 MAXTICS=atoi(argv[3]);
868 static int misdn_show_stacks (int fd, int argc, char *argv[])
872 ast_cli(fd, "BEGIN STACK_LIST:\n");
874 for (port=misdn_cfg_get_next_port(0); port > 0;
875 port=misdn_cfg_get_next_port(port)) {
877 get_show_stack_details(port,buf);
878 ast_cli(fd," %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
887 static int misdn_show_ports_stats (int fd, int argc, char *argv[])
891 ast_cli(fd, "Port\tin_calls\tout_calls\n");
893 for (port=misdn_cfg_get_next_port(0); port > 0;
894 port=misdn_cfg_get_next_port(port)) {
895 ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]);
904 static int misdn_show_port (int fd, int argc, char *argv[])
909 return RESULT_SHOWUSAGE;
911 port = atoi(argv[3]);
913 ast_cli(fd, "BEGIN STACK_LIST:\n");
916 get_show_stack_details(port,buf);
917 ast_cli(fd," %s Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
923 static int misdn_send_cd (int fd, int argc, char *argv[])
929 return RESULT_SHOWUSAGE;
934 ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
937 struct chan_list *tmp=get_chan_by_ast_name(channame);
940 ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
944 misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
951 static int misdn_send_digit (int fd, int argc, char *argv[])
957 return RESULT_SHOWUSAGE;
962 ast_cli(fd, "Sending %s to %s\n",msg, channame);
965 struct chan_list *tmp=get_chan_by_ast_name(channame);
968 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
973 int msglen = strlen(msg);
974 for (i=0; i<msglen; i++) {
975 ast_cli(fd, "Sending: %c\n",msg[i]);
976 send_digit_to_chan(tmp, msg[i]);
977 /* res = ast_safe_sleep(tmp->ast, 250); */
979 /* res = ast_waitfor(tmp->ast,100); */
983 res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
991 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
996 return RESULT_SHOWUSAGE;
1000 ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
1003 struct chan_list *tmp=get_chan_by_ast_name(channame);
1006 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
1009 tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
1011 if (tmp->bc->ec_enable) {
1012 manager_ec_enable(tmp->bc);
1014 manager_ec_disable(tmp->bc);
1022 static int misdn_send_display (int fd, int argc, char *argv[])
1028 return RESULT_SHOWUSAGE;
1033 ast_cli(fd, "Sending %s to %s\n",msg, channame);
1035 struct chan_list *tmp;
1036 tmp=get_chan_by_ast_name(channame);
1038 if (tmp && tmp->bc) {
1039 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
1040 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
1042 ast_cli(fd,"No such channel %s\n",channame);
1043 return RESULT_FAILURE;
1047 return RESULT_SUCCESS ;
1050 static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos)
1052 struct ast_channel *c;
1057 c = ast_channel_walk_locked(NULL);
1059 if (!strncasecmp(word, c->name, strlen(word))) {
1060 if (++which > state)
1063 ast_mutex_unlock(&c->lock);
1064 c = ast_channel_walk_locked(c);
1067 ret = strdup(c->name);
1068 ast_mutex_unlock(&c->lock);
1074 static char *complete_ch(const char *line, const char *word, int pos, int state)
1076 return complete_ch_helper(line, word, pos, state, 3);
1079 static char *complete_debug_port (const char *line, const char *word, int pos, int state)
1085 case 4: if (*word == 'p')
1086 return strdup("port");
1087 else if (*word == 'o')
1088 return strdup("only");
1090 case 6: if (*word == 'o')
1091 return strdup("only");
1097 static char *complete_show_config (const char *line, const char *word, int pos, int state)
1099 char buffer[BUFFERSIZE];
1100 enum misdn_cfg_elements elem;
1101 int wordlen = strlen(word);
1106 case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state))
1107 return strdup("description");
1108 if ((!strncmp(word, "descriptions", wordlen)) && (++which > state))
1109 return strdup("descriptions");
1110 if ((!strncmp(word, "0", wordlen)) && (++which > state))
1112 while ((port = misdn_cfg_get_next_port(port)) != -1) {
1113 snprintf(buffer, sizeof(buffer), "%d", port);
1114 if ((!strncmp(word, buffer, wordlen)) && (++which > state)) {
1115 return strdup(buffer);
1120 if (strstr(line, "description ")) {
1121 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
1122 if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST))
1124 misdn_cfg_get_name(elem, buffer, BUFFERSIZE);
1125 if (!wordlen || !strncmp(word, buffer, wordlen)) {
1126 if (++which > state)
1127 return strdup(buffer);
1130 } else if (strstr(line, "descriptions ")) {
1131 if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state))
1132 return strdup("general");
1133 if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state))
1134 return strdup("ports");
1141 static struct ast_cli_entry cli_send_cd =
1142 { {"misdn","send","calldeflect", NULL},
1144 "Sends CallDeflection to mISDN Channel",
1145 "Usage: misdn send calldeflect <channel> \"<nr>\" \n",
1149 static struct ast_cli_entry cli_send_digit =
1150 { {"misdn","send","digit", NULL},
1152 "Sends DTMF Digit to mISDN Channel",
1153 "Usage: misdn send digit <channel> \"<msg>\" \n"
1154 " Send <digit> to <channel> as DTMF Tone\n"
1155 " when channel is a mISDN channel\n",
1159 static struct ast_cli_entry cli_toggle_echocancel =
1160 { {"misdn","toggle","echocancel", NULL},
1161 misdn_toggle_echocancel,
1162 "Toggles EchoCancel on mISDN Channel",
1163 "Usage: misdn toggle echocancel <channel>\n",
1167 static struct ast_cli_entry cli_send_display =
1168 { {"misdn","send","display", NULL},
1170 "Sends Text to mISDN Channel",
1171 "Usage: misdn send display <channel> \"<msg>\" \n"
1172 " Send <msg> to <channel> as Display Message\n"
1173 " when channel is a mISDN channel\n",
1177 static struct ast_cli_entry cli_show_config =
1178 { {"misdn","show","config", NULL},
1180 "Shows internal mISDN config, read from cfg-file",
1181 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
1182 " Use 0 for <port> to only print the general config.\n",
1183 complete_show_config
1186 static struct ast_cli_entry cli_reload =
1187 { {"misdn","reload", NULL},
1189 "Reloads internal mISDN config, read from cfg-file",
1190 "Usage: misdn reload\n"
1193 static struct ast_cli_entry cli_set_tics =
1194 { {"misdn","set","tics", NULL},
1200 static struct ast_cli_entry cli_show_cls =
1201 { {"misdn","show","channels", NULL},
1203 "Shows internal mISDN chan_list",
1204 "Usage: misdn show channels\n"
1207 static struct ast_cli_entry cli_show_cl =
1208 { {"misdn","show","channel", NULL},
1210 "Shows internal mISDN chan_list",
1211 "Usage: misdn show channels\n",
1217 static struct ast_cli_entry cli_restart_port =
1218 { {"misdn","restart","port", NULL},
1220 "Restarts the given port",
1221 "Usage: misdn restart port\n"
1224 static struct ast_cli_entry cli_port_up =
1225 { {"misdn","port","up", NULL},
1227 "Tries to establish L1 on the given port",
1228 "Usage: misdn port up <port>\n"
1231 static struct ast_cli_entry cli_port_down =
1232 { {"misdn","port","down", NULL},
1234 "Tries to deacivate the L1 on the given port",
1235 "Usage: misdn port down <port>\n"
1240 static struct ast_cli_entry cli_show_stacks =
1241 { {"misdn","show","stacks", NULL},
1243 "Shows internal mISDN stack_list",
1244 "Usage: misdn show stacks\n"
1247 static struct ast_cli_entry cli_show_ports_stats =
1248 { {"misdn","show","ports","stats", NULL},
1249 misdn_show_ports_stats,
1250 "Shows chan_misdns call statistics per port",
1251 "Usage: misdn show port stats\n"
1255 static struct ast_cli_entry cli_show_port =
1256 { {"misdn","show","port", NULL},
1258 "Shows detailed information for given port",
1259 "Usage: misdn show port <port>\n"
1262 static struct ast_cli_entry cli_set_debug =
1263 { {"misdn","set","debug", NULL},
1265 "Sets Debuglevel of chan_misdn",
1266 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n",
1270 static struct ast_cli_entry cli_set_crypt_debug =
1271 { {"misdn","set","crypt","debug", NULL},
1272 misdn_set_crypt_debug,
1273 "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
1274 "Usage: misdn set crypt debug <level>\n"
1279 static int update_config (struct chan_list *ch, int orig)
1282 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1286 struct ast_channel *ast=ch->ast;
1287 struct misdn_bchannel *bc=ch->bc;
1288 if (! ast || ! bc ) {
1289 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1295 chan_misdn_log(5,port,"update_config: Getting Config\n");
1299 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1302 switch (bc->capability) {
1303 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1304 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1305 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1315 misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
1316 misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
1317 chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
1319 if ( (pres + screen) < 0 ) {
1321 chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
1323 switch (ast->cid.cid_pres & 0x60){
1325 case AST_PRES_RESTRICTED:
1327 chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
1331 case AST_PRES_UNAVAILABLE:
1333 chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
1338 chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
1341 switch (ast->cid.cid_pres & 0x3){
1343 case AST_PRES_USER_NUMBER_UNSCREENED:
1345 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1348 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
1350 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
1352 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
1354 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
1357 case AST_PRES_NETWORK_NUMBER:
1359 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
1364 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
1380 static void config_jitterbuffer(struct chan_list *ch)
1382 struct misdn_bchannel *bc=ch->bc;
1383 int len=ch->jb_len, threshold=ch->jb_upper_threshold;
1385 chan_misdn_log(5,bc->port, "config_jb: Called\n");
1388 chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
1392 if (len <=100 || len > 8000) {
1393 chan_misdn_log(-1,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
1397 if ( threshold > len ) {
1398 chan_misdn_log(-1,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
1402 cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
1403 misdn_jb_destroy(ch->jb);
1407 ch->jb=misdn_jb_init(len, threshold);
1415 void debug_numplan(int port, int numplan, char *type)
1418 case NUMPLAN_INTERNATIONAL:
1419 chan_misdn_log(2, port, " --> %s: International\n",type);
1421 case NUMPLAN_NATIONAL:
1422 chan_misdn_log(2, port, " --> %s: National\n",type);
1424 case NUMPLAN_SUBSCRIBER:
1425 chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
1427 case NUMPLAN_UNKNOWN:
1428 chan_misdn_log(2, port, " --> %s: Unknown\n",type);
1430 /* Maybe we should cut off the prefix if present ? */
1432 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
1441 static int read_config(struct chan_list *ch, int orig) {
1444 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
1448 struct ast_channel *ast=ch->ast;
1449 struct misdn_bchannel *bc=ch->bc;
1450 if (! ast || ! bc ) {
1451 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
1457 chan_misdn_log(1,port,"read_config: Getting Config\n");
1459 char lang[BUFFERSIZE+1];
1462 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
1463 ast_string_field_set(ast, language, lang);
1465 char localmusicclass[BUFFERSIZE+1];
1467 misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE);
1468 ast_string_field_set(ast, musicclass, localmusicclass);
1471 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
1472 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
1474 misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
1476 misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
1478 misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
1480 misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
1482 misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
1486 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
1489 switch (bc->capability) {
1490 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
1491 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
1492 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
1498 /*Initialize new Jitterbuffer*/
1500 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
1501 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
1503 config_jitterbuffer(ch);
1506 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
1508 ast_copy_string (ast->context,ch->context,sizeof(ast->context));
1512 misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
1514 misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
1517 } else if ( ec > 1 ) {
1523 bc->ec_training=ectr;
1530 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
1531 bc->early_bconnect=eb3;
1540 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
1541 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
1543 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
1544 ast->pickupgroup=pg;
1548 if ( orig == ORG_AST) {
1549 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
1552 char callerid[BUFFERSIZE+1];
1553 misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
1554 if ( ! ast_strlen_zero(callerid) ) {
1555 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
1557 int l = sizeof(bc->oad);
1558 strncpy(bc->oad,callerid, l);
1565 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
1566 misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
1567 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1568 debug_numplan(port, bc->dnumplan,"TON");
1569 debug_numplan(port, bc->onumplan,"LTON");
1570 debug_numplan(port, bc->cpnnumplan,"CTON");
1575 } else { /** ORIGINATOR MISDN **/
1577 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
1578 debug_numplan(port, bc->cpnnumplan,"CTON");
1580 char prefix[BUFFERSIZE+1]="";
1581 switch( bc->onumplan ) {
1582 case NUMPLAN_INTERNATIONAL:
1583 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1586 case NUMPLAN_NATIONAL:
1587 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1594 int l = strlen(prefix) + strlen(bc->oad);
1597 strcat(tmp,bc->oad);
1598 strcpy(bc->oad,tmp);
1601 if (!ast_strlen_zero(bc->dad)) {
1602 ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
1605 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
1606 ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
1611 switch( bc->dnumplan ) {
1612 case NUMPLAN_INTERNATIONAL:
1613 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
1615 case NUMPLAN_NATIONAL:
1616 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
1623 int l = strlen(prefix) + strlen(bc->dad);
1626 strcat(tmp,bc->dad);
1627 strcpy(bc->dad,tmp);
1630 if ( strcmp(bc->dad,ast->exten)) {
1631 ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
1634 ast_set_callerid(ast, bc->oad, NULL, bc->oad);
1636 if ( !ast_strlen_zero(bc->rad) ) {
1637 if (ast->cid.cid_rdnis)
1638 free(ast->cid.cid_rdnis);
1639 ast->cid.cid_rdnis = strdup(bc->rad);
1641 } /* ORIG MISDN END */
1647 /*****************************/
1648 /*** AST Indications Start ***/
1649 /*****************************/
1651 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
1655 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1656 struct misdn_bchannel *newbc;
1657 char *opts=NULL, *ext,*tokb;
1661 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
1662 dest_cp[sizeof(dest_cp)]=0;
1664 ext=strtok_r(dest_cp,"/",&tokb);
1667 ext=strtok_r(NULL,"/",&tokb);
1669 opts=strtok_r(NULL,"/",&tokb);
1671 chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
1678 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
1682 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) {
1683 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1684 ast->hangupcause=41;
1685 ast_setstate(ast, AST_STATE_DOWN);
1690 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1691 ast->hangupcause=41;
1692 ast_setstate(ast, AST_STATE_DOWN);
1699 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
1700 ast->hangupcause=41;
1701 ast_setstate(ast, AST_STATE_DOWN);
1706 strncpy(newbc->dad,ext,sizeof( newbc->dad));
1707 strncpy(ast->exten,ext,sizeof(ast->exten));
1710 if ((exceed=add_out_calls(port))) {
1712 sprintf(tmp,"%d",exceed);
1713 pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp);
1717 chan_misdn_log(1, port, "* CALL: %s\n",dest);
1719 chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
1721 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
1723 int l = sizeof(newbc->dad);
1724 strncpy(newbc->dad,ast->exten, l);
1725 newbc->dad[l-1] = 0;
1728 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
1729 if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
1731 if (AST_CID_P(ast)) {
1732 int l = sizeof(newbc->oad);
1733 strncpy(newbc->oad,AST_CID_P(ast), l);
1734 newbc->oad[l-1] = 0;
1739 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
1740 if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
1742 newbc->capability=ast->transfercapability;
1743 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
1744 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
1745 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
1749 /* update screening and presentation */
1750 update_config(ch,ORG_AST);
1752 /* fill in some ies from channel vary*/
1753 import_ch(ast, newbc, ch);
1755 /* Finally The Options Override Everything */
1757 misdn_set_opt_exec(ast,opts);
1759 chan_misdn_log(2,port,"NO OPTS GIVEN\n");
1761 ch->state=MISDN_CALLING;
1763 r=misdn_lib_send_event( newbc, EVENT_SETUP );
1765 /** we should have l3id after sending setup **/
1766 ch->l3id=newbc->l3_id;
1769 if ( r == -ENOCHAN ) {
1770 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
1771 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
1772 ast->hangupcause=34;
1773 ast_setstate(ast, AST_STATE_DOWN);
1777 chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
1779 ast_setstate(ast, AST_STATE_DIALING);
1780 ast->hangupcause=16;
1782 if (newbc->nt) stop_bc_tones(ch);
1788 static int misdn_answer(struct ast_channel *ast)
1790 struct chan_list *p;
1793 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
1795 chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
1798 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
1799 ast_queue_hangup(ast);
1803 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
1805 ast_queue_hangup(ast);
1809 const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
1812 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
1814 int l = sizeof(p->bc->crypt_key);
1815 strncpy(p->bc->crypt_key,tmp_key, l);
1816 p->bc->crypt_key[l-1] = 0;
1819 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
1825 const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
1827 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
1834 p->state = MISDN_CONNECTED;
1835 misdn_lib_echo(p->bc,0);
1838 if ( ast_strlen_zero(p->bc->cad) ) {
1839 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
1840 ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
1843 misdn_lib_send_event( p->bc, EVENT_CONNECT);
1849 static int misdn_digit(struct ast_channel *ast, char digit )
1851 struct chan_list *p;
1853 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
1855 struct misdn_bchannel *bc=p->bc;
1856 chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
1859 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
1863 switch (p->state ) {
1871 int l = sizeof(bc->infos_pending);
1872 strncat(bc->infos_pending,buf,l);
1873 bc->infos_pending[l-1] = 0;
1876 case MISDN_CALLING_ACKNOWLEDGE:
1878 bc->info_dad[0]=digit;
1882 int l = sizeof(bc->dad);
1883 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
1887 int l = sizeof(p->ast->exten);
1888 strncpy(p->ast->exten, bc->dad, l);
1889 p->ast->exten[l-1] = 0;
1892 misdn_lib_send_event( bc, EVENT_INFORMATION);
1897 if ( bc->send_dtmf ) {
1898 send_digit_to_chan(p,digit);
1907 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
1909 struct chan_list *p;
1911 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
1913 chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s Holded:%d L3id:%x\n", misdn_get_ch_state(p), p->holded, p->l3id);
1916 p->state=MISDN_CONNECTED;
1923 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
1925 struct chan_list *p;
1928 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
1929 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
1934 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
1935 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
1939 chan_misdn_log(1, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
1942 case AST_CONTROL_BUSY:
1943 chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
1944 chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
1945 ast_setstate(ast,AST_STATE_BUSY);
1947 p->bc->out_cause=17;
1948 if (p->state != MISDN_CONNECTED) {
1950 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
1952 chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
1956 case AST_CONTROL_RING:
1957 chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
1961 case AST_CONTROL_RINGING:
1963 case MISDN_ALERTING:
1964 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
1966 case MISDN_CONNECTED:
1967 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
1971 p->state=MISDN_ALERTING;
1972 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
1973 misdn_lib_send_event( p->bc, EVENT_ALERTING);
1975 if (p->other_ch && p->other_ch->bc) {
1976 if (misdn_inband_avail(p->other_ch->bc)) {
1977 chan_misdn_log(1,p->bc->port, " --> other End is mISDN and has inband info available\n");
1981 if (!p->other_ch->bc->nt) {
1982 chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
1987 chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
1988 ast_setstate(ast,AST_STATE_RINGING);
1990 if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio )
1991 chan_misdn_log(1,p->bc->port, " --> incoming_early_audio off\n");
1996 case AST_CONTROL_ANSWER:
1997 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
2000 case AST_CONTROL_TAKEOFFHOOK:
2001 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
2004 case AST_CONTROL_OFFHOOK:
2005 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
2008 case AST_CONTROL_FLASH:
2009 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
2011 case AST_CONTROL_PROGRESS:
2012 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
2013 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
2015 case AST_CONTROL_PROCEEDING:
2016 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
2017 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
2019 case AST_CONTROL_CONGESTION:
2020 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
2022 p->bc->out_cause=42;
2023 if (p->state != MISDN_CONNECTED) {
2025 misdn_lib_send_event( p->bc, EVENT_RELEASE);
2027 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
2031 hanguptone_indicate(p);
2035 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
2039 if (p->state == MISDN_CONNECTED)
2044 case AST_CONTROL_HOLD:
2045 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2047 case AST_CONTROL_UNHOLD:
2048 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
2051 ast_log(LOG_NOTICE, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
2057 static int misdn_hangup(struct ast_channel *ast)
2059 struct chan_list *p;
2060 struct misdn_bchannel *bc=NULL;
2062 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
2067 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
2070 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
2079 ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
2084 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2089 if (ast->_state == AST_STATE_RESERVED) {
2090 /* between request and call */
2091 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
2094 cl_dequeue_chan(&cl_te, p);
2098 misdn_lib_release(bc);
2110 const char *varcause=NULL;
2111 bc->out_cause=ast->hangupcause?ast->hangupcause:16;
2113 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
2114 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
2115 int tmpcause=atoi(varcause);
2116 bc->out_cause=tmpcause?tmpcause:16;
2119 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_P(ast), misdn_get_ch_state(p));
2120 chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
2121 chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
2122 chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
2123 chan_misdn_log(1, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
2127 p->state=MISDN_CLEANING;
2128 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
2133 hanguptone_indicate(p);
2136 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2138 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
2139 p->state=MISDN_CLEANING;
2143 case MISDN_CALLING_ACKNOWLEDGE:
2145 hanguptone_indicate(p);
2147 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2150 case MISDN_ALERTING:
2151 case MISDN_PROGRESS:
2152 case MISDN_PROCEEDING:
2153 if (p->orginator != ORG_AST)
2154 hanguptone_indicate(p);
2156 /*p->state=MISDN_CLEANING;*/
2157 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2159 case MISDN_CONNECTED:
2160 /* Alerting or Disconect */
2163 hanguptone_indicate(p);
2164 p->bc->progress_indicator=8;
2166 misdn_lib_send_event( bc, EVENT_DISCONNECT);
2168 /*p->state=MISDN_CLEANING;*/
2170 case MISDN_DISCONNECTED:
2171 misdn_lib_send_event( bc, EVENT_RELEASE);
2172 p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
2175 case MISDN_RELEASED:
2176 case MISDN_CLEANING:
2177 p->state=MISDN_CLEANING;
2183 case MISDN_HOLD_DISCONNECT:
2184 /* need to send release here */
2185 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
2186 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
2189 misdn_lib_send_event(bc,EVENT_RELEASE);
2190 p->state=MISDN_CLEANING;
2195 misdn_lib_send_event(bc, EVENT_RELEASE);
2196 p->state=MISDN_CLEANING;
2198 misdn_lib_send_event(bc, EVENT_DISCONNECT);
2202 p->state=MISDN_CLEANING;
2207 chan_misdn_log(1, bc->port, "Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
2213 struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
2215 struct ast_frame *f,*f2;
2217 f2=ast_translate(tmp->trans, frame,0);
2219 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
2223 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
2224 if (f && (f->frametype == AST_FRAME_DTMF)) {
2225 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
2226 if (f->subclass == 'f' && tmp->faxdetect) {
2227 /* Fax tone -- Handle and return NULL */
2228 struct ast_channel *ast = tmp->ast;
2229 if (!tmp->faxhandled) {
2231 if (strcmp(ast->exten, "fax")) {
2232 if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
2233 if (option_verbose > 2)
2234 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
2235 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
2236 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
2237 if (ast_async_goto(ast, ast->context, "fax", 1))
2238 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
2240 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
2242 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
2244 ast_log(LOG_DEBUG, "Fax already handled\n");
2246 } else if ( tmp->ast_dsp) {
2247 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
2252 frame->frametype = AST_FRAME_NULL;
2253 frame->subclass = 0;
2258 static struct ast_frame *misdn_read(struct ast_channel *ast)
2260 struct chan_list *tmp;
2264 chan_misdn_log(1,0,"misdn_read called without ast\n");
2267 if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) {
2268 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
2272 chan_misdn_log(1,0,"misdn_read called without bc\n");
2276 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
2279 /* we hangup here, since our pipe is closed */
2280 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
2284 tmp->frame.frametype = AST_FRAME_VOICE;
2285 tmp->frame.subclass = AST_FORMAT_ALAW;
2286 tmp->frame.datalen = len;
2287 tmp->frame.samples = len ;
2288 tmp->frame.mallocd =0 ;
2289 tmp->frame.offset= 0 ;
2290 tmp->frame.src = NULL;
2291 tmp->frame.data = tmp->ast_rd_buf ;
2293 if (tmp->faxdetect || tmp->ast_dsp ) {
2294 return process_ast_dsp(tmp, &tmp->frame);
2301 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
2303 struct chan_list *ch;
2306 if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
2309 ast_log(LOG_WARNING, "private but no bc\n");
2314 chan_misdn_log(5, ch->bc->port, "misdn_write: Returning because holded\n");
2319 chan_misdn_log(5, ch->bc->port, "misdn_write: Returning because notxone\n");
2324 if ( !frame->subclass) {
2325 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
2329 if ( !(frame->subclass & prefformat)) {
2331 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
2336 if ( !frame->samples ) {
2337 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
2341 if ( ! ch->bc->addr ) {
2342 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
2348 int i, max=5>frame->samples?frame->samples:5;
2350 printf("write2mISDN %p %d bytes: ", p, frame->samples);
2352 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
2358 switch (ch->bc->bc_state) {
2359 case BCHAN_ACTIVATED:
2363 if (!ch->dropped_frame_cnt)
2364 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state);
2366 ch->dropped_frame_cnt++;
2367 if (ch->dropped_frame_cnt > 100) {
2368 ch->dropped_frame_cnt=0;
2369 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x dropped > 100 frames!\n",frame->samples,ch->bc->addr);
2376 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
2378 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
2379 /* Buffered Transmit (triggert by read from isdn side)*/
2380 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
2382 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
2386 /*transmit without jitterbuffer*/
2387 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
2398 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
2399 struct ast_channel *c1, int flags,
2400 struct ast_frame **fo,
2401 struct ast_channel **rc,
2405 struct chan_list *ch1,*ch2;
2406 struct ast_channel *carr[2], *who;
2408 struct ast_frame *f;
2410 ch1=get_chan_by_ast(c0);
2411 ch2=get_chan_by_ast(c1);
2423 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2426 misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
2427 misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
2428 if ( !ecwb && ec ) {
2429 chan_misdn_log(2, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
2430 ch1->bc->ec_enable=0;
2431 manager_ec_disable(ch1->bc);
2433 misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
2434 misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
2436 chan_misdn_log(2, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
2437 ch2->bc->ec_enable=0;
2438 manager_ec_disable(ch2->bc);
2441 /* trying to make a mISDN_dsp conference */
2442 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
2444 misdn_lib_bridge(ch1->bc,ch2->bc);
2447 if (option_verbose > 2)
2448 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
2450 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
2452 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
2455 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
2460 who = ast_waitfor_n(carr, 2, &to);
2463 ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
2468 if (!f || f->frametype == AST_FRAME_CONTROL) {
2472 chan_misdn_log(1,ch1->bc->port,"Read Null Frame\n");
2474 chan_misdn_log(1,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
2482 if ( f->frametype == AST_FRAME_DTMF ) {
2483 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
2500 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
2502 misdn_lib_split_bridge(ch1->bc,ch2->bc);
2505 return AST_BRIDGE_COMPLETE;
2508 /** AST INDICATIONS END **/
2510 static int dialtone_indicate(struct chan_list *cl)
2512 const struct tone_zone_sound *ts= NULL;
2513 struct ast_channel *ast=cl->ast;
2514 chan_misdn_log(3,cl->bc->port," --> Dial\n");
2515 ts=ast_get_indication_tone(ast->zone,"dial");
2521 ast_playtones_start(ast,0, ts->data, 0);
2522 chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
2523 misdn_lib_tone_generator_start(cl->bc);
2529 static int hanguptone_indicate(struct chan_list *cl)
2531 misdn_lib_send_tone(cl->bc,TONE_HANGUP);
2532 misdn_lib_tone_generator_start(cl->bc);
2536 static int stop_indicate(struct chan_list *cl)
2538 struct ast_channel *ast=cl->ast;
2539 chan_misdn_log(3,cl->bc->port," --> None\n");
2540 misdn_lib_tone_generator_stop(cl->bc);
2541 ast_playtones_stop(ast);
2542 /*ast_deactivate_generator(ast);*/
2548 static int start_bc_tones(struct chan_list* cl)
2550 misdn_lib_tone_generator_stop(cl->bc);
2556 static int stop_bc_tones(struct chan_list *cl)
2567 static struct chan_list *init_chan_list(int orig)
2569 struct chan_list *cl=malloc(sizeof(struct chan_list));
2572 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
2576 memset(cl,0,sizeof(struct chan_list));
2579 cl->need_queue_hangup=1;
2586 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
2589 struct ast_channel *tmp = NULL;
2590 char group[BUFFERSIZE+1]="";
2592 char buf2[128], *ext=NULL, *port_str;
2593 char *tokb=NULL, *p=NULL;
2594 int channel=0, port=0;
2595 struct misdn_bchannel *newbc = NULL;
2597 struct chan_list *cl=init_chan_list(ORG_AST);
2599 sprintf(buf,"%s/%s",misdn_type,(char*)data);
2600 ast_copy_string(buf2,data, 128);
2602 port_str=strtok_r(buf2,"/", &tokb);
2604 ext=strtok_r(NULL,"/", &tokb);
2607 if (port_str[0]=='g' && port_str[1]==':' ) {
2608 /* We make a group call lets checkout which ports are in my group */
2610 strncpy(group, port_str, BUFFERSIZE);
2612 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
2614 else if ((p = strchr(port_str, ':'))) {
2615 /* we have a preselected channel */
2617 channel = atoi(++p);
2618 port = atoi(port_str);
2619 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
2622 port = atoi(port_str);
2627 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
2631 if (!ast_strlen_zero(group)) {
2633 char cfg_group[BUFFERSIZE+1];
2634 struct robin_list *rr = NULL;
2636 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
2637 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
2638 rr = get_robin_position(group);
2642 int robin_channel = rr->channel;
2648 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
2649 port = misdn_cfg_get_next_port_spin(port)) {
2654 if (port >= port_start)
2657 if (port <= port_start && next_chan) {
2658 int maxbchans=misdn_lib_get_maxchans(port);
2659 if (++robin_channel >= maxbchans) {
2665 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
2667 if (!strcasecmp(cfg_group, group)) {
2670 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
2671 misdn_cfg_get(port, MISDN_CFG_PP_L2_CHECK, &checkl2, sizeof(int));
2672 check=checkl2?2:check;
2674 port_up = misdn_lib_port_up(port, check);
2676 if (check && !port_up)
2677 chan_misdn_log(1,port,"L1 is not Up on this Port\n");
2681 newbc = misdn_lib_get_free_bc(port, robin_channel);
2683 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
2685 chan_misdn_log(4, port, "portup:%d\n", port_up);
2686 rr->port = newbc->port;
2687 rr->channel = newbc->channel;
2693 } while (!newbc && robin_channel != rr->channel);
2696 chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
2700 for (port=misdn_cfg_get_next_port(0); port > 0;
2701 port=misdn_cfg_get_next_port(port)) {
2703 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
2705 chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
2706 if (!strcasecmp(cfg_group, group)) {
2709 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
2710 misdn_cfg_get(port, MISDN_CFG_PP_L2_CHECK, &checkl2, sizeof(int));
2711 check=checkl2?2:check;
2712 port_up = misdn_lib_port_up(port, check);
2714 chan_misdn_log(4, port, "portup:%d\n", port_up);
2717 newbc = misdn_lib_get_free_bc(port, 0);
2727 chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
2728 newbc = misdn_lib_get_free_bc(port, channel);
2732 chan_misdn_log(-1, 0, "Could not create channel on port:%d with extensions:%s\n",port,ext);
2736 /* create ast_channel and link all the objects together */
2739 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
2742 /* register chan in local list */
2743 cl_queue_chan(&cl_te, cl) ;
2745 /* fill in the config into the objects */
2746 read_config(cl, ORG_AST);
2755 static int misdn_send_text (struct ast_channel *chan, const char *text)
2757 struct chan_list *tmp=chan->tech_pvt;
2759 if (tmp && tmp->bc) {
2760 ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
2761 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
2763 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
2770 static struct ast_channel_tech misdn_tech = {
2772 .description="Channel driver for mISDN Support (Bri/Pri)",
2773 .capabilities= AST_FORMAT_ALAW ,
2774 .requester=misdn_request,
2775 .send_digit=misdn_digit,
2777 .bridge=misdn_bridge,
2778 .hangup=misdn_hangup,
2779 .answer=misdn_answer,
2782 .indicate=misdn_indication,
2784 .send_text=misdn_send_text,
2788 static struct ast_channel_tech misdn_tech_wo_bridge = {
2790 .description="Channel driver for mISDN Support (Bri/Pri)",
2791 .capabilities=AST_FORMAT_ALAW ,
2792 .requester=misdn_request,
2793 .send_digit=misdn_digit,
2795 .hangup=misdn_hangup,
2796 .answer=misdn_answer,
2799 .indicate=misdn_indication,
2801 .send_text=misdn_send_text,
2806 static unsigned long glob_channel=0;
2808 static void update_name(struct ast_channel *tmp, int port, int c)
2812 ast_string_field_build(tmp, name, "%s/%d-u%d",
2813 misdn_type, port, c);
2815 ast_string_field_build(tmp, name, "%s/%d-%d",
2816 misdn_type, port, c);
2819 chan_misdn_log(3,port," --> updating channel name to [%s]\n",tmp->name);
2823 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
2825 struct ast_channel *tmp;
2827 tmp = ast_channel_alloc(1);
2830 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
2832 update_name(tmp,port,c);
2834 tmp->nativeformats = prefformat;
2836 tmp->readformat = format;
2837 tmp->rawreadformat = format;
2838 tmp->writeformat = format;
2839 tmp->rawwriteformat = format;
2841 tmp->tech_pvt = chlist;
2844 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
2846 tmp->tech = &misdn_tech;
2848 tmp->tech = &misdn_tech_wo_bridge;
2850 tmp->writeformat = format;
2851 tmp->readformat = format;
2855 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
2857 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
2860 char *cid_name, *cid_num;
2862 ast_callerid_parse(callerid, &cid_name, &cid_num);
2863 ast_set_callerid(tmp, cid_num,cid_name,cid_num);
2865 ast_set_callerid(tmp, NULL,NULL,NULL);
2869 if (pipe(chlist->pipe)<0)
2870 perror("Pipe failed\n");
2872 tmp->fds[0]=chlist->pipe[0];
2876 ast_setstate(tmp, state);
2877 if (state == AST_STATE_RING)
2884 chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
2890 static struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
2892 struct chan_list *help=list;
2893 for (;help; help=help->next) {
2894 if (help->l3id == l3id ) return help;
2897 chan_misdn_log(6, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
2902 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
2904 struct chan_list *help=list;
2905 for (;help; help=help->next) {
2906 if (help->bc == bc) return help;
2909 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
2914 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
2916 struct chan_list *help=list;
2917 for (;help; help=help->next) {
2918 if (help->bc->pid == pid) return help;
2921 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
2926 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
2928 struct chan_list *help=list;
2930 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
2931 for (;help; help=help->next) {
2932 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
2933 if (help->bc->port == bc->port
2934 && help->bc->holded ) return help;
2937 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
2942 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
2944 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
2946 ast_mutex_lock(&cl_te_lock);
2950 struct chan_list *help=*list;
2951 for (;help->next; help=help->next);
2955 ast_mutex_unlock(&cl_te_lock);
2958 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
2961 ast_dsp_free(chan->dsp);
2963 ast_translator_free_path(chan->trans);
2967 ast_mutex_lock(&cl_te_lock);
2969 ast_mutex_unlock(&cl_te_lock);
2973 if (*list == chan) {
2974 *list=(*list)->next;
2975 ast_mutex_unlock(&cl_te_lock);
2980 struct chan_list *help=*list;
2981 for (;help->next; help=help->next) {
2982 if (help->next == chan) {
2983 help->next=help->next->next;
2984 ast_mutex_unlock(&cl_te_lock);
2990 ast_mutex_unlock(&cl_te_lock);
2993 /** Channel Queue End **/
2996 int pbx_start_chan(struct chan_list *ch)
2998 int ret=ast_pbx_start(ch->ast);
3008 static void hangup_chan(struct chan_list *ch)
3011 cb_log(1,0,"Cannot hangup chan, no ch\n");
3016 if (ch->need_hangup)
3018 send_cause2ast(ch->ast,ch->bc,ch);
3020 ch->need_queue_hangup=0;
3022 ast_hangup(ch->ast);
3026 if (!ch->need_queue_hangup) {
3027 cb_log(1,ch->bc->port,"No need to queue hangup\n");
3030 ch->need_queue_hangup=0;
3032 send_cause2ast(ch->ast,ch->bc,ch);
3033 ast_queue_hangup(ch->ast);
3035 cb_log(1,ch->bc->port,"Cannot hangup chan, no ast\n");
3039 /** Isdn asks us to release channel, pendant to misdn_hangup **/
3040 static void release_chan(struct misdn_bchannel *bc) {
3041 struct ast_channel *ast=NULL;
3043 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
3044 if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
3046 chan_misdn_log(0, bc->port, "release_chan: Ch not found!\n");
3056 chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
3058 /*releaseing jitterbuffer*/
3060 misdn_jb_destroy(ch->jb);
3064 chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
3068 if (ch->orginator == ORG_AST) {
3069 misdn_out_calls[bc->port]--;
3071 misdn_in_calls[bc->port]--;
3080 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
3081 chan_misdn_log(1, bc->port, "* RELEASING CHANNEL pid:%d ctx:%s dad:%s oad:%s state: %s\n",bc?bc->pid:-1, ast->context, ast->exten,AST_CID_P(ast),misdn_get_ch_state(ch));
3082 chan_misdn_log(3, bc->port, " --> * State Down\n");
3083 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
3086 if (ast->_state != AST_STATE_RESERVED) {
3087 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
3088 ast_setstate(ast, AST_STATE_DOWN);
3092 ch->state=MISDN_CLEANING;
3093 cl_dequeue_chan(&cl_te, ch);
3097 /* chan is already cleaned, so exiting */
3101 /*** release end **/
3103 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
3105 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
3107 tmp_ch->state=MISDN_HOLD_DISCONNECT;
3109 ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
3111 holded_chan->state=MISDN_CONNECTED;
3112 holded_chan->holded=0;
3113 misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
3114 ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
3118 static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
3120 char predial[256]="";
3123 struct ast_frame fr;
3125 strncpy(predial, ast->exten, sizeof(predial) -1 );
3127 ch->state=MISDN_DIALING;
3131 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3134 if ( misdn_lib_is_ptp(bc->port)) {
3135 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
3137 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
3141 if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio )
3142 chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
3144 dialtone_indicate(ch);
3146 chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast));
3148 strncpy(ast->exten,"s", 2);
3150 if (pbx_start_chan(ch)<0) {
3153 hanguptone_indicate(ch);
3156 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
3158 misdn_lib_send_event(bc, EVENT_DISCONNECT );