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 char global_tracefile[BUFFERSIZE+1];
00066
00067
00068 struct misdn_jb{
00069 int size;
00070 int upper_threshold;
00071 char *samples, *ok;
00072 int wp,rp;
00073 int state_empty;
00074 int state_full;
00075 int state_buffer;
00076 int bytes_wrote;
00077 ast_mutex_t mutexjb;
00078 };
00079
00080
00081
00082
00083 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
00084
00085
00086 void misdn_jb_destroy(struct misdn_jb *jb);
00087
00088
00089
00090 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
00091
00092
00093
00094
00095 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
00096
00097
00098
00099
00100
00101
00102
00103
00104 enum misdn_chan_state {
00105 MISDN_NOTHING=0,
00106 MISDN_WAITING4DIGS,
00107 MISDN_EXTCANTMATCH,
00108 MISDN_DIALING,
00109 MISDN_PROGRESS,
00110 MISDN_PROCEEDING,
00111 MISDN_CALLING,
00112 MISDN_CALLING_ACKNOWLEDGE,
00113 MISDN_ALERTING,
00114 MISDN_BUSY,
00115 MISDN_CONNECTED,
00116 MISDN_PRECONNECTED,
00117 MISDN_DISCONNECTED,
00118 MISDN_RELEASED,
00119 MISDN_BRIDGED,
00120 MISDN_CLEANING,
00121 MISDN_HUNGUP_FROM_MISDN,
00122 MISDN_HUNGUP_FROM_AST,
00123
00124 MISDN_HOLDED,
00125 MISDN_HOLD_DISCONNECT,
00126 MISDN_FIXUP
00127
00128 };
00129
00130 #define ORG_AST 1
00131 #define ORG_MISDN 2
00132
00133 struct hold_info {
00134 int port;
00135 int channel;
00136 };
00137
00138 struct chan_list {
00139
00140 ast_mutex_t lock;
00141
00142 char allowed_bearers[BUFFERSIZE+1];
00143
00144 enum misdn_chan_state state;
00145 int need_queue_hangup;
00146 int need_hangup;
00147 int need_busy;
00148
00149 int orginator;
00150
00151 int norxtone;
00152 int notxtone;
00153
00154 int toggle_ec;
00155
00156 int incoming_early_audio;
00157
00158 int ignore_dtmf;
00159
00160 int pipe[2];
00161 char ast_rd_buf[4096];
00162 struct ast_frame frame;
00163
00164 int faxdetect;
00165 int faxhandled;
00166
00167 int ast_dsp;
00168
00169 int jb_len;
00170 int jb_upper_threshold;
00171 struct misdn_jb *jb;
00172
00173 struct ast_dsp *dsp;
00174 struct ast_trans_pvt *trans;
00175
00176 struct ast_channel * ast;
00177
00178 int dummy;
00179
00180 struct misdn_bchannel *bc;
00181
00182 struct hold_info hold_info;
00183
00184 unsigned int l3id;
00185 int addr;
00186
00187 char context[BUFFERSIZE];
00188
00189 int zero_read_cnt;
00190 int dropped_frame_cnt;
00191
00192 int far_alerting;
00193 int other_pid;
00194 struct chan_list *other_ch;
00195
00196 const struct tone_zone_sound *ts;
00197
00198 struct chan_list *peer;
00199 struct chan_list *next;
00200 struct chan_list *prev;
00201 struct chan_list *first;
00202 };
00203
00204
00205
00206 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
00207 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
00208
00209 struct robin_list {
00210 char *group;
00211 int port;
00212 int channel;
00213 struct robin_list *next;
00214 struct robin_list *prev;
00215 };
00216 static struct robin_list *robin = NULL;
00217
00218
00219
00220 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
00221
00222
00223
00224 static inline void free_robin_list_r (struct robin_list *r)
00225 {
00226 if (r) {
00227 if (r->next) free_robin_list_r(r->next);
00228 if (r->group) free(r->group);
00229 free(r);
00230 }
00231 }
00232
00233 static void free_robin_list ( void )
00234 {
00235 free_robin_list_r(robin);
00236 robin = NULL;
00237 }
00238
00239 static struct robin_list* get_robin_position (char *group)
00240 {
00241 struct robin_list *iter = robin;
00242 for (; iter; iter = iter->next) {
00243 if (!strcasecmp(iter->group, group))
00244 return iter;
00245 }
00246 struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
00247 new->group = strndup(group, strlen(group));
00248 new->channel = 1;
00249 if (robin) {
00250 new->next = robin;
00251 robin->prev = new;
00252 }
00253 robin = new;
00254 return robin;
00255 }
00256
00257
00258 static void chan_misdn_log(int level, int port, char *tmpl, ...);
00259
00260 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c);
00261 static void send_digit_to_chan(struct chan_list *cl, char digit );
00262
00263
00264 #define AST_CID_P(ast) ast->cid.cid_num
00265 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast)
00266 #define AST_LOAD_CFG ast_config_load
00267 #define AST_DESTROY_CFG ast_config_destroy
00268
00269 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
00270 #define MISDN_ASTERISK_PVT(ast) 1
00271
00272 #include <asterisk/strings.h>
00273
00274
00275
00276 static char *desc = "Channel driver for mISDN Support (Bri/Pri)";
00277 static const char misdn_type[] = "mISDN";
00278
00279 static int tracing = 0 ;
00280
00281 static int usecnt=0;
00282
00283 static char **misdn_key_vector=NULL;
00284 static int misdn_key_vector_size=0;
00285
00286
00287 static int prefformat = AST_FORMAT_ALAW ;
00288
00289 static ast_mutex_t usecnt_lock;
00290
00291 static int *misdn_debug;
00292 static int *misdn_debug_only;
00293 static int max_ports;
00294
00295 struct chan_list dummy_cl;
00296
00297 struct chan_list *cl_te=NULL;
00298 ast_mutex_t cl_te_lock;
00299
00300 static enum event_response_e
00301 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
00302
00303 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch);
00304
00305 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
00306 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
00307 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
00308 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid);
00309
00310
00311
00312 static int dialtone_indicate(struct chan_list *cl);
00313 static int hanguptone_indicate(struct chan_list *cl);
00314 static int stop_indicate(struct chan_list *cl);
00315
00316 static int start_bc_tones(struct chan_list *cl);
00317 static int stop_bc_tones(struct chan_list *cl);
00318 static void release_chan(struct misdn_bchannel *bc);
00319
00320 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
00321 static int misdn_facility_exec(struct ast_channel *chan, void *data);
00322
00323 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
00324
00325 static int update_ec_config(struct misdn_bchannel *bc);
00326
00327
00328
00329 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
00330 {
00331 struct chan_list *tmp;
00332
00333 for (tmp=cl_te; tmp; tmp = tmp->next) {
00334 if ( tmp->ast == ast ) return tmp;
00335 }
00336
00337 return NULL;
00338 }
00339
00340 static struct chan_list * get_chan_by_ast_name(char *name)
00341 {
00342 struct chan_list *tmp;
00343
00344 for (tmp=cl_te; tmp; tmp = tmp->next) {
00345 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp;
00346 }
00347
00348 return NULL;
00349 }
00350
00351
00352
00353 struct allowed_bearers {
00354 int cap;
00355 int val;
00356 char *name;
00357 };
00358
00359 struct allowed_bearers allowed_bearers_array[]={
00360 {INFO_CAPABILITY_SPEECH,1,"speech"},
00361 {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"},
00362 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"},
00363 {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"},
00364 {INFO_CAPABILITY_VIDEO,16,"video"}
00365 };
00366
00367 static char *bearer2str(int cap) {
00368 static char *bearers[]={
00369 "Speech",
00370 "Audio 3.1k",
00371 "Unres Digital",
00372 "Res Digital",
00373 "Video",
00374 "Unknown Bearer"
00375 };
00376
00377 switch (cap) {
00378 case INFO_CAPABILITY_SPEECH:
00379 return bearers[0];
00380 break;
00381 case INFO_CAPABILITY_AUDIO_3_1K:
00382 return bearers[1];
00383 break;
00384 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00385 return bearers[2];
00386 break;
00387 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00388 return bearers[3];
00389 break;
00390 case INFO_CAPABILITY_VIDEO:
00391 return bearers[4];
00392 break;
00393 default:
00394 return bearers[5];
00395 break;
00396 }
00397 }
00398
00399
00400 static void print_facility( struct misdn_bchannel *bc)
00401 {
00402 switch (bc->fac_type) {
00403 case FACILITY_CALLDEFLECT:
00404 chan_misdn_log(2,bc->port," --> calldeflect: %s\n",
00405 bc->fac.calldeflect_nr);
00406 break;
00407 case FACILITY_CENTREX:
00408 chan_misdn_log(2,bc->port," --> centrex: %s\n",
00409 bc->fac.cnip);
00410 break;
00411 default:
00412 chan_misdn_log(2,bc->port," --> unknown\n");
00413
00414 }
00415 }
00416
00417 static void print_bearer(struct misdn_bchannel *bc)
00418 {
00419
00420 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00421
00422 switch(bc->law) {
00423 case INFO_CODEC_ALAW:
00424 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00425 break;
00426 case INFO_CODEC_ULAW:
00427 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00428 break;
00429 }
00430 }
00431
00432
00433 static void send_digit_to_chan(struct chan_list *cl, char digit )
00434 {
00435 static const char* dtmf_tones[] = {
00436 "!941+1336/100,!0/100",
00437 "!697+1209/100,!0/100",
00438 "!697+1336/100,!0/100",
00439 "!697+1477/100,!0/100",
00440 "!770+1209/100,!0/100",
00441 "!770+1336/100,!0/100",
00442 "!770+1477/100,!0/100",
00443 "!852+1209/100,!0/100",
00444 "!852+1336/100,!0/100",
00445 "!852+1477/100,!0/100",
00446 "!697+1633/100,!0/100",
00447 "!770+1633/100,!0/100",
00448 "!852+1633/100,!0/100",
00449 "!941+1633/100,!0/100",
00450 "!941+1209/100,!0/100",
00451 "!941+1477/100,!0/100" };
00452 struct ast_channel *chan=cl->ast;
00453
00454 if (digit >= '0' && digit <='9')
00455 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00456 else if (digit >= 'A' && digit <= 'D')
00457 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00458 else if (digit == '*')
00459 ast_playtones_start(chan,0,dtmf_tones[14], 0);
00460 else if (digit == '#')
00461 ast_playtones_start(chan,0,dtmf_tones[15], 0);
00462 else {
00463
00464 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00465
00466
00467 }
00468 }
00469
00470 static int misdn_set_debug(int fd, int argc, char *argv[])
00471 {
00472 if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
00473 return RESULT_SHOWUSAGE;
00474
00475 int level = atoi(argv[3]);
00476
00477 switch (argc) {
00478 case 4:
00479 case 5: {
00480 int only = 0;
00481 if (argc == 5) {
00482 if (strncasecmp(argv[4], "only", strlen(argv[4])))
00483 return RESULT_SHOWUSAGE;
00484 else
00485 only = 1;
00486 }
00487 int i;
00488 for (i=0; i<=max_ports; i++) {
00489 misdn_debug[i] = level;
00490 misdn_debug_only[i] = only;
00491 }
00492 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00493 }
00494 break;
00495 case 6:
00496 case 7: {
00497 if (strncasecmp(argv[4], "port", strlen(argv[4])))
00498 return RESULT_SHOWUSAGE;
00499 int port = atoi(argv[5]);
00500 if (port <= 0 || port > max_ports) {
00501 switch (max_ports) {
00502 case 0:
00503 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00504 break;
00505 case 1:
00506 ast_cli(fd, "port number not valid! only port 1 is availble.\n");
00507 break;
00508 default:
00509 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00510 }
00511 return 0;
00512 }
00513 if (argc == 7) {
00514 if (strncasecmp(argv[6], "only", strlen(argv[6])))
00515 return RESULT_SHOWUSAGE;
00516 else
00517 misdn_debug_only[port] = 1;
00518 } else
00519 misdn_debug_only[port] = 0;
00520 misdn_debug[port] = level;
00521 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
00522 }
00523 }
00524 return 0;
00525 }
00526
00527 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
00528 {
00529 if (argc != 5) return RESULT_SHOWUSAGE;
00530
00531 return 0;
00532 }
00533
00534
00535 static int misdn_port_block(int fd, int argc, char *argv[])
00536 {
00537 int port;
00538
00539 if (argc != 4)
00540 return RESULT_SHOWUSAGE;
00541
00542 port = atoi(argv[3]);
00543
00544 misdn_lib_port_block(port);
00545
00546 return 0;
00547 }
00548
00549 static int misdn_port_unblock(int fd, int argc, char *argv[])
00550 {
00551 int port;
00552
00553 if (argc != 4)
00554 return RESULT_SHOWUSAGE;
00555
00556 port = atoi(argv[3]);
00557
00558 misdn_lib_port_unblock(port);
00559
00560 return 0;
00561 }
00562
00563
00564 static int misdn_restart_port (int fd, int argc, char *argv[])
00565 {
00566 int port;
00567
00568 if (argc != 4)
00569 return RESULT_SHOWUSAGE;
00570
00571 port = atoi(argv[3]);
00572
00573 misdn_lib_port_restart(port);
00574
00575 return 0;
00576 }
00577
00578 static int misdn_port_up (int fd, int argc, char *argv[])
00579 {
00580 int port;
00581
00582 if (argc != 4)
00583 return RESULT_SHOWUSAGE;
00584
00585 port = atoi(argv[3]);
00586
00587 misdn_lib_get_port_up(port);
00588
00589 return 0;
00590 }
00591
00592 static int misdn_port_down (int fd, int argc, char *argv[])
00593 {
00594 int port;
00595
00596 if (argc != 4)
00597 return RESULT_SHOWUSAGE;
00598
00599 port = atoi(argv[3]);
00600
00601 misdn_lib_get_port_down(port);
00602
00603 return 0;
00604 }
00605
00606
00607 static int misdn_show_config (int fd, int argc, char *argv[])
00608 {
00609 char buffer[BUFFERSIZE];
00610 enum misdn_cfg_elements elem;
00611 int linebreak;
00612
00613 int onlyport = -1;
00614 if (argc >= 4) {
00615 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
00616 ast_cli(fd, "Unknown option: %s\n", argv[3]);
00617 return RESULT_SHOWUSAGE;
00618 }
00619 }
00620
00621 if (argc == 3 || onlyport == 0) {
00622 ast_cli(fd,"Misdn General-Config: \n");
00623 ast_cli(fd," -> Version: chan_misdn-" CHAN_MISDN_VERSION "\n");
00624 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
00625 misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
00626 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00627 }
00628 ast_cli(fd, "\n");
00629 }
00630
00631 if (onlyport < 0) {
00632 int port = misdn_cfg_get_next_port(0);
00633 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
00634 ast_cli(fd, "\n[PORT %d]\n", port);
00635 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00636 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
00637 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00638 }
00639 ast_cli(fd, "\n");
00640 }
00641 }
00642
00643 if (onlyport > 0) {
00644 if (misdn_cfg_is_port_valid(onlyport)) {
00645 ast_cli(fd, "[PORT %d]\n", onlyport);
00646 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00647 misdn_cfg_get_config_string( onlyport, elem, buffer, BUFFERSIZE);
00648 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00649 }
00650 ast_cli(fd, "\n");
00651 } else {
00652 ast_cli(fd, "Port %d is not active!\n", onlyport);
00653 }
00654 }
00655 return 0;
00656 }
00657
00658 struct state_struct {
00659 enum misdn_chan_state state;
00660 char txt[255] ;
00661 } ;
00662
00663 static struct state_struct state_array[] = {
00664 {MISDN_NOTHING,"NOTHING"},
00665 {MISDN_WAITING4DIGS,"WAITING4DIGS"},
00666 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"},
00667 {MISDN_DIALING,"DIALING"},
00668 {MISDN_PROGRESS,"PROGRESS"},
00669 {MISDN_PROCEEDING,"PROCEEDING"},
00670 {MISDN_CALLING,"CALLING"},
00671 {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"},
00672 {MISDN_ALERTING,"ALERTING"},
00673 {MISDN_BUSY,"BUSY"},
00674 {MISDN_CONNECTED,"CONNECTED"},
00675 {MISDN_PRECONNECTED,"PRECONNECTED"},
00676 {MISDN_DISCONNECTED,"DISCONNECTED"},
00677 {MISDN_RELEASED,"RELEASED"},
00678 {MISDN_BRIDGED,"BRIDGED"},
00679 {MISDN_CLEANING,"CLEANING"},
00680 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"},
00681 {MISDN_HOLDED,"HOLDED"},
00682 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"},
00683 {MISDN_FIXUP,"FIXUP"},
00684 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"}
00685
00686 };
00687
00688 static char *misdn_get_ch_state(struct chan_list *p)
00689 {
00690 int i;
00691 static char state[8];
00692
00693 if( !p) return NULL;
00694
00695 for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
00696 if ( state_array[i].state == p->state) return state_array[i].txt;
00697 }
00698
00699 sprintf(state,"%d",p->state) ;
00700
00701 return state;
00702 }
00703
00704
00705
00706 static void reload_config(void)
00707 {
00708 int i, cfg_debug;
00709
00710 free_robin_list();
00711 misdn_cfg_reload();
00712 misdn_cfg_update_ptp();
00713 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
00714 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
00715
00716 for (i = 0; i <= max_ports; i++) {
00717 misdn_debug[i] = cfg_debug;
00718 misdn_debug_only[i] = 0;
00719 }
00720 }
00721
00722 static int misdn_reload (int fd, int argc, char *argv[])
00723 {
00724 ast_cli(fd, "Reloading mISDN Config\n");
00725 reload_config();
00726 return 0;
00727 }
00728
00729 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
00730 {
00731 struct ast_channel *ast=help->ast;
00732 ast_cli(fd,
00733 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n",
00734
00735 bc->pid, bc->port, bc->channel,
00736 bc->nt?"NT":"TE",
00737 help->orginator == ORG_AST?"*":"I",
00738 ast?ast->exten:NULL,
00739 ast?AST_CID_P(ast):NULL,
00740 bc->rad,
00741 ast?ast->context:NULL,
00742 misdn_get_ch_state(help)
00743 );
00744 if (misdn_debug[bc->port] > 0)
00745 ast_cli(fd,
00746 " --> astname: %s\n"
00747 " --> ch_l3id: %x\n"
00748 " --> ch_addr: %x\n"
00749 " --> bc_addr: %x\n"
00750 " --> bc_l3id: %x\n"
00751 " --> display: %s\n"
00752 " --> activated: %d\n"
00753 " --> state: %s\n"
00754 " --> capability: %s\n"
00755 " --> echo_cancel: %d\n"
00756 " --> notone : rx %d tx:%d\n"
00757 " --> bc_hold: %d\n",
00758 help->ast->name,
00759 help->l3id,
00760 help->addr,
00761 bc->addr,
00762 bc?bc->l3_id:-1,
00763 bc->display,
00764
00765 bc->active,
00766 bc_state2str(bc->bc_state),
00767 bearer2str(bc->capability),
00768 bc->ec_enable,
00769
00770 help->norxtone,help->notxtone,
00771 bc->holded
00772 );
00773
00774 }
00775
00776 static int misdn_show_cls (int fd, int argc, char *argv[])
00777 {
00778 struct chan_list *help=cl_te;
00779
00780 ast_cli(fd,"Chan List: %p\n",cl_te);
00781
00782 for (;help; help=help->next) {
00783 struct misdn_bchannel *bc=help->bc;
00784 struct ast_channel *ast=help->ast;
00785 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
00786 if (bc) {
00787 print_bc_info(fd, help, bc);
00788 } else {
00789 if (help->state == MISDN_HOLDED) {
00790 chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
00791 chan_misdn_log(0,0," --> l3_id: %x\n"
00792 " --> dad:%s oad:%s\n"
00793
00794 ,help->l3id
00795 ,ast->exten
00796 ,AST_CID_P(ast)
00797 );
00798 } else {
00799 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
00800 }
00801 }
00802 }
00803
00804
00805 return 0;
00806 }
00807
00808 static int misdn_show_cl (int fd, int argc, char *argv[])
00809 {
00810 struct chan_list *help=cl_te;
00811
00812 if (argc != 4)
00813 return RESULT_SHOWUSAGE;
00814
00815 for (;help; help=help->next) {
00816 struct misdn_bchannel *bc=help->bc;
00817 struct ast_channel *ast=help->ast;
00818
00819 if (bc && ast) {
00820 if (!strcasecmp(ast->name,argv[3])) {
00821 print_bc_info(fd, help, bc);
00822 break;
00823 }
00824 }
00825 }
00826
00827
00828 return 0;
00829 }
00830
00831 ast_mutex_t lock;
00832 int MAXTICS=8;
00833
00834 static int misdn_set_tics (int fd, int argc, char *argv[])
00835 {
00836 if (argc != 4)
00837 return RESULT_SHOWUSAGE;
00838
00839 MAXTICS=atoi(argv[3]);
00840
00841 return 0;
00842 }
00843
00844 static int misdn_show_stacks (int fd, int argc, char *argv[])
00845 {
00846 int port;
00847
00848 ast_cli(fd, "BEGIN STACK_LIST:\n");
00849
00850 for (port=misdn_cfg_get_next_port(0); port > 0;
00851 port=misdn_cfg_get_next_port(port)) {
00852 char buf[128];
00853 get_show_stack_details(port,buf);
00854 ast_cli(fd," %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00855 }
00856
00857
00858 return 0;
00859
00860 }
00861
00862 static int misdn_show_port (int fd, int argc, char *argv[])
00863 {
00864 int port;
00865
00866 if (argc != 4)
00867 return RESULT_SHOWUSAGE;
00868
00869 port = atoi(argv[3]);
00870
00871 ast_cli(fd, "BEGIN STACK_LIST:\n");
00872
00873 char buf[128];
00874 get_show_stack_details(port,buf);
00875 ast_cli(fd," %s Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00876
00877
00878 return 0;
00879 }
00880
00881 static int misdn_send_cd (int fd, int argc, char *argv[])
00882 {
00883 char *channame;
00884 char *nr;
00885
00886 if (argc != 5)
00887 return RESULT_SHOWUSAGE;
00888
00889 channame = argv[3];
00890 nr = argv[4];
00891
00892 ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
00893
00894 {
00895 struct chan_list *tmp=get_chan_by_ast_name(channame);
00896
00897 if (!tmp) {
00898 ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
00899 return 0;
00900 } else {
00901
00902 misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
00903 }
00904 }
00905
00906 return 0;
00907 }
00908
00909 static int misdn_send_digit (int fd, int argc, char *argv[])
00910 {
00911 char *channame;
00912 char *msg;
00913
00914 if (argc != 5)
00915 return RESULT_SHOWUSAGE;
00916
00917 channame = argv[3];
00918 msg = argv[4];
00919
00920 ast_cli(fd, "Sending %s to %s\n",msg, channame);
00921
00922 {
00923 struct chan_list *tmp=get_chan_by_ast_name(channame);
00924
00925 if (!tmp) {
00926 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
00927 return 0;
00928 } else {
00929 #if 1
00930 int i;
00931 int msglen = strlen(msg);
00932 for (i=0; i<msglen; i++) {
00933 ast_cli(fd, "Sending: %c\n",msg[i]);
00934 send_digit_to_chan(tmp, msg[i]);
00935
00936 usleep(250000);
00937
00938 }
00939 #else
00940 int res;
00941 res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
00942 #endif
00943 }
00944 }
00945
00946 return 0;
00947 }
00948
00949 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
00950 {
00951 char *channame;
00952
00953 if (argc != 4)
00954 return RESULT_SHOWUSAGE;
00955
00956 channame = argv[3];
00957
00958 ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
00959
00960 {
00961 struct chan_list *tmp=get_chan_by_ast_name(channame);
00962
00963 if (!tmp) {
00964 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
00965 return 0;
00966 } else {
00967
00968 tmp->toggle_ec=tmp->toggle_ec?0:1;
00969
00970 if (tmp->toggle_ec) {
00971 update_ec_config(tmp->bc);
00972 manager_ec_enable(tmp->bc);
00973 } else {
00974 manager_ec_disable(tmp->bc);
00975 }
00976 }
00977 }
00978
00979 return 0;
00980 }
00981
00982 static int misdn_send_display (int fd, int argc, char *argv[])
00983 {
00984 char *channame;
00985 char *msg;
00986
00987 if (argc != 5)
00988 return RESULT_SHOWUSAGE;
00989
00990 channame = argv[3];
00991 msg = argv[4];
00992
00993 ast_cli(fd, "Sending %s to %s\n",msg, channame);
00994 {
00995 struct chan_list *tmp;
00996 tmp=get_chan_by_ast_name(channame);
00997
00998 if (tmp && tmp->bc) {
00999 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
01000 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
01001 } else {
01002 ast_cli(fd,"No such channel %s\n",channame);
01003 return RESULT_FAILURE;
01004 }
01005 }
01006
01007 return RESULT_SUCCESS ;
01008 }
01009
01010 static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
01011 {
01012 struct ast_channel *c;
01013 int which=0;
01014 char *ret;
01015 if (pos != rpos)
01016 return NULL;
01017 c = ast_channel_walk_locked(NULL);
01018 while(c) {
01019 if (!strncasecmp(word, c->name, strlen(word))) {
01020 if (++which > state)
01021 break;
01022 }
01023 ast_mutex_unlock(&c->lock);
01024 c = ast_channel_walk_locked(c);
01025 }
01026 if (c) {
01027 ret = strdup(c->name);
01028 ast_mutex_unlock(&c->lock);
01029 } else
01030 ret = NULL;
01031 return ret;
01032 }
01033
01034 static char *complete_ch(char *line, char *word, int pos, int state)
01035 {
01036 return complete_ch_helper(line, word, pos, state, 3);
01037 }
01038
01039 static char *complete_debug_port (char *line, char *word, int pos, int state)
01040 {
01041 if (state)
01042 return NULL;
01043
01044 switch (pos) {
01045 case 4: if (*word == 'p')
01046 return strdup("port");
01047 else if (*word == 'o')
01048 return strdup("only");
01049 break;
01050 case 6: if (*word == 'o')
01051 return strdup("only");
01052 break;
01053 }
01054 return NULL;
01055 }
01056
01057 static struct ast_cli_entry cli_send_cd =
01058 { {"misdn","send","calldeflect", NULL},
01059 misdn_send_cd,
01060 "Sends CallDeflection to mISDN Channel",
01061 "Usage: misdn send calldeflect <channel> \"<nr>\" \n",
01062 complete_ch
01063 };
01064
01065 static struct ast_cli_entry cli_send_digit =
01066 { {"misdn","send","digit", NULL},
01067 misdn_send_digit,
01068 "Sends DTMF Digit to mISDN Channel",
01069 "Usage: misdn send digit <channel> \"<msg>\" \n"
01070 " Send <digit> to <channel> as DTMF Tone\n"
01071 " when channel is a mISDN channel\n",
01072 complete_ch
01073 };
01074
01075 static struct ast_cli_entry cli_toggle_echocancel =
01076 { {"misdn","toggle","echocancel", NULL},
01077 misdn_toggle_echocancel,
01078 "Toggles EchoCancel on mISDN Channel",
01079 "Usage: misdn toggle echocancel <channel>\n",
01080 complete_ch
01081 };
01082
01083 static struct ast_cli_entry cli_send_display =
01084 { {"misdn","send","display", NULL},
01085 misdn_send_display,
01086 "Sends Text to mISDN Channel",
01087 "Usage: misdn send display <channel> \"<msg>\" \n"
01088 " Send <msg> to <channel> as Display Message\n"
01089 " when channel is a mISDN channel\n",
01090 complete_ch
01091 };
01092
01093 static struct ast_cli_entry cli_show_config =
01094 { {"misdn","show","config", NULL},
01095 misdn_show_config,
01096 "Shows internal mISDN config, read from cfg-file",
01097 "Usage: misdn show config [port | 0]\n use 0 to only print the general config.\n"
01098 };
01099
01100 static struct ast_cli_entry cli_reload =
01101 { {"misdn","reload", NULL},
01102 misdn_reload,
01103 "Reloads internal mISDN config, read from cfg-file",
01104 "Usage: misdn reload\n"
01105 };
01106
01107 static struct ast_cli_entry cli_set_tics =
01108 { {"misdn","set","tics", NULL},
01109 misdn_set_tics,
01110 "",
01111 "\n"
01112 };
01113
01114 static struct ast_cli_entry cli_show_cls =
01115 { {"misdn","show","channels", NULL},
01116 misdn_show_cls,
01117 "Shows internal mISDN chan_list",
01118 "Usage: misdn show channels\n"
01119 };
01120
01121 static struct ast_cli_entry cli_show_cl =
01122 { {"misdn","show","channel", NULL},
01123 misdn_show_cl,
01124 "Shows internal mISDN chan_list",
01125 "Usage: misdn show channels\n",
01126 complete_ch
01127 };
01128
01129 static struct ast_cli_entry cli_port_block=
01130 { {"misdn","port","block", NULL},
01131 misdn_port_block,
01132 "Blocks the given port",
01133 "Usage: misdn port block\n"
01134 };
01135
01136 static struct ast_cli_entry cli_port_unblock=
01137 { {"misdn","port","unblock", NULL},
01138 misdn_port_unblock,
01139 "Unblocks the given port",
01140 "Usage: misdn port unblock\n"
01141 };
01142
01143
01144 static struct ast_cli_entry cli_restart_port =
01145 { {"misdn","restart","port", NULL},
01146 misdn_restart_port,
01147 "Restarts the given port",
01148 "Usage: misdn restart port\n"
01149 };
01150
01151 static struct ast_cli_entry cli_port_up =
01152 { {"misdn","port","up", NULL},
01153 misdn_port_up,
01154 "Tries to establish L1 on the given port",
01155 "Usage: misdn port up <port>\n"
01156 };
01157
01158 static struct ast_cli_entry cli_port_down =
01159 { {"misdn","port","down", NULL},
01160 misdn_port_down,
01161 "Tries to deacivate the L1 on the given port",
01162 "Usage: misdn port down <port>\n"
01163 };
01164
01165
01166
01167 static struct ast_cli_entry cli_show_stacks =
01168 { {"misdn","show","stacks", NULL},
01169 misdn_show_stacks,
01170 "Shows internal mISDN stack_list",
01171 "Usage: misdn show stacks\n"
01172 };
01173
01174 static struct ast_cli_entry cli_show_port =
01175 { {"misdn","show","port", NULL},
01176 misdn_show_port,
01177 "Shows detailed information for given port",
01178 "Usage: misdn show port <port>\n"
01179 };
01180
01181 static struct ast_cli_entry cli_set_debug =
01182 { {"misdn","set","debug", NULL},
01183 misdn_set_debug,
01184 "Sets Debuglevel of chan_misdn",
01185 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n",
01186 complete_debug_port
01187 };
01188
01189 static struct ast_cli_entry cli_set_crypt_debug =
01190 { {"misdn","set","crypt","debug", NULL},
01191 misdn_set_crypt_debug,
01192 "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}",
01193 "Usage: misdn set crypt debug <level>\n"
01194 };
01195
01196
01197
01198 static int update_config (struct chan_list *ch, int orig)
01199 {
01200 if (!ch) {
01201 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01202 return -1;
01203 }
01204
01205 struct ast_channel *ast=ch->ast;
01206 struct misdn_bchannel *bc=ch->bc;
01207 if (! ast || ! bc ) {
01208 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01209 return -1;
01210 }
01211
01212 int port=bc->port;
01213
01214 chan_misdn_log(1,port,"update_config: Getting Config\n");
01215
01216
01217 int hdlc=0;
01218 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01219
01220 if (hdlc) {
01221 switch (bc->capability) {
01222 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01223 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01224 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
01225 bc->hdlc=1;
01226 break;
01227 }
01228
01229 }
01230
01231
01232 int pres, screen;
01233
01234 misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
01235 misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int));
01236 chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen);
01237
01238 if ( (pres + screen) < 0 ) {
01239
01240 chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres);
01241
01242 switch (ast->cid.cid_pres & 0x60){
01243
01244 case AST_PRES_RESTRICTED:
01245 bc->pres=1;
01246 chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
01247 break;
01248
01249
01250 case AST_PRES_UNAVAILABLE:
01251 bc->pres=2;
01252 chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
01253 break;
01254
01255 default:
01256 bc->pres=0;
01257 chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
01258 }
01259
01260 switch (ast->cid.cid_pres & 0x3){
01261
01262 case AST_PRES_USER_NUMBER_UNSCREENED:
01263 bc->screen=0;
01264 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01265 break;
01266
01267 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
01268 bc->screen=1;
01269 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
01270 break;
01271 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
01272 bc->screen=2;
01273 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
01274 break;
01275
01276 case AST_PRES_NETWORK_NUMBER:
01277 bc->screen=3;
01278 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
01279 break;
01280
01281 default:
01282 bc->screen=0;
01283 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01284 }
01285
01286
01287 } else {
01288 bc->screen=screen;
01289 bc->pres=pres;
01290 }
01291
01292 return 0;
01293
01294 }
01295
01296
01297
01298
01299 void config_jitterbuffer(struct chan_list *ch)
01300 {
01301 struct misdn_bchannel *bc=ch->bc;
01302 int len=ch->jb_len, threshold=ch->jb_upper_threshold;
01303
01304 chan_misdn_log(5,bc->port, "config_jb: Called\n");
01305
01306 if ( ! len ) {
01307 chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n");
01308 bc->nojitter=1;
01309 } else {
01310
01311 if (len <=100 || len > 8000) {
01312 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
01313 len=1000;
01314 }
01315
01316 if ( threshold > len ) {
01317 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
01318 }
01319
01320 if ( ch->jb) {
01321 cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n");
01322 misdn_jb_destroy(ch->jb);
01323 ch->jb=NULL;
01324 }
01325
01326 ch->jb=misdn_jb_init(len, threshold);
01327
01328 if (!ch->jb )
01329 bc->nojitter=1;
01330 }
01331 }
01332
01333
01334 void debug_numplan(int port, int numplan, char *type)
01335 {
01336 switch (numplan) {
01337 case NUMPLAN_INTERNATIONAL:
01338 chan_misdn_log(2, port, " --> %s: International\n",type);
01339 break;
01340 case NUMPLAN_NATIONAL:
01341 chan_misdn_log(2, port, " --> %s: National\n",type);
01342 break;
01343 case NUMPLAN_SUBSCRIBER:
01344 chan_misdn_log(2, port, " --> %s: Subscriber\n",type);
01345 break;
01346 case NUMPLAN_UNKNOWN:
01347 chan_misdn_log(2, port, " --> %s: Unknown\n",type);
01348 break;
01349
01350 default:
01351 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01352 break;
01353 }
01354 }
01355
01356
01357
01358
01359 static int update_ec_config(struct misdn_bchannel *bc)
01360 {
01361 int ec;
01362 int port=bc->port;
01363
01364 misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
01365
01366 if (ec == 1 ) {
01367 bc->ec_enable=1;
01368 } else if ( ec > 1 ) {
01369 bc->ec_enable=1;
01370 bc->ec_deftaps=ec;
01371 }
01372
01373 return 0;
01374 }
01375
01376
01377 static int read_config(struct chan_list *ch, int orig) {
01378
01379 if (!ch) {
01380 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
01381 return -1;
01382 }
01383
01384 struct ast_channel *ast=ch->ast;
01385 struct misdn_bchannel *bc=ch->bc;
01386 if (! ast || ! bc ) {
01387 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
01388 return -1;
01389 }
01390
01391 int port=bc->port;
01392
01393 chan_misdn_log(5,port,"read_config: Getting Config\n");
01394
01395 char lang[BUFFERSIZE+1];
01396
01397 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE);
01398 ast_copy_string(ast->language, lang, sizeof(ast->language));
01399
01400 char musicclass[BUFFERSIZE+1];
01401
01402 misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, musicclass, BUFFERSIZE);
01403 ast_copy_string(ast->musicclass, musicclass, sizeof(ast->musicclass));
01404
01405 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int));
01406 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int));
01407
01408 misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int));
01409
01410 misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int));
01411
01412 misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int));
01413
01414 misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int));
01415
01416 misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE);
01417
01418
01419 int hdlc=0;
01420 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
01421
01422 if (hdlc) {
01423 switch (bc->capability) {
01424 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
01425 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
01426 chan_misdn_log(1,bc->port," --> CONF HDLC\n");
01427 bc->hdlc=1;
01428 break;
01429 }
01430
01431 }
01432
01433 {
01434 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int));
01435 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int));
01436
01437 config_jitterbuffer(ch);
01438 }
01439
01440 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
01441
01442 ast_copy_string (ast->context,ch->context,sizeof(ast->context));
01443
01444 update_ec_config(bc);
01445
01446 {
01447 int eb3;
01448
01449 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
01450 bc->early_bconnect=eb3;
01451 }
01452
01453 port=bc->port;
01454
01455 {
01456 char buf[256];
01457 ast_group_t pg,cg;
01458
01459 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
01460 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
01461
01462 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
01463 ast->pickupgroup=pg;
01464 ast->callgroup=cg;
01465 }
01466
01467 if ( orig == ORG_AST) {
01468 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int));
01469
01470 {
01471 char callerid[BUFFERSIZE+1];
01472 misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
01473 if ( ! ast_strlen_zero(callerid) ) {
01474 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
01475 {
01476 int l = sizeof(bc->oad);
01477 strncpy(bc->oad,callerid, l);
01478 bc->oad[l-1] = 0;
01479 }
01480
01481 }
01482
01483
01484 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int));
01485 misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int));
01486 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
01487 debug_numplan(port, bc->dnumplan,"TON");
01488 debug_numplan(port, bc->onumplan,"LTON");
01489 debug_numplan(port, bc->cpnnumplan,"CTON");
01490 }
01491
01492
01493
01494 } else {
01495
01496 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int));
01497 debug_numplan(port, bc->cpnnumplan,"CTON");
01498
01499 char prefix[BUFFERSIZE+1]="";
01500 switch( bc->onumplan ) {
01501 case NUMPLAN_INTERNATIONAL:
01502 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
01503 break;
01504
01505 case NUMPLAN_NATIONAL:
01506 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
01507 break;
01508 default:
01509 break;
01510 }
01511
01512 {
01513 int l = strlen(prefix) + strlen(bc->oad);
01514 char tmp[l+1];
01515 strcpy(tmp,prefix);
01516 strcat(tmp,bc->oad);
01517 strcpy(bc->oad,tmp);
01518 }
01519
01520 if (!ast_strlen_zero(bc->dad)) {
01521 ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
01522 }
01523
01524 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
01525 ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad));
01526 }
01527
01528 prefix[0] = 0;
01529
01530 switch( bc->dnumplan ) {
01531 case NUMPLAN_INTERNATIONAL:
01532 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
01533 break;
01534 case NUMPLAN_NATIONAL:
01535 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
01536 break;
01537 default:
01538 break;
01539 }
01540
01541 {
01542 int l = strlen(prefix) + strlen(bc->dad);
01543 char tmp[l+1];
01544 strcpy(tmp,prefix);
01545 strcat(tmp,bc->dad);
01546 strcpy(bc->dad,tmp);
01547 }
01548
01549 if ( strcmp(bc->dad,ast->exten)) {
01550 ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten));
01551 }
01552
01553 ast_set_callerid(ast, bc->oad, NULL, bc->oad);
01554
01555 if ( !ast_strlen_zero(bc->rad) )
01556 ast->cid.cid_rdnis=strdup(bc->rad);
01557
01558 }
01559
01560 return 0;
01561 }
01562
01563
01564
01565
01566
01567
01568 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
01569 {
01570 int port=0;
01571 int r;
01572 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01573 struct misdn_bchannel *newbc;
01574 char *opts=NULL, *ext,*tokb;
01575 char dest_cp[256];
01576
01577 {
01578 strncpy(dest_cp,dest,sizeof(dest_cp)-1);
01579 dest_cp[sizeof(dest_cp)]=0;
01580
01581 ext=strtok_r(dest_cp,"/",&tokb);
01582
01583 if (ext) {
01584 ext=strtok_r(NULL,"/",&tokb);
01585 if (ext) {
01586 opts=strtok_r(NULL,"/",&tokb);
01587 } else {
01588 chan_misdn_log(0,0,"misdn_call: No Extension given!\n");
01589 return -1;
01590 }
01591 }
01592 }
01593
01594 if (!ast) {
01595 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
01596 return -1;
01597 }
01598
01599 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) {
01600 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01601 ast->hangupcause=41;
01602 ast_setstate(ast, AST_STATE_DOWN);
01603 return -1;
01604 }
01605
01606 if (!ch) {
01607 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01608 ast->hangupcause=41;
01609 ast_setstate(ast, AST_STATE_DOWN);
01610 return -1;
01611 }
01612
01613 newbc=ch->bc;
01614
01615 if (!newbc) {
01616 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01617 ast->hangupcause=41;
01618 ast_setstate(ast, AST_STATE_DOWN);
01619 return -1;
01620 }
01621
01622 port=newbc->port;
01623 strncpy(newbc->dad,ext,sizeof( newbc->dad));
01624 strncpy(ast->exten,ext,sizeof(ast->exten));
01625
01626 chan_misdn_log(1, port, "* CALL: %s\n",dest);
01627
01628 chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
01629
01630 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
01631 if (ast->exten) {
01632 int l = sizeof(newbc->dad);
01633 strncpy(newbc->dad,ast->exten, l);
01634 newbc->dad[l-1] = 0;
01635 }
01636 newbc->rad[0]=0;
01637 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
01638 if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
01639
01640 if (AST_CID_P(ast)) {
01641 int l = sizeof(newbc->oad);
01642 strncpy(newbc->oad,AST_CID_P(ast), l);
01643 newbc->oad[l-1] = 0;
01644 }
01645 }
01646
01647 {
01648 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01649 if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;}
01650
01651 newbc->capability=ast->transfercapability;
01652 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
01653 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
01654 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
01655 }
01656
01657
01658
01659 update_config(ch,ORG_AST);
01660
01661
01662 import_ch(ast, newbc, ch);
01663
01664
01665 if (opts)
01666 misdn_set_opt_exec(ast,opts);
01667 else
01668 chan_misdn_log(2,port,"NO OPTS GIVEN\n");
01669
01670 r=misdn_lib_send_event( newbc, EVENT_SETUP );
01671
01672
01673 ch->l3id=newbc->l3_id;
01674 }
01675
01676 if ( r == -ENOCHAN ) {
01677 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
01678 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
01679 ast->hangupcause=34;
01680 ast_setstate(ast, AST_STATE_DOWN);
01681 return -1;
01682 }
01683
01684 chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
01685
01686 ast_setstate(ast, AST_STATE_DIALING);
01687 ast->hangupcause=16;
01688
01689 if (newbc->nt) stop_bc_tones(ch);
01690
01691 ch->state=MISDN_CALLING;
01692
01693 return 0;
01694 }
01695
01696
01697 static int misdn_answer(struct ast_channel *ast)
01698 {
01699 struct chan_list *p;
01700
01701
01702 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
01703
01704 chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
01705
01706 if (!p) {
01707 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
01708 ast_queue_hangup(ast);
01709 }
01710
01711 if (!p->bc) {
01712 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
01713
01714 ast_queue_hangup(ast);
01715 }
01716
01717 {
01718 const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
01719
01720 if (tmp_key ) {
01721 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
01722 {
01723 int l = sizeof(p->bc->crypt_key);
01724 strncpy(p->bc->crypt_key,tmp_key, l);
01725 p->bc->crypt_key[l-1] = 0;
01726 }
01727 } else {
01728 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
01729 }
01730
01731 }
01732
01733 {
01734 const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
01735 if (nodsp) {
01736 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
01737 p->bc->nodsp=1;
01738 p->bc->hdlc=0;
01739 p->bc->nojitter=1;
01740 }
01741 }
01742
01743 p->state = MISDN_CONNECTED;
01744 misdn_lib_echo(p->bc,0);
01745 stop_indicate(p);
01746
01747 if ( ast_strlen_zero(p->bc->cad) ) {
01748 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n");
01749 ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad));
01750 }
01751
01752 misdn_lib_send_event( p->bc, EVENT_CONNECT);
01753 start_bc_tones(p);
01754
01755 return 0;
01756 }
01757
01758 static int misdn_digit(struct ast_channel *ast, char digit )
01759 {
01760 struct chan_list *p;
01761
01762 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1;
01763
01764 struct misdn_bchannel *bc=p->bc;
01765 chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
01766
01767 if (!bc) {
01768 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
01769 return -1;
01770 }
01771
01772 switch (p->state ) {
01773 case MISDN_CALLING:
01774 {
01775
01776 char buf[8];
01777 buf[0]=digit;
01778 buf[1]=0;
01779
01780 int l = sizeof(bc->infos_pending);
01781 strncat(bc->infos_pending,buf,l);
01782 bc->infos_pending[l-1] = 0;
01783 }
01784 break;
01785 case MISDN_CALLING_ACKNOWLEDGE:
01786 {
01787 bc->info_dad[0]=digit;
01788 bc->info_dad[1]=0;
01789
01790 {
01791 int l = sizeof(bc->dad);
01792 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
01793 bc->dad[l-1] = 0;
01794 }
01795 {
01796 int l = sizeof(p->ast->exten);
01797 strncpy(p->ast->exten, bc->dad, l);
01798 p->ast->exten[l-1] = 0;
01799 }
01800
01801 misdn_lib_send_event( bc, EVENT_INFORMATION);
01802 }
01803 break;
01804
01805 default:
01806 if ( bc->send_dtmf ) {
01807 send_digit_to_chan(p,digit);
01808 }
01809 break;
01810 }
01811
01812 return 0;
01813 }
01814
01815
01816 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
01817 {
01818 struct chan_list *p;
01819
01820 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1;
01821
01822 chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
01823
01824 p->ast = ast ;
01825 p->state=MISDN_FIXUP;
01826
01827 return 0;
01828 }
01829
01830
01831
01832 static int misdn_indication(struct ast_channel *ast, int cond)
01833 {
01834 struct chan_list *p;
01835
01836
01837 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) {
01838 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
01839 return -1;
01840 }
01841
01842 if (!p->bc ) {
01843 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
01844 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
01845 return -1;
01846 }
01847
01848 chan_misdn_log(1, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten);
01849
01850 switch (cond) {
01851 case AST_CONTROL_BUSY:
01852 chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
01853 chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
01854 ast_setstate(ast,AST_STATE_BUSY);
01855
01856 p->bc->out_cause=17;
01857 if (p->state != MISDN_CONNECTED) {
01858 start_bc_tones(p);
01859 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01860 } else {
01861 chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name);
01862 }
01863 return -1;
01864 break;
01865 case AST_CONTROL_RING:
01866 chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
01867 return -1;
01868 break;
01869
01870 case AST_CONTROL_RINGING:
01871 switch (p->state) {
01872 case MISDN_ALERTING:
01873 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
01874 break;
01875 case MISDN_CONNECTED:
01876 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n",p->bc?p->bc->pid:-1);
01877 return -1;
01878 break;
01879 default:
01880 p->state=MISDN_ALERTING;
01881 chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
01882 misdn_lib_send_event( p->bc, EVENT_ALERTING);
01883
01884 if (p->other_ch && p->other_ch->bc) {
01885 if (misdn_inband_avail(p->other_ch->bc)) {
01886 chan_misdn_log(1,p->bc->port, " --> other End is mISDN and has inband info available\n");
01887 break;
01888 }
01889
01890 if (!p->other_ch->bc->nt) {
01891 chan_misdn_log(1,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
01892 break;
01893 }
01894 }
01895
01896 chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
01897 ast_setstate(ast,AST_STATE_RINGING);
01898
01899 if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio )
01900 chan_misdn_log(1,p->bc->port, " --> incoming_early_audio off\n");
01901 else
01902 return -1;
01903 }
01904 break;
01905 case AST_CONTROL_ANSWER:
01906 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
01907 start_bc_tones(p);
01908 break;
01909 case AST_CONTROL_TAKEOFFHOOK:
01910 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
01911 return -1;
01912 break;
01913 case AST_CONTROL_OFFHOOK:
01914 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
01915 return -1;
01916 break;
01917 case AST_CONTROL_FLASH:
01918 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
01919 break;
01920 case AST_CONTROL_PROGRESS:
01921 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
01922 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
01923 break;
01924 case AST_CONTROL_PROCEEDING:
01925 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1);
01926 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
01927 break;
01928 case AST_CONTROL_CONGESTION:
01929 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
01930
01931 p->bc->out_cause=42;
01932 if (p->state != MISDN_CONNECTED) {
01933 start_bc_tones(p);
01934 misdn_lib_send_event( p->bc, EVENT_RELEASE);
01935 } else {
01936 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01937 }
01938
01939 if (p->bc->nt) {
01940 hanguptone_indicate(p);
01941 }
01942 break;
01943 case -1 :
01944 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1);
01945
01946 stop_indicate(p);
01947
01948 if (p->state == MISDN_CONNECTED)
01949 start_bc_tones(p);
01950
01951 break;
01952
01953 case AST_CONTROL_HOLD:
01954 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01955 break;
01956 case AST_CONTROL_UNHOLD:
01957 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01958 break;
01959 default:
01960 ast_log(LOG_NOTICE, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
01961 }
01962
01963 return 0;
01964 }
01965
01966 static int misdn_hangup(struct ast_channel *ast)
01967 {
01968 struct chan_list *p;
01969 struct misdn_bchannel *bc=NULL;
01970
01971 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
01972
01973 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
01974
01975 if (!p) {
01976 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
01977 return 0 ;
01978 }
01979
01980 bc=p->bc;
01981
01982
01983
01984 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01985 p->ast=NULL;
01986
01987 bc=p->bc;
01988
01989 if (ast->_state == AST_STATE_RESERVED ||
01990 p->state == MISDN_NOTHING ||
01991 p->state == MISDN_HOLDED ||
01992 p->state == MISDN_FIXUP ||
01993 p->state == MISDN_HOLD_DISCONNECT ) {
01994
01995 CLEAN_CH:
01996
01997 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
01998 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01999
02000 cl_dequeue_chan(&cl_te, p);
02001
02002 close(p->pipe[0]);
02003 close(p->pipe[1]);
02004
02005 free(p);
02006 if (bc)
02007 misdn_lib_release(bc);
02008
02009 return 0;
02010 }
02011
02012 if (!bc) {
02013 ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02014 goto CLEAN_CH;
02015 }
02016
02017
02018 p->need_hangup=0;
02019 p->need_queue_hangup=0;
02020
02021
02022 if (!p->bc->nt)
02023 stop_bc_tones(p);
02024
02025
02026 {
02027 const char *varcause=NULL;
02028 bc->out_cause=ast->hangupcause?ast->hangupcause:16;
02029
02030 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02031 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02032 int tmpcause=atoi(varcause);
02033 bc->out_cause=tmpcause?tmpcause:16;
02034 }
02035
02036 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));
02037 chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
02038 chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
02039 chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
02040 chan_misdn_log(1, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02041
02042 switch (p->state) {
02043 case MISDN_CALLING:
02044 p->state=MISDN_CLEANING;
02045 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02046 break;
02047 case MISDN_HOLDED:
02048 case MISDN_DIALING:
02049 start_bc_tones(p);
02050 hanguptone_indicate(p);
02051
02052 if (bc->need_disconnect)
02053 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02054 break;
02055
02056 case MISDN_CALLING_ACKNOWLEDGE:
02057 start_bc_tones(p);
02058 hanguptone_indicate(p);
02059
02060 if (bc->need_disconnect)
02061 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02062 break;
02063
02064 case MISDN_ALERTING:
02065 case MISDN_PROGRESS:
02066 case MISDN_PROCEEDING:
02067 if (p->orginator != ORG_AST)
02068 hanguptone_indicate(p);
02069
02070
02071 if (bc->need_disconnect)
02072 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02073 break;
02074 case MISDN_CONNECTED:
02075 case MISDN_PRECONNECTED:
02076
02077 if (p->bc->nt) {
02078 start_bc_tones(p);
02079 hanguptone_indicate(p);
02080 p->bc->progress_indicator=8;
02081 }
02082 if (bc->need_disconnect)
02083 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02084
02085
02086 break;
02087 case MISDN_DISCONNECTED:
02088 misdn_lib_send_event( bc, EVENT_RELEASE);
02089 p->state=MISDN_CLEANING;
02090 break;
02091
02092 case MISDN_RELEASED:
02093 case MISDN_CLEANING:
02094 p->state=MISDN_CLEANING;
02095 break;
02096
02097 case MISDN_BUSY:
02098 break;
02099
02100 case MISDN_HOLD_DISCONNECT:
02101
02102 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
02103 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
02104
02105 bc->out_cause=-1;
02106 misdn_lib_send_event(bc,EVENT_RELEASE);
02107 p->state=MISDN_CLEANING;
02108 break;
02109 default:
02110 if (bc->nt) {
02111 bc->out_cause=-1;
02112 misdn_lib_send_event(bc, EVENT_RELEASE);
02113 p->state=MISDN_CLEANING;
02114 } else {
02115 if (bc->need_disconnect)
02116 misdn_lib_send_event(bc, EVENT_DISCONNECT);
02117 }
02118 }
02119
02120 p->state=MISDN_CLEANING;
02121
02122 }
02123
02124
02125 chan_misdn_log(1, bc->port, "Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
02126
02127 return 0;
02128 }
02129
02130 static struct ast_frame *misdn_read(struct ast_channel *ast)
02131 {
02132 struct chan_list *tmp;
02133 int len;
02134
02135 if (!ast) {
02136 chan_misdn_log(1,0,"misdn_read called without ast\n");
02137 return NULL;
02138 }
02139 if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) {
02140 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
02141 return NULL;
02142 }
02143 if (!tmp->bc) {
02144 chan_misdn_log(1,0,"misdn_read called without bc\n");
02145 return NULL;
02146 }
02147
02148 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
02149
02150 if (len<=0) {
02151
02152 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
02153 return NULL;
02154 }
02155
02156 tmp->frame.frametype = AST_FRAME_VOICE;
02157 tmp->frame.subclass = AST_FORMAT_ALAW;
02158 tmp->frame.datalen = len;
02159 tmp->frame.samples = len ;
02160 tmp->frame.mallocd =0 ;
02161 tmp->frame.offset= 0 ;
02162 tmp->frame.delivery= ast_tv(0,0) ;
02163 tmp->frame.src = NULL;
02164 tmp->frame.data = tmp->ast_rd_buf ;
02165
02166 if (tmp->faxdetect || tmp->ast_dsp ) {
02167 return process_ast_dsp(tmp, &tmp->frame);
02168 }
02169
02170 return &tmp->frame;
02171 }
02172
02173
02174 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
02175 {
02176 struct chan_list *ch;
02177 int i = 0;
02178
02179 if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02180
02181 if (ch->state == MISDN_HOLDED) {
02182 chan_misdn_log(8, 0, "misdn_write: Returning because holded\n");
02183 return 0;
02184 }
02185
02186 if (!ch->bc ) {
02187
02188 ast_log(LOG_WARNING, "private but no bc\n");
02189 return -1;
02190 }
02191
02192 if (ch->notxtone) {
02193 chan_misdn_log(9, ch->bc->port, "misdn_write: Returning because notxone\n");
02194 return 0;
02195 }
02196
02197
02198 if ( !frame->subclass) {
02199 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
02200 return 0;
02201 }
02202
02203 if ( !(frame->subclass & prefformat)) {
02204
02205 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
02206 return 0;
02207 }
02208
02209
02210 if ( !frame->samples ) {
02211 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
02212 return 0;
02213 }
02214
02215 if ( ! ch->bc->addr ) {
02216 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
02217 return 0;
02218 }
02219
02220 #if MISDN_DEBUG
02221 {
02222 int i, max=5>frame->samples?frame->samples:5;
02223
02224 printf("write2mISDN %p %d bytes: ", p, frame->samples);
02225
02226 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
02227 printf ("\n");
02228 }
02229 #endif
02230
02231
02232 switch (ch->bc->bc_state) {
02233 case BCHAN_ACTIVATED:
02234 case BCHAN_BRIDGED:
02235 break;
02236 default:
02237 if (!ch->dropped_frame_cnt)
02238 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",frame->samples,ch->bc->addr, ast->exten, ast->cid.cid_num,misdn_get_ch_state( ch), ch->bc->bc_state, ch->bc->l3_id);
02239
02240 ch->dropped_frame_cnt++;
02241 if (ch->dropped_frame_cnt > 100) {
02242 ch->dropped_frame_cnt=0;
02243 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) droping: %d frames addr:%x dropped > 100 frames!\n",frame->samples,ch->bc->addr);
02244
02245 }
02246
02247 return 0;
02248 }
02249
02250 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
02251
02252 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
02253
02254 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
02255 if (ch->bc->active)
02256 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
02257 }
02258
02259 } else {
02260
02261 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
02262 }
02263
02264
02265
02266 return 0;
02267 }
02268
02269
02270
02271
02272 enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
02273 struct ast_channel *c1, int flags,
02274 struct ast_frame **fo,
02275 struct ast_channel **rc,
02276 int timeoutms)
02277
02278 {
02279 struct chan_list *ch1,*ch2;
02280 struct ast_channel *carr[2], *who;
02281 int to=-1;
02282 struct ast_frame *f;
02283
02284 ch1=get_chan_by_ast(c0);
02285 ch2=get_chan_by_ast(c1);
02286
02287 carr[0]=c0;
02288 carr[1]=c1;
02289
02290 if (ch1 && ch2 ) ;
02291 else
02292 return -1;
02293
02294
02295 int bridging;
02296 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02297 if (bridging) {
02298 int ec;
02299 misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
02300 if ( ec ) {
02301 chan_misdn_log(2, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
02302 ch1->bc->ec_enable=0;
02303 manager_ec_disable(ch1->bc);
02304 }
02305 misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
02306 if ( ec ) {
02307 chan_misdn_log(2, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
02308 ch2->bc->ec_enable=0;
02309 manager_ec_disable(ch2->bc);
02310 }
02311
02312 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
02313
02314 misdn_lib_bridge(ch1->bc,ch2->bc);
02315 }
02316
02317 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
02318
02319
02320 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
02321 ch1->ignore_dtmf=1;
02322
02323 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
02324 ch2->ignore_dtmf=1;
02325
02326
02327 while(1) {
02328 to=-1;
02329 who = ast_waitfor_n(carr, 2, &to);
02330
02331 if (!who) {
02332 ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
02333 break;
02334 }
02335 f = ast_read(who);
02336
02337 if (!f || f->frametype == AST_FRAME_CONTROL) {
02338
02339
02340 if (!f)
02341 chan_misdn_log(1,ch1->bc->port,"Read Null Frame\n");
02342 else
02343 chan_misdn_log(1,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
02344
02345 *fo=f;
02346 *rc=who;
02347
02348 break;
02349 }
02350
02351 if ( f->frametype == AST_FRAME_DTMF ) {
02352 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
02353
02354 *fo=f;
02355 *rc=who;
02356 break;
02357 }
02358
02359 if (f->frametype == AST_FRAME_VOICE) {
02360 chan_misdn_log(1,0,"Got Voice frame in Bridged state..\n");
02361 continue;
02362 }
02363
02364 if (who == c0) {
02365 ast_write(c1,f);
02366 }
02367 else {
02368 ast_write(c0,f);
02369 }
02370
02371 }
02372
02373 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
02374
02375 misdn_lib_split_bridge(ch1->bc,ch2->bc);
02376
02377
02378 return AST_BRIDGE_COMPLETE;
02379 }
02380
02381
02382
02383 static int dialtone_indicate(struct chan_list *cl)
02384 {
02385 const struct tone_zone_sound *ts= NULL;
02386 struct ast_channel *ast=cl->ast;
02387
02388
02389 int nd=0;
02390 misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
02391
02392 if (nd) {
02393 chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
02394 return 0;
02395 }
02396
02397 chan_misdn_log(3,cl->bc->port," --> Dial\n");
02398 ts=ast_get_indication_tone(ast->zone,"dial");
02399 cl->ts=ts;
02400
02401 if (ts) {
02402 cl->notxtone=0;
02403 cl->norxtone=0;
02404 ast_playtones_start(ast,0, ts->data, 0);
02405 chan_misdn_log(4,cl->bc->port,"Starting Playtones\n");
02406 misdn_lib_tone_generator_start(cl->bc);
02407 }
02408
02409 return 0;
02410 }
02411
02412 static int hanguptone_indicate(struct chan_list *cl)
02413 {
02414 misdn_lib_send_tone(cl->bc,TONE_HANGUP);
02415 return 0;
02416 }
02417
02418 static int stop_indicate(struct chan_list *cl)
02419 {
02420 struct ast_channel *ast=cl->ast;
02421 chan_misdn_log(3,cl->bc->port," --> None\n");
02422 misdn_lib_tone_generator_stop(cl->bc);
02423 ast_playtones_stop(ast);
02424
02425
02426 return 0;
02427 }
02428
02429
02430 static int start_bc_tones(struct chan_list* cl)
02431 {
02432 misdn_lib_tone_generator_stop(cl->bc);
02433 cl->notxtone=0;
02434 cl->norxtone=0;
02435 return 0;
02436 }
02437
02438 static int stop_bc_tones(struct chan_list *cl)
02439 {
02440 if (!cl) return -1;
02441
02442 cl->notxtone=1;
02443 cl->norxtone=1;
02444
02445 return 0;
02446 }
02447
02448
02449 static struct chan_list *init_chan_list(int orig)
02450 {
02451 struct chan_list *cl=malloc(sizeof(struct chan_list));
02452
02453 if (!cl) {
02454 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
02455 return NULL;
02456 }
02457
02458 memset(cl,0,sizeof(struct chan_list));
02459
02460 cl->orginator=orig;
02461 cl->need_queue_hangup=1;
02462 cl->need_hangup=1;
02463 cl->need_busy=1;
02464
02465 return cl;
02466
02467 }
02468
02469 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
02470
02471 {
02472 struct ast_channel *tmp = NULL;
02473 char group[BUFFERSIZE+1]="";
02474 char buf[128];
02475 char buf2[128], *ext=NULL, *port_str;
02476 char *tokb=NULL, *p=NULL;
02477 int channel=0, port=0;
02478 struct misdn_bchannel *newbc = NULL;
02479
02480 struct chan_list *cl=init_chan_list(ORG_AST);
02481
02482 sprintf(buf,"%s/%s",misdn_type,(char*)data);
02483 ast_copy_string(buf2,data, 128);
02484
02485 port_str=strtok_r(buf2,"/", &tokb);
02486
02487 ext=strtok_r(NULL,"/", &tokb);
02488
02489 if (port_str) {
02490 if (port_str[0]=='g' && port_str[1]==':' ) {
02491
02492 port_str += 2;
02493 strncpy(group, port_str, BUFFERSIZE);
02494 group[127] = 0;
02495 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
02496 }
02497 else if ((p = strchr(port_str, ':'))) {
02498
02499 *p = 0;
02500 channel = atoi(++p);
02501 port = atoi(port_str);
02502 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
02503 }
02504 else {
02505 port = atoi(port_str);
02506 }
02507
02508
02509 } else {
02510 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
02511 return NULL;
02512 }
02513
02514 if (!ast_strlen_zero(group)) {
02515
02516 char cfg_group[BUFFERSIZE+1];
02517 struct robin_list *rr = NULL;
02518
02519 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
02520 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
02521 rr = get_robin_position(group);
02522 }
02523
02524 if (rr) {
02525 int robin_channel = rr->channel;
02526 int port_start;
02527 int next_chan = 1;
02528
02529 do {
02530 port_start = 0;
02531 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
02532 port = misdn_cfg_get_next_port_spin(port)) {
02533
02534 if (!port_start)
02535 port_start = port;
02536
02537 if (port >= port_start)
02538 next_chan = 1;
02539
02540 if (port <= port_start && next_chan) {
02541 int maxbchans=misdn_lib_get_maxchans(port);
02542 if (++robin_channel >= maxbchans) {
02543 robin_channel = 1;
02544 }
02545 next_chan = 0;
02546 }
02547
02548 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02549
02550 if (!strcasecmp(cfg_group, group)) {
02551 int port_up;
02552 int check;
02553 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
02554 port_up = misdn_lib_port_up(port, check);
02555
02556 if (check && !port_up)
02557 chan_misdn_log(1,port,"L1 is not Up on this Port\n");
02558
02559 if (check && port_up<0) {
02560 ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
02561 }
02562
02563
02564 if ( port_up>0 ) {
02565 newbc = misdn_lib_get_free_bc(port, robin_channel,0);
02566 if (newbc) {
02567 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
02568 if (port_up)
02569 chan_misdn_log(4, port, "portup:%d\n", port_up);
02570 rr->port = newbc->port;
02571 rr->channel = newbc->channel;
02572 break;
02573 }
02574 }
02575 }
02576 }
02577 } while (!newbc && robin_channel != rr->channel);
02578
02579 if (!newbc)
02580 chan_misdn_log(-1, port, " Failed! No free channel in group %d!", group);
02581 }
02582
02583 else {
02584 for (port=misdn_cfg_get_next_port(0); port > 0;
02585 port=misdn_cfg_get_next_port(port)) {
02586
02587 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02588
02589 chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
02590 if (!strcasecmp(cfg_group, group)) {
02591 int port_up;
02592 int check;
02593 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
02594 port_up = misdn_lib_port_up(port, check);
02595
02596 chan_misdn_log(4, port, "portup:%d\n", port_up);
02597
02598 if ( port_up>0 ) {
02599 newbc = misdn_lib_get_free_bc(port, 0, 0);
02600 if (newbc)
02601 break;
02602 }
02603 }
02604 }
02605 }
02606
02607 } else {
02608 if (channel)
02609 chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
02610 newbc = misdn_lib_get_free_bc(port, channel, 0);
02611 }
02612
02613 if (!newbc) {
02614 chan_misdn_log(-1, 0, "Could not create channel on port:%d with extensions:%s\n",port,ext);
02615 return NULL;
02616 }
02617
02618
02619 cl->bc=newbc;
02620
02621 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
02622 cl->ast=tmp;
02623
02624
02625 cl_queue_chan(&cl_te, cl) ;
02626
02627
02628 read_config(cl, ORG_AST);
02629
02630
02631 cl->need_hangup=0;
02632
02633 return tmp;
02634 }
02635
02636
02637 int misdn_send_text (struct ast_channel *chan, const char *text)
02638 {
02639 struct chan_list *tmp=chan->tech_pvt;
02640
02641 if (tmp && tmp->bc) {
02642 ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
02643 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
02644 } else {
02645 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
02646 return -1;
02647 }
02648
02649 return 0;
02650 }
02651
02652 static struct ast_channel_tech misdn_tech = {
02653 .type="mISDN",
02654 .description="Channel driver for mISDN Support (Bri/Pri)",
02655 .capabilities= AST_FORMAT_ALAW ,
02656 .requester=misdn_request,
02657 .send_digit=misdn_digit,
02658 .call=misdn_call,
02659 .bridge=misdn_bridge,
02660 .hangup=misdn_hangup,
02661 .answer=misdn_answer,
02662 .read=misdn_read,
02663 .write=misdn_write,
02664 .indicate=misdn_indication,
02665 .fixup=misdn_fixup,
02666 .send_text=misdn_send_text,
02667 .properties=0
02668 };
02669
02670 static struct ast_channel_tech misdn_tech_wo_bridge = {
02671 .type="mISDN",
02672 .description="Channel driver for mISDN Support (Bri/Pri)",
02673 .capabilities=AST_FORMAT_ALAW ,
02674 .requester=misdn_request,
02675 .send_digit=misdn_digit,
02676 .call=misdn_call,
02677 .hangup=misdn_hangup,
02678 .answer=misdn_answer,
02679 .read=misdn_read,
02680 .write=misdn_write,
02681 .indicate=misdn_indication,
02682 .fixup=misdn_fixup,
02683 .send_text=misdn_send_text,
02684 .properties=0
02685 };
02686
02687
02688 static unsigned long glob_channel=0;
02689
02690 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
02691 {
02692 struct ast_channel *tmp;
02693
02694 tmp = ast_channel_alloc(1);
02695
02696 if (tmp) {
02697 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
02698
02699
02700 if (c<=0) {
02701 c=glob_channel++;
02702 snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
02703 misdn_type, port, c);
02704 } else {
02705 snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
02706 misdn_type, port, c);
02707 }
02708
02709 tmp->type = misdn_type;
02710
02711 tmp->nativeformats = prefformat;
02712
02713 tmp->readformat = format;
02714 tmp->rawreadformat = format;
02715 tmp->writeformat = format;
02716 tmp->rawwriteformat = format;
02717
02718 tmp->tech_pvt = chlist;
02719
02720 int bridging;
02721 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02722 if (bridging)
02723 tmp->tech = &misdn_tech;
02724 else
02725 tmp->tech = &misdn_tech_wo_bridge;
02726
02727 tmp->writeformat = format;
02728 tmp->readformat = format;
02729 tmp->priority=1;
02730
02731 if (exten)
02732 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
02733 else
02734 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
02735
02736 if (callerid) {
02737 char *cid_name, *cid_num;
02738
02739 ast_callerid_parse(callerid, &cid_name, &cid_num);
02740
02741 if (!ast_strlen_zero(cid_num))
02742 tmp->cid.cid_num = strdup(cid_num);
02743 if (!ast_strlen_zero(cid_name))
02744 tmp->cid.cid_name = strdup(cid_name);
02745 }
02746
02747 {
02748 if (pipe(chlist->pipe)<0)
02749 perror("Pipe failed\n");
02750
02751 tmp->fds[0]=chlist->pipe[0];
02752
02753 }
02754
02755 ast_setstate(tmp, state);
02756 if (state == AST_STATE_RING)
02757 tmp->rings = 1;
02758 else
02759 tmp->rings = 0;
02760
02761
02762 } else {
02763 chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
02764 }
02765
02766 return tmp;
02767 }
02768
02769
02770 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
02771 {
02772 struct ast_frame *f,*f2;
02773 if (tmp->trans)
02774 f2=ast_translate(tmp->trans, frame,0);
02775 else {
02776 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02777 return NULL;
02778 }
02779
02780 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02781 if (f && (f->frametype == AST_FRAME_DTMF)) {
02782 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
02783 if (f->subclass == 'f' && tmp->faxdetect) {
02784
02785 struct ast_channel *ast = tmp->ast;
02786 if (!tmp->faxhandled) {
02787 tmp->faxhandled++;
02788 if (strcmp(ast->exten, "fax")) {
02789 if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
02790 if (option_verbose > 2)
02791 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
02792
02793 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02794 if (ast_async_goto(ast, ast->context, "fax", 1))
02795 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
02796 } else
02797 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
02798 } else
02799 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02800 } else
02801 ast_log(LOG_DEBUG, "Fax already handled\n");
02802
02803 } else if ( tmp->ast_dsp) {
02804 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
02805 return f;
02806 }
02807 }
02808
02809 frame->frametype = AST_FRAME_NULL;
02810 frame->subclass = 0;
02811 return frame;
02812 }
02813
02814
02815 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
02816 {
02817 struct chan_list *help=list;
02818 for (;help; help=help->next) {
02819 if (help->bc == bc) return help;
02820 }
02821
02822 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02823
02824 return NULL;
02825 }
02826
02827 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
02828 {
02829 struct chan_list *help=list;
02830 for (;help; help=help->next) {
02831 if ( help->bc && (help->bc->pid == pid) ) return help;
02832 }
02833
02834 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
02835
02836 return NULL;
02837 }
02838
02839 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
02840 {
02841 struct chan_list *help=list;
02842
02843 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
02844 for (;help; help=help->next) {
02845 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel);
02846 if (help->hold_info.port == bc->port
02847 ) return help;
02848 }
02849
02850 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02851
02852 return NULL;
02853 }
02854
02855
02856 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
02857
02858 {
02859 struct chan_list *help=list;
02860
02861 for (;help; help=help->next) {
02862 if ( (help->state == MISDN_HOLDED) &&
02863 (help->l3id == l3_id)
02864 )
02865 return help;
02866 }
02867
02868 return NULL;
02869 }
02870
02871 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
02872 {
02873 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
02874
02875 ast_mutex_lock(&cl_te_lock);
02876 if (!*list) {
02877 *list = chan;
02878 } else {
02879 struct chan_list *help=*list;
02880 for (;help->next; help=help->next);
02881 help->next=chan;
02882 }
02883 chan->next=NULL;
02884 ast_mutex_unlock(&cl_te_lock);
02885 }
02886
02887 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
02888 {
02889 if (chan->dsp)
02890 ast_dsp_free(chan->dsp);
02891 if (chan->trans)
02892 ast_translator_free_path(chan->trans);
02893
02894
02895
02896 ast_mutex_lock(&cl_te_lock);
02897 if (!*list) {
02898 ast_mutex_unlock(&cl_te_lock);
02899 return;
02900 }
02901
02902 if (*list == chan) {
02903 *list=(*list)->next;
02904 ast_mutex_unlock(&cl_te_lock);
02905 return ;
02906 }
02907
02908 {
02909 struct chan_list *help=*list;
02910 for (;help->next; help=help->next) {
02911 if (help->next == chan) {
02912 help->next=help->next->next;
02913 ast_mutex_unlock(&cl_te_lock);
02914 return;
02915 }
02916 }
02917 }
02918
02919 ast_mutex_unlock(&cl_te_lock);
02920 }
02921
02922
02923
02924
02925 static int pbx_start_chan(struct chan_list *ch)
02926 {
02927 int ret=ast_pbx_start(ch->ast);
02928
02929 if (ret>=0)
02930 ch->need_hangup=0;
02931 else
02932 ch->need_hangup=1;
02933
02934 return ret;
02935 }
02936
02937 static void hangup_chan(struct chan_list *ch)
02938 {
02939 int port=ch?ch->bc?ch->bc->port:0:0;
02940 if (!ch) {
02941 cb_log(1,0,"Cannot hangup chan, no ch\n");
02942 return;
02943 }
02944
02945 cb_log(1,port,"hangup_chan\n");
02946
02947 if (ch->need_hangup)
02948 {
02949 cb_log(1,port,"-> hangup\n");
02950 send_cause2ast(ch->ast,ch->bc,ch);
02951 ch->need_hangup=0;
02952 ch->need_queue_hangup=0;
02953 if (ch->ast)
02954 ast_hangup(ch->ast);
02955 return;
02956 }
02957
02958 if (!ch->need_queue_hangup) {
02959 cb_log(1,port,"No need to queue hangup\n");
02960 }
02961
02962 ch->need_queue_hangup=0;
02963 if (ch->ast) {
02964 send_cause2ast(ch->ast,ch->bc,ch);
02965
02966 if (ch->ast)
02967 ast_queue_hangup(ch->ast);
02968 cb_log(1,port,"-> queue_hangup\n");
02969 } else {
02970 cb_log(1,port,"Cannot hangup chan, no ast\n");
02971 }
02972 }
02973
02974
02975 static void release_chan(struct misdn_bchannel *bc) {
02976 struct ast_channel *ast=NULL;
02977 {
02978 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02979 if (!ch) {
02980 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
02981 return;
02982 }
02983
02984 if (ch->ast) {
02985 ast=ch->ast;
02986 }
02987
02988 chan_misdn_log(1, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
02989
02990
02991 if (ch->jb ) {
02992 misdn_jb_destroy(ch->jb);
02993 ch->jb=NULL;
02994 } else {
02995 if (!bc->nojitter)
02996 chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
02997 }
02998
02999 if (ch) {
03000
03001 close(ch->pipe[0]);
03002 close(ch->pipe[1]);
03003
03004
03005 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03006 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));
03007 chan_misdn_log(3, bc->port, " --> * State Down\n");
03008 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
03009
03010
03011 if (ast->_state != AST_STATE_RESERVED) {
03012 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03013 ast_setstate(ast, AST_STATE_DOWN);
03014 }
03015 }
03016
03017 ch->state=MISDN_CLEANING;
03018 cl_dequeue_chan(&cl_te, ch);
03019
03020 free(ch);
03021 } else {
03022
03023 }
03024 }
03025 }
03026
03027
03028 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
03029 {
03030 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
03031
03032 tmp_ch->state=MISDN_HOLD_DISCONNECT;
03033
03034 ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
03035
03036 holded_chan->state=MISDN_CONNECTED;
03037
03038 ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
03039 }
03040
03041
03042 static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
03043 {
03044 char predial[256]="";
03045 char *p = predial;
03046
03047 struct ast_frame fr;
03048
03049 strncpy(predial, ast->exten, sizeof(predial) -1 );
03050
03051 ch->state=MISDN_DIALING;
03052
03053 if (bc->nt) {
03054 int ret;
03055 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03056 } else {
03057 int ret;
03058 if ( misdn_lib_is_ptp(bc->port)) {
03059 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03060 } else {
03061 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03062 }
03063 }
03064
03065 if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio )
03066 chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n");
03067 else
03068 dialtone_indicate(ch);
03069
03070 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));
03071
03072 strncpy(ast->exten,"s", 2);
03073
03074 if (pbx_start_chan(ch)<0) {
03075 ast=NULL;
03076 hangup_chan(ch);
03077 hanguptone_indicate(ch);
03078
03079 if (bc->nt)
03080 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03081 else
03082 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03083 }
03084
03085
03086 while (!ast_strlen_zero(p) ) {
03087 fr.frametype = AST_FRAME_DTMF;
03088 fr.subclass = *p ;
03089 fr.src=NULL;
03090 fr.data = NULL ;
03091 fr.datalen = 0;
03092 fr.samples = 0 ;
03093 fr.mallocd =0 ;
03094 fr.offset= 0 ;
03095 fr.delivery= ast_tv(0,0) ;
03096
03097 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03098 ast_queue_frame(ch->ast, &fr);
03099 }
03100 p++;
03101 }
03102 }
03103
03104
03105
03106 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
03107 if (!ast) {
03108 chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
03109 return;
03110 }
03111 if (!bc) {
03112 chan_misdn_log(1,0,"send_cause2ast: No BC\n");
03113 return;
03114 }
03115 if (!ch) {
03116 chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
03117 return;
03118 }
03119
03120 ast->hangupcause=bc->cause;
03121
03122 switch ( bc->cause) {
03123
03124 case 1:
03125 case 2:
03126 case 3:
03127 case 4:
03128 case 22:
03129 case 27:
03130
03131
03132
03133
03134
03135
03136
03137
03138
03139 break;
03140
03141 case 21:
03142 case 17:
03143
03144 ch->state=MISDN_BUSY;
03145
03146 if (!ch->need_busy) {
03147 chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
03148 break;
03149 }
03150
03151 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
03152
03153 ast_queue_control(ast, AST_CONTROL_BUSY);
03154
03155 ch->need_busy=0;
03156
03157 break;
03158 }
03159 }
03160
03161 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03162 {
03163 char *tmp;
03164 tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
03165 if (tmp) {
03166 ch->other_pid=atoi(tmp);
03167 chan_misdn_log(1,bc->port,"IMPORT_PID: importing pid:%s\n",tmp);
03168
03169 if (ch->other_pid >0) {
03170 ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
03171 if (ch->other_ch) ch->other_ch->other_ch=ch;
03172 }
03173 }
03174 }
03175
03176 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03177 {
03178 char tmp[32];
03179
03180 chan_misdn_log(1,bc->port,"EXPORT_PID: pid:%d\n",bc->pid);
03181 sprintf(tmp,"%d",bc->pid);
03182 pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
03183 }
03184
03185
03186
03187
03188
03189
03190 static enum event_response_e
03191 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
03192 {
03193 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03194
03195 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
03196 int debuglevel=1;
03197
03198 if ( event==EVENT_CLEANUP && !user_data)
03199 debuglevel=5;
03200
03201 chan_misdn_log(debuglevel, bc->port, "I IND :%s oad:%s dad:%s pid:%d state:%s\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->pid, ch?misdn_get_ch_state(ch):"none");
03202 if (debuglevel==1) {
03203 misdn_lib_log_ies(bc);
03204 chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
03205 }
03206 }
03207
03208 if (!ch) {
03209 switch(event) {
03210 case EVENT_SETUP:
03211 case EVENT_DISCONNECT:
03212 case EVENT_PORT_ALARM:
03213 case EVENT_RETRIEVE:
03214 case EVENT_NEW_BC:
03215 break;
03216 case EVENT_RELEASE_COMPLETE:
03217 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
03218 break;
03219 case EVENT_CLEANUP:
03220 case EVENT_TONE_GENERATE:
03221 case EVENT_BCHAN_DATA:
03222 return -1;
03223
03224 default:
03225 chan_misdn_log(1,bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n",bc->l3_id, bc, manager_isdn_get_info( event), bc->port,bc->channel);
03226 return -1;
03227 }
03228 }
03229
03230 if (ch ) {
03231 switch (event) {
03232 case EVENT_TONE_GENERATE:
03233 break;
03234 case EVENT_DISCONNECT:
03235 case EVENT_RELEASE:
03236 case EVENT_RELEASE_COMPLETE:
03237 case EVENT_CLEANUP:
03238 case EVENT_TIMEOUT:
03239 if (!ch->ast)
03240 chan_misdn_log(3,bc->port,"ast_hangup already called, so we have no ast ptr anymore in event(%s)\n",manager_isdn_get_info(event));
03241 break;
03242 default:
03243 if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03244 if (event!=EVENT_BCHAN_DATA)
03245 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
03246 return -1;
03247 }
03248 }
03249 }
03250
03251
03252 switch (event) {
03253 case EVENT_PORT_ALARM:
03254 {
03255 int boa=0;
03256
03257 misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
03258 if (boa) {
03259 cb_log(1,bc->port," --> blocking\n");
03260 misdn_lib_port_block(bc->port);
03261 }
03262 }
03263 break;
03264
03265 case EVENT_BCHAN_ACTIVATED:
03266 break;
03267
03268 case EVENT_NEW_L3ID:
03269 ch->l3id=bc->l3_id;
03270 ch->addr=bc->addr;
03271 break;
03272
03273 case EVENT_NEW_BC:
03274 if (!ch) {
03275 ch=find_holded(cl_te,bc);
03276 }
03277
03278 if (!ch) {
03279 ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
03280 break;
03281 }
03282
03283 if (bc)
03284 ch->bc=(struct misdn_bchannel*)user_data;
03285 break;
03286
03287 case EVENT_DTMF_TONE:
03288 {
03289
03290 struct ast_frame fr;
03291 memset(&fr, 0 , sizeof(fr));
03292 fr.frametype = AST_FRAME_DTMF;
03293 fr.subclass = bc->dtmf ;
03294 fr.src=NULL;
03295 fr.data = NULL ;
03296 fr.datalen = 0;
03297 fr.samples = 0 ;
03298 fr.mallocd =0 ;
03299 fr.offset= 0 ;
03300 fr.delivery= ast_tv(0,0) ;
03301
03302 if (!ch->ignore_dtmf) {
03303 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
03304 ast_queue_frame(ch->ast, &fr);
03305 } else {
03306 chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
03307 }
03308 }
03309 break;
03310 case EVENT_STATUS:
03311 break;
03312
03313 case EVENT_INFORMATION:
03314 {
03315 int stop_tone;
03316 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03317 if ( stop_tone ) {
03318 stop_indicate(ch);
03319 }
03320
03321 if (ch->state == MISDN_WAITING4DIGS ) {
03322
03323
03324 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
03325 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
03326 strcpy(bc->info_dad,bc->keypad);
03327 }
03328
03329 {
03330 int l = sizeof(bc->dad);
03331 strncat(bc->dad,bc->info_dad, l);
03332 bc->dad[l-1] = 0;
03333 }
03334
03335
03336 {
03337 int l = sizeof(ch->ast->exten);
03338 strncpy(ch->ast->exten, bc->dad, l);
03339 ch->ast->exten[l-1] = 0;
03340 }
03341
03342
03343
03344 if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
03345 int ret;
03346 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03347 if (ast_pickup_call(ch->ast)) {
03348 hangup_chan(ch);
03349 } else {
03350 struct ast_channel *chan=ch->ast;
03351 ch->state = MISDN_CALLING_ACKNOWLEDGE;
03352 ast_setstate(chan, AST_STATE_DOWN);
03353 hangup_chan(ch);
03354 ch->ast=NULL;
03355 break;
03356 }
03357 }
03358
03359 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03360
03361 chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
03362 if (bc->nt)
03363 hanguptone_indicate(ch);
03364 ch->state=MISDN_EXTCANTMATCH;
03365 bc->out_cause=1;
03366
03367 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03368
03369 break;
03370 }
03371 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03372 ch->state=MISDN_DIALING;
03373
03374 stop_indicate(ch);
03375
03376 if (pbx_start_chan(ch)<0) {
03377 hangup_chan(ch);
03378
03379 chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n");
03380 if (bc->nt) hanguptone_indicate(ch);
03381
03382 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03383 }
03384 }
03385
03386 } else {
03387
03388 struct ast_frame fr;
03389 fr.frametype = AST_FRAME_DTMF;
03390 fr.subclass = bc->info_dad[0] ;
03391 fr.src=NULL;
03392 fr.data = NULL ;
03393 fr.datalen = 0;
03394 fr.samples = 0 ;
03395 fr.mallocd =0 ;
03396 fr.offset= 0 ;
03397 fr.delivery= ast_tv(0,0) ;
03398
03399
03400 int digits;
03401 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
03402 if (ch->state != MISDN_CONNECTED ) {
03403 if (digits) {
03404 int l = sizeof(bc->dad);
03405 strncat(bc->dad,bc->info_dad, l);
03406 bc->dad[l-1] = 0;
03407 l = sizeof(ch->ast->exten);
03408 strncpy(ch->ast->exten, bc->dad, l);
03409 ch->ast->exten[l-1] = 0;
03410
03411 ast_cdr_update(ch->ast);
03412 }
03413
03414 ast_queue_frame(ch->ast, &fr);
03415 }
03416 }
03417 }
03418 break;
03419 case EVENT_SETUP:
03420 {
03421 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03422 if (ch) {
03423 switch (ch->state) {
03424 case MISDN_NOTHING:
03425 ch=NULL;
03426 break;
03427 default:
03428 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
03429 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE;
03430 }
03431 }
03432 }
03433
03434
03435 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
03436 if (!bc->nt && ! msn_valid) {
03437 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
03438 return RESPONSE_IGNORE_SETUP;
03439 }
03440
03441 if (bc->cw) {
03442 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
03443 int cause;
03444 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
03445 bc->out_cause=cause?cause:16;
03446 return RESPONSE_RELEASE_SETUP;
03447 }
03448
03449 print_bearer(bc);
03450
03451 {
03452 struct chan_list *ch=init_chan_list(ORG_MISDN);
03453 struct ast_channel *chan;
03454
03455 if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
03456
03457 ch->bc = bc;
03458 ch->l3id=bc->l3_id;
03459 ch->addr=bc->addr;
03460 ch->orginator = ORG_MISDN;
03461
03462 chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
03463 ch->ast = chan;
03464
03465 read_config(ch, ORG_MISDN);
03466
03467 export_ch(chan, bc, ch);
03468
03469 ch->ast->rings=1;
03470 ast_setstate(ch->ast, AST_STATE_RINGING);
03471
03472 int pres,screen;
03473
03474 switch (bc->pres) {
03475 case 1:
03476 pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
03477 break;
03478 case 2:
03479 pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
03480 break;
03481 default:
03482 pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
03483 }
03484
03485 switch (bc->screen) {
03486 case 0:
03487 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
03488 break;
03489 case 1:
03490 screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
03491 break;
03492 case 2:
03493 screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
03494 break;
03495 case 3:
03496 screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
03497 break;
03498 default:
03499 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
03500 }
03501
03502 chan->cid.cid_pres=pres+screen;
03503
03504 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
03505 chan->transfercapability=bc->capability;
03506
03507 switch (bc->capability) {
03508 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
03509 pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
03510 break;
03511 default:
03512 pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
03513 }
03514
03515
03516 cl_queue_chan(&cl_te, ch) ;
03517
03518
03519 if (!strstr(ch->allowed_bearers,"all")) {
03520 int i;
03521 for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
03522 if (allowed_bearers_array[i].cap == bc->capability) {
03523 if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
03524 chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
03525 bc->out_cause=88;
03526
03527 ch->state=MISDN_EXTCANTMATCH;
03528 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03529 return RESPONSE_OK;
03530 }
03531 }
03532
03533 }
03534 }
03535
03536
03537 if (!strcmp(chan->exten, ast_pickup_ext())) {
03538 int ret;
03539 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03540 if (ast_pickup_call(chan)) {
03541 hangup_chan(ch);
03542 } else {
03543 ch->state = MISDN_CALLING_ACKNOWLEDGE;
03544 ast_setstate(chan, AST_STATE_DOWN);
03545 hangup_chan(ch);
03546 ch->ast=NULL;
03547 break;
03548 }
03549 }
03550
03551
03552
03553
03554
03555 {
03556 int ai;
03557 misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
03558 if ( ai ) {
03559 do_immediate_setup(bc, ch , chan);
03560 break;
03561 }
03562
03563
03564
03565 }
03566
03567
03568 {
03569 int im;
03570 misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
03571 if ( im && ast_strlen_zero(bc->dad) ) {
03572 do_immediate_setup(bc, ch , chan);
03573 break;
03574 }
03575 }
03576
03577
03578 chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
03579 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03580
03581 chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n");
03582
03583 if (bc->nt)
03584 hanguptone_indicate(ch);
03585 ch->state=MISDN_EXTCANTMATCH;
03586 bc->out_cause=1;
03587
03588 if (bc->nt)
03589 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03590 else
03591 misdn_lib_send_event(bc, EVENT_RELEASE );
03592
03593 break;
03594 }
03595
03596 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
03597 ch->state=MISDN_DIALING;
03598
03599 if (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)) ) {
03600 int ret;
03601 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03602 } else {
03603 int ret;
03604 ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
03605 }
03606
03607 if (pbx_start_chan(ch)<0) {
03608 hangup_chan(ch);
03609
03610 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03611 chan=NULL;
03612
03613 if (bc->nt) {
03614 hanguptone_indicate(ch);
03615 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03616 } else
03617 misdn_lib_send_event(bc, EVENT_RELEASE);
03618 }
03619 } else {
03620
03621 if (bc->sending_complete) {
03622 ch->state=MISDN_EXTCANTMATCH;
03623 bc->out_cause=1;
03624
03625 if (bc->nt) {
03626 chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
03627 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
03628 } else {
03629 chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n");
03630 misdn_lib_send_event(bc, EVENT_RELEASE);
03631 }
03632
03633 } else {
03634
03635 int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03636 if (ret == -ENOCHAN) {
03637 ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
03638 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03639 }
03640
03641
03642
03643
03644 int stop_tone;
03645 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03646 if ( (!ast_strlen_zero(bc->dad)) && stop_tone )
03647 stop_indicate(ch);
03648 else {
03649 dialtone_indicate(ch);
03650 }
03651
03652 ch->state=MISDN_WAITING4DIGS;
03653 }
03654 }
03655
03656 }
03657 break;
03658 case EVENT_SETUP_ACKNOWLEDGE:
03659 {
03660 ch->state = MISDN_CALLING_ACKNOWLEDGE;
03661 if (!ast_strlen_zero(bc->infos_pending)) {
03662
03663
03664 {
03665 int l = sizeof(bc->dad);
03666 strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
03667 bc->dad[l-1] = 0;
03668 }
03669 {
03670 int l = sizeof(ch->ast->exten);
03671 strncpy(ch->ast->exten, bc->dad, l);
03672 ch->ast->exten[l-1] = 0;
03673 }
03674 {
03675 int l = sizeof(bc->info_dad);
03676 strncpy(bc->info_dad, bc->infos_pending, l);
03677 bc->info_dad[l-1] = 0;
03678 }
03679 strncpy(bc->infos_pending,"", 1);
03680
03681 misdn_lib_send_event(bc, EVENT_INFORMATION);
03682 }
03683 }
03684 break;
03685 case EVENT_PROCEEDING:
03686 {
03687
03688 if ( misdn_cap_is_speech(bc->capability) &&
03689 misdn_inband_avail(bc) ) {
03690 start_bc_tones(ch);
03691 }
03692
03693 ch->state = MISDN_PROCEEDING;
03694
03695 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
03696 }
03697 break;
03698 case EVENT_PROGRESS:
03699 if (!bc->nt ) {
03700 if ( misdn_cap_is_speech(bc->capability) &&
03701 misdn_inband_avail(bc)
03702 ) {
03703 start_bc_tones(ch);
03704 }
03705
03706 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
03707
03708 ch->state=MISDN_PROGRESS;
03709 }
03710 break;
03711
03712
03713 case EVENT_ALERTING:
03714 {
03715 ch->state = MISDN_ALERTING;
03716
03717 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
03718 ast_setstate(ch->ast, AST_STATE_RINGING);
03719
03720 cb_log(1,bc->port,"Set State Ringing\n");
03721
03722 if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
03723 cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
03724 start_bc_tones(ch);
03725 } else {
03726 cb_log(1,bc->port,"We have no inband Data, the other end must create ringing\n");
03727 if (ch->far_alerting) {
03728 cb_log(1,bc->port,"The other end can not do ringing eh ?.. we must do all ourself..");
03729 start_bc_tones(ch);
03730
03731 }
03732 }
03733 }
03734 break;
03735 case EVENT_CONNECT:
03736 {
03737
03738 misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
03739
03740 struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
03741
03742 misdn_lib_echo(bc,0);
03743 stop_indicate(ch);
03744
03745 if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
03746 struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
03747
03748 chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
03749 if (bridged_ch) {
03750 bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
03751 ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
03752 }
03753 }
03754 }
03755
03756
03757 case EVENT_CONNECT_ACKNOWLEDGE:
03758 {
03759 ch->l3id=bc->l3_id;
03760 ch->addr=bc->addr;
03761
03762 start_bc_tones(ch);
03763
03764
03765 ch->state = MISDN_CONNECTED;
03766 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
03767 }
03768 break;
03769 case EVENT_DISCONNECT:
03770
03771 if (ch) {
03772 struct chan_list *holded_ch=find_holded(cl_te, bc);
03773
03774 chan_misdn_log(3,bc->port," --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->orginator, bc->nt, misdn_inband_avail(bc), ch->state);
03775 if ( ch->orginator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
03776
03777
03778
03779
03780
03781 chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
03782
03783 ch->state=MISDN_DISCONNECTED;
03784 start_bc_tones(ch);
03785 break;
03786 }
03787
03788
03789 if ( holded_ch &&
03790 holded_ch != ch &&
03791 ch->ast &&
03792 ch->state == MISDN_CONNECTED ) {
03793 cb_log(1,bc->port," --> found holded ch\n");
03794 misdn_transfer_bc(ch, holded_ch) ;
03795 }
03796
03797 stop_bc_tones(ch);
03798 hangup_chan(ch);
03799 } else {
03800 ch=find_holded_l3(cl_te, bc->l3_id,1);
03801 if (ch) {
03802 hangup_chan(ch);
03803 }
03804 }
03805 bc->out_cause=-1;
03806 if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
03807 break;
03808
03809 case EVENT_RELEASE:
03810 {
03811 bc->out_cause=16;
03812
03813 hangup_chan(ch);
03814 release_chan(bc);
03815
03816 if (bc->need_release_complete)
03817 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03818 }
03819 break;
03820 case EVENT_RELEASE_COMPLETE:
03821 {
03822 stop_bc_tones(ch);
03823 hangup_chan(ch);
03824 release_chan(bc);
03825 if(ch)
03826 ch->state=MISDN_CLEANING;
03827 }
03828 break;
03829 case EVENT_CLEANUP:
03830 {
03831 stop_bc_tones(ch);
03832
03833 switch(ch->state) {
03834 case MISDN_CALLING:
03835 bc->cause=27;
03836 break;
03837 default:
03838 break;
03839 }
03840
03841 hangup_chan(ch);
03842 release_chan(bc);
03843 }
03844 break;
03845
03846 case EVENT_TONE_GENERATE:
03847 {
03848 int tone_len=bc->tone_cnt;
03849 struct ast_channel *ast=ch->ast;
03850 void *tmp;
03851 int res;
03852 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
03853
03854 chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
03855
03856 if (!ast) break;
03857
03858 if (!ast->generator) break;
03859
03860
03861
03862 tmp = ast->generatordata;
03863 ast->generatordata = NULL;
03864 generate = ast->generator->generate;
03865
03866 if (tone_len <0 || tone_len > 512 ) {
03867 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
03868 tone_len=128;
03869 }
03870
03871 res = generate(ast, tmp, tone_len, tone_len);
03872 ast->generatordata = tmp;
03873
03874 if (res) {
03875 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
03876 ast_deactivate_generator(ast);
03877 } else {
03878 bc->tone_cnt=0;
03879 }
03880 }
03881 break;
03882
03883 case EVENT_BCHAN_DATA:
03884 {
03885 if ( !misdn_cap_is_speech(ch->bc->capability) ) {
03886 struct ast_frame frame;
03887
03888 frame.frametype = AST_FRAME_VOICE;
03889 frame.subclass = AST_FORMAT_ALAW;
03890 frame.datalen = bc->bframe_len;
03891 frame.samples = bc->bframe_len ;
03892 frame.mallocd =0 ;
03893 frame.offset= 0 ;
03894 frame.delivery= ast_tv(0,0) ;
03895 frame.src = NULL;
03896 frame.data = bc->bframe ;
03897
03898 ast_queue_frame(ch->ast,&frame);
03899 } else {
03900 fd_set wrfs;
03901 struct timeval tv;
03902 tv.tv_sec=0;
03903 tv.tv_usec=0;
03904
03905
03906 FD_ZERO(&wrfs);
03907 FD_SET(ch->pipe[1],&wrfs);
03908
03909 int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
03910
03911 if (!t) {
03912 chan_misdn_log(9, bc->port, "Select Timed out\n");
03913 break;
03914 }
03915
03916 if (t<0) {
03917 chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
03918 break;
03919 }
03920
03921 if (FD_ISSET(ch->pipe[1],&wrfs)) {
03922 chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
03923 int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
03924
03925 if (ret<=0) {
03926 chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s)\n",strerror(errno));
03927 }
03928 } else {
03929 chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
03930 }
03931 }
03932 }
03933 break;
03934 case EVENT_TIMEOUT:
03935 {
03936 if (ch && bc)
03937 chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
03938
03939 switch (ch->state) {
03940 case MISDN_CALLING:
03941 case MISDN_DIALING:
03942 case MISDN_PROGRESS:
03943 case MISDN_ALERTING:
03944 case MISDN_PROCEEDING:
03945 case MISDN_CALLING_ACKNOWLEDGE:
03946 if (bc->nt) {
03947 bc->progress_indicator=8;
03948 hanguptone_indicate(ch);
03949 }
03950
03951 bc->out_cause=1;
03952 misdn_lib_send_event(bc,EVENT_DISCONNECT);
03953 break;
03954
03955 case MISDN_WAITING4DIGS:
03956 if (bc->nt) {
03957 bc->progress_indicator=8;
03958 bc->out_cause=1;
03959 hanguptone_indicate(ch);
03960 misdn_lib_send_event(bc,EVENT_DISCONNECT);
03961 } else {
03962 bc->out_cause=16;
03963 misdn_lib_send_event(bc,EVENT_RELEASE);
03964 }
03965
03966 break;
03967
03968
03969 case MISDN_CLEANING:
03970 chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
03971 break;
03972
03973 default:
03974 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03975 }
03976 }
03977 break;
03978
03979
03980
03981
03982
03983 case EVENT_RETRIEVE:
03984 {
03985 ch=find_holded_l3(cl_te, bc->l3_id,1);
03986 if (!ch) {
03987 ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
03988 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
03989 break;
03990 }
03991
03992
03993 ch->bc=bc;
03994 ch->state = MISDN_CONNECTED;
03995
03996 struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
03997
03998 if (hold_ast) {
03999 ast_moh_stop(hold_ast);
04000 }
04001
04002 if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
04003 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04004 }
04005 break;
04006
04007 case EVENT_HOLD:
04008 {
04009 int hold_allowed;
04010 misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04011
04012 if (!hold_allowed) {
04013
04014 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04015 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04016 break;
04017 }
04018
04019 struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
04020
04021 if (bridged) {
04022 chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
04023 ch->state = MISDN_HOLDED;
04024 ch->l3id = bc->l3_id;
04025
04026 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04027
04028 ast_moh_start(bridged, NULL);
04029
04030
04031 ch->bc=NULL;
04032 ch->hold_info.port=bc->port;
04033 ch->hold_info.channel=bc->channel;
04034
04035 } else {
04036 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04037 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04038 }
04039 }
04040 break;
04041
04042 case EVENT_FACILITY:
04043 print_facility(bc);
04044
04045 switch (bc->fac_type) {
04046 case FACILITY_CALLDEFLECT:
04047 {
04048 struct ast_channel *bridged=AST_BRIDGED_P(ch->ast);
04049 struct chan_list *ch;
04050
04051 if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04052 ch=MISDN_ASTERISK_TECH_PVT(bridged);
04053
04054 if (ch->bc) {
04055
04056 }
04057
04058 }
04059
04060 }
04061
04062 break;
04063 default:
04064 chan_misdn_log(1, bc->port," --> not yet handled\n");
04065 }
04066
04067 break;
04068
04069 case EVENT_RESTART:
04070
04071 stop_bc_tones(ch);
04072 release_chan(bc);
04073
04074 break;
04075
04076 default:
04077 ast_log(LOG_NOTICE, "Got Unknown Event\n");
04078 break;
04079 }
04080
04081 return RESPONSE_OK;
04082 }
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094 static int g_config_initialized=0;
04095
04096 int load_module(void)
04097 {
04098 int i;
04099
04100 char ports[256]="";
04101
04102 max_ports=misdn_lib_maxports_get();
04103
04104 if (max_ports<=0) {
04105 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
04106 return 0;
04107 }
04108
04109
04110 misdn_cfg_init(max_ports);
04111 g_config_initialized=1;
04112
04113 misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
04114 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
04115 for (i = 1; i <= max_ports; i++)
04116 misdn_debug[i] = misdn_debug[0];
04117 misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
04118
04119
04120 {
04121 char tempbuf[BUFFERSIZE+1];
04122 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
04123 if (strlen(tempbuf))
04124 tracing = 1;
04125 }
04126
04127 ast_mutex_init(&cl_te_lock);
04128
04129 misdn_cfg_update_ptp();
04130 misdn_cfg_get_ports_string(ports);
04131
04132 if (strlen(ports))
04133 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
04134
04135 {
04136 struct misdn_lib_iface iface = {
04137 .cb_event = cb_events,
04138 .cb_log = chan_misdn_log,
04139 .cb_jb_empty = chan_misdn_jb_empty,
04140 };
04141 if (misdn_lib_init(ports, &iface, NULL))
04142 chan_misdn_log(0, 0, "No te ports initialized\n");
04143
04144 int ntflags=0;
04145 char ntfile[BUFFERSIZE+1];
04146
04147 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
04148 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
04149
04150 misdn_lib_nt_debug_init(ntflags,ntfile);
04151
04152 }
04153
04154
04155 {
04156 if (ast_channel_register(&misdn_tech)) {
04157 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
04158 unload_module();
04159 return -1;
04160 }
04161 }
04162
04163 ast_cli_register(&cli_send_display);
04164 ast_cli_register(&cli_send_cd);
04165 ast_cli_register(&cli_send_digit);
04166 ast_cli_register(&cli_toggle_echocancel);
04167 ast_cli_register(&cli_set_tics);
04168
04169 ast_cli_register(&cli_show_cls);
04170 ast_cli_register(&cli_show_cl);
04171 ast_cli_register(&cli_show_config);
04172 ast_cli_register(&cli_show_port);
04173 ast_cli_register(&cli_show_stacks);
04174
04175 ast_cli_register(&cli_port_block);
04176 ast_cli_register(&cli_port_unblock);
04177 ast_cli_register(&cli_restart_port);
04178 ast_cli_register(&cli_port_up);
04179 ast_cli_register(&cli_port_down);
04180 ast_cli_register(&cli_set_debug);
04181 ast_cli_register(&cli_set_crypt_debug);
04182 ast_cli_register(&cli_reload);
04183
04184
04185 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
04186 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
04187 "Sets mISDN opts. and optargs\n"
04188 "\n"
04189 "The available options are:\n"
04190 " d - Send display text on called phone, text is the optparam\n"
04191 " n - don't detect dtmf tones on called channel\n"
04192 " h - make digital outgoing call\n"
04193 " c - make crypted outgoing call, param is keyindex\n"
04194 " e - perform echo cancelation on this channel,\n"
04195 " takes taps as arguments (32,64,128,256)\n"
04196 " s - send Non Inband DTMF as inband\n"
04197 " vr - rxgain control\n"
04198 " vt - txgain control\n"
04199 );
04200
04201
04202 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
04203 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
04204 "Sends the Facility Message FACILITY_TYPE with \n"
04205 "the given Arguments to the current ISDN Channel\n"
04206 "Supported Facilities are:\n"
04207 "\n"
04208 "type=calldeflect args=Nr where to deflect\n"
04209 );
04210
04211
04212 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
04213
04214 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
04215
04216 return 0;
04217 }
04218
04219
04220
04221 int unload_module(void)
04222 {
04223
04224 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
04225
04226 if (!g_config_initialized) return 0;
04227
04228 ast_cli_unregister(&cli_send_display);
04229
04230 ast_cli_unregister(&cli_send_cd);
04231
04232 ast_cli_unregister(&cli_send_digit);
04233 ast_cli_unregister(&cli_toggle_echocancel);
04234 ast_cli_unregister(&cli_set_tics);
04235
04236 ast_cli_unregister(&cli_show_cls);
04237 ast_cli_unregister(&cli_show_cl);
04238 ast_cli_unregister(&cli_show_config);
04239 ast_cli_unregister(&cli_show_port);
04240 ast_cli_unregister(&cli_show_stacks);
04241 ast_cli_unregister(&cli_port_block);
04242 ast_cli_unregister(&cli_port_unblock);
04243 ast_cli_unregister(&cli_restart_port);
04244 ast_cli_unregister(&cli_port_up);
04245 ast_cli_unregister(&cli_port_down);
04246 ast_cli_unregister(&cli_set_debug);
04247 ast_cli_unregister(&cli_set_crypt_debug);
04248 ast_cli_unregister(&cli_reload);
04249
04250 ast_unregister_application("misdn_set_opt");
04251 ast_unregister_application("misdn_facility");
04252
04253 ast_channel_unregister(&misdn_tech);
04254
04255
04256 free_robin_list();
04257 misdn_cfg_destroy();
04258 misdn_lib_destroy();
04259
04260 if (misdn_debug)
04261 free(misdn_debug);
04262 if (misdn_debug_only)
04263 free(misdn_debug_only);
04264
04265 return 0;
04266 }
04267
04268 int reload(void)
04269 {
04270 reload_config();
04271
04272 return 0;
04273 }
04274
04275 int usecount(void)
04276 {
04277 int res;
04278 ast_mutex_lock(&usecnt_lock);
04279 res = usecnt;
04280 ast_mutex_unlock(&usecnt_lock);
04281 return res;
04282 }
04283
04284 char *description(void)
04285 {
04286 return desc;
04287 }
04288
04289 char *key(void)
04290 {
04291 return ASTERISK_GPL_KEY;
04292 }
04293
04294
04295
04296
04297
04298
04299 static int misdn_facility_exec(struct ast_channel *chan, void *data)
04300 {
04301 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
04302 char *tok, *tokb;
04303
04304 chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
04305
04306 if (strcasecmp(chan->tech->type,"mISDN")) {
04307 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
04308 return -1;
04309 }
04310
04311 if (ast_strlen_zero((char *)data)) {
04312 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
04313 return -1;
04314 }
04315
04316 tok=strtok_r((char*)data,"|", &tokb) ;
04317
04318 if (!tok) {
04319 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
04320 return -1;
04321 }
04322
04323 if (!strcasecmp(tok,"calldeflect")) {
04324 tok=strtok_r(NULL,"|", &tokb) ;
04325
04326 if (!tok) {
04327 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
04328 }
04329
04330 misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
04331
04332 } else {
04333 ast_log(LOG_WARNING, "Unknown Facility: %s\n",tok);
04334 }
04335
04336 return 0;
04337
04338 }
04339
04340
04341 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
04342 {
04343 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
04344 char *tok,*tokb;
04345 int keyidx=0;
04346 int rxgain=0;
04347 int txgain=0;
04348 int change_jitter=0;
04349
04350 if (strcasecmp(chan->tech->type,"mISDN")) {
04351 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
04352 return -1;
04353 }
04354
04355 if (ast_strlen_zero((char *)data)) {
04356 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
04357 return -1;
04358 }
04359
04360 for (tok=strtok_r((char*)data, ":",&tokb);
04361 tok;
04362 tok=strtok_r(NULL,":",&tokb) ) {
04363 int neglect=0;
04364
04365 if (tok[0] == '!' ) {
04366 neglect=1;
04367 tok++;
04368 }
04369
04370 switch(tok[0]) {
04371
04372 case 'd' :
04373 ast_copy_string(ch->bc->display,++tok,84);
04374 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
04375 break;
04376
04377 case 'n':
04378 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
04379 ch->bc->nodsp=1;
04380 break;
04381
04382 case 'j':
04383 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
04384 tok++;
04385 change_jitter=1;
04386
04387 switch ( tok[0] ) {
04388 case 'b' :
04389 ch->jb_len=atoi(++tok);
04390 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
04391 break;
04392 case 't' :
04393 ch->jb_upper_threshold=atoi(++tok);
04394 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
04395 break;
04396
04397 case 'n':
04398 ch->bc->nojitter=1;
04399 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
04400 break;
04401
04402 default:
04403 ch->jb_len=4000;
04404 ch->jb_upper_threshold=0;
04405 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
04406 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
04407 }
04408
04409 break;
04410
04411 case 'v':
04412 tok++;
04413
04414 switch ( tok[0] ) {
04415 case 'r' :
04416 rxgain=atoi(++tok);
04417 if (rxgain<-8) rxgain=-8;
04418 if (rxgain>8) rxgain=8;
04419 ch->bc->rxgain=rxgain;
04420 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
04421 break;
04422 case 't':
04423 txgain=atoi(++tok);
04424 if (txgain<-8) txgain=-8;
04425 if (txgain>8) txgain=8;
04426 ch->bc->txgain=txgain;
04427 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
04428 break;
04429 }
04430 break;
04431
04432 case 'c':
04433 keyidx=atoi(++tok);
04434
04435 if (keyidx > misdn_key_vector_size || keyidx < 0 ) {
04436 ast_log(LOG_WARNING, "You entered the keyidx: %d but we have only %d keys\n",keyidx, misdn_key_vector_size );
04437 continue;
04438 }
04439
04440 {
04441 ast_copy_string(ch->bc->crypt_key, misdn_key_vector[keyidx], sizeof(ch->bc->crypt_key));
04442 }
04443
04444 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
04445 break;
04446
04447 case 'e':
04448 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
04449
04450 if (neglect) {
04451 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
04452 ch->bc->ec_enable=0;
04453
04454 } else {
04455 ch->bc->ec_enable=1;
04456 ch->bc->orig=ch->orginator;
04457 tok++;
04458 if (tok) {
04459 ch->bc->ec_deftaps=atoi(tok);
04460 }
04461 }
04462
04463 break;
04464
04465 case 'h':
04466 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
04467
04468 if (strlen(tok) > 1 && tok[1]=='1') {
04469 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
04470 if (!ch->bc->hdlc) {
04471 ch->bc->hdlc=1;
04472 misdn_lib_setup_bc(ch->bc);
04473 }
04474 }
04475 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
04476 break;
04477
04478 case 's':
04479 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
04480 ch->bc->send_dtmf=1;
04481 break;
04482
04483 case 'f':
04484 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
04485 ch->faxdetect=1;
04486 break;
04487
04488 case 'a':
04489 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
04490 ch->ast_dsp=1;
04491 break;
04492
04493 case 'p':
04494 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
04495
04496 if (strstr(tok,"allowed") ) {
04497 ch->bc->pres=0;
04498 } else if (strstr(tok,"not_screened")) {
04499 ch->bc->pres=1;
04500 }
04501
04502
04503 break;
04504
04505
04506 default:
04507 break;
04508 }
04509 }
04510
04511 if (change_jitter)
04512 config_jitterbuffer(ch);
04513
04514
04515 if (ch->faxdetect || ch->ast_dsp) {
04516
04517 if (!ch->dsp) ch->dsp = ast_dsp_new();
04518 if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
04519 if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
04520 }
04521
04522 if (ch->ast_dsp) {
04523 chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
04524 ch->bc->nodsp=1;
04525 ch->bc->nojitter=1;
04526 }
04527
04528 return 0;
04529 }
04530
04531
04532 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
04533 {
04534 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
04535
04536 if (ch && ch->jb) {
04537 return misdn_jb_empty(ch->jb, buf, len);
04538 }
04539
04540 return -1;
04541 }
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
04552 {
04553 int i;
04554 struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
04555 jb->size = size;
04556 jb->upper_threshold = upper_threshold;
04557 jb->wp = 0;
04558 jb->rp = 0;
04559 jb->state_full = 0;
04560 jb->state_empty = 0;
04561 jb->bytes_wrote = 0;
04562 jb->samples = (char *)malloc(size*sizeof(char));
04563
04564 if (!jb->samples) {
04565 chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
04566 return NULL;
04567 }
04568
04569 jb->ok = (char *)malloc(size*sizeof(char));
04570
04571 if (!jb->ok) {
04572 chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
04573 return NULL;
04574 }
04575
04576 for(i=0; i<size; i++)
04577 jb->ok[i]=0;
04578
04579 ast_mutex_init(&jb->mutexjb);
04580
04581 return jb;
04582 }
04583
04584
04585 void misdn_jb_destroy(struct misdn_jb *jb)
04586 {
04587 ast_mutex_destroy(&jb->mutexjb);
04588
04589 free(jb->samples);
04590 free(jb);
04591 }
04592
04593
04594
04595 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
04596 {
04597 int i, j, rp, wp;
04598
04599 if (!jb || ! data) return 0;
04600
04601 ast_mutex_lock (&jb->mutexjb);
04602
04603 wp=jb->wp;
04604 rp=jb->rp;
04605
04606 for(i=0; i<len; i++)
04607 {
04608 jb->samples[wp]=data[i];
04609 jb->ok[wp]=1;
04610 wp = (wp!=jb->size-1 ? wp+1 : 0);
04611
04612 if(wp==jb->rp)
04613 jb->state_full=1;
04614 }
04615
04616 if(wp>=rp)
04617 jb->state_buffer=wp-rp;
04618 else
04619 jb->state_buffer= jb->size-rp+wp;
04620 chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
04621
04622 if(jb->state_full)
04623 {
04624 jb->wp=wp;
04625
04626 rp=wp;
04627 for(j=0; j<jb->upper_threshold; j++)
04628 rp = (rp!=0 ? rp-1 : jb->size-1);
04629 jb->rp=rp;
04630 jb->state_full=0;
04631 jb->state_empty=1;
04632
04633 ast_mutex_unlock (&jb->mutexjb);
04634
04635 return -1;
04636 }
04637
04638 if(!jb->state_empty)
04639 {
04640 jb->bytes_wrote+=len;
04641 if(jb->bytes_wrote>=jb->upper_threshold)
04642 {
04643 jb->state_empty=1;
04644 jb->bytes_wrote=0;
04645 }
04646 }
04647 jb->wp=wp;
04648
04649 ast_mutex_unlock (&jb->mutexjb);
04650
04651 return 0;
04652 }
04653
04654
04655
04656
04657 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
04658 {
04659 int i, wp, rp, read=0;
04660
04661 ast_mutex_lock (&jb->mutexjb);
04662
04663 rp=jb->rp;
04664 wp=jb->wp;
04665
04666 if(jb->state_empty)
04667 {
04668 for(i=0; i<len; i++)
04669 {
04670 if(wp==rp)
04671 {
04672 jb->rp=rp;
04673 jb->state_empty=0;
04674
04675 ast_mutex_unlock (&jb->mutexjb);
04676
04677 return read;
04678 }
04679 else
04680 {
04681 if(jb->ok[rp]==1)
04682 {
04683 data[i]=jb->samples[rp];
04684 jb->ok[rp]=0;
04685 rp=(rp!=jb->size-1 ? rp+1 : 0);
04686 read+=1;
04687 }
04688 }
04689 }
04690
04691 if(wp >= rp)
04692 jb->state_buffer=wp-rp;
04693 else
04694 jb->state_buffer= jb->size-rp+wp;
04695 chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
04696
04697 jb->rp=rp;
04698 }
04699 else
04700 chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
04701
04702 ast_mutex_unlock (&jb->mutexjb);
04703
04704 return read;
04705 }
04706
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717 void chan_misdn_log(int level, int port, char *tmpl, ...)
04718 {
04719 if (! ((0 <= port) && (port <= max_ports))) {
04720 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
04721 port=0;
04722 level=-1;
04723 }
04724
04725 va_list ap;
04726 char buf[1024];
04727 char port_buf[8];
04728 sprintf(port_buf,"P[%2d] ",port);
04729
04730 va_start(ap, tmpl);
04731 vsnprintf( buf, 1023, tmpl, ap );
04732 va_end(ap);
04733
04734 if (level == -1)
04735 ast_log(LOG_WARNING, buf);
04736
04737 else if (misdn_debug_only[port] ?
04738 (level==1 && misdn_debug[port]) || (level==misdn_debug[port])
04739 : level <= misdn_debug[port]) {
04740
04741 ast_console_puts(port_buf);
04742 ast_console_puts(buf);
04743 }
04744
04745 if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
04746 time_t tm = time(NULL);
04747 char *tmp=ctime(&tm),*p;
04748
04749 FILE *fp= fopen(global_tracefile, "a+");
04750
04751 p=strchr(tmp,'\n');
04752 if (p) *p=':';
04753
04754 if (!fp) {
04755 ast_console_puts("Error opening Tracefile: [ ");
04756 ast_console_puts(global_tracefile);
04757 ast_console_puts(" ] ");
04758
04759 ast_console_puts(strerror(errno));
04760 ast_console_puts("\n");
04761 return ;
04762 }
04763
04764 fputs(tmp,fp);
04765 fputs(" ", fp);
04766 fputs(port_buf,fp);
04767 fputs(" ", fp);
04768 fputs(buf, fp);
04769
04770 fclose(fp);
04771 }
04772 }
04773
04774