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 ast_set_callerid(tmp, cid_num, cid_name, cid_num);
02168 }
02169
02170 {
02171 if (pipe(chlist->pipe)<0)
02172 perror("Pipe failed\n");
02173
02174 tmp->fds[0]=chlist->pipe[0];
02175
02176 }
02177
02178 if (chlist->bc) {
02179 int port=chlist->bc->port;
02180 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
02181
02182 {
02183 char buf[256];
02184 ast_group_t pg,cg;
02185
02186 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02187 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02188
02189 chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
02190 tmp->pickupgroup=pg;
02191 tmp->callgroup=cg;
02192 }
02193 misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
02194 misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
02195 chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
02196
02197 } else {
02198 chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
02199 }
02200
02201 ast_setstate(tmp, state);
02202 if (state == AST_STATE_RING)
02203 tmp->rings = 1;
02204 else
02205 tmp->rings = 0;
02206 } else {
02207 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02208 chan_misdn_log(0,0,"Unable to allocate channel structure\n");
02209 }
02210
02211 return tmp;
02212 }
02213
02214
02215
02216 int misdn_tx2ast_frm(struct chan_list * tmp, char * buf, int len )
02217 {
02218 struct ast_frame frame;
02219
02220
02221 if (tmp->holded ) return 0;
02222
02223 switch(tmp->state) {
02224 case MISDN_CLEANING:
02225 case MISDN_EXTCANTMATCH:
02226 case MISDN_WAITING4DIGS:
02227 return 0;
02228 default:
02229 break;
02230 }
02231
02232 if (tmp->norxtone) {
02233 chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
02234 return 0;
02235 }
02236
02237 frame.frametype = AST_FRAME_VOICE;
02238 frame.subclass = AST_FORMAT_ALAW;
02239 frame.datalen = len;
02240 frame.samples = len ;
02241 frame.mallocd =0 ;
02242 frame.offset= 0 ;
02243 frame.src = NULL;
02244 frame.data = buf ;
02245
02246 if (tmp->faxdetect || tmp->ast_dsp ) {
02247 struct ast_frame *f,*f2;
02248 if (tmp->trans)
02249 f2=ast_translate(tmp->trans, &frame,0);
02250 else {
02251 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02252 return 0;
02253 }
02254
02255 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02256 if (f && (f->frametype == AST_FRAME_DTMF)) {
02257 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
02258 if (f->subclass == 'f' && tmp->faxdetect) {
02259
02260 struct ast_channel *ast = tmp->ast;
02261 if (!tmp->faxhandled) {
02262 tmp->faxhandled++;
02263 if (strcmp(ast->exten, "fax")) {
02264 if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
02265 if (option_verbose > 2)
02266 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
02267
02268 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02269 if (ast_async_goto(ast, ast->context, "fax", 1))
02270 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
02271 } else
02272 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
02273 } else
02274 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02275 } else
02276 ast_log(LOG_DEBUG, "Fax already handled\n");
02277 frame.frametype = AST_FRAME_NULL;
02278 frame.subclass = 0;
02279 f = &frame;
02280 } else if ( tmp->ast_dsp) {
02281 struct ast_frame fr;
02282 memset(&fr, 0 , sizeof(fr));
02283 fr.frametype = AST_FRAME_DTMF;
02284 fr.subclass = f->subclass ;
02285 fr.src=NULL;
02286 fr.data = NULL ;
02287 fr.datalen = 0;
02288 fr.samples = 0 ;
02289 fr.mallocd =0 ;
02290 fr.offset= 0 ;
02291
02292 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
02293 ast_queue_frame(tmp->ast, &fr);
02294
02295 frame.frametype = AST_FRAME_NULL;
02296 frame.subclass = 0;
02297 f = &frame;
02298 }
02299 }
02300 }
02301
02302 if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
02303 #if MISDN_DEBUG
02304 int i, max=5>len?len:5;
02305
02306 printf("write2* %p %d bytes: ",tmp, len);
02307
02308 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
02309 printf ("\n");
02310 #endif
02311 chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
02312 ast_queue_frame(tmp->ast,&frame);
02313
02314 } else {
02315 ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
02316 }
02317
02318 return 0;
02319 }
02320
02321
02322
02323 struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
02324 {
02325 struct chan_list *help=list;
02326 for (;help; help=help->next) {
02327 if (help->l3id == l3id ) return help;
02328 }
02329
02330 chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
02331
02332 return NULL;
02333 }
02334
02335 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
02336 {
02337 struct chan_list *help=list;
02338 for (;help; help=help->next) {
02339 if (help->bc == bc) return help;
02340 }
02341
02342 chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02343
02344 return NULL;
02345 }
02346
02347
02348 struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
02349 {
02350 struct chan_list *help=list;
02351
02352 chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
02353 for (;help; help=help->next) {
02354 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
02355 if (help->bc->port == bc->port
02356 && help->bc->holded ) return help;
02357 }
02358
02359 chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02360
02361 return NULL;
02362 }
02363
02364 void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
02365 {
02366 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
02367
02368 ast_mutex_lock(&cl_te_lock);
02369 if (!*list) {
02370 *list = chan;
02371 } else {
02372 struct chan_list *help=*list;
02373 for (;help->next; help=help->next);
02374 help->next=chan;
02375 }
02376 chan->next=NULL;
02377 ast_mutex_unlock(&cl_te_lock);
02378 }
02379
02380 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
02381 {
02382 if (chan->dsp)
02383 ast_dsp_free(chan->dsp);
02384 if (chan->trans)
02385 ast_translator_free_path(chan->trans);
02386
02387
02388 ast_mutex_lock(&cl_te_lock);
02389 if (!*list) {
02390 ast_mutex_unlock(&cl_te_lock);
02391 return;
02392 }
02393
02394 if (*list == chan) {
02395 *list=(*list)->next;
02396 ast_mutex_unlock(&cl_te_lock);
02397 return ;
02398 }
02399
02400 {
02401 struct chan_list *help=*list;
02402 for (;help->next; help=help->next) {
02403 if (help->next == chan) {
02404 help->next=help->next->next;
02405 ast_mutex_unlock(&cl_te_lock);
02406 return;
02407 }
02408 }
02409 }
02410
02411 ast_mutex_unlock(&cl_te_lock);
02412 }
02413
02414
02415
02416
02417
02418
02419 static void release_chan(struct misdn_bchannel *bc) {
02420 struct ast_channel *ast=NULL;
02421
02422 {
02423 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02424 if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
02425
02426 release_lock;
02427 if (ch->ast) {
02428 ast=ch->ast;
02429 }
02430 release_unlock;
02431
02432 chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
02433 if (ch) {
02434 if (ast)
02435 chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
02436
02437 close(ch->pipe[0]);
02438 close(ch->pipe[1]);
02439
02440 if (ast && MISDN_ASTERISK_PVT(ast)) {
02441 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));
02442 chan_misdn_log(3, bc->port, " --> * State Down\n");
02443
02444 send_cause2ast(ast,bc);
02445
02446 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02447
02448
02449 if (ast->_state != AST_STATE_RESERVED) {
02450 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
02451 ast_setstate(ast, AST_STATE_DOWN);
02452 }
02453
02454 switch(ch->state) {
02455 case MISDN_EXTCANTMATCH:
02456 case MISDN_WAITING4DIGS:
02457 {
02458 chan_misdn_log(3, bc->port, " --> * State Wait4dig | ExtCantMatch\n");
02459 ast_hangup(ast);
02460 }
02461 break;
02462
02463 case MISDN_DIALING:
02464 case MISDN_CALLING_ACKNOWLEDGE:
02465 case MISDN_PROGRESS:
02466 chan_misdn_log(2, bc->port, "* --> In State Dialin\n");
02467 chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
02468
02469
02470 ast_queue_hangup(ast);
02471 break;
02472 case MISDN_CALLING:
02473
02474 chan_misdn_log(2, bc->port, "* --> In State Callin\n");
02475
02476 if (!bc->nt) {
02477 chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
02478 ast_queue_hangup(ast);
02479 } else {
02480 chan_misdn_log(2, bc->port, "* --> Hangup\n");
02481 ast_queue_hangup(ast);
02482
02483 }
02484 break;
02485
02486 case MISDN_CLEANING:
02487
02488 chan_misdn_log(2, bc->port, "* --> In StateCleaning\n");
02489 break;
02490 case MISDN_HOLD_DISCONNECT:
02491 chan_misdn_log(2, bc->port, "* --> In HOLD_DISC\n");
02492 break;
02493 default:
02494 chan_misdn_log(2, bc->port, "* --> In State Default\n");
02495 chan_misdn_log(2, bc->port, "* --> Queue Hangup\n");
02496
02497
02498 if (ast && MISDN_ASTERISK_PVT(ast)) {
02499 ast_queue_hangup(ast);
02500 } else {
02501 chan_misdn_log (0, bc->port, "!! Not really queued!\n");
02502 }
02503 }
02504 }
02505 cl_dequeue_chan(&cl_te, ch);
02506
02507 free(ch);
02508 } else {
02509
02510 }
02511 }
02512 }
02513
02514
02515 void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
02516 {
02517 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
02518
02519 tmp_ch->state=MISDN_HOLD_DISCONNECT;
02520
02521 ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
02522
02523 holded_chan->state=MISDN_CONNECTED;
02524 holded_chan->holded=0;
02525 misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
02526
02527 ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
02528 }
02529
02530
02531 void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
02532 {
02533 char predial[256]="";
02534 char *p = predial;
02535
02536 struct ast_frame fr;
02537
02538 strncpy(predial, ast->exten, sizeof(predial) -1 );
02539
02540 ch->state=MISDN_DIALING;
02541
02542 if (bc->nt) {
02543 int ret;
02544 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02545 } else {
02546 int ret;
02547 if ( misdn_lib_is_ptp(bc->port)) {
02548 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02549 } else {
02550 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
02551 }
02552 }
02553
02554 manager_send_tone(bc,TONE_DIAL);
02555
02556 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));
02557
02558 strncpy(ast->exten,"s", 2);
02559
02560 if (ast_pbx_start(ast)<0) {
02561 ast=NULL;
02562 manager_send_tone(bc,TONE_BUSY);
02563 if (bc->nt)
02564 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02565 else
02566 misdn_lib_send_event(bc, EVENT_DISCONNECT );
02567 }
02568
02569
02570 while (!ast_strlen_zero(p) ) {
02571 fr.frametype = AST_FRAME_DTMF;
02572 fr.subclass = *p ;
02573 fr.src=NULL;
02574 fr.data = NULL ;
02575 fr.datalen = 0;
02576 fr.samples = 0 ;
02577 fr.mallocd =0 ;
02578 fr.offset= 0 ;
02579
02580 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02581 ast_queue_frame(ch->ast, &fr);
02582 }
02583 p++;
02584 }
02585 }
02586
02587
02588
02589 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
02590
02591 ast->hangupcause=bc->cause;
02592
02593 switch ( bc->cause) {
02594
02595 case 1:
02596 case 2:
02597 case 3:
02598 case 4:
02599 case 22:
02600 case 27:
02601 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
02602
02603 ast_queue_control(ast, AST_CONTROL_CONGESTION);
02604 break;
02605
02606 case 21:
02607 case 17:
02608 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
02609
02610 ast_queue_control(ast, AST_CONTROL_BUSY);
02611
02612 break;
02613 }
02614 }
02615
02616
02617
02618
02619 enum event_response_e
02620 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
02621 {
02622 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02623
02624 if (!ch)
02625 ch=find_chan_by_l3id(cl_te, bc->l3_id);
02626
02627 if (event != EVENT_BCHAN_DATA) {
02628 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);
02629 misdn_lib_log_ies(bc);
02630 }
02631
02632 if (event != EVENT_SETUP) {
02633 if (!ch) {
02634 if (event != EVENT_CLEANUP )
02635 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);
02636 return -1;
02637 }
02638 }
02639
02640 if (ch ) {
02641 switch (event) {
02642 case EVENT_RELEASE:
02643 case EVENT_RELEASE_COMPLETE:
02644 case EVENT_CLEANUP:
02645 break;
02646 default:
02647 if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02648 if (event!=EVENT_BCHAN_DATA)
02649 ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
02650 return -1;
02651 }
02652 }
02653 }
02654
02655
02656 switch (event) {
02657 case EVENT_NEW_L3ID:
02658 ch->l3id=bc->l3_id;
02659 break;
02660
02661 case EVENT_NEW_BC:
02662 if (bc)
02663 ch->bc=bc;
02664 break;
02665
02666 case EVENT_DTMF_TONE:
02667 {
02668
02669 struct ast_frame fr;
02670 memset(&fr, 0 , sizeof(fr));
02671 fr.frametype = AST_FRAME_DTMF;
02672 fr.subclass = bc->dtmf ;
02673 fr.src=NULL;
02674 fr.data = NULL ;
02675 fr.datalen = 0;
02676 fr.samples = 0 ;
02677 fr.mallocd =0 ;
02678 fr.offset= 0 ;
02679
02680 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
02681
02682 ast_queue_frame(ch->ast, &fr);
02683 }
02684 break;
02685 case EVENT_STATUS:
02686 break;
02687
02688 case EVENT_INFORMATION:
02689 {
02690 int stop_tone;
02691 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
02692 if ( stop_tone && bc->tone != TONE_NONE) {
02693 manager_send_tone(bc,TONE_NONE);
02694 }
02695
02696 if (ch->state == MISDN_WAITING4DIGS ) {
02697
02698 {
02699 int l = sizeof(bc->dad);
02700 strncat(bc->dad,bc->info_dad, l);
02701 bc->dad[l-1] = 0;
02702 }
02703
02704
02705 {
02706 int l = sizeof(ch->ast->exten);
02707 strncpy(ch->ast->exten, bc->dad, l);
02708 ch->ast->exten[l-1] = 0;
02709 }
02710
02711
02712 char bc_context[BUFFERSIZE];
02713 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02714 if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02715 chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
02716 manager_send_tone(bc,TONE_BUSY);
02717 ch->state=MISDN_EXTCANTMATCH;
02718 bc->out_cause=1;
02719 if (bc->nt)
02720 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02721 else
02722 misdn_lib_send_event(bc, EVENT_DISCONNECT );
02723 break;
02724 }
02725 if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02726 ch->state=MISDN_DIALING;
02727
02728 manager_send_tone(bc,TONE_NONE);
02729
02730 if (ast_pbx_start(ch->ast)<0) {
02731 chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
02732 manager_send_tone(bc,TONE_BUSY);
02733 if (bc->nt)
02734 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02735 else
02736 misdn_lib_send_event(bc, EVENT_DISCONNECT );
02737 }
02738 }
02739
02740 } else {
02741
02742 struct ast_frame fr;
02743 fr.frametype = AST_FRAME_DTMF;
02744 fr.subclass = bc->info_dad[0] ;
02745 fr.src=NULL;
02746 fr.data = NULL ;
02747 fr.datalen = 0;
02748 fr.samples = 0 ;
02749 fr.mallocd =0 ;
02750 fr.offset= 0 ;
02751
02752
02753 int digits;
02754 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
02755 if (ch->state != MISDN_CONNECTED ) {
02756 if (digits) {
02757 int l = sizeof(bc->dad);
02758 strncat(bc->dad,bc->info_dad, l);
02759 bc->dad[l-1] = 0;
02760 l = sizeof(ch->ast->exten);
02761 strncpy(ch->ast->exten, bc->dad, l);
02762 ch->ast->exten[l-1] = 0;
02763
02764 ast_cdr_update(ch->ast);
02765 }
02766
02767 ast_queue_frame(ch->ast, &fr);
02768 }
02769
02770 }
02771 }
02772 break;
02773 case EVENT_SETUP:
02774 {
02775 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02776 if (ch && ch->state != MISDN_NOTHING ) {
02777 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
02778 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE;
02779 }
02780 }
02781
02782 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
02783 if (!bc->nt && ! msn_valid) {
02784 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
02785 return RESPONSE_IGNORE_SETUP;
02786 }
02787
02788 print_bearer(bc);
02789
02790 {
02791 struct chan_list *ch=init_chan_list();
02792 struct ast_channel *chan;
02793 char name[128];
02794 if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
02795
02796 ch->bc = bc;
02797 ch->l3id=bc->l3_id;
02798 ch->addr=bc->addr;
02799 ch->orginator = ORG_MISDN;
02800
02801
02802 {
02803 char prefix[BUFFERSIZE]="";
02804 switch( bc->onumplan ) {
02805 case NUMPLAN_INTERNATIONAL:
02806 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02807 break;
02808
02809 case NUMPLAN_NATIONAL:
02810 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02811 break;
02812
02813
02814 case NUMPLAN_SUBSCRIBER:
02815
02816 break;
02817
02818 case NUMPLAN_UNKNOWN:
02819 break;
02820 default:
02821 break;
02822 }
02823
02824 {
02825 int l = strlen(prefix) + strlen(bc->oad);
02826 char tmp[l+1];
02827 strcpy(tmp,prefix);
02828 strcat(tmp,bc->oad);
02829 strcpy(bc->oad,tmp);
02830 }
02831
02832 if (!ast_strlen_zero(bc->oad))
02833 sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
02834 else
02835 sprintf(name,"mISDN/%d",bc->port);
02836
02837
02838 if (!ast_strlen_zero(bc->dad)) {
02839 strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
02840 bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
02841 }
02842
02843 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02844 strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
02845 bc->dad[sizeof(bc->dad)-1] = 0;
02846 }
02847 prefix[0] = 0;
02848
02849 switch( bc->dnumplan ) {
02850 case NUMPLAN_INTERNATIONAL:
02851 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02852 break;
02853
02854 case NUMPLAN_NATIONAL:
02855 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02856 break;
02857
02858
02859 case NUMPLAN_SUBSCRIBER:
02860
02861 break;
02862
02863 case NUMPLAN_UNKNOWN:
02864 break;
02865 default:
02866 break;
02867 }
02868
02869 {
02870 int l = strlen(prefix) + strlen(bc->dad);
02871 char tmp[l+1];
02872 strcpy(tmp,prefix);
02873 strcat(tmp,bc->dad);
02874 strcpy(bc->dad,tmp);
02875 }
02876
02877 char bc_context[BUFFERSIZE];
02878 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02879 chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
02880
02881 if (!chan) {
02882 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02883 return 0;
02884 }
02885
02886 ch->ast = chan;
02887 pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
02888
02889 }
02890
02891
02892
02893 chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
02894
02895 if ( bc->pres ) {
02896 chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
02897 } else {
02898 chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
02899 }
02900
02901 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
02902 chan->transfercapability=bc->capability;
02903
02904 switch (bc->capability) {
02905 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02906 pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
02907 break;
02908 default:
02909 pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
02910 }
02911
02912
02913 cl_queue_chan(&cl_te, ch) ;
02914
02915
02916
02917
02918
02919
02920 {
02921
02922 misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));
02923
02924 }
02925
02926 {
02927 int eb3;
02928
02929 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
02930 bc->early_bconnect=eb3;
02931
02932 }
02933
02934 {
02935 int ec, ectr;
02936
02937 misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
02938
02939 misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
02940 if (ec == 1 ) {
02941 bc->ec_enable=1;
02942 } else if ( ec > 1 ) {
02943 bc->ec_enable=1;
02944 bc->ec_deftaps=ec;
02945 }
02946
02947 if ( ectr>=0 ) {
02948 bc->ec_training=ectr;
02949 }
02950 }
02951
02952
02953 if (bc->urate>0) {
02954 char buf[16];
02955 snprintf(buf,16,"%d",bc->urate);
02956 pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
02957 }
02958
02959
02960
02961
02962
02963
02964
02965
02966 int ai;
02967 misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
02968 if ( ai ) {
02969 do_immediate_setup(bc, ch , chan);
02970 break;
02971 }
02972
02973
02974 int immediate;
02975 misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
02976
02977 if (ast_strlen_zero(bc->orig_dad) && immediate ) {
02978 do_immediate_setup(bc, ch , chan);
02979 break;
02980 }
02981
02982
02983 if (!strcmp(chan->exten, ast_pickup_ext())) {
02984 int ret;
02985 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02986
02987 if (ast_pickup_call(chan)) {
02988 ast_hangup(chan);
02989 } else {
02990 ch->state = MISDN_CALLING_ACKNOWLEDGE;
02991
02992 ch->ast=NULL;
02993
02994 ast_setstate(chan, AST_STATE_DOWN);
02995 ast_hangup(chan);
02996
02997 break;
02998 }
02999 }
03000
03001
03002
03003
03004 char bc_context[BUFFERSIZE];
03005 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
03006 if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03007 chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
03008 manager_send_tone(bc,TONE_BUSY);
03009 ch->state=MISDN_EXTCANTMATCH;
03010 bc->out_cause=1;
03011 if (bc->nt)
03012 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03013 else
03014 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03015 break;
03016 }
03017
03018 if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03019 ch->state=MISDN_DIALING;
03020
03021 if (bc->nt) {
03022 int ret;
03023 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03024 } else {
03025 int ret;
03026 ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
03027 }
03028
03029 if (ast_pbx_start(chan)<0) {
03030 chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03031 chan=NULL;
03032 manager_send_tone(bc,TONE_BUSY);
03033 if (bc->nt)
03034 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03035 else
03036 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03037 }
03038 } else {
03039 int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03040 if (ret == -ENOCHAN) {
03041 ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
03042 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03043 }
03044
03045
03046 int stop_tone;
03047 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03048 if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
03049 manager_send_tone(bc,TONE_NONE);
03050 else
03051 manager_send_tone(bc,TONE_DIAL);
03052
03053 ch->state=MISDN_WAITING4DIGS;
03054 }
03055
03056 }
03057 break;
03058 case EVENT_SETUP_ACKNOWLEDGE:
03059 {
03060 ch->state = MISDN_CALLING_ACKNOWLEDGE;
03061 if (!ast_strlen_zero(bc->infos_pending)) {
03062
03063
03064 {
03065 int l = sizeof(bc->dad);
03066 strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
03067 bc->dad[l-1] = 0;
03068 }
03069 {
03070 int l = sizeof(ch->ast->exten);
03071 strncpy(ch->ast->exten, bc->dad, l);
03072 ch->ast->exten[l-1] = 0;
03073 }
03074 {
03075 int l = sizeof(bc->info_dad);
03076 strncpy(bc->info_dad, bc->infos_pending, l);
03077 bc->info_dad[l-1] = 0;
03078 }
03079 strncpy(bc->infos_pending,"", 1);
03080
03081 misdn_lib_send_event(bc, EVENT_INFORMATION);
03082 }
03083 }
03084 break;
03085 case EVENT_PROCEEDING:
03086 {
03087
03088 if ( misdn_cap_is_speech(bc->capability) &&
03089 misdn_inband_avail(bc) ) {
03090 start_bc_tones(ch);
03091 }
03092 }
03093 break;
03094 case EVENT_PROGRESS:
03095 if (!bc->nt ) {
03096 if ( misdn_cap_is_speech(bc->capability) &&
03097 misdn_inband_avail(bc)
03098 ) {
03099 start_bc_tones(ch);
03100 }
03101
03102 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
03103
03104 ch->state=MISDN_PROGRESS;
03105 }
03106 break;
03107
03108
03109 case EVENT_ALERTING:
03110 {
03111 ch->state = MISDN_ALERTING;
03112
03113 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
03114 ast_setstate(ch->ast, AST_STATE_RINGING);
03115
03116 cb_log(1,bc->port,"Set State Ringing\n");
03117
03118 if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
03119 start_bc_tones(ch);
03120 }
03121 }
03122 break;
03123 case EVENT_CONNECT:
03124 misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
03125 case EVENT_CONNECT_ACKNOWLEDGE:
03126 {
03127 bc->state=STATE_CONNECTED;
03128
03129 ch->l3id=bc->l3_id;
03130 ch->addr=bc->addr;
03131
03132 start_bc_tones(ch);
03133
03134 chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
03135
03136 ch->state = MISDN_CONNECTED;
03137 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
03138 }
03139 break;
03140 case EVENT_DISCONNECT:
03141 {
03142
03143 struct chan_list *holded_ch=find_holded(cl_te, bc);
03144
03145
03146 send_cause2ast(ch->ast,bc);
03147
03148 if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
03149
03150
03151
03152
03153
03154 start_bc_tones(ch);
03155 break;
03156 }
03157
03158
03159 if (holded_ch ) {
03160 if (ch->state == MISDN_CONNECTED ) {
03161 misdn_transfer_bc(ch, holded_ch) ;
03162 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03163 break;
03164 }
03165 }
03166
03167 stop_bc_tones(ch);
03168 bc->out_cause=16;
03169 misdn_lib_send_event(bc,EVENT_RELEASE);
03170
03171 }
03172 break;
03173
03174 case EVENT_RELEASE:
03175 {
03176
03177 switch ( bc->cause) {
03178
03179 case -1:
03180
03181
03182
03183
03184
03185
03186 return RESPONSE_OK;
03187 break;
03188 }
03189
03190
03191 bc->out_cause=16;
03192
03193 stop_bc_tones(ch);
03194 release_chan(bc);
03195 }
03196 break;
03197 case EVENT_RELEASE_COMPLETE:
03198 {
03199 stop_bc_tones(ch);
03200 release_chan(bc);
03201 }
03202 break;
03203
03204 case EVENT_BCHAN_DATA:
03205 {
03206 chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
03207
03208 if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
03209 misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
03210 } else {
03211 int len=bc->bframe_len;
03212 int free=misdn_ibuf_freecount(bc->astbuf);
03213
03214
03215 if (bc->bframe_len > free) {
03216 ast_log(LOG_DEBUG, "sbuf overflow!\n");
03217 len=misdn_ibuf_freecount(bc->astbuf);
03218
03219 if (len == 0) {
03220 ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
03221 }
03222 }
03223
03224 misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
03225
03226 {
03227 char blah[1]="\0";
03228 #ifdef FLATTEN_JITTER
03229 {
03230 struct timeval tv;
03231 gettimeofday(&tv,NULL);
03232
03233 if (tv.tv_usec % 10000 > 0 ) {
03234 write(ch->pipe[1], blah,sizeof(blah));
03235 bc->time_usec=tv.tv_usec;
03236 }
03237 }
03238 #else
03239 write(ch->pipe[1], blah,sizeof(blah));
03240 #endif
03241
03242
03243 }
03244 }
03245
03246 }
03247 break;
03248 case EVENT_TIMEOUT:
03249 break;
03250 {
03251 switch (ch->state) {
03252 case MISDN_CALLING:
03253 chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
03254 break;
03255 case MISDN_DIALING:
03256 case MISDN_PROGRESS:
03257 break;
03258 default:
03259 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03260 }
03261 }
03262 break;
03263 case EVENT_CLEANUP:
03264 {
03265 stop_bc_tones(ch);
03266 release_chan(bc);
03267 }
03268 break;
03269
03270
03271
03272
03273 case EVENT_RETRIEVE:
03274 {
03275 struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
03276 ch->state = MISDN_CONNECTED;
03277
03278 if (hold_ast) {
03279 ast_moh_stop(hold_ast);
03280 }
03281
03282 if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
03283 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
03284
03285
03286 }
03287 break;
03288
03289 case EVENT_HOLD:
03290 {
03291 int hold_allowed;
03292 misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
03293
03294 if (!hold_allowed) {
03295 chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
03296 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03297 break;
03298 }
03299
03300 {
03301 struct chan_list *holded_ch=find_holded(cl_te, bc);
03302 if (holded_ch) {
03303 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03304 chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
03305 break;
03306 }
03307 }
03308
03309 if (AST_BRIDGED_P(ch->ast)){
03310 ch->state = MISDN_HOLDED;
03311 ch->l3id = bc->l3_id;
03312
03313 ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
03314 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
03315 } else {
03316 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03317 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
03318 }
03319 }
03320 break;
03321 default:
03322 ast_log(LOG_WARNING, "Got Unknown Event\n");
03323 break;
03324 }
03325
03326 return RESPONSE_OK;
03327 }
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339 int clearl3_true ( void ) {
03340 int default_clearl3;
03341 misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
03342 return default_clearl3;
03343 }
03344
03345 int g_config_initialized=0;
03346
03347 int load_module(void)
03348 {
03349 int i;
03350
03351 char ports[256]="";
03352
03353 max_ports=misdn_lib_maxports_get();
03354
03355 if (max_ports<=0) {
03356 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
03357 return -1;
03358 }
03359
03360
03361 misdn_cfg_init(max_ports);
03362 g_config_initialized=1;
03363
03364 misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
03365 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
03366 for (i = 1; i <= max_ports; i++)
03367 misdn_debug[i] = misdn_debug[0];
03368 misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
03369
03370
03371 {
03372 char tempbuf[BUFFERSIZE];
03373 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
03374 if (strlen(tempbuf))
03375 tracing = 1;
03376 }
03377
03378 ast_mutex_init(&cl_te_lock);
03379 ast_mutex_init(&release_lock_mutex);
03380
03381 misdn_cfg_get_ports_string(ports);
03382 if (strlen(ports))
03383 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
03384
03385 {
03386 struct misdn_lib_iface iface = {
03387 .cb_event = cb_events,
03388 .cb_log = chan_misdn_log,
03389 .cb_clearl3_true = clearl3_true
03390 };
03391 if (misdn_lib_init(ports, &iface, NULL))
03392 chan_misdn_log(0, 0, "No te ports initialized\n");
03393 }
03394
03395
03396 {
03397 if (ast_channel_register(&misdn_tech)) {
03398 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
03399 unload_module();
03400 return -1;
03401 }
03402 }
03403
03404 ast_cli_register(&cli_send_display);
03405 ast_cli_register(&cli_send_cd);
03406 ast_cli_register(&cli_send_digit);
03407 ast_cli_register(&cli_toggle_echocancel);
03408 ast_cli_register(&cli_set_tics);
03409
03410 ast_cli_register(&cli_show_cls);
03411 ast_cli_register(&cli_show_cl);
03412 ast_cli_register(&cli_show_config);
03413 ast_cli_register(&cli_show_port);
03414 ast_cli_register(&cli_show_stacks);
03415
03416 ast_cli_register(&cli_restart_port);
03417 ast_cli_register(&cli_port_up);
03418 ast_cli_register(&cli_set_debug);
03419 ast_cli_register(&cli_set_crypt_debug);
03420 ast_cli_register(&cli_reload);
03421
03422
03423 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
03424 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
03425 "Sets mISDN opts. and optargs\n"
03426 "\n"
03427 );
03428
03429
03430 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
03431 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
03432 "Sends the Facility Message FACILITY_TYPE with \n"
03433 "the given Arguments to the current ISDN Channel\n"
03434 "Supported Facilities are:\n"
03435 "\n"
03436 "type=calldeflect args=Nr where to deflect\n"
03437 "\n"
03438 );
03439
03440 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
03441
03442 return 0;
03443 }
03444
03445
03446
03447 int unload_module(void)
03448 {
03449
03450 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
03451
03452 if (!g_config_initialized) return 0;
03453
03454 ast_cli_unregister(&cli_send_display);
03455
03456 ast_cli_unregister(&cli_send_cd);
03457
03458 ast_cli_unregister(&cli_send_digit);
03459 ast_cli_unregister(&cli_toggle_echocancel);
03460 ast_cli_unregister(&cli_set_tics);
03461
03462 ast_cli_unregister(&cli_show_cls);
03463 ast_cli_unregister(&cli_show_cl);
03464 ast_cli_unregister(&cli_show_config);
03465 ast_cli_unregister(&cli_show_port);
03466 ast_cli_unregister(&cli_show_stacks);
03467 ast_cli_unregister(&cli_restart_port);
03468 ast_cli_unregister(&cli_port_up);
03469 ast_cli_unregister(&cli_set_debug);
03470 ast_cli_unregister(&cli_set_crypt_debug);
03471 ast_cli_unregister(&cli_reload);
03472
03473 ast_unregister_application("misdn_set_opt");
03474 ast_unregister_application("misdn_facility");
03475
03476 ast_channel_unregister(&misdn_tech);
03477
03478 free_robin_list();
03479 misdn_cfg_destroy();
03480 misdn_lib_destroy();
03481
03482 if (misdn_debug)
03483 free(misdn_debug);
03484 if (misdn_debug_only)
03485 free(misdn_debug_only);
03486
03487 return 0;
03488 }
03489
03490 int usecount(void)
03491 {
03492 int res;
03493 ast_mutex_lock(&usecnt_lock);
03494 res = usecnt;
03495 ast_mutex_unlock(&usecnt_lock);
03496 return res;
03497 }
03498
03499 char *description(void)
03500 {
03501 return desc;
03502 }
03503
03504 char *key(void)
03505 {
03506 return ASTERISK_GPL_KEY;
03507 }
03508
03509 void chan_misdn_log(int level, int port, char *tmpl, ...)
03510 {
03511 if (! ((0 <= port) && (port <= max_ports))) {
03512 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
03513 return;
03514 }
03515
03516 va_list ap;
03517 char buf[1024];
03518
03519 va_start(ap, tmpl);
03520 vsnprintf( buf, 1023, tmpl, ap );
03521 va_end(ap);
03522
03523 if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
03524 ast_console_puts(buf);
03525 }
03526
03527 if (level <= misdn_debug[0] && tracing) {
03528 time_t tm = time(NULL);
03529 char *tmp=ctime(&tm),*p;
03530 char file[BUFFERSIZE];
03531 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
03532 FILE *fp= fopen(file, "a+");
03533
03534 p=strchr(tmp,'\n');
03535 if (p) *p=':';
03536
03537 if (!fp) {
03538 ast_console_puts("Error opening Tracefile: ");
03539 ast_console_puts(strerror(errno));
03540 ast_console_puts("\n");
03541 return ;
03542 }
03543
03544 fputs(tmp,fp);
03545 fputs(" ", fp);
03546 fputs(buf, fp);
03547
03548 fclose(fp);
03549 }
03550 }
03551
03552
03553 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
03554 {
03555 va_list ap;
03556 char buf[1024];
03557 char name[1024];
03558
03559 int trace;
03560 misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
03561 if (!trace) return ;
03562
03563 if (misdn_debug[0] < debug) return ;
03564
03565 char tracedir[BUFFERSIZE];
03566 misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
03567 sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
03568
03569 va_start(ap, tmpl);
03570
03571 vsprintf( buf, tmpl, ap );
03572
03573 va_end(ap);
03574
03575 time_t tm = time(NULL);
03576 char *tmp=ctime(&tm),*p;
03577 FILE *fp= fopen(name, "a");
03578 int fd;
03579
03580 if (!fp) {
03581 ast_console_puts("Error opening Tracefile");
03582 ast_console_puts(strerror(errno));
03583 ast_console_puts("\n");
03584 return ;
03585 }
03586
03587 fd=fileno(fp) ;
03588
03589 flock(fd, LOCK_EX);
03590
03591 p=strchr(tmp,'\n');
03592 if (p) *p=':';
03593
03594
03595
03596 fputs(tmp,fp);
03597 fputs(" ", fp);
03598 fputs(buf, fp);
03599
03600 flock(fd, LOCK_UN);
03601
03602 fclose(fp);
03603
03604 }
03605
03606
03607
03608
03609 static int misdn_facility_exec(struct ast_channel *chan, void *data)
03610 {
03611 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03612 char *tok, *tokb;
03613
03614
03615 if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03616 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
03617 return -1;
03618 }
03619
03620 if (ast_strlen_zero((char *)data)) {
03621 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03622 return -1;
03623 }
03624
03625 tok=strtok_r((char*)data,"|", &tokb) ;
03626
03627 if (!tok) {
03628 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03629 return -1;
03630 }
03631
03632 if (!strcasecmp(tok,"calldeflect")) {
03633 tok=strtok_r(NULL,"|", &tokb) ;
03634
03635 if (!tok) {
03636 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
03637 }
03638
03639 misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
03640
03641 } else {
03642 ast_log(LOG_WARNING, "Unknown Facility: %s\n",tok);
03643 }
03644
03645 return 0;
03646
03647 }
03648
03649
03650 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
03651 {
03652 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03653 char *tok,*tokb;
03654 int keyidx=0;
03655 int rxgain=0;
03656 int txgain=0;
03657
03658 if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03659 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
03660 return -1;
03661 }
03662
03663 if (ast_strlen_zero((char *)data)) {
03664 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
03665 return -1;
03666 }
03667
03668 for (tok=strtok_r((char*)data, ":",&tokb);
03669 tok;
03670 tok=strtok_r(NULL,":",&tokb) ) {
03671 int neglect=0;
03672
03673 if (tok[0] == '!' ) {
03674 neglect=1;
03675 tok++;
03676 }
03677
03678 switch(tok[0]) {
03679
03680 case 'd' :
03681 strncpy(ch->bc->display,++tok,84);
03682 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
03683 break;
03684
03685 case 'n':
03686 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
03687 ch->bc->nodsp=1;
03688 break;
03689
03690 case 'j':
03691 chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
03692 ch->bc->nojitter=1;
03693 break;
03694
03695 case 'v':
03696 tok++;
03697
03698 switch ( tok[0] ) {
03699 case 'r' :
03700 rxgain=atoi(++tok);
03701 if (rxgain<-8) rxgain=-8;
03702 if (rxgain>8) rxgain=8;
03703 ch->bc->rxgain=rxgain;
03704 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
03705 break;
03706 case 't':
03707 txgain=atoi(++tok);
03708 if (txgain<-8) txgain=-8;
03709 if (txgain>8) txgain=8;
03710 ch->bc->txgain=txgain;
03711 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
03712 break;
03713 }
03714 break;
03715
03716 case 'c':
03717 keyidx=atoi(++tok);
03718
03719 if (keyidx > misdn_key_vector_size || keyidx < 0 ) {
03720 ast_log(LOG_WARNING, "You entered the keyidx: %d but we have only %d keys\n",keyidx, misdn_key_vector_size );
03721 continue;
03722 }
03723
03724 {
03725 int l = sizeof(ch->bc->crypt_key);
03726 strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
03727 ch->bc->crypt_key[l-1] = 0;
03728 }
03729 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
03730 break;
03731
03732 case 'e':
03733 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
03734
03735 if (neglect) {
03736 ch->bc->ec_enable=0;
03737 } else {
03738 ch->bc->ec_enable=1;
03739 ch->bc->orig=ch->orginator;
03740 tok++;
03741 if (tok) {
03742 ch->bc->ec_deftaps=atoi(tok);
03743 }
03744 }
03745
03746 break;
03747
03748 case 'h':
03749 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
03750 if (strlen(tok) > 1 && tok[1]=='1') {
03751 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
03752 ch->bc->async=1;
03753 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03754
03755
03756 } else {
03757 ch->bc->async=0;
03758 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03759
03760
03761 }
03762 break;
03763
03764 case 's':
03765 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
03766 ch->bc->send_dtmf=1;
03767 break;
03768
03769 case 'f':
03770 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
03771 ch->faxdetect=1;
03772 break;
03773
03774 case 'a':
03775 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
03776 ch->ast_dsp=1;
03777 break;
03778
03779 case 'p':
03780 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
03781
03782 if (strstr(tok,"allowed") ) {
03783 ch->bc->pres=0;
03784 } else if (strstr(tok,"not_screened")) {
03785 ch->bc->pres=1;
03786 }
03787
03788
03789 break;
03790
03791
03792 default:
03793 break;
03794 }
03795 }
03796
03797 if (ch->faxdetect || ch->ast_dsp) {
03798
03799 if (!ch->dsp) ch->dsp = ast_dsp_new();
03800 if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
03801 if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
03802 }
03803
03804 if (ch->ast_dsp) {
03805 chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
03806 ch->bc->nodsp=1;
03807 ch->bc->nojitter=1;
03808 }
03809
03810 return 0;
03811 }
03812
03813