00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <pthread.h>
00031 #include <string.h>
00032 #include <sys/socket.h>
00033 #include <sys/time.h>
00034 #include <errno.h>
00035 #include <unistd.h>
00036 #include <stdlib.h>
00037 #include <arpa/inet.h>
00038 #include <fcntl.h>
00039 #include <sys/ioctl.h>
00040 #include <sys/file.h>
00041
00042 #include <asterisk/channel.h>
00043 #include <asterisk/config.h>
00044 #include <asterisk/logger.h>
00045 #include <asterisk/module.h>
00046 #include <asterisk/pbx.h>
00047 #include <asterisk/options.h>
00048 #include <asterisk/io.h>
00049 #include <asterisk/frame.h>
00050 #include <asterisk/translate.h>
00051 #include <asterisk/cli.h>
00052 #include <asterisk/musiconhold.h>
00053 #include <asterisk/dsp.h>
00054 #include <asterisk/translate.h>
00055 #include <asterisk/config.h>
00056 #include <asterisk/file.h>
00057 #include <asterisk/callerid.h>
00058 #include <asterisk/indications.h>
00059 #include <asterisk/app.h>
00060 #include <asterisk/features.h>
00061
00062 #include "chan_misdn_config.h"
00063 #include "isdn_lib.h"
00064
00065 ast_mutex_t release_lock_mutex;
00066
00067 #define release_lock ast_mutex_lock(&release_lock_mutex)
00068 #define release_unlock ast_mutex_unlock(&release_lock_mutex)
00069
00070
00071
00072
00073 enum misdn_chan_state {
00074 MISDN_NOTHING,
00075 MISDN_WAITING4DIGS,
00076 MISDN_EXTCANTMATCH,
00077 MISDN_DIALING,
00078 MISDN_PROGRESS,
00079 MISDN_CALLING,
00080 MISDN_CALLING_ACKNOWLEDGE,
00081 MISDN_ALERTING,
00082 MISDN_BUSY,
00083 MISDN_CONNECTED,
00084 MISDN_BRIDGED,
00085 MISDN_CLEANING,
00086 MISDN_HUNGUP_FROM_MISDN,
00087 MISDN_HUNGUP_FROM_AST,
00088
00089 MISDN_HOLDED,
00090 MISDN_HOLD_DISCONNECT
00091
00092 };
00093
00094 #define ORG_AST 1
00095 #define ORG_MISDN 2
00096
00097 struct chan_list {
00098
00099 ast_mutex_t lock;
00100
00101 enum misdn_chan_state state;
00102 int holded;
00103 int orginator;
00104
00105 int norxtone;
00106 int notxtone;
00107
00108 int pipe[2];
00109 char ast_rd_buf[4096];
00110 struct ast_frame frame;
00111
00112 int faxdetect;
00113 int faxhandled;
00114
00115 int ast_dsp;
00116
00117 struct ast_dsp *dsp;
00118 struct ast_trans_pvt *trans;
00119
00120 struct ast_channel * ast;
00121
00122 struct misdn_bchannel *bc;
00123 struct misdn_bchannel *holded_bc;
00124
00125 unsigned int l3id;
00126 int addr;
00127
00128 struct chan_list *peer;
00129 struct chan_list *next;
00130 struct chan_list *prev;
00131 struct chan_list *first;
00132 };
00133
00134 struct robin_list {
00135 char *group;
00136 int port;
00137 int channel;
00138 struct robin_list *next;
00139 struct robin_list *prev;
00140 };
00141 static struct robin_list *robin = NULL;
00142
00143 static inline void free_robin_list_r (struct robin_list *r)
00144 {
00145 if (r) {
00146 if (r->next) free_robin_list_r(r->next);
00147 if (r->group) free(r->group);
00148 free(r);
00149 }
00150 }
00151
00152 static void free_robin_list ( void )
00153 {
00154 free_robin_list_r(robin);
00155 robin = NULL;
00156 }
00157
00158 struct robin_list* get_robin_position (char *group)
00159 {
00160 struct robin_list *iter = robin;
00161 for (; iter; iter = iter->next) {
00162 if (!strcasecmp(iter->group, group))
00163 return iter;
00164 }
00165 struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
00166 new->group = strndup(group, strlen(group));
00167 new->channel = 1;
00168 if (robin) {
00169 new->next = robin;
00170 robin->prev = new;
00171 }
00172 robin = new;
00173 return robin;
00174 }
00175
00176 struct ast_channel *misdn_new(struct chan_list *cl, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c);
00177 void send_digit_to_chan(struct chan_list *cl, char digit );
00178
00179
00180 #define AST_CID_P(ast) ast->cid.cid_num
00181 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast)
00182 #define AST_LOAD_CFG ast_config_load
00183 #define AST_DESTROY_CFG ast_config_destroy
00184
00185 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
00186 #define MISDN_ASTERISK_PVT(ast) 1
00187 #define MISDN_ASTERISK_TYPE(ast) ast->tech->type
00188
00189
00190
00191 #include <asterisk/strings.h>
00192
00193
00194
00195 static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
00196 static char *type = "mISDN";
00197
00198 int tracing = 0 ;
00199
00200 static int usecnt=0;
00201
00202 char **misdn_key_vector=NULL;
00203 int misdn_key_vector_size=0;
00204
00205
00206 static int prefformat = AST_FORMAT_ALAW ;
00207
00208 static ast_mutex_t usecnt_lock;
00209
00210 int *misdn_debug;
00211 int *misdn_debug_only;
00212 int max_ports;
00213
00214 struct chan_list dummy_cl;
00215
00216 struct chan_list *cl_te=NULL;
00217 ast_mutex_t cl_te_lock;
00218
00219 enum event_response_e
00220 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
00221
00222 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc);
00223
00224 void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
00225 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
00226 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
00227 void chan_misdn_log(int level, int port, char *tmpl, ...);
00228 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...);
00229
00230 static int start_bc_tones(struct chan_list *cl);
00231 static int stop_bc_tones(struct chan_list *cl);
00232 static void release_chan(struct misdn_bchannel *bc);
00233
00234 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
00235 static int misdn_facility_exec(struct ast_channel *chan, void *data);
00236
00237
00238
00239 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
00240 {
00241 struct chan_list *tmp;
00242
00243 for (tmp=cl_te; tmp; tmp = tmp->next) {
00244 if ( tmp->ast == ast ) return tmp;
00245 }
00246
00247 return NULL;
00248 }
00249
00250 static struct chan_list * get_chan_by_ast_name(char *name)
00251 {
00252 struct chan_list *tmp;
00253
00254 for (tmp=cl_te; tmp; tmp = tmp->next) {
00255 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp;
00256 }
00257
00258 return NULL;
00259 }
00260
00261 static char* tone2str(struct misdn_bchannel *bc)
00262 {
00263 static struct {
00264 char name[16];
00265 enum tone_e tone;
00266 } *tone, tone_buf[] = {
00267 {"NOTONE",TONE_NONE},
00268 {"DIAL",TONE_DIAL},
00269 {"BUSY",TONE_BUSY},
00270 {"ALERT",TONE_ALERTING},
00271 {"",TONE_NONE}
00272 };
00273
00274
00275 for (tone=&tone_buf[0]; tone->name[0]; tone++) {
00276 if (tone->tone == bc->tone) return tone->name;
00277 }
00278 return NULL;
00279 }
00280
00281 static char *bearer2str(int cap) {
00282 static char *bearers[]={
00283 "Speech",
00284 "Audio 3.1k",
00285 "Unres Digital",
00286 "Res Digital",
00287 "Unknown Bearer"
00288 };
00289
00290 switch (cap) {
00291 case INFO_CAPABILITY_SPEECH:
00292 return bearers[0];
00293 break;
00294 case INFO_CAPABILITY_AUDIO_3_1K:
00295 return bearers[1];
00296 break;
00297 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00298 return bearers[2];
00299 break;
00300 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00301 return bearers[3];
00302 break;
00303 default:
00304 return bearers[4];
00305 break;
00306 }
00307 }
00308
00309 static void print_bearer(struct misdn_bchannel *bc)
00310 {
00311
00312 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00313
00314 switch(bc->law) {
00315 case INFO_CODEC_ALAW:
00316 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00317 break;
00318 case INFO_CODEC_ULAW:
00319 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00320 break;
00321 }
00322 }
00323
00324
00325 void send_digit_to_chan(struct chan_list *cl, char digit )
00326 {
00327 static const char* dtmf_tones[] = {
00328 "!941+1336/100,!0/100",
00329 "!697+1209/100,!0/100",
00330 "!697+1336/100,!0/100",
00331 "!697+1477/100,!0/100",
00332 "!770+1209/100,!0/100",
00333 "!770+1336/100,!0/100",
00334 "!770+1477/100,!0/100",
00335 "!852+1209/100,!0/100",
00336 "!852+1336/100,!0/100",
00337 "!852+1477/100,!0/100",
00338 "!697+1633/100,!0/100",
00339 "!770+1633/100,!0/100",
00340 "!852+1633/100,!0/100",
00341 "!941+1633/100,!0/100",
00342 "!941+1209/100,!0/100",
00343 "!941+1477/100,!0/100" };
00344 struct ast_channel *chan=cl->ast;
00345
00346 if (digit >= '0' && digit <='9')
00347 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00348 else if (digit >= 'A' && digit <= 'D')
00349 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00350 else if (digit == '*')
00351 ast_playtones_start(chan,0,dtmf_tones[14], 0);
00352 else if (digit == '#')
00353 ast_playtones_start(chan,0,dtmf_tones[15], 0);
00354 else {
00355
00356 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00357
00358
00359 }
00360 }
00361
00362 static int misdn_set_debug(int fd, int argc, char *argv[])
00363 {
00364 if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
00365 return RESULT_SHOWUSAGE;
00366
00367 int level = atoi(argv[3]);
00368
00369 switch (argc) {
00370 case 4:
00371 case 5: {
00372 int only = 0;
00373 if (argc == 5) {
00374 if (strncasecmp(argv[4], "only", strlen(argv[4])))
00375 return RESULT_SHOWUSAGE;
00376 else
00377 only = 1;
00378 }
00379 int i;
00380 for (i=0; i<=max_ports; i++) {
00381 misdn_debug[i] = level;
00382 misdn_debug_only[i] = only;
00383 }
00384 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00385 }
00386 break;
00387 case 6:
00388 case 7: {
00389 if (strncasecmp(argv[4], "port", strlen(argv[4])))
00390 return RESULT_SHOWUSAGE;
00391 int port = atoi(argv[5]);
00392 if (port <= 0 || port > max_ports) {
00393 switch (max_ports) {
00394 case 0:
00395 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00396 break;
00397 case 1:
00398 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
00399 break;
00400 default:
00401 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00402 }
00403 return 0;
00404 }
00405 if (argc == 7) {
00406 if (strncasecmp(argv[6], "only", strlen(argv[6])))
00407 return RESULT_SHOWUSAGE;
00408 else
00409 misdn_debug_only[port] = 1;
00410 } else
00411 misdn_debug_only[port] = 0;
00412 misdn_debug[port] = level;
00413 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
00414 }
00415 }
00416 return 0;
00417 }
00418
00419
00420 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
00421 {
00422 if (argc != 5 )return RESULT_SHOWUSAGE;
00423
00424 return 0;
00425 }
00426
00427
00428 static int misdn_restart_port (int fd, int argc, char *argv[])
00429 {
00430 int port;
00431
00432 if (argc != 4)
00433 return RESULT_SHOWUSAGE;
00434
00435 port = atoi(argv[3]);
00436
00437 misdn_lib_port_restart(port);
00438
00439 return 0;
00440 }
00441
00442 static int misdn_port_up (int fd, int argc, char *argv[])
00443 {
00444 int port;
00445
00446 if (argc != 4)
00447 return RESULT_SHOWUSAGE;
00448
00449 port = atoi(argv[3]);
00450
00451 misdn_lib_get_port_up(port);
00452
00453 return 0;
00454 }
00455
00456
00457 static int misdn_show_config (int fd, int argc, char *argv[])
00458 {
00459 char buffer[BUFFERSIZE];
00460 enum misdn_cfg_elements elem;
00461 int linebreak;
00462
00463 int onlyport = -1;
00464 if (argc >= 4) {
00465 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
00466 ast_cli(fd, "Unknown option: %s\n", argv[3]);
00467 return RESULT_SHOWUSAGE;
00468 }
00469 }
00470
00471 if (argc == 3 || onlyport == 0) {
00472 ast_cli(fd,"Misdn General-Config: \n");
00473 ast_cli(fd," -> VERSION: " CHAN_MISDN_VERSION "\n");
00474
00475 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
00476 misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
00477 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00478 }
00479 }
00480
00481 if (onlyport < 0) {
00482 int port = misdn_cfg_get_next_port(0);
00483 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
00484 ast_cli(fd, "\n[PORT %d]\n", port);
00485 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00486 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
00487 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00488 }
00489 ast_cli(fd, "\n");
00490 }
00491 }
00492
00493 if (onlyport > 0) {
00494 if (misdn_cfg_is_port_valid(onlyport)) {
00495 ast_cli(fd, "[PORT %d]\n", onlyport);
00496 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00497 misdn_cfg_get_config_string( onlyport, elem, buffer, BUFFERSIZE);
00498 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00499 }
00500 ast_cli(fd, "\n");
00501 } else {
00502 ast_cli(fd, "Port %d is not active!\n", onlyport);
00503 }
00504 }
00505 return 0;
00506 }
00507
00508
00509
00510 struct state_struct {
00511 enum misdn_chan_state state;
00512 char txt[255] ;
00513 } ;
00514
00515 struct state_struct state_array[] = {
00516 {MISDN_NOTHING,"NOTHING"},
00517 {MISDN_WAITING4DIGS,"WAITING4DIGS"},
00518 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"},
00519 {MISDN_DIALING,"DIALING"},
00520 {MISDN_PROGRESS,"PROGRESS"},
00521 {MISDN_CALLING,"CALLING"},
00522 {MISDN_ALERTING,"ALERTING"},
00523 {MISDN_BUSY,"BUSY"},
00524 {MISDN_CONNECTED,"CONNECTED"},
00525 {MISDN_BRIDGED,"BRIDGED"},
00526 {MISDN_CLEANING,"CLEANING"},
00527 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"},
00528 {MISDN_HOLDED,"HOLDED"},
00529 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"},
00530 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"}
00531
00532 };
00533
00534
00535
00536
00537 char *misdn_get_ch_state(struct chan_list *p)
00538 {
00539 int i;
00540 if( !p) return NULL;
00541
00542 for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
00543 if ( state_array[i].state == p->state) return state_array[i].txt;
00544 }
00545
00546 return NULL;
00547 }
00548
00549 static int misdn_reload (int fd, int argc, char *argv[])
00550 {
00551 int i, cfg_debug;
00552
00553 ast_cli(fd, "Reloading mISDN Config\n");
00554 chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
00555
00556 free_robin_list();
00557
00558 misdn_cfg_reload();
00559
00560 {
00561 char tempbuf[BUFFERSIZE];
00562 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
00563 if (strlen(tempbuf))
00564 tracing = 1;
00565 }
00566
00567 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
00568 for (i = 0; i <= max_ports; i++) {
00569 misdn_debug[i] = cfg_debug;
00570 misdn_debug_only[i] = 0;
00571 }
00572
00573 return 0;
00574 }
00575
00576 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
00577 {
00578 struct ast_channel *ast=help->ast;
00579 ast_cli(fd,
00580 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
00581 bc->pid, bc->port, bc->channel,
00582 bc->nt?"NT":"TE",
00583 help->orginator == ORG_AST?"*":"I",
00584 ast?ast->exten:NULL,
00585 ast?AST_CID_P(ast):NULL,
00586 ast?ast->context:NULL,
00587 misdn_get_ch_state(help)
00588 );
00589 if (misdn_debug[bc->port] > 0)
00590 ast_cli(fd,
00591 " --> astname: %s\n"
00592 " --> ch_l3id: %x\n"
00593 " --> ch_addr: %x\n"
00594 " --> bc_addr: %x\n"
00595 " --> bc_l3id: %x\n"
00596 " --> tone: %s\n"
00597 " --> display: %s\n"
00598 " --> activated: %d\n"
00599 " --> capability: %s\n"
00600 " --> echo_cancel: %d\n"
00601 " --> notone : rx %d tx:%d\n"
00602 " --> bc_hold: %d holded_bc :%d\n",
00603 help->ast->name,
00604 help->l3id,
00605 help->addr,
00606 bc->addr,
00607 bc?bc->l3_id:-1,
00608 tone2str(bc),
00609 bc->display,
00610
00611 bc->active,
00612 bearer2str(bc->capability),
00613 bc->ec_enable,
00614 help->norxtone,help->notxtone,
00615 bc->holded, help->holded_bc?1:0
00616 );
00617
00618 }
00619
00620
00621 static int misdn_show_cls (int fd, int argc, char *argv[])
00622 {
00623 struct chan_list *help=cl_te;
00624
00625 ast_cli(fd,"Chan List: %p\n",cl_te);
00626
00627 for (;help; help=help->next) {
00628 struct misdn_bchannel *bc=help->bc;
00629 struct ast_channel *ast=help->ast;
00630 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
00631 if (bc) {
00632 print_bc_info(fd, help, bc);
00633 } else if ( (bc=help->holded_bc) ) {
00634 chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
00635 print_bc_info(fd, help, bc);
00636 } else {
00637 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
00638 }
00639 }
00640
00641
00642 return 0;
00643 }
00644
00645
00646
00647 static int misdn_show_cl (int fd, int argc, char *argv[])
00648 {
00649 struct chan_list *help=cl_te;
00650
00651 if (argc != 4)
00652 return RESULT_SHOWUSAGE;
00653
00654 for (;help; help=help->next) {
00655 struct misdn_bchannel *bc=help->bc;
00656 struct ast_channel *ast=help->ast;
00657
00658 if (bc && ast) {
00659 if (!strcasecmp(ast->name,argv[3])) {
00660 print_bc_info(fd, help, bc);
00661 break;
00662 }
00663 }
00664 }
00665
00666
00667 return 0;
00668 }
00669
00670 ast_mutex_t lock;
00671 int MAXTICS=8;
00672
00673 static int misdn_set_tics (int fd, int argc, char *argv[])
00674 {
00675 if (argc != 4)
00676 return RESULT_SHOWUSAGE;
00677
00678 MAXTICS=atoi(argv[3]);
00679
00680 return 0;
00681 }
00682
00683
00684
00685 static int misdn_show_stacks (int fd, int argc, char *argv[])
00686 {
00687 int port;
00688
00689 ast_cli(fd, "BEGIN STACK_LIST:\n");
00690 for (port=misdn_cfg_get_next_port(0); port > 0;
00691 port=misdn_cfg_get_next_port(port)) {
00692 char buf[128];
00693 get_show_stack_details(port,buf);
00694 ast_cli(fd," %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00695 }
00696
00697
00698 return 0;
00699
00700 }
00701
00702 static int misdn_show_port (int fd, int argc, char *argv[])
00703 {
00704 int port;
00705
00706 if (argc != 4)
00707 return RESULT_SHOWUSAGE;
00708
00709 port = atoi(argv[3]);
00710
00711 ast_cli(fd, "BEGIN STACK_LIST:\n");
00712
00713 char buf[128];
00714 get_show_stack_details(port,buf);
00715 ast_cli(fd," %s Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00716
00717
00718 return 0;
00719 }
00720
00721 static int misdn_send_cd (int fd, int argc, char *argv[])
00722 {
00723 char *channame;
00724 char *nr;
00725
00726 if (argc != 5)
00727 return RESULT_SHOWUSAGE;
00728
00729 channame = argv[3];
00730 nr = argv[4];
00731
00732 ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
00733
00734 {
00735 struct chan_list *tmp=get_chan_by_ast_name(channame);
00736
00737 if (!tmp) {
00738 ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
00739 return 0;
00740 } else {
00741
00742 misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
00743 }
00744 }
00745
00746 return 0;
00747 }
00748
00749
00750
00751 static int misdn_send_digit (int fd, int argc, char *argv[])
00752 {
00753 char *channame;
00754 char *msg;
00755
00756 if (argc != 5)
00757 return RESULT_SHOWUSAGE;
00758
00759 channame = argv[3];
00760 msg = argv[4];
00761
00762 ast_cli(fd, "Sending %s to %s\n",msg, channame);
00763
00764 {
00765 struct chan_list *tmp=get_chan_by_ast_name(channame);
00766
00767 if (!tmp) {
00768 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
00769 return 0;
00770 } else {
00771 #if 1
00772 int i;
00773 int msglen = strlen(msg);
00774 for (i=0; i<msglen; i++) {
00775 ast_cli(fd, "Sending: %c\n",msg[i]);
00776 send_digit_to_chan(tmp, msg[i]);
00777
00778 usleep(250000);
00779
00780 }
00781 #else
00782 int res;
00783 res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
00784 #endif
00785 }
00786 }
00787
00788 return 0;
00789 }
00790
00791 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
00792 {
00793 char *channame;
00794
00795 if (argc != 4)
00796 return RESULT_SHOWUSAGE;
00797
00798 channame = argv[3];
00799
00800 ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
00801
00802 {
00803 struct chan_list *tmp=get_chan_by_ast_name(channame);
00804
00805 if (!tmp) {
00806 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
00807 return 0;
00808 } else {
00809 tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
00810
00811 if (tmp->bc->ec_enable) {
00812 manager_ec_enable(tmp->bc);
00813 } else {
00814 manager_ec_disable(tmp->bc);
00815 }
00816 }
00817 }
00818
00819 return 0;
00820 }
00821
00822
00823
00824 static int misdn_send_display (int fd, int argc, char *argv[])
00825 {
00826 char *channame;
00827 char *msg;
00828
00829 if (argc != 5)
00830 return RESULT_SHOWUSAGE;
00831
00832 channame = argv[3];
00833 msg = argv[4];
00834
00835 ast_cli(fd, "Sending %s to %s\n",msg, channame);
00836 {
00837 struct chan_list *tmp;
00838 tmp=get_chan_by_ast_name(channame);
00839
00840 if (tmp && tmp->bc) {
00841 int l = sizeof(tmp->bc->display);
00842 strncpy(tmp->bc->display, msg, l);
00843 tmp->bc->display[l-1] = 0;
00844 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
00845 } else {
00846 ast_cli(fd,"No such channel %s\n",channame);
00847 return RESULT_FAILURE;
00848 }
00849 }
00850
00851 return RESULT_SUCCESS ;
00852 }
00853
00854
00855
00856
00857 static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
00858 {
00859 struct ast_channel *c;
00860 int which=0;
00861 char *ret;
00862 if (pos != rpos)
00863 return NULL;
00864 c = ast_channel_walk_locked(NULL);
00865 while(c) {
00866 if (!strncasecmp(word, c->name, strlen(word))) {
00867 if (++which > state)
00868 break;
00869 }
00870 ast_mutex_unlock(&c->lock);
00871 c = ast_channel_walk_locked(c);
00872 }
00873 if (c) {
00874 ret = strdup(c->name);
00875 ast_mutex_unlock(&c->lock);
00876 } else
00877 ret = NULL;
00878 return ret;
00879 }
00880
00881 static char *complete_ch(char *line, char *word, int pos, int state)
00882 {
00883 return complete_ch_helper(line, word, pos, state, 3);
00884 }
00885
00886 static char *complete_debug_port (char *line, char *word, int pos, int state)
00887 {
00888 if (state)
00889 return NULL;
00890
00891 switch (pos) {
00892 case 4: if (*word == 'p')
00893 return strdup("port");
00894 else if (*word == 'o')
00895 return strdup("only");
00896 break;
00897 case 6: if (*word == 'o')
00898 return strdup("only");
00899 break;
00900 }
00901 return NULL;
00902 }
00903
00904 static struct ast_cli_entry cli_send_cd =
00905 { {"misdn","send","calldeflect", NULL},
00906 misdn_send_cd,
00907 "Sends CallDeflection to mISDN Channel",
00908 "Usage: misdn send calldeflect <channel> \"<nr>\" \n",
00909 complete_ch
00910 };
00911
00912
00913 static struct ast_cli_entry cli_send_digit =
00914 { {"misdn","send","digit", NULL},
00915 misdn_send_digit,
00916 "Sends DTMF Digit to mISDN Channel",
00917 "Usage: misdn send digit <channel> \"<msg>\" \n"
00918 " Send <digit> to <channel> as DTMF Tone\n"
00919 " when channel is a mISDN channel\n",
00920 complete_ch
00921 };
00922
00923
00924 static struct ast_cli_entry cli_toggle_echocancel =
00925 { {"misdn","toggle","echocancel", NULL},
00926 misdn_toggle_echocancel,
00927 "Toggles EchoCancel on mISDN Channel",
00928 "Usage: misdn toggle echocancel <channel>\n",
00929 complete_ch
00930 };
00931
00932
00933
00934 static struct ast_cli_entry cli_send_display =
00935 { {"misdn","send","display", NULL},
00936 misdn_send_display,
00937 "Sends Text to mISDN Channel",
00938 "Usage: misdn send display <channel> \"<msg>\" \n"
00939 " Send <msg> to <channel> as Display Message\n"
00940 " when channel is a mISDN channel\n",
00941 complete_ch
00942 };
00943
00944
00945 static struct ast_cli_entry cli_show_config =
00946 { {"misdn","show","config", NULL},
00947 misdn_show_config,
00948 "Shows internal mISDN config, read from cfg-file",
00949 "Usage: misdn show config [port | 0]\n use 0 to only print the general config.\n"
00950 };
00951
00952
00953 static struct ast_cli_entry cli_reload =
00954 { {"misdn","reload", NULL},
00955 misdn_reload,
00956 "Reloads internal mISDN config, read from cfg-file",
00957 "Usage: misdn reload\n"
00958 };
00959
00960 static struct ast_cli_entry cli_set_tics =
00961 { {"misdn","set","tics", NULL},
00962 misdn_set_tics,
00963 "",
00964 "\n"
00965 };
00966
00967
00968 static struct ast_cli_entry cli_show_cls =
00969 { {"misdn","show","channels", NULL},
00970 misdn_show_cls,
00971 "Shows internal mISDN chan_list",
00972 "Usage: misdn show channels\n"
00973 };
00974
00975 static struct ast_cli_entry cli_show_cl =
00976 { {"misdn","show","channel", NULL},
00977 misdn_show_cl,
00978 "Shows internal mISDN chan_list",
00979 "Usage: misdn show channels\n",
00980 complete_ch
00981 };
00982
00983
00984
00985 static struct ast_cli_entry cli_restart_port =
00986 { {"misdn","restart","port", NULL},
00987 misdn_restart_port,
00988 "Restarts the given port",
00989 "Usage: misdn restart port\n"
00990 };
00991
00992
00993 static struct ast_cli_entry cli_port_up =
00994 { {"misdn","port","up", NULL},
00995 misdn_port_up,
00996 "Tries to establish L1 on the given port",
00997 "Usage: misdn port up <port>\n"
00998 };
00999
01000
01001 static struct ast_cli_entry cli_show_stacks =
01002 { {"misdn","show","stacks", NULL},
01003 misdn_show_stacks,
01004 "Shows internal mISDN stack_list",
01005 "Usage: misdn show stacks\n"
01006 };
01007
01008 static struct ast_cli_entry cli_show_port =
01009 { {"misdn","show","port", NULL},
01010 misdn_show_port,
01011 "Shows detailed information for given port",
01012 "Usage: misdn show port <port>\n"
01013 };
01014
01015
01016
01017 static struct ast_cli_entry cli_set_debug =
01018 { {"misdn","set","debug", NULL},
01019 misdn_set_debug,
01020 "Sets Debuglevel of chan_misdn",
01021 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n",
01022 complete_debug_port
01023 };
01024
01025 static struct ast_cli_entry cli_set_crypt_debug =
01026 { {"misdn","set","crypt","debug", NULL},
01027 misdn_set_crypt_debug,
01028 "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
01029 "Usage: misdn set crypt debug <level>\n"
01030 };
01031
01032
01033
01034
01035
01036
01037
01038 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
01039 {
01040 int port=0;
01041 int r;
01042 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01043 struct misdn_bchannel *newbc;
01044 char *opts=NULL, *ext=NULL;
01045 char dest_cp[256];
01046 char *tokb;
01047
01048 {
01049 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
01050 dest_cp[sizeof(dest_cp)]=0;
01051
01052 ext=strtok_r(dest_cp,"/",&tokb);
01053
01054 if (ext) {
01055 ext=strtok_r(NULL,"/",&tokb);
01056 if (ext) {
01057 opts=strtok_r(NULL,"/",&tokb);
01058 } else {
01059 chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
01060 return -1;
01061 }
01062 }
01063
01064
01065 }
01066
01067 if (!ast) {
01068 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
01069 return -1;
01070 }
01071
01072 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) {
01073 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01074 ast->hangupcause=41;
01075 ast_setstate(ast, AST_STATE_DOWN);
01076 return -1;
01077 }
01078
01079
01080 if (!ch) {
01081 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01082 ast->hangupcause=41;
01083 ast_setstate(ast, AST_STATE_DOWN);
01084 return -1;
01085 }
01086
01087 newbc=ch->bc;
01088
01089 if (!newbc) {
01090 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01091 ast->hangupcause=41;
01092 ast_setstate(ast, AST_STATE_DOWN);
01093 return -1;
01094 }
01095
01096 port=newbc->port;
01097
01098 ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
01099 ast_copy_string(ast->exten, ext, sizeof(ast->exten));
01100
01101 chan_misdn_log(1, 0, "* CALL: %s\n",dest);
01102
01103 chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
01104
01105 {
01106 char context[BUFFERSIZE];
01107
01108 misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
01109 {
01110 int l = sizeof(ast->context);
01111 strncpy(ast->context,context, l);
01112 ast->context[l-1] = 0;
01113 }
01114 chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
01115 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
01116
01117 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
01118 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
01119
01120 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
01121
01122
01123 {
01124 char callerid[BUFFERSIZE];
01125 misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
01126 if ( ! ast_strlen_zero(callerid) ) {
01127 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
01128 {
01129 int l = sizeof(newbc->oad);
01130 strncpy(newbc->oad,callerid, l);
01131 newbc->oad[l-1] = 0;
01132 }
01133 }
01134
01135
01136 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
01137 switch (newbc->dnumplan) {
01138 case NUMPLAN_INTERNATIONAL:
01139 chan_misdn_log(2, port, " --> TON: International\n");
01140 break;
01141 case NUMPLAN_NATIONAL:
01142 chan_misdn_log(2, port, " --> TON: National\n");
01143 break;
01144 case NUMPLAN_SUBSCRIBER:
01145 chan_misdn_log(2, port, " --> TON: Subscriber\n");
01146 break;
01147 case NUMPLAN_UNKNOWN:
01148 chan_misdn_log(2, port, " --> TON: Unknown\n");
01149 break;
01150
01151 default:
01152 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01153 break;
01154 }
01155
01156
01157 misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &newbc->onumplan, sizeof(int));
01158 switch (newbc->onumplan) {
01159 case NUMPLAN_INTERNATIONAL:
01160 chan_misdn_log(2, port, " --> TON: International\n");
01161 break;
01162 case NUMPLAN_NATIONAL:
01163 chan_misdn_log(2, port, " --> TON: National\n");
01164 break;
01165 case NUMPLAN_SUBSCRIBER:
01166 chan_misdn_log(2, port, " --> TON: Subscriber\n");
01167 break;
01168 case NUMPLAN_UNKNOWN:
01169 chan_misdn_log(2, port, " --> TON: Unknown\n");
01170 break;
01171
01172 default:
01173 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01174 break;
01175 }
01176 }
01177
01178
01179
01180
01181 {
01182 int eb3;
01183
01184 misdn_cfg_get( port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
01185 newbc->early_bconnect=eb3;
01186
01187 }
01188
01189
01190
01191
01192 {
01193 int pres;
01194
01195 misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
01196 newbc->pres=pres?0:1;
01197
01198 }
01199
01200 int def_callingpres;
01201 misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
01202 if ( def_callingpres) {
01203
01204 switch (ast->cid.cid_pres & 0x60){
01205
01206 case AST_PRES_RESTRICTED:
01207 chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
01208 newbc->pres=1;
01209 break;
01210
01211
01212 case AST_PRES_UNAVAILABLE:
01213 chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
01214 newbc->pres=2;
01215 break;
01216
01217 default:
01218 chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
01219 newbc->pres=0;
01220 }
01221
01222 switch (ast->cid.cid_pres & 0x3){
01223
01224 case AST_PRES_USER_NUMBER_UNSCREENED:
01225 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01226 newbc->screen=0;
01227 break;
01228
01229 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
01230 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
01231 newbc->screen=1;
01232 break;
01233 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
01234 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
01235 newbc->screen=2;
01236 break;
01237
01238 case AST_PRES_NETWORK_NUMBER:
01239 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
01240 newbc->screen=3;
01241 break;
01242
01243 default:
01244 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01245 newbc->screen=0;
01246 }
01247 }
01248
01249
01250 {
01251 int ec, ectr;
01252
01253 misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
01254
01255 misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
01256 if (ec == 1 ) {
01257 newbc->ec_enable=1;
01258 } else if ( ec > 1 ) {
01259 newbc->ec_enable=1;
01260 newbc->ec_deftaps=ec;
01261 }
01262
01263
01264 if (ectr>=0) {
01265 newbc->ec_training=ectr;
01266 }
01267
01268 }
01269
01270 }
01271
01272 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
01273 if (ast->exten) {
01274 int l = sizeof(newbc->dad);
01275 strncpy(newbc->dad,ast->exten, l);
01276 newbc->dad[l-1] = 0;
01277 }
01278 newbc->rad[0]=0;
01279 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
01280 if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
01281 if (AST_CID_P(ast)) {
01282 int l = sizeof(newbc->oad);
01283 strncpy(newbc->oad,AST_CID_P(ast), l);
01284 newbc->oad[l-1] = 0;
01285 }
01286 }
01287
01288 {
01289 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01290 if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
01291 ch->bc = newbc;
01292 ch->orginator=ORG_AST;
01293 ch->ast = ast;
01294
01295 MISDN_ASTERISK_TECH_PVT(ast) = ch ;
01296
01297
01298
01299 newbc->capability=ast->transfercapability;
01300 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
01301 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
01302 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
01303 }
01304
01305
01306
01307 if (opts)
01308 misdn_set_opt_exec(ast,opts);
01309 else
01310 chan_misdn_log(1,0,"NO OPTS GIVEN\n");
01311
01312
01313 cl_queue_chan(&cl_te, ch) ;
01314 ch->state=MISDN_CALLING;
01315
01316 chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
01317
01318 r=misdn_lib_send_event( newbc, EVENT_SETUP );
01319
01320
01321 ch->l3id=newbc->l3_id;
01322 }
01323
01324 if ( r == -ENOCHAN ) {
01325 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
01326 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
01327 ast->hangupcause=34;
01328 ast_setstate(ast, AST_STATE_DOWN);
01329 return -1;
01330 }
01331
01332 chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
01333
01334 ast_setstate(ast, AST_STATE_DIALING);
01335
01336 ast->hangupcause=16;
01337 return 0;
01338 }
01339
01340
01341 int misdn_answer(struct ast_channel *ast)
01342 {
01343 struct chan_list *p;
01344
01345
01346 if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01347 p = MISDN_ASTERISK_TECH_PVT(ast) ;
01348
01349 chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
01350
01351 chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
01352
01353 if (!p) {
01354 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
01355 ast_queue_hangup(ast);
01356 }
01357
01358 if (!p->bc) {
01359 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
01360
01361 ast_queue_hangup(ast);
01362 }
01363
01364 {
01365 char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
01366
01367 if (tmp_key ) {
01368 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
01369 {
01370 int l = sizeof(p->bc->crypt_key);
01371 strncpy(p->bc->crypt_key,tmp_key, l);
01372 p->bc->crypt_key[l-1] = 0;
01373 }
01374 } else {
01375 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
01376 }
01377
01378 }
01379
01380 {
01381 char *async=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
01382 if (async) {
01383 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
01384 p->bc->async=1;
01385 }
01386 }
01387
01388 p->state = MISDN_CONNECTED;
01389 misdn_lib_send_event( p->bc, EVENT_CONNECT);
01390 start_bc_tones(p);
01391
01392 return 0;
01393 }
01394
01395 int misdn_digit(struct ast_channel *ast, char digit )
01396 {
01397 struct chan_list *p;
01398
01399 if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01400 p = MISDN_ASTERISK_TECH_PVT(ast) ;
01401
01402
01403 struct misdn_bchannel *bc=p->bc;
01404 chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
01405
01406 if (!bc) {
01407 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
01408 return -1;
01409 }
01410
01411 switch (p->state ) {
01412 case MISDN_CALLING:
01413 {
01414
01415 char buf[8];
01416 buf[0]=digit;
01417 buf[1]=0;
01418
01419 int l = sizeof(bc->infos_pending);
01420 strncat(bc->infos_pending,buf,l);
01421 bc->infos_pending[l-1] = 0;
01422 }
01423 break;
01424 case MISDN_CALLING_ACKNOWLEDGE:
01425 {
01426 bc->info_dad[0]=digit;
01427 bc->info_dad[1]=0;
01428
01429 {
01430 int l = sizeof(bc->dad);
01431 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
01432 bc->dad[l-1] = 0;
01433 }
01434 {
01435 int l = sizeof(p->ast->exten);
01436 strncpy(p->ast->exten, bc->dad, l);
01437 p->ast->exten[l-1] = 0;
01438 }
01439
01440 misdn_lib_send_event( bc, EVENT_INFORMATION);
01441 }
01442 break;
01443
01444 default:
01445 if ( bc->send_dtmf ) {
01446 send_digit_to_chan(p,digit);
01447 }
01448 break;
01449 }
01450
01451 return 0;
01452 }
01453
01454
01455 int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
01456 {
01457 struct chan_list *p;
01458
01459 if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01460 p = MISDN_ASTERISK_TECH_PVT(ast) ;
01461
01462 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);
01463
01464 p->ast = ast ;
01465 p->state=MISDN_CONNECTED;
01466
01467 return 0;
01468 }
01469
01470
01471 int misdn_transfer (struct ast_channel *ast, char *dest)
01472 {
01473 struct chan_list *p;
01474
01475 if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01476 p = MISDN_ASTERISK_TECH_PVT(ast) ;
01477
01478 chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
01479 return 0;
01480 }
01481
01482
01483
01484 int misdn_indication(struct ast_channel *ast, int cond)
01485 {
01486 struct chan_list *p;
01487
01488
01489 if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
01490 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
01491 return -1;
01492 }
01493 p = MISDN_ASTERISK_TECH_PVT(ast) ;
01494
01495 if (!p->bc ) {
01496 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
01497 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
01498 return -1;
01499 }
01500
01501 chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
01502
01503 switch (cond) {
01504 case AST_CONTROL_BUSY:
01505 chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
01506 chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
01507 ast_setstate(ast,AST_STATE_BUSY);
01508
01509 p->bc->out_cause=17;
01510 if (p->state != MISDN_CONNECTED) {
01511 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01512 manager_send_tone(p->bc, TONE_BUSY);
01513 } else {
01514 chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
01515 p->bc->port, ast->name);
01516 }
01517 break;
01518 case AST_CONTROL_RING:
01519 chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
01520 break;
01521 case AST_CONTROL_RINGING:
01522 if ( p->state == MISDN_ALERTING) {
01523 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I ws Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
01524 break;
01525 }
01526 p->state=MISDN_ALERTING;
01527
01528 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
01529
01530 misdn_lib_send_event( p->bc, EVENT_ALERTING);
01531
01532 manager_send_tone(p->bc, TONE_ALERTING);
01533 chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
01534 ast_setstate(ast,AST_STATE_RINGING);
01535 break;
01536
01537 case AST_CONTROL_ANSWER:
01538 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
01539 break;
01540 case AST_CONTROL_TAKEOFFHOOK:
01541 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
01542 break;
01543 case AST_CONTROL_OFFHOOK:
01544 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
01545 break;
01546 case AST_CONTROL_FLASH:
01547 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
01548 break;
01549 case AST_CONTROL_PROGRESS:
01550 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
01551 break;
01552 case AST_CONTROL_CONGESTION:
01553 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
01554
01555 p->bc->out_cause=42;
01556 if (p->state != MISDN_CONNECTED) {
01557 start_bc_tones(p);
01558
01559 misdn_lib_send_event( p->bc, EVENT_RELEASE);
01560 } else {
01561 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01562 }
01563 if (p->bc->nt) {
01564 manager_send_tone(p->bc, TONE_BUSY);
01565 }
01566 break;
01567 case -1 :
01568 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
01569 break;
01570 case AST_CONTROL_HOLD:
01571 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01572 break;
01573 case AST_CONTROL_UNHOLD:
01574 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01575 break;
01576 default:
01577 ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
01578 }
01579
01580 return 0;
01581 }
01582
01583 int misdn_hangup(struct ast_channel *ast)
01584 {
01585 struct chan_list *p;
01586 struct misdn_bchannel *bc=NULL;
01587
01588 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
01589
01590 release_lock;
01591
01592 chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
01593
01594 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
01595
01596 if (!p) {
01597 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
01598 release_unlock;
01599 return 0 ;
01600 }
01601
01602 bc=p->bc;
01603
01604 if (!bc) {
01605 release_unlock;
01606 ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
01607 return 0;
01608 }
01609
01610
01611 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01612 p->ast=NULL;
01613
01614 if (ast->_state == AST_STATE_RESERVED) {
01615
01616 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01617 release_unlock;
01618
01619 cl_dequeue_chan(&cl_te, p);
01620 free(p);
01621
01622 misdn_lib_release(bc);
01623
01624 return 0;
01625 }
01626
01627 stop_bc_tones(p);
01628
01629 release_unlock;
01630
01631
01632
01633
01634
01635
01636 {
01637 char *varcause=NULL;
01638 bc->cause=ast->hangupcause?ast->hangupcause:16;
01639
01640 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
01641 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
01642 int tmpcause=atoi(varcause);
01643 bc->out_cause=tmpcause?tmpcause:16;
01644 }
01645
01646 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));
01647 chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
01648 chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
01649 chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
01650
01651 switch (p->state) {
01652 case MISDN_CALLING:
01653 p->state=MISDN_CLEANING;
01654 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
01655 break;
01656 case MISDN_HOLDED:
01657 case MISDN_DIALING:
01658 start_bc_tones(p);
01659 manager_send_tone(bc, TONE_BUSY);
01660 p->state=MISDN_CLEANING;
01661
01662 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
01663
01664 break;
01665
01666 case MISDN_ALERTING:
01667 chan_misdn_log(2, bc->port, " --> * State Alerting\n");
01668
01669 if (p->orginator != ORG_AST)
01670 manager_send_tone(bc, TONE_BUSY);
01671
01672 p->state=MISDN_CLEANING;
01673 misdn_lib_send_event( bc, EVENT_DISCONNECT);
01674 break;
01675 case MISDN_CONNECTED:
01676
01677 chan_misdn_log(2, bc->port, " --> * State Connected\n");
01678 start_bc_tones(p);
01679 manager_send_tone(bc, TONE_BUSY);
01680 misdn_lib_send_event( bc, EVENT_DISCONNECT);
01681
01682 p->state=MISDN_CLEANING;
01683 break;
01684
01685 case MISDN_CLEANING:
01686 break;
01687
01688 case MISDN_HOLD_DISCONNECT:
01689
01690 chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
01691 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
01692 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
01693
01694 misdn_lib_send_event(bc,EVENT_RELEASE);
01695 break;
01696 default:
01697
01698 if (bc->nt)
01699 misdn_lib_send_event(bc, EVENT_RELEASE);
01700 else
01701 misdn_lib_send_event(bc, EVENT_DISCONNECT);
01702 p->state=MISDN_CLEANING;
01703 }
01704
01705 }
01706
01707 chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
01708
01709 return 0;
01710 }
01711
01712 struct ast_frame *misdn_read(struct ast_channel *ast)
01713 {
01714 struct chan_list *tmp;
01715
01716 char blah[255];
01717 int len =0 ;
01718
01719 if (!ast) return NULL;
01720 if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
01721 if (!tmp->bc) return NULL;
01722
01723
01724 read(tmp->pipe[0],blah,sizeof(blah));
01725
01726
01727 len = misdn_ibuf_usedcount(tmp->bc->astbuf);
01728
01729
01730 len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
01731
01732 misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
01733
01734 tmp->frame.frametype = AST_FRAME_VOICE;
01735 tmp->frame.subclass = AST_FORMAT_ALAW;
01736 tmp->frame.datalen = len;
01737 tmp->frame.samples = len ;
01738 tmp->frame.mallocd =0 ;
01739 tmp->frame.offset= 0 ;
01740 tmp->frame.src = NULL;
01741 tmp->frame.data = tmp->ast_rd_buf ;
01742
01743 chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
01744 return &tmp->frame;
01745 }
01746
01747 int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
01748 {
01749 struct chan_list *p;
01750 int i = 0;
01751
01752 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
01753
01754 if (!p->bc ) {
01755 ast_log(LOG_WARNING, "private but no bc\n");
01756 return -1;
01757 }
01758
01759 if (p->bc->tone != TONE_NONE)
01760 manager_send_tone(p->bc,TONE_NONE);
01761
01762
01763 if (p->holded ) {
01764 chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
01765 return 0;
01766 }
01767
01768 if (p->notxtone) {
01769 chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
01770 return 0;
01771 }
01772
01773 if ( !(frame->subclass & prefformat)) {
01774 chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
01775 }
01776
01777
01778 #if MISDN_DEBUG
01779 {
01780 int i, max=5>frame->samples?frame->samples:5;
01781
01782 printf("write2mISDN %p %d bytes: ", p, frame->samples);
01783
01784 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
01785 printf ("\n");
01786 }
01787 #endif
01788 chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
01789 i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
01790
01791 return 0;
01792 }
01793
01794
01795 enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
01796 struct ast_channel *c1, int flags,
01797 struct ast_frame **fo,
01798 struct ast_channel **rc,
01799 int timeoutms)
01800
01801 {
01802 struct chan_list *ch1,*ch2;
01803 struct ast_channel *carr[2], *who;
01804 int to=-1;
01805 struct ast_frame *f;
01806
01807 ch1=get_chan_by_ast(c0);
01808 ch2=get_chan_by_ast(c1);
01809
01810 carr[0]=c0;
01811 carr[1]=c1;
01812
01813
01814 if (ch1 && ch2 ) ;
01815 else
01816 return -1;
01817
01818
01819 int bridging;
01820 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
01821 if (bridging) {
01822 int ecwb;
01823 misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
01824 if ( !ecwb ) {
01825 chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
01826 ch1->bc->ec_enable=0;
01827 manager_ec_disable(ch1->bc);
01828 }
01829 misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
01830 if ( !ecwb ) {
01831 chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
01832 ch2->bc->ec_enable=0;
01833 manager_ec_disable(ch2->bc);
01834 }
01835
01836
01837 chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
01838
01839 misdn_lib_bridge(ch1->bc,ch2->bc);
01840 }
01841
01842 chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
01843
01844 while(1) {
01845 to=-1;
01846 who = ast_waitfor_n(carr, 2, &to);
01847
01848 if (!who) {
01849 ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
01850 continue;
01851 }
01852 f = ast_read(who);
01853
01854 if (!f || f->frametype == AST_FRAME_CONTROL) {
01855
01856 *fo=f;
01857 *rc=who;
01858
01859 break;
01860 }
01861
01862
01863 if (who == c0) {
01864 ast_write(c1,f);
01865 }
01866 else {
01867 ast_write(c0,f);
01868 }
01869
01870 }
01871
01872 if (bridging) {
01873 misdn_lib_split_bridge(ch1->bc,ch2->bc);
01874 }
01875
01876 return 0;
01877 }
01878
01879
01880
01881 static int start_bc_tones(struct chan_list* cl)
01882 {
01883 manager_bchannel_activate(cl->bc);
01884 manager_send_tone(cl->bc ,TONE_NONE);
01885 cl->notxtone=0;
01886 cl->norxtone=0;
01887 return 0;
01888 }
01889
01890 static int stop_bc_tones(struct chan_list *cl)
01891 {
01892 if (cl->bc) {
01893 manager_bchannel_deactivate(cl->bc);
01894 }
01895 cl->notxtone=1;
01896 cl->norxtone=1;
01897
01898 return 0;
01899 }
01900
01901
01902 struct chan_list *init_chan_list(void)
01903 {
01904 struct chan_list *cl=malloc(sizeof(struct chan_list));
01905
01906 if (!cl) {
01907 chan_misdn_log(0, 0, "misdn_request: malloc failed!");
01908 return NULL;
01909 }
01910
01911 memset(cl,0,sizeof(struct chan_list));
01912
01913 return cl;
01914
01915 }
01916
01917 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
01918
01919 {
01920 struct ast_channel *tmp = NULL;
01921 char group[BUFFERSIZE]="";
01922 char buf[128];
01923 char buf2[128], *ext=NULL, *port_str;
01924 char *tokb=NULL, *p=NULL;
01925 int channel=0, port=0;
01926 struct misdn_bchannel *newbc = NULL;
01927
01928 struct chan_list *cl=init_chan_list();
01929
01930 sprintf(buf,"%s/%s",type,(char*)data);
01931 strncpy(buf2,data, 128);
01932 buf2[127] = 0;
01933 port_str=strtok_r(buf2,"/", &tokb);
01934
01935 ext=strtok_r(NULL,"/", &tokb);
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945 if (port_str) {
01946 if (port_str[0]=='g' && port_str[1]==':' ) {
01947
01948 port_str += 2;
01949 strncpy(group, port_str, BUFFERSIZE);
01950 group[127] = 0;
01951 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
01952 }
01953 else if ((p = strchr(port_str, ':'))) {
01954
01955 *p = 0;
01956 channel = atoi(++p);
01957 port = atoi(port_str);
01958 chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
01959 }
01960 else {
01961 port = atoi(port_str);
01962 }
01963
01964
01965 } else {
01966 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
01967 return NULL;
01968 }
01969
01970 if (!ast_strlen_zero(group)) {
01971
01972 char cfg_group[BUFFERSIZE];
01973 struct robin_list *rr = NULL;
01974
01975 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
01976 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
01977 rr = get_robin_position(group);
01978 }
01979
01980 if (rr) {
01981 int robin_channel = rr->channel;
01982 int port_start;
01983 int next_chan = 1;
01984
01985 do {
01986 port_start = 0;
01987 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
01988 port = misdn_cfg_get_next_port_spin(port)) {
01989
01990 if (!port_start)
01991 port_start = port;
01992
01993 if (port >= port_start)
01994 next_chan = 1;
01995
01996 if (port < port_start && next_chan) {
01997 if (++robin_channel >= MAX_BCHANS) {
01998 robin_channel = 1;
01999 }
02000 next_chan = 0;
02001 }
02002
02003 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02004
02005 if (!strcasecmp(cfg_group, group)) {
02006 int l1, port_up;
02007
02008 misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
02009 port_up = misdn_lib_port_up(port);
02010
02011 if ((l1 && port_up) || !l1) {
02012 newbc = misdn_lib_get_free_bc(port, robin_channel);
02013 if (newbc) {
02014 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
02015 if (port_up)
02016 chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
02017 rr->port = newbc->port;
02018 rr->channel = newbc->channel;
02019 break;
02020 }
02021 }
02022 }
02023 }
02024 } while (!newbc && robin_channel != rr->channel);
02025
02026 if (!newbc)
02027 chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
02028 }
02029
02030 else {
02031 for (port=misdn_cfg_get_next_port(0); port > 0;
02032 port=misdn_cfg_get_next_port(port)) {
02033
02034 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02035
02036 if (!strcasecmp(cfg_group, group)) {
02037 int l1, port_up;
02038
02039 misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
02040 port_up = misdn_lib_port_up(port);
02041
02042 chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
02043
02044 if ((l1 && port_up) || !l1) {
02045 newbc = misdn_lib_get_free_bc(port, 0);
02046 if (newbc)
02047 break;
02048 }
02049 }
02050 }
02051 }
02052
02053 } else {
02054 if (channel)
02055 chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
02056 newbc = misdn_lib_get_free_bc(port, channel);
02057 }
02058
02059 if (!newbc) {
02060 chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
02061 chan_misdn_log(1, 0, " --> SEND: State Down\n");
02062 return NULL;
02063 }
02064
02065 cl->bc=newbc;
02066
02067 tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
02068
02069 return tmp;
02070 }
02071
02072
02073 struct ast_channel_tech misdn_tech = {
02074 .type="mISDN",
02075 .description="Channel driver for mISDN Support (Bri/Pri)",
02076 .capabilities= AST_FORMAT_ALAW ,
02077 .requester=misdn_request,
02078 .send_digit=misdn_digit,
02079 .call=misdn_call,
02080 .bridge=misdn_bridge,
02081 .hangup=misdn_hangup,
02082 .answer=misdn_answer,
02083 .read=misdn_read,
02084 .write=misdn_write,
02085 .indicate=misdn_indication,
02086 .fixup=misdn_fixup,
02087 .properties=0
02088
02089 };
02090
02091 struct ast_channel_tech misdn_tech_wo_bridge = {
02092 .type="mISDN",
02093 .description="Channel driver for mISDN Support (Bri/Pri)",
02094 .capabilities=AST_FORMAT_ALAW ,
02095 .requester=misdn_request,
02096 .send_digit=misdn_digit,
02097 .call=misdn_call,
02098 .hangup=misdn_hangup,
02099 .answer=misdn_answer,
02100 .read=misdn_read,
02101 .write=misdn_write,
02102 .indicate=misdn_indication,
02103 .fixup=misdn_fixup,
02104 .properties=0
02105
02106 };
02107
02108
02109 unsigned long glob_channel=0;
02110
02111 struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c)
02112 {
02113 struct ast_channel *tmp;
02114
02115 tmp = ast_channel_alloc(1);
02116
02117 if (tmp) {
02118 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
02119
02120
02121 if (c<=0) {
02122 c=glob_channel++;
02123 snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
02124 type, port, c);
02125 } else {
02126 snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
02127 type, port, c);
02128 }
02129
02130 tmp->type = type;
02131
02132 tmp->nativeformats = prefformat;
02133 tmp->readformat = format;
02134 tmp->writeformat = format;
02135
02136 tmp->tech_pvt = chlist;
02137
02138 int bridging;
02139 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02140 if (bridging)
02141 tmp->tech = &misdn_tech;
02142 else
02143 tmp->tech = &misdn_tech_wo_bridge;
02144
02145
02146 tmp->writeformat = format;
02147 tmp->readformat = format;
02148 tmp->priority=1;
02149
02150
02151 if (context) {
02152 ast_copy_string(tmp->context, context, sizeof(tmp->context));
02153 } else {
02154 chan_misdn_log(1,0,"misdn_new: no context given.\n");
02155 }
02156
02157 if (exten) {
02158 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
02159 } else {
02160 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
02161 }
02162
02163 if (callerid) {
02164 char *cid_name, *cid_num;
02165
02166 ast_callerid_parse(callerid, &cid_name, &cid_num);
02167 if (cid_name)
02168 tmp->cid.cid_name=strdup(cid_name);
02169 if (cid_num)
02170 tmp->cid.cid_num=strdup(cid_num);
02171 }
02172
02173 {
02174 if (pipe(chlist->pipe)<0)
02175 perror("Pipe failed\n");
02176
02177 tmp->fds[0]=chlist->pipe[0];
02178
02179 }
02180
02181 if (chlist->bc) {
02182 int port=chlist->bc->port;
02183 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
02184
02185 {
02186 char buf[256];
02187 ast_group_t pg,cg;
02188
02189 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02190 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02191
02192 chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
02193 tmp->pickupgroup=pg;
02194 tmp->callgroup=cg;
02195 }
02196 misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
02197 misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
02198 chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
02199
02200 } else {
02201 chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
02202 }
02203
02204 ast_setstate(tmp, state);
02205 if (state == AST_STATE_RING)
02206 tmp->rings = 1;
02207 else
02208 tmp->rings = 0;
02209 } else {
02210 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02211 chan_misdn_log(0,0,"Unable to allocate channel structure\n");
02212 }
02213
02214 return tmp;
02215 }
02216
02217
02218
02219 int misdn_tx2ast_frm(struct chan_list * tmp, char * buf, int len )
02220 {
02221 struct ast_frame frame;
02222
02223
02224 if (tmp->holded ) return 0;
02225
02226 switch(tmp->state) {
02227 case MISDN_CLEANING:
02228 case MISDN_EXTCANTMATCH:
02229 case MISDN_WAITING4DIGS:
02230 return 0;
02231 default:
02232 break;
02233 }
02234
02235 if (tmp->norxtone) {
02236 chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
02237 return 0;
02238 }
02239
02240 frame.frametype = AST_FRAME_VOICE;
02241 frame.subclass = AST_FORMAT_ALAW;
02242 frame.datalen = len;
02243 frame.samples = len ;
02244 frame.mallocd =0 ;
02245 frame.offset= 0 ;
02246 frame.src = NULL;
02247 frame.data = buf ;
02248
02249 if (tmp->faxdetect || tmp->ast_dsp ) {
02250 struct ast_frame *f,*f2;
02251 if (tmp->trans)
02252 f2=ast_translate(tmp->trans, &frame,0);
02253 else {
02254 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02255 return 0;
02256 }
02257
02258 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02259 if (f && (f->frametype == AST_FRAME_DTMF)) {
02260 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
02261 if (f->subclass == 'f' && tmp->faxdetect) {
02262
02263 struct ast_channel *ast = tmp->ast;
02264 if (!tmp->faxhandled) {
02265 tmp->faxhandled++;
02266 if (strcmp(ast->exten, "fax")) {
02267 if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
02268 if (option_verbose > 2)
02269 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
02270
02271 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02272 if (ast_async_goto(ast, ast->context, "fax", 1))
02273 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
02274 } else
02275 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
02276 } else
02277 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02278 } else
02279 ast_log(LOG_DEBUG, "Fax already handled\n");
02280 frame.frametype = AST_FRAME_NULL;
02281 frame.subclass = 0;
02282 f = &frame;
02283 } else if ( tmp->ast_dsp) {
02284 struct ast_frame fr;
02285 memset(&fr, 0 , sizeof(fr));
02286 fr.frametype = AST_FRAME_DTMF;
02287 fr.subclass = f->subclass ;
02288 fr.src=NULL;
02289 fr.data = NULL ;
02290 fr.datalen = 0;
02291 fr.samples = 0 ;
02292 fr.mallocd =0 ;
02293 fr.offset= 0 ;
02294
02295 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
02296 ast_queue_frame(tmp->ast, &fr);
02297
02298 frame.frametype = AST_FRAME_NULL;
02299 frame.subclass = 0;
02300 f = &frame;
02301 }
02302 }
02303 }
02304
02305 if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
02306 #if MISDN_DEBUG
02307 int i, max=5>len?len:5;
02308
02309 printf("write2* %p %d bytes: ",tmp, len);
02310
02311 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
02312 printf ("\n");
02313 #endif
02314 chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
02315 ast_queue_frame(tmp->ast,&frame);
02316
02317 } else {
02318 ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
02319 }
02320
02321 return 0;
02322 }
02323
02324
02325
02326 struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
02327 {
02328 struct chan_list *help=list;
02329 for (;help; help=help->next) {
02330 if (help->l3id == l3id ) return help;
02331 }
02332
02333 chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
02334
02335 return NULL;
02336 }
02337
02338 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
02339 {
02340 struct chan_list *help=list;
02341 for (;help; help=help->next) {
02342 if (help->bc == bc) return help;
02343 }
02344
02345 chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02346
02347 return NULL;
02348 }
02349
02350
02351 struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
02352 {
02353 struct chan_list *help=list;
02354
02355 chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
02356 for (;help; help=help->next) {
02357 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
02358 if (help->bc->port == bc->port
02359 && help->bc->holded ) return help;
02360 }
02361
02362 chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02363
02364 return NULL;
02365 }
02366
02367 void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
02368 {
02369 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
02370
02371 ast_mutex_lock(&cl_te_lock);
02372 if (!*list) {
02373 *list = chan;
02374 } else {
02375 struct chan_list *help=*list;
02376 for (;help->next; help=help->next);
02377 help->next=chan;
02378 }
02379 chan->next=NULL;
02380 ast_mutex_unlock(&cl_te_lock);
02381 }
02382
02383 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
02384 {
02385 if (chan->dsp)
02386 ast_dsp_free(chan->dsp);
02387 if (chan->trans)
02388 ast_translator_free_path(chan->trans);
02389
02390
02391 ast_mutex_lock(&cl_te_lock);
02392 if (!*list) {
02393 ast_mutex_unlock(&cl_te_lock);
02394 return;
02395 }
02396
02397 if (*list == chan) {
02398 *list=(*list)->next;
02399 ast_mutex_unlock(&cl_te_lock);
02400 return ;
02401 }
02402
02403 {
02404 struct chan_list *help=*list;
02405 for (;help->next; help=help->next) {
02406 if (help->next == chan) {
02407 help->next=help->next->next;
02408 ast_mutex_unlock(&cl_te_lock);
02409 return;
02410 }
02411 }
02412 }
02413
02414 ast_mutex_unlock(&cl_te_lock);
02415 }
02416
02417
02418
02419
02420
02421
02422 static void release_chan(struct misdn_bchannel *bc) {
02423 struct ast_channel *ast=NULL;
02424
02425 {
02426 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02427 if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
02428
02429 release_lock;
02430 if (ch->ast) {
02431 ast=ch->ast;
02432 }
02433 release_unlock;
02434
02435 chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
02436 if (ch) {
02437 if (ast)
02438 chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
02439
02440 close(ch->pipe[0]);
02441 close(ch->pipe[1]);
02442
02443 if (ast && MISDN_ASTERISK_PVT(ast)) {
02444 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));
02445 chan_misdn_log(3, bc->port, " --> * State Down\n");
02446
02447 send_cause2ast(ast,bc);
02448
02449 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02450
02451
02452 if (ast->_state != AST_STATE_RESERVED) {
02453 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
02454 ast_setstate(ast, AST_STATE_DOWN);
02455 }
02456
02457 switch(ch->state) {
02458 case MISDN_EXTCANTMATCH:
02459 case MISDN_WAITING4DIGS:
02460 {
02461 chan_misdn_log(3, bc->port, " --> * State Wait4dig | ExtCantMatch\n");
02462 ast_hangup(ast);
02463 }
02464 break;
02465
02466 case MISDN_DIALING:
02467 case MISDN_CALLING_ACKNOWLEDGE:
02468 case MISDN_PROGRESS:
02469 chan_misdn_log(2, bc->port, "* --> In State Dialin\n");
02470 chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
02471
02472
02473 ast_queue_hangup(ast);
02474 break;
02475 case MISDN_CALLING:
02476
02477 chan_misdn_log(2, bc->port, "* --> In State Callin\n");
02478
02479 if (!bc->nt) {
02480 chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
02481 ast_queue_hangup(ast);
02482 } else {
02483 chan_misdn_log(2, bc->port, "* --> Hangup\n");
02484 ast_queue_hangup(ast);
02485
02486 }
02487 break;
02488
02489 case MISDN_CLEANING:
02490
02491 chan_misdn_log(2, bc->port, "* --> In StateCleaning\n");
02492 break;
02493 case MISDN_HOLD_DISCONNECT:
02494 chan_misdn_log(2, bc->port, "* --> In HOLD_DISC\n");
02495 break;
02496 default:
02497 chan_misdn_log(2, bc->port, "* --> In State Default\n");
02498 chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
02499
02500
02501 if (ast && MISDN_ASTERISK_PVT(ast)) {
02502 ast_queue_hangup(ast);
02503 } else {
02504 chan_misdn_log (0, bc->port, "!! Not really queued!\n");
02505 }
02506 }
02507 }
02508 cl_dequeue_chan(&cl_te, ch);
02509
02510 free(ch);
02511 } else {
02512
02513 }
02514 }
02515 }
02516
02517
02518 void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
02519 {
02520 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
02521
02522 tmp_ch->state=MISDN_HOLD_DISCONNECT;
02523
02524 ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
02525
02526 holded_chan->state=MISDN_CONNECTED;
02527 holded_chan->holded=0;
02528 misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
02529
02530 ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
02531 }
02532
02533
02534 void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
02535 {
02536 char predial[256]="";
02537 char *p = predial;
02538
02539 struct ast_frame fr;
02540
02541 strncpy(predial, ast->exten, sizeof(predial) -1 );
02542
02543 ch->state=MISDN_DIALING;
02544
02545 if (bc->nt) {
02546 int ret;
02547 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02548 } else {
02549 int ret;
02550 if ( misdn_lib_is_ptp(bc->port)) {
02551 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02552 } else {
02553 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
02554 }
02555 }
02556
02557 manager_send_tone(bc,TONE_DIAL);
02558
02559 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));
02560
02561 strncpy(ast->exten,"s", 2);
02562
02563 if (ast_pbx_start(ast)<0) {
02564 ast=NULL;
02565 manager_send_tone(bc,TONE_BUSY);
02566 if (bc->nt)
02567 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02568 else
02569 misdn_lib_send_event(bc, EVENT_DISCONNECT );
02570 }
02571
02572
02573 while (!ast_strlen_zero(p) ) {
02574 fr.frametype = AST_FRAME_DTMF;
02575 fr.subclass = *p ;
02576 fr.src=NULL;
02577 fr.data = NULL ;
02578 fr.datalen = 0;
02579 fr.samples = 0 ;
02580 fr.mallocd =0 ;
02581 fr.offset= 0 ;
02582
02583 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02584 ast_queue_frame(ch->ast, &fr);
02585 }
02586 p++;
02587 }
02588 }
02589
02590
02591
02592 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
02593
02594 ast->hangupcause=bc->cause;
02595
02596 switch ( bc->cause) {
02597
02598 case 1:
02599 case 2:
02600 case 3:
02601 case 4:
02602 case 22:
02603 case 27:
02604 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
02605
02606 ast_queue_control(ast, AST_CONTROL_CONGESTION);
02607 break;
02608
02609 case 21:
02610 case 17:
02611 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
02612
02613 ast_queue_control(ast, AST_CONTROL_BUSY);
02614
02615 break;
02616 }
02617 }
02618
02619
02620
02621
02622 enum event_response_e
02623 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
02624 {
02625 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02626
02627 if (!ch)
02628 ch=find_chan_by_l3id(cl_te, bc->l3_id);
02629
02630 if (event != EVENT_BCHAN_DATA) {
02631 chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s port:%d\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->port);
02632 misdn_lib_log_ies(bc);
02633 }
02634
02635 if (event != EVENT_SETUP) {
02636 if (!ch) {
02637 if (event != EVENT_CLEANUP )
02638 ast_log(LOG_WARNING, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
02639 return -1;
02640 }
02641 }
02642
02643 if (ch ) {
02644 switch (event) {
02645 case EVENT_RELEASE:
02646 case EVENT_RELEASE_COMPLETE:
02647 case EVENT_CLEANUP:
02648 break;
02649 default:
02650 if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02651 if (event!=EVENT_BCHAN_DATA)
02652 ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
02653 return -1;
02654 }
02655 }
02656 }
02657
02658
02659 switch (event) {
02660 case EVENT_NEW_L3ID:
02661 ch->l3id=bc->l3_id;
02662 break;
02663
02664 case EVENT_NEW_BC:
02665 if (bc)
02666 ch->bc=bc;
02667 break;
02668
02669 case EVENT_DTMF_TONE:
02670 {
02671
02672 struct ast_frame fr;
02673 memset(&fr, 0 , sizeof(fr));
02674 fr.frametype = AST_FRAME_DTMF;
02675 fr.subclass = bc->dtmf ;
02676 fr.src=NULL;
02677 fr.data = NULL ;
02678 fr.datalen = 0;
02679 fr.samples = 0 ;
02680 fr.mallocd =0 ;
02681 fr.offset= 0 ;
02682
02683 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
02684
02685 ast_queue_frame(ch->ast, &fr);
02686 }
02687 break;
02688 case EVENT_STATUS:
02689 break;
02690
02691 case EVENT_INFORMATION:
02692 {
02693 int stop_tone;
02694 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
02695 if ( stop_tone && bc->tone != TONE_NONE) {
02696 manager_send_tone(bc,TONE_NONE);
02697 }
02698
02699 if (ch->state == MISDN_WAITING4DIGS ) {
02700
02701 {
02702 int l = sizeof(bc->dad);
02703 strncat(bc->dad,bc->info_dad, l);
02704 bc->dad[l-1] = 0;
02705 }
02706
02707
02708 {
02709 int l = sizeof(ch->ast->exten);
02710 strncpy(ch->ast->exten, bc->dad, l);
02711 ch->ast->exten[l-1] = 0;
02712 }
02713
02714
02715 char bc_context[BUFFERSIZE];
02716 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02717 if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02718 chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
02719 manager_send_tone(bc,TONE_BUSY);
02720 ch->state=MISDN_EXTCANTMATCH;
02721 bc->out_cause=1;
02722 if (bc->nt)
02723 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02724 else
02725 misdn_lib_send_event(bc, EVENT_DISCONNECT );
02726 break;
02727 }
02728 if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02729 ch->state=MISDN_DIALING;
02730
02731 manager_send_tone(bc,TONE_NONE);
02732
02733 if (ast_pbx_start(ch->ast)<0) {
02734 chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
02735 manager_send_tone(bc,TONE_BUSY);
02736 if (bc->nt)
02737 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02738 else
02739 misdn_lib_send_event(bc, EVENT_DISCONNECT );
02740 }
02741 }
02742
02743 } else {
02744
02745 struct ast_frame fr;
02746 fr.frametype = AST_FRAME_DTMF;
02747 fr.subclass = bc->info_dad[0] ;
02748 fr.src=NULL;
02749 fr.data = NULL ;
02750 fr.datalen = 0;
02751 fr.samples = 0 ;
02752 fr.mallocd =0 ;
02753 fr.offset= 0 ;
02754
02755
02756 int digits;
02757 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
02758 if (ch->state != MISDN_CONNECTED ) {
02759 if (digits) {
02760 int l = sizeof(bc->dad);
02761 strncat(bc->dad,bc->info_dad, l);
02762 bc->dad[l-1] = 0;
02763 l = sizeof(ch->ast->exten);
02764 strncpy(ch->ast->exten, bc->dad, l);
02765 ch->ast->exten[l-1] = 0;
02766
02767 ast_cdr_update(ch->ast);
02768 }
02769
02770 ast_queue_frame(ch->ast, &fr);
02771 }
02772
02773 }
02774 }
02775 break;
02776 case EVENT_SETUP:
02777 {
02778 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02779 if (ch && ch->state != MISDN_NOTHING ) {
02780 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
02781 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE;
02782 }
02783 }
02784
02785 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
02786 if (!bc->nt && ! msn_valid) {
02787 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
02788 return RESPONSE_IGNORE_SETUP;
02789 }
02790
02791 print_bearer(bc);
02792
02793 {
02794 struct chan_list *ch=init_chan_list();
02795 struct ast_channel *chan;
02796 char name[128];
02797 if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
02798
02799 ch->bc = bc;
02800 ch->l3id=bc->l3_id;
02801 ch->addr=bc->addr;
02802 ch->orginator = ORG_MISDN;
02803
02804
02805 {
02806 char prefix[BUFFERSIZE]="";
02807 switch( bc->onumplan ) {
02808 case NUMPLAN_INTERNATIONAL:
02809 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02810 break;
02811
02812 case NUMPLAN_NATIONAL:
02813 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02814 break;
02815
02816
02817 case NUMPLAN_SUBSCRIBER:
02818
02819 break;
02820
02821 case NUMPLAN_UNKNOWN:
02822 break;
02823 default:
02824 break;
02825 }
02826
02827 {
02828 int l = strlen(prefix) + strlen(bc->oad);
02829 char tmp[l+1];
02830 strcpy(tmp,prefix);
02831 strcat(tmp,bc->oad);
02832 strcpy(bc->oad,tmp);
02833 }
02834
02835 if (!ast_strlen_zero(bc->oad))
02836 sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
02837 else
02838 sprintf(name,"mISDN/%d",bc->port);
02839
02840
02841 if (!ast_strlen_zero(bc->dad)) {
02842 strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
02843 bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
02844 }
02845
02846 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02847 strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
02848 bc->dad[sizeof(bc->dad)-1] = 0;
02849 }
02850 prefix[0] = 0;
02851
02852 switch( bc->dnumplan ) {
02853 case NUMPLAN_INTERNATIONAL:
02854 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02855 break;
02856
02857 case NUMPLAN_NATIONAL:
02858 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02859 break;
02860
02861
02862 case NUMPLAN_SUBSCRIBER:
02863
02864 break;
02865
02866 case NUMPLAN_UNKNOWN:
02867 break;
02868 default:
02869 break;
02870 }
02871
02872 {
02873 int l = strlen(prefix) + strlen(bc->dad);
02874 char tmp[l+1];
02875 strcpy(tmp,prefix);
02876 strcat(tmp,bc->dad);
02877 strcpy(bc->dad,tmp);
02878 }
02879
02880 char bc_context[BUFFERSIZE];
02881 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02882 chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
02883
02884 if (!chan) {
02885 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02886 return 0;
02887 }
02888
02889 ch->ast = chan;
02890 pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
02891
02892 }
02893
02894
02895
02896 chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
02897
02898 if ( bc->pres ) {
02899 chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
02900 } else {
02901 chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
02902 }
02903
02904 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
02905 chan->transfercapability=bc->capability;
02906
02907 switch (bc->capability) {
02908 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02909 pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
02910 break;
02911 default:
02912 pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
02913 }
02914
02915
02916 cl_queue_chan(&cl_te, ch) ;
02917
02918
02919
02920
02921
02922
02923 {
02924
02925 misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));
02926
02927 }
02928
02929 {
02930 int eb3;
02931
02932 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
02933 bc->early_bconnect=eb3;
02934
02935 }
02936
02937 {
02938 int ec, ectr;
02939
02940 misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
02941
02942 misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
02943 if (ec == 1 ) {
02944 bc->ec_enable=1;
02945 } else if ( ec > 1 ) {
02946 bc->ec_enable=1;
02947 bc->ec_deftaps=ec;
02948 }
02949
02950 if ( ectr>=0 ) {
02951 bc->ec_training=ectr;
02952 }
02953 }
02954
02955
02956 if (bc->urate>0) {
02957 char buf[16];
02958 snprintf(buf,16,"%d",bc->urate);
02959 pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
02960 }
02961
02962
02963
02964
02965
02966
02967
02968
02969 int ai;
02970 misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
02971 if ( ai ) {
02972 do_immediate_setup(bc, ch , chan);
02973 break;
02974 }
02975
02976
02977 int immediate;
02978 misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
02979
02980 if (ast_strlen_zero(bc->orig_dad) && immediate ) {
02981 do_immediate_setup(bc, ch , chan);
02982 break;
02983 }
02984
02985
02986 if (!strcmp(chan->exten, ast_pickup_ext())) {
02987 int ret;
02988 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02989
02990 if (ast_pickup_call(chan)) {
02991 ast_hangup(chan);
02992 } else {
02993 ch->state = MISDN_CALLING_ACKNOWLEDGE;
02994
02995 ch->ast=NULL;
02996
02997 ast_setstate(chan, AST_STATE_DOWN);
02998 ast_hangup(chan);
02999
03000 break;
03001 }
03002 }
03003
03004
03005
03006
03007 char bc_context[BUFFERSIZE];
03008 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
03009 if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03010 chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
03011 manager_send_tone(bc,TONE_BUSY);
03012 ch->state=MISDN_EXTCANTMATCH;
03013 bc->out_cause=1;
03014 if (bc->nt)
03015 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03016 else
03017 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03018 break;
03019 }
03020
03021 if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03022 ch->state=MISDN_DIALING;
03023
03024 if (bc->nt) {
03025 int ret;
03026 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03027 } else {
03028 int ret;
03029 ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
03030 }
03031
03032 if (ast_pbx_start(chan)<0) {
03033 chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03034 chan=NULL;
03035 manager_send_tone(bc,TONE_BUSY);
03036 if (bc->nt)
03037 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03038 else
03039 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03040 }
03041 } else {
03042 int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03043 if (ret == -ENOCHAN) {
03044 ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
03045 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03046 }
03047
03048
03049 int stop_tone;
03050 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03051 if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
03052 manager_send_tone(bc,TONE_NONE);
03053 else
03054 manager_send_tone(bc,TONE_DIAL);
03055
03056 ch->state=MISDN_WAITING4DIGS;
03057 }
03058
03059 }
03060 break;
03061 case EVENT_SETUP_ACKNOWLEDGE:
03062 {
03063 ch->state = MISDN_CALLING_ACKNOWLEDGE;
03064 if (!ast_strlen_zero(bc->infos_pending)) {
03065
03066
03067 {
03068 int l = sizeof(bc->dad);
03069 strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
03070 bc->dad[l-1] = 0;
03071 }
03072 {
03073 int l = sizeof(ch->ast->exten);
03074 strncpy(ch->ast->exten, bc->dad, l);
03075 ch->ast->exten[l-1] = 0;
03076 }
03077 {
03078 int l = sizeof(bc->info_dad);
03079 strncpy(bc->info_dad, bc->infos_pending, l);
03080 bc->info_dad[l-1] = 0;
03081 }
03082 strncpy(bc->infos_pending,"", 1);
03083
03084 misdn_lib_send_event(bc, EVENT_INFORMATION);
03085 }
03086 }
03087 break;
03088 case EVENT_PROCEEDING:
03089 {
03090
03091 if ( misdn_cap_is_speech(bc->capability) &&
03092 misdn_inband_avail(bc) ) {
03093 start_bc_tones(ch);
03094 }
03095 }
03096 break;
03097 case EVENT_PROGRESS:
03098 if (!bc->nt ) {
03099 if ( misdn_cap_is_speech(bc->capability) &&
03100 misdn_inband_avail(bc)
03101 ) {
03102 start_bc_tones(ch);
03103 }
03104
03105 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
03106
03107 ch->state=MISDN_PROGRESS;
03108 }
03109 break;
03110
03111
03112 case EVENT_ALERTING:
03113 {
03114 ch->state = MISDN_ALERTING;
03115
03116 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
03117 ast_setstate(ch->ast, AST_STATE_RINGING);
03118
03119 cb_log(1,bc->port,"Set State Ringing\n");
03120
03121 if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
03122 start_bc_tones(ch);
03123 }
03124 }
03125 break;
03126 case EVENT_CONNECT:
03127 misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
03128 case EVENT_CONNECT_ACKNOWLEDGE:
03129 {
03130 bc->state=STATE_CONNECTED;
03131
03132 ch->l3id=bc->l3_id;
03133 ch->addr=bc->addr;
03134
03135 start_bc_tones(ch);
03136
03137 chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
03138
03139 ch->state = MISDN_CONNECTED;
03140 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
03141 }
03142 break;
03143 case EVENT_DISCONNECT:
03144 {
03145
03146 struct chan_list *holded_ch=find_holded(cl_te, bc);
03147
03148
03149 send_cause2ast(ch->ast,bc);
03150
03151 if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
03152
03153
03154
03155
03156
03157 start_bc_tones(ch);
03158 break;
03159 }
03160
03161
03162 if (holded_ch ) {
03163 if (ch->state == MISDN_CONNECTED ) {
03164 misdn_transfer_bc(ch, holded_ch) ;
03165 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03166 break;
03167 }
03168 }
03169
03170 stop_bc_tones(ch);
03171 bc->out_cause=16;
03172 misdn_lib_send_event(bc,EVENT_RELEASE);
03173
03174 }
03175 break;
03176
03177 case EVENT_RELEASE:
03178 {
03179
03180 switch ( bc->cause) {
03181
03182 case -1:
03183
03184
03185
03186
03187
03188
03189 return RESPONSE_OK;
03190 break;
03191 }
03192
03193
03194 bc->out_cause=16;
03195
03196 stop_bc_tones(ch);
03197 release_chan(bc);
03198 }
03199 break;
03200 case EVENT_RELEASE_COMPLETE:
03201 {
03202 stop_bc_tones(ch);
03203 release_chan(bc);
03204 }
03205 break;
03206
03207 case EVENT_BCHAN_DATA:
03208 {
03209 chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
03210
03211 if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
03212 misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
03213 } else {
03214 int len=bc->bframe_len;
03215 int free=misdn_ibuf_freecount(bc->astbuf);
03216
03217
03218 if (bc->bframe_len > free) {
03219 ast_log(LOG_DEBUG, "sbuf overflow!\n");
03220 len=misdn_ibuf_freecount(bc->astbuf);
03221
03222 if (len == 0) {
03223 ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
03224 }
03225 }
03226
03227 misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
03228
03229 {
03230 char blah[1]="\0";
03231 #ifdef FLATTEN_JITTER
03232 {
03233 struct timeval tv;
03234 gettimeofday(&tv,NULL);
03235
03236 if (tv.tv_usec % 10000 > 0 ) {
03237 write(ch->pipe[1], blah,sizeof(blah));
03238 bc->time_usec=tv.tv_usec;
03239 }
03240 }
03241 #else
03242 write(ch->pipe[1], blah,sizeof(blah));
03243 #endif
03244
03245
03246 }
03247 }
03248
03249 }
03250 break;
03251 case EVENT_TIMEOUT:
03252 break;
03253 {
03254 switch (ch->state) {
03255 case MISDN_CALLING:
03256 chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
03257 break;
03258 case MISDN_DIALING:
03259 case MISDN_PROGRESS:
03260 break;
03261 default:
03262 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03263 }
03264 }
03265 break;
03266 case EVENT_CLEANUP:
03267 {
03268 stop_bc_tones(ch);
03269 release_chan(bc);
03270 }
03271 break;
03272
03273
03274
03275
03276 case EVENT_RETRIEVE:
03277 {
03278 struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
03279 ch->state = MISDN_CONNECTED;
03280
03281 if (hold_ast) {
03282 ast_moh_stop(hold_ast);
03283 }
03284
03285 if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
03286 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
03287
03288
03289 }
03290 break;
03291
03292 case EVENT_HOLD:
03293 {
03294 int hold_allowed;
03295 misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
03296
03297 if (!hold_allowed) {
03298 chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
03299 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03300 break;
03301 }
03302
03303 {
03304 struct chan_list *holded_ch=find_holded(cl_te, bc);
03305 if (holded_ch) {
03306 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03307 chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
03308 break;
03309 }
03310 }
03311
03312 if (AST_BRIDGED_P(ch->ast)){
03313 ch->state = MISDN_HOLDED;
03314 ch->l3id = bc->l3_id;
03315
03316 ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
03317 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
03318 } else {
03319 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03320 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
03321 }
03322 }
03323 break;
03324 default:
03325 ast_log(LOG_WARNING, "Got Unknown Event\n");
03326 break;
03327 }
03328
03329 return RESPONSE_OK;
03330 }
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342 int clearl3_true ( void ) {
03343 int default_clearl3;
03344 misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
03345 return default_clearl3;
03346 }
03347
03348 int g_config_initialized=0;
03349
03350 int load_module(void)
03351 {
03352 int i;
03353
03354 char ports[256]="";
03355
03356 max_ports=misdn_lib_maxports_get();
03357
03358 if (max_ports<=0) {
03359 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
03360 return -1;
03361 }
03362
03363
03364 misdn_cfg_init(max_ports);
03365 g_config_initialized=1;
03366
03367 misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
03368 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
03369 for (i = 1; i <= max_ports; i++)
03370 misdn_debug[i] = misdn_debug[0];
03371 misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
03372
03373
03374 {
03375 char tempbuf[BUFFERSIZE];
03376 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
03377 if (strlen(tempbuf))
03378 tracing = 1;
03379 }
03380
03381 ast_mutex_init(&cl_te_lock);
03382 ast_mutex_init(&release_lock_mutex);
03383
03384 misdn_cfg_get_ports_string(ports);
03385 if (strlen(ports))
03386 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
03387
03388 {
03389 struct misdn_lib_iface iface = {
03390 .cb_event = cb_events,
03391 .cb_log = chan_misdn_log,
03392 .cb_clearl3_true = clearl3_true
03393 };
03394 if (misdn_lib_init(ports, &iface, NULL))
03395 chan_misdn_log(0, 0, "No te ports initialized\n");
03396 }
03397
03398
03399 {
03400 if (ast_channel_register(&misdn_tech)) {
03401 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
03402 unload_module();
03403 return -1;
03404 }
03405 }
03406
03407 ast_cli_register(&cli_send_display);
03408 ast_cli_register(&cli_send_cd);
03409 ast_cli_register(&cli_send_digit);
03410 ast_cli_register(&cli_toggle_echocancel);
03411 ast_cli_register(&cli_set_tics);
03412
03413 ast_cli_register(&cli_show_cls);
03414 ast_cli_register(&cli_show_cl);
03415 ast_cli_register(&cli_show_config);
03416 ast_cli_register(&cli_show_port);
03417 ast_cli_register(&cli_show_stacks);
03418
03419 ast_cli_register(&cli_restart_port);
03420 ast_cli_register(&cli_port_up);
03421 ast_cli_register(&cli_set_debug);
03422 ast_cli_register(&cli_set_crypt_debug);
03423 ast_cli_register(&cli_reload);
03424
03425
03426 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
03427 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
03428 "Sets mISDN opts. and optargs\n"
03429 "\n"
03430 );
03431
03432
03433 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
03434 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
03435 "Sends the Facility Message FACILITY_TYPE with \n"
03436 "the given Arguments to the current ISDN Channel\n"
03437 "Supported Facilities are:\n"
03438 "\n"
03439 "type=calldeflect args=Nr where to deflect\n"
03440 "\n"
03441 );
03442
03443 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
03444
03445 return 0;
03446 }
03447
03448
03449
03450 int unload_module(void)
03451 {
03452
03453 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
03454
03455 if (!g_config_initialized) return 0;
03456
03457 ast_cli_unregister(&cli_send_display);
03458
03459 ast_cli_unregister(&cli_send_cd);
03460
03461 ast_cli_unregister(&cli_send_digit);
03462 ast_cli_unregister(&cli_toggle_echocancel);
03463 ast_cli_unregister(&cli_set_tics);
03464
03465 ast_cli_unregister(&cli_show_cls);
03466 ast_cli_unregister(&cli_show_cl);
03467 ast_cli_unregister(&cli_show_config);
03468 ast_cli_unregister(&cli_show_port);
03469 ast_cli_unregister(&cli_show_stacks);
03470 ast_cli_unregister(&cli_restart_port);
03471 ast_cli_unregister(&cli_port_up);
03472 ast_cli_unregister(&cli_set_debug);
03473 ast_cli_unregister(&cli_set_crypt_debug);
03474 ast_cli_unregister(&cli_reload);
03475
03476 ast_unregister_application("misdn_set_opt");
03477 ast_unregister_application("misdn_facility");
03478
03479 ast_channel_unregister(&misdn_tech);
03480
03481 free_robin_list();
03482 misdn_cfg_destroy();
03483 misdn_lib_destroy();
03484
03485 if (misdn_debug)
03486 free(misdn_debug);
03487 if (misdn_debug_only)
03488 free(misdn_debug_only);
03489
03490 return 0;
03491 }
03492
03493 int usecount(void)
03494 {
03495 int res;
03496 ast_mutex_lock(&usecnt_lock);
03497 res = usecnt;
03498 ast_mutex_unlock(&usecnt_lock);
03499 return res;
03500 }
03501
03502 char *description(void)
03503 {
03504 return desc;
03505 }
03506
03507 char *key(void)
03508 {
03509 return ASTERISK_GPL_KEY;
03510 }
03511
03512 void chan_misdn_log(int level, int port, char *tmpl, ...)
03513 {
03514 if (! ((0 <= port) && (port <= max_ports))) {
03515 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
03516 return;
03517 }
03518
03519 va_list ap;
03520 char buf[1024];
03521
03522 va_start(ap, tmpl);
03523 vsnprintf( buf, 1023, tmpl, ap );
03524 va_end(ap);
03525
03526 if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
03527 ast_console_puts(buf);
03528 }
03529
03530 if (level <= misdn_debug[0] && tracing) {
03531 time_t tm = time(NULL);
03532 char *tmp=ctime(&tm),*p;
03533 char file[BUFFERSIZE];
03534 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
03535 FILE *fp= fopen(file, "a+");
03536
03537 p=strchr(tmp,'\n');
03538 if (p) *p=':';
03539
03540 if (!fp) {
03541 ast_console_puts("Error opening Tracefile: ");
03542 ast_console_puts(strerror(errno));
03543 ast_console_puts("\n");
03544 return ;
03545 }
03546
03547 fputs(tmp,fp);
03548 fputs(" ", fp);
03549 fputs(buf, fp);
03550
03551 fclose(fp);
03552 }
03553 }
03554
03555
03556 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
03557 {
03558 va_list ap;
03559 char buf[1024];
03560 char name[1024];
03561
03562 int trace;
03563 misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
03564 if (!trace) return ;
03565
03566 if (misdn_debug[0] < debug) return ;
03567
03568 char tracedir[BUFFERSIZE];
03569 misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
03570 sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
03571
03572 va_start(ap, tmpl);
03573
03574 vsprintf( buf, tmpl, ap );
03575
03576 va_end(ap);
03577
03578 time_t tm = time(NULL);
03579 char *tmp=ctime(&tm),*p;
03580 FILE *fp= fopen(name, "a");
03581 int fd;
03582
03583 if (!fp) {
03584 ast_console_puts("Error opening Tracefile");
03585 ast_console_puts(strerror(errno));
03586 ast_console_puts("\n");
03587 return ;
03588 }
03589
03590 fd=fileno(fp) ;
03591
03592 flock(fd, LOCK_EX);
03593
03594 p=strchr(tmp,'\n');
03595 if (p) *p=':';
03596
03597
03598
03599 fputs(tmp,fp);
03600 fputs(" ", fp);
03601 fputs(buf, fp);
03602
03603 flock(fd, LOCK_UN);
03604
03605 fclose(fp);
03606
03607 }
03608
03609
03610
03611
03612 static int misdn_facility_exec(struct ast_channel *chan, void *data)
03613 {
03614 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03615 char *tok, *tokb;
03616
03617
03618 if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03619 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
03620 return -1;
03621 }
03622
03623 if (ast_strlen_zero((char *)data)) {
03624 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03625 return -1;
03626 }
03627
03628 tok=strtok_r((char*)data,"|", &tokb) ;
03629
03630 if (!tok) {
03631 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03632 return -1;
03633 }
03634
03635 if (!strcasecmp(tok,"calldeflect")) {
03636 tok=strtok_r(NULL,"|", &tokb) ;
03637
03638 if (!tok) {
03639 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
03640 }
03641
03642 misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
03643
03644 } else {
03645 ast_log(LOG_WARNING, "Unknown Facility: %s\n",tok);
03646 }
03647
03648 return 0;
03649
03650 }
03651
03652
03653 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
03654 {
03655 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03656 char *tok,*tokb;
03657 int keyidx=0;
03658 int rxgain=0;
03659 int txgain=0;
03660
03661 if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03662 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
03663 return -1;
03664 }
03665
03666 if (ast_strlen_zero((char *)data)) {
03667 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
03668 return -1;
03669 }
03670
03671 for (tok=strtok_r((char*)data, ":",&tokb);
03672 tok;
03673 tok=strtok_r(NULL,":",&tokb) ) {
03674 int neglect=0;
03675
03676 if (tok[0] == '!' ) {
03677 neglect=1;
03678 tok++;
03679 }
03680
03681 switch(tok[0]) {
03682
03683 case 'd' :
03684 strncpy(ch->bc->display,++tok,84);
03685 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
03686 break;
03687
03688 case 'n':
03689 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
03690 ch->bc->nodsp=1;
03691 break;
03692
03693 case 'j':
03694 chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
03695 ch->bc->nojitter=1;
03696 break;
03697
03698 case 'v':
03699 tok++;
03700
03701 switch ( tok[0] ) {
03702 case 'r' :
03703 rxgain=atoi(++tok);
03704 if (rxgain<-8) rxgain=-8;
03705 if (rxgain>8) rxgain=8;
03706 ch->bc->rxgain=rxgain;
03707 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
03708 break;
03709 case 't':
03710 txgain=atoi(++tok);
03711 if (txgain<-8) txgain=-8;
03712 if (txgain>8) txgain=8;
03713 ch->bc->txgain=txgain;
03714 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
03715 break;
03716 }
03717 break;
03718
03719 case 'c':
03720 keyidx=atoi(++tok);
03721
03722 if (keyidx > misdn_key_vector_size || keyidx < 0 ) {
03723 ast_log(LOG_WARNING, "You entered the keyidx: %d but we have only %d keys\n",keyidx, misdn_key_vector_size );
03724 continue;
03725 }
03726
03727 {
03728 int l = sizeof(ch->bc->crypt_key);
03729 strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
03730 ch->bc->crypt_key[l-1] = 0;
03731 }
03732 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
03733 break;
03734
03735 case 'e':
03736 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
03737
03738 if (neglect) {
03739 ch->bc->ec_enable=0;
03740 } else {
03741 ch->bc->ec_enable=1;
03742 ch->bc->orig=ch->orginator;
03743 tok++;
03744 if (tok) {
03745 ch->bc->ec_deftaps=atoi(tok);
03746 }
03747 }
03748
03749 break;
03750
03751 case 'h':
03752 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
03753 if (strlen(tok) > 1 && tok[1]=='1') {
03754 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
03755 ch->bc->async=1;
03756 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03757
03758
03759 } else {
03760 ch->bc->async=0;
03761 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03762
03763
03764 }
03765 break;
03766
03767 case 's':
03768 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
03769 ch->bc->send_dtmf=1;
03770 break;
03771
03772 case 'f':
03773 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
03774 ch->faxdetect=1;
03775 break;
03776
03777 case 'a':
03778 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
03779 ch->ast_dsp=1;
03780 break;
03781
03782 case 'p':
03783 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
03784
03785 if (strstr(tok,"allowed") ) {
03786 ch->bc->pres=0;
03787 } else if (strstr(tok,"not_screened")) {
03788 ch->bc->pres=1;
03789 }
03790
03791
03792 break;
03793
03794
03795 default:
03796 break;
03797 }
03798 }
03799
03800 if (ch->faxdetect || ch->ast_dsp) {
03801
03802 if (!ch->dsp) ch->dsp = ast_dsp_new();
03803 if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
03804 if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
03805 }
03806
03807 if (ch->ast_dsp) {
03808 chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
03809 ch->bc->nodsp=1;
03810 ch->bc->nojitter=1;
03811 }
03812
03813 return 0;
03814 }
03815
03816