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