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