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