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: 211596 $")
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], "%30d", &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 }
02436 return -1;
02437 case AST_CONTROL_RING:
02438 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02439 return -1;
02440 case AST_CONTROL_RINGING:
02441 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02442 switch (p->state) {
02443 case MISDN_ALERTING:
02444 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);
02445 break;
02446 case MISDN_CONNECTED:
02447 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);
02448 return -1;
02449 default:
02450 p->state = MISDN_ALERTING;
02451 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02452 misdn_lib_send_event( p->bc, EVENT_ALERTING);
02453
02454 if (p->other_ch && p->other_ch->bc) {
02455 if (misdn_inband_avail(p->other_ch->bc)) {
02456 chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02457 break;
02458 }
02459
02460 if (!p->other_ch->bc->nt) {
02461 chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02462 break;
02463 }
02464 }
02465
02466 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02467 ast_setstate(ast, AST_STATE_RING);
02468
02469 if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio)
02470 chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02471 else
02472 return -1;
02473 }
02474 break;
02475 case AST_CONTROL_ANSWER:
02476 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02477 start_bc_tones(p);
02478 break;
02479 case AST_CONTROL_TAKEOFFHOOK:
02480 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02481 return -1;
02482 case AST_CONTROL_OFFHOOK:
02483 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02484 return -1;
02485 case AST_CONTROL_FLASH:
02486 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02487 break;
02488 case AST_CONTROL_PROGRESS:
02489 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02490 misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02491 break;
02492 case AST_CONTROL_PROCEEDING:
02493 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02494 misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02495 break;
02496 case AST_CONTROL_CONGESTION:
02497 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02498
02499 p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02500 start_bc_tones(p);
02501 misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02502
02503 if (p->bc->nt) {
02504 hanguptone_indicate(p);
02505 }
02506 break;
02507 case -1 :
02508 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02509
02510 stop_indicate(p);
02511
02512 if (p->state == MISDN_CONNECTED)
02513 start_bc_tones(p);
02514 break;
02515 case AST_CONTROL_HOLD:
02516 ast_moh_start(ast, data, p->mohinterpret);
02517 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02518 break;
02519 case AST_CONTROL_UNHOLD:
02520 ast_moh_stop(ast);
02521 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02522 break;
02523 default:
02524 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02525 }
02526
02527 return 0;
02528 }
02529
02530 static int misdn_hangup(struct ast_channel *ast)
02531 {
02532 struct chan_list *p;
02533 struct misdn_bchannel *bc = NULL;
02534 const char *varcause = NULL;
02535
02536 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
02537
02538 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
02539
02540 if (!p) {
02541 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
02542 return 0 ;
02543 }
02544
02545 bc = p->bc;
02546
02547 if (bc) {
02548 const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
02549 if (tmp) {
02550 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
02551 strcpy(bc->uu, tmp);
02552 bc->uulen=strlen(bc->uu);
02553 }
02554 }
02555
02556 MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02557 p->ast = NULL;
02558
02559 if (ast->_state == AST_STATE_RESERVED ||
02560 p->state == MISDN_NOTHING ||
02561 p->state == MISDN_HOLDED ||
02562 p->state == MISDN_HOLD_DISCONNECT ) {
02563
02564 CLEAN_CH:
02565
02566 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
02567 MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02568
02569 ast_mutex_lock(&release_lock);
02570 cl_dequeue_chan(&cl_te, p);
02571 close(p->pipe[0]);
02572 close(p->pipe[1]);
02573 free(p);
02574 ast_mutex_unlock(&release_lock);
02575
02576 if (bc)
02577 misdn_lib_release(bc);
02578
02579 return 0;
02580 }
02581
02582 if (!bc) {
02583 ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02584 goto CLEAN_CH;
02585 }
02586
02587
02588 p->need_hangup = 0;
02589 p->need_queue_hangup = 0;
02590 p->need_busy = 0;
02591
02592
02593 if (!p->bc->nt)
02594 stop_bc_tones(p);
02595
02596 bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02597
02598 if ((varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02599 (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02600 int tmpcause = atoi(varcause);
02601 bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02602 }
02603
02604 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));
02605 chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02606 chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02607 chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02608 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02609
02610 switch (p->state) {
02611 case MISDN_INCOMING_SETUP:
02612
02613
02614
02615 ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02616 release_chan(bc);
02617
02618 p->state = MISDN_CLEANING;
02619 if (bc->need_release_complete)
02620 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02621 break;
02622 case MISDN_HOLDED:
02623 case MISDN_DIALING:
02624 start_bc_tones(p);
02625 hanguptone_indicate(p);
02626
02627 if (bc->need_disconnect)
02628 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02629 break;
02630 case MISDN_CALLING_ACKNOWLEDGE:
02631 start_bc_tones(p);
02632 hanguptone_indicate(p);
02633
02634 if (bc->need_disconnect)
02635 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02636 break;
02637
02638 case MISDN_CALLING:
02639 case MISDN_ALERTING:
02640 case MISDN_PROGRESS:
02641 case MISDN_PROCEEDING:
02642 if (p->originator != ORG_AST)
02643 hanguptone_indicate(p);
02644
02645
02646 if (bc->need_disconnect)
02647 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02648 break;
02649 case MISDN_CONNECTED:
02650 case MISDN_PRECONNECTED:
02651
02652 if (p->bc->nt) {
02653 start_bc_tones(p);
02654 hanguptone_indicate(p);
02655 p->bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
02656 }
02657 if (bc->need_disconnect)
02658 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02659
02660
02661 break;
02662 case MISDN_DISCONNECTED:
02663 if (bc->need_release)
02664 misdn_lib_send_event( bc, EVENT_RELEASE);
02665 p->state = MISDN_CLEANING;
02666 break;
02667
02668 case MISDN_RELEASED:
02669 case MISDN_CLEANING:
02670 p->state = MISDN_CLEANING;
02671 break;
02672
02673 case MISDN_BUSY:
02674 break;
02675
02676 case MISDN_HOLD_DISCONNECT:
02677
02678 chan_misdn_log(1, bc->port, " --> cause %d\n", bc->cause);
02679 chan_misdn_log(1, bc->port, " --> out_cause %d\n", bc->out_cause);
02680
02681 bc->out_cause = -1;
02682 if (bc->need_release)
02683 misdn_lib_send_event(bc, EVENT_RELEASE);
02684 p->state = MISDN_CLEANING;
02685 break;
02686 default:
02687 if (bc->nt) {
02688 bc->out_cause = -1;
02689 if (bc->need_release)
02690 misdn_lib_send_event(bc, EVENT_RELEASE);
02691 p->state = MISDN_CLEANING;
02692 } else {
02693 if (bc->need_disconnect)
02694 misdn_lib_send_event(bc, EVENT_DISCONNECT);
02695 }
02696 }
02697
02698 p->state = MISDN_CLEANING;
02699
02700 chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
02701
02702 return 0;
02703 }
02704
02705
02706 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
02707 {
02708 struct ast_frame *f,*f2;
02709
02710 if (tmp->trans) {
02711 f2 = ast_translate(tmp->trans, frame, 0);
02712 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02713 } else {
02714 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02715 return NULL;
02716 }
02717
02718 if (!f || (f->frametype != AST_FRAME_DTMF))
02719 return frame;
02720
02721 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
02722
02723 if (tmp->faxdetect && (f->subclass == 'f')) {
02724
02725 if (!tmp->faxhandled) {
02726 struct ast_channel *ast = tmp->ast;
02727 tmp->faxhandled++;
02728 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02729 tmp->bc->rxgain = 0;
02730 isdn_lib_update_rxgain(tmp->bc);
02731 tmp->bc->txgain = 0;
02732 isdn_lib_update_txgain(tmp->bc);
02733 #ifdef MISDN_1_2
02734 *tmp->bc->pipeline = 0;
02735 #else
02736 tmp->bc->ec_enable = 0;
02737 #endif
02738 isdn_lib_update_ec(tmp->bc);
02739 isdn_lib_stop_dtmf(tmp->bc);
02740 switch (tmp->faxdetect) {
02741 case 1:
02742 if (strcmp(ast->exten, "fax")) {
02743 char *context;
02744 char context_tmp[BUFFERSIZE];
02745 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02746 context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02747 if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02748 if (option_verbose > 2)
02749 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02750
02751 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02752 if (ast_async_goto(ast, context, "fax", 1))
02753 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02754 } else
02755 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02756 } else {
02757 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02758 }
02759 break;
02760 case 2:
02761 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02762 break;
02763 }
02764 } else {
02765 ast_log(LOG_DEBUG, "Fax already handled\n");
02766 }
02767 }
02768
02769 if (tmp->ast_dsp && (f->subclass != 'f')) {
02770 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02771 }
02772
02773 return f;
02774 }
02775
02776
02777 static struct ast_frame *misdn_read(struct ast_channel *ast)
02778 {
02779 struct chan_list *tmp;
02780 fd_set rrfs;
02781 struct timeval tv;
02782 int len, t;
02783
02784 if (!ast) {
02785 chan_misdn_log(1, 0, "misdn_read called without ast\n");
02786 return NULL;
02787 }
02788 if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
02789 chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
02790 return NULL;
02791 }
02792
02793 if (!tmp->bc && !(tmp->state == MISDN_HOLDED)) {
02794 chan_misdn_log(1, 0, "misdn_read called without bc\n");
02795 return NULL;
02796 }
02797
02798 tv.tv_sec=0;
02799 tv.tv_usec=20000;
02800
02801 FD_ZERO(&rrfs);
02802 FD_SET(tmp->pipe[0],&rrfs);
02803
02804 t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
02805
02806 if (!t) {
02807 chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
02808 len=160;
02809 }
02810
02811 if (t<0) {
02812 chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
02813 return NULL;
02814 }
02815
02816 if (FD_ISSET(tmp->pipe[0],&rrfs)) {
02817 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
02818
02819 if (len<=0) {
02820
02821 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
02822 return NULL;
02823 }
02824
02825 } else {
02826 return NULL;
02827 }
02828
02829 tmp->frame.frametype = AST_FRAME_VOICE;
02830 tmp->frame.subclass = AST_FORMAT_ALAW;
02831 tmp->frame.datalen = len;
02832 tmp->frame.samples = len;
02833 tmp->frame.mallocd = 0;
02834 tmp->frame.offset = 0;
02835 tmp->frame.delivery = ast_tv(0,0);
02836 tmp->frame.src = NULL;
02837 tmp->frame.data = tmp->ast_rd_buf;
02838
02839 if (tmp->faxdetect && !tmp->faxhandled) {
02840 if (tmp->faxdetect_timeout) {
02841 if (ast_tvzero(tmp->faxdetect_tv)) {
02842 tmp->faxdetect_tv = ast_tvnow();
02843 chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
02844 return process_ast_dsp(tmp, &tmp->frame);
02845 } else {
02846 struct timeval tv_now = ast_tvnow();
02847 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
02848 if (diff <= (tmp->faxdetect_timeout * 1000)) {
02849 chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
02850 return process_ast_dsp(tmp, &tmp->frame);
02851 } else {
02852 chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
02853 tmp->faxdetect = 0;
02854 return &tmp->frame;
02855 }
02856 }
02857 } else {
02858 chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
02859 return process_ast_dsp(tmp, &tmp->frame);
02860 }
02861 } else {
02862 if (tmp->ast_dsp)
02863 return process_ast_dsp(tmp, &tmp->frame);
02864 else
02865 return &tmp->frame;
02866 }
02867 }
02868
02869
02870 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
02871 {
02872 struct chan_list *ch;
02873 int i = 0;
02874
02875 if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02876
02877 if (ch->state == MISDN_HOLDED) {
02878 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
02879 return 0;
02880 }
02881
02882 if (!ch->bc ) {
02883 ast_log(LOG_WARNING, "private but no bc\n");
02884 return -1;
02885 }
02886
02887 if (ch->notxtone) {
02888 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
02889 return 0;
02890 }
02891
02892
02893 if (!frame->subclass) {
02894 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
02895 return 0;
02896 }
02897
02898 if (!(frame->subclass & prefformat)) {
02899
02900 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
02901 return 0;
02902 }
02903
02904
02905 if (!frame->samples ) {
02906 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
02907
02908 if (!strcmp(frame->src,"ast_prod")) {
02909 chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
02910
02911 if (ch->ts) {
02912 chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
02913 misdn_lib_tone_generator_start(ch->bc);
02914 }
02915 return 0;
02916 }
02917
02918 return -1;
02919 }
02920
02921 if ( ! ch->bc->addr ) {
02922 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
02923 return 0;
02924 }
02925
02926 #ifdef MISDN_DEBUG
02927 {
02928 int i, max = 5 > frame->samples ? frame->samples : 5;
02929
02930 printf("write2mISDN %p %d bytes: ", p, frame->samples);
02931
02932 for (i = 0; i < max; i++)
02933 printf("%2.2x ", ((char*) frame->data)[i]);
02934 printf ("\n");
02935 }
02936 #endif
02937
02938 switch (ch->bc->bc_state) {
02939 case BCHAN_ACTIVATED:
02940 case BCHAN_BRIDGED:
02941 break;
02942 default:
02943 if (!ch->dropped_frame_cnt)
02944 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);
02945
02946 ch->dropped_frame_cnt++;
02947 if (ch->dropped_frame_cnt > 100) {
02948 ch->dropped_frame_cnt = 0;
02949 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);
02950 }
02951
02952 return 0;
02953 }
02954
02955 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
02956 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
02957
02958 if (misdn_jb_fill(ch->jb, frame->data, frame->samples) < 0) {
02959 if (ch->bc->active)
02960 cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
02961 }
02962
02963 } else {
02964
02965 i = misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
02966 }
02967
02968 return 0;
02969 }
02970
02971
02972
02973
02974 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
02975 struct ast_channel *c1, int flags,
02976 struct ast_frame **fo,
02977 struct ast_channel **rc,
02978 int timeoutms)
02979
02980 {
02981 struct chan_list *ch1, *ch2;
02982 struct ast_channel *carr[2], *who;
02983 int to = -1;
02984 struct ast_frame *f;
02985 int p1_b, p2_b;
02986 int bridging;
02987
02988 ch1 = get_chan_by_ast(c0);
02989 ch2 = get_chan_by_ast(c1);
02990
02991 carr[0] = c0;
02992 carr[1] = c1;
02993
02994 if (!(ch1 && ch2))
02995 return -1;
02996
02997 misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(int));
02998 misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(int));
02999
03000 if (! p1_b || ! p2_b) {
03001 ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03002 return AST_BRIDGE_FAILED;
03003 }
03004
03005 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03006 if (bridging) {
03007
03008 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03009 misdn_lib_bridge(ch1->bc, ch2->bc);
03010 }
03011
03012 if (option_verbose > 2)
03013 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03014
03015 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03016
03017 if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
03018 ch1->ignore_dtmf = 1;
03019
03020 if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
03021 ch2->ignore_dtmf = 1;
03022
03023 for (;;) {
03024 to = -1;
03025 who = ast_waitfor_n(carr, 2, &to);
03026
03027 if (!who) {
03028 ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03029 break;
03030 }
03031 f = ast_read(who);
03032
03033 if (!f || f->frametype == AST_FRAME_CONTROL) {
03034
03035
03036 if (!f)
03037 chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03038 else
03039 chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03040
03041 *fo = f;
03042 *rc = who;
03043 break;
03044 }
03045
03046 if ( f->frametype == AST_FRAME_DTMF ) {
03047 chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03048
03049 *fo = f;
03050 *rc = who;
03051 break;
03052 }
03053
03054 #if 0
03055 if (f->frametype == AST_FRAME_VOICE) {
03056 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03057
03058 continue;
03059 }
03060 #endif
03061
03062 if (who == c0) {
03063 ast_write(c1, f);
03064 }
03065 else {
03066 ast_write(c0, f);
03067 }
03068 }
03069
03070 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03071
03072 misdn_lib_split_bridge(ch1->bc, ch2->bc);
03073
03074 return AST_BRIDGE_COMPLETE;
03075 }
03076
03077
03078
03079 static int dialtone_indicate(struct chan_list *cl)
03080 {
03081 const struct tone_zone_sound *ts = NULL;
03082 struct ast_channel *ast = cl->ast;
03083 int nd = 0;
03084
03085 if (!ast) {
03086 chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03087 return -1;
03088 }
03089
03090 misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03091
03092 if (nd) {
03093 chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03094 return 0;
03095 }
03096
03097 chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03098 ts = ast_get_indication_tone(ast->zone, "dial");
03099 cl->ts = ts;
03100
03101 if (ts) {
03102 cl->notxtone = 0;
03103 cl->norxtone = 0;
03104
03105 ast_playtones_start(ast, 0, ts->data, 0);
03106 }
03107
03108 return 0;
03109 }
03110
03111 static int hanguptone_indicate(struct chan_list *cl)
03112 {
03113 misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03114 return 0;
03115 }
03116
03117 static int stop_indicate(struct chan_list *cl)
03118 {
03119 struct ast_channel *ast = cl->ast;
03120
03121 if (!ast) {
03122 chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03123 return -1;
03124 }
03125
03126 chan_misdn_log(3, cl->bc->port, " --> None\n");
03127 misdn_lib_tone_generator_stop(cl->bc);
03128 ast_playtones_stop(ast);
03129
03130 cl->ts = NULL;
03131
03132
03133 return 0;
03134 }
03135
03136
03137 static int start_bc_tones(struct chan_list* cl)
03138 {
03139 misdn_lib_tone_generator_stop(cl->bc);
03140 cl->notxtone = 0;
03141 cl->norxtone = 0;
03142 return 0;
03143 }
03144
03145 static int stop_bc_tones(struct chan_list *cl)
03146 {
03147 if (!cl) return -1;
03148
03149 cl->notxtone = 1;
03150 cl->norxtone = 1;
03151
03152 return 0;
03153 }
03154
03155
03156 static struct chan_list *init_chan_list(int orig)
03157 {
03158 struct chan_list *cl;
03159
03160 cl = calloc(1, sizeof(struct chan_list));
03161 if (!cl) {
03162 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03163 return NULL;
03164 }
03165
03166 cl->originator = orig;
03167 cl->need_queue_hangup = 1;
03168 cl->need_hangup = 1;
03169 cl->need_busy = 1;
03170 cl->overlap_dial_task = -1;
03171
03172 return cl;
03173 }
03174
03175 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
03176 {
03177 struct ast_channel *tmp = NULL;
03178 char group[BUFFERSIZE + 1] = "";
03179 char dial_str[128];
03180 char *buf2 = ast_strdupa(data);
03181 char *ext;
03182 char *port_str;
03183 char *p = NULL;
03184 int channel = 0;
03185 int port = 0;
03186 struct misdn_bchannel *newbc = NULL;
03187 int dec = 0;
03188
03189 struct chan_list *cl = init_chan_list(ORG_AST);
03190
03191 snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201 port_str = strsep(&buf2, "/");
03202 if (!ast_strlen_zero(port_str)) {
03203 if (port_str[0] == 'g' && port_str[1] == ':' ) {
03204
03205 port_str += 2;
03206 ast_copy_string(group, port_str, sizeof(group));
03207 chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03208 } else if ((p = strchr(port_str, ':'))) {
03209
03210 *p = 0;
03211 channel = atoi(++p);
03212 port = atoi(port_str);
03213 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03214 } else {
03215 port = atoi(port_str);
03216 }
03217 } else {
03218 ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
03219 return NULL;
03220 }
03221
03222 ext = strsep(&buf2, "/");
03223 if (!ext) {
03224 ext = "";
03225 }
03226
03227 if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03228 chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
03229 dec = 1;
03230 }
03231
03232 if (!ast_strlen_zero(group)) {
03233 char cfg_group[BUFFERSIZE + 1];
03234 struct robin_list *rr = NULL;
03235
03236
03237
03238 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03239 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03240 rr = get_robin_position(group);
03241 }
03242
03243 if (rr) {
03244 int port_start = 0;
03245 int port_bak = rr->port;
03246 int chan_bak = rr->channel;
03247
03248 if (!rr->port)
03249 rr->port = misdn_cfg_get_next_port_spin(rr->port);
03250
03251 for (; rr->port > 0; rr->port = misdn_cfg_get_next_port_spin(rr->port)) {
03252 int port_up;
03253 int check;
03254 int max_chan;
03255 int last_chance = 0;
03256
03257 misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03258 if (strcasecmp(cfg_group, group))
03259 continue;
03260
03261 misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03262 port_up = misdn_lib_port_up(rr->port, check);
03263
03264 if (check && !port_up)
03265 chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
03266
03267 if (check && port_up < 0)
03268 ast_log(LOG_WARNING,"This port (%d) is blocked\n", rr->port);
03269
03270 if ((port_start == rr->port) && (port_up <= 0))
03271 break;
03272
03273 if (!port_start)
03274 port_start = rr->port;
03275
03276 if (port_up <= 0)
03277 continue;
03278
03279 max_chan = misdn_lib_get_maxchans(rr->port);
03280
03281 for (++rr->channel; !last_chance && rr->channel <= max_chan; ++rr->channel) {
03282 if (rr->port == port_bak && rr->channel == chan_bak)
03283 last_chance = 1;
03284
03285 chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr->port, rr->channel);
03286 newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0);
03287 if (newbc) {
03288 chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03289 if (port_up)
03290 chan_misdn_log(4, rr->port, "portup:%d\n", port_up);
03291 port = rr->port;
03292 break;
03293 }
03294 }
03295
03296 if (newbc || last_chance)
03297 break;
03298
03299 rr->channel = 0;
03300 }
03301 if (!newbc) {
03302 rr->port = port_bak;
03303 rr->channel = chan_bak;
03304 }
03305 } else {
03306 for (port = misdn_cfg_get_next_port(0); port > 0;
03307 port = misdn_cfg_get_next_port(port)) {
03308
03309 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03310
03311 chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03312 if (!strcasecmp(cfg_group, group)) {
03313 int port_up;
03314 int check;
03315 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03316 port_up = misdn_lib_port_up(port, check);
03317
03318 chan_misdn_log(4, port, "portup:%d\n", port_up);
03319
03320 if (port_up > 0) {
03321 newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03322 if (newbc)
03323 break;
03324 }
03325 }
03326 }
03327 }
03328
03329
03330 if (!newbc) {
03331 ast_log(LOG_WARNING,
03332 "Could not Dial out on group '%s'.\n"
03333 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03334 "\tOr there was no free channel on none of the ports\n\n"
03335 , group);
03336 return NULL;
03337 }
03338 } else {
03339
03340 if (channel)
03341 chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03342 newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03343
03344 if (!newbc) {
03345 ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03346 return NULL;
03347 }
03348 }
03349
03350
03351
03352 cl->bc = newbc;
03353
03354 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03355 if (!tmp) {
03356 ast_log(LOG_ERROR,"Could not create Asterisk object\n");
03357 return NULL;
03358 }
03359
03360 cl->ast=tmp;
03361
03362
03363 cl_queue_chan(&cl_te, cl) ;
03364
03365
03366 read_config(cl, ORG_AST);
03367
03368
03369 cl->need_hangup = 0;
03370
03371 return tmp;
03372 }
03373
03374
03375 static int misdn_send_text(struct ast_channel *chan, const char *text)
03376 {
03377 struct chan_list *tmp = chan->tech_pvt;
03378
03379 if (tmp && tmp->bc) {
03380 ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03381 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03382 } else {
03383 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03384 return -1;
03385 }
03386
03387 return 0;
03388 }
03389
03390 static struct ast_channel_tech misdn_tech = {
03391 .type = "mISDN",
03392 .description = "Channel driver for mISDN Support (Bri/Pri)",
03393 .capabilities = AST_FORMAT_ALAW ,
03394 .requester = misdn_request,
03395 .send_digit_begin = misdn_digit_begin,
03396 .send_digit_end = misdn_digit_end,
03397 .call = misdn_call,
03398 .bridge = misdn_bridge,
03399 .hangup = misdn_hangup,
03400 .answer = misdn_answer,
03401 .read = misdn_read,
03402 .write = misdn_write,
03403 .indicate = misdn_indication,
03404 .fixup = misdn_fixup,
03405 .send_text = misdn_send_text,
03406 .properties = 0
03407 };
03408
03409 static struct ast_channel_tech misdn_tech_wo_bridge = {
03410 .type = "mISDN",
03411 .description = "Channel driver for mISDN Support (Bri/Pri)",
03412 .capabilities = AST_FORMAT_ALAW ,
03413 .requester = misdn_request,
03414 .send_digit_begin = misdn_digit_begin,
03415 .send_digit_end = misdn_digit_end,
03416 .call = misdn_call,
03417 .hangup = misdn_hangup,
03418 .answer = misdn_answer,
03419 .read = misdn_read,
03420 .write = misdn_write,
03421 .indicate = misdn_indication,
03422 .fixup = misdn_fixup,
03423 .send_text = misdn_send_text,
03424 .properties = 0
03425 };
03426
03427
03428 static int glob_channel = 0;
03429
03430 static void update_name(struct ast_channel *tmp, int port, int c)
03431 {
03432 int chan_offset = 0;
03433 int tmp_port = misdn_cfg_get_next_port(0);
03434 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03435 if (tmp_port == port)
03436 break;
03437 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03438 }
03439 if (c < 0)
03440 c = 0;
03441
03442 ast_string_field_build(tmp, name, "%s/%d-u%d",
03443 misdn_type, chan_offset + c, glob_channel++);
03444
03445 chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03446 }
03447
03448 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
03449 {
03450 struct ast_channel *tmp;
03451 char *cid_name = 0, *cid_num = 0;
03452 int chan_offset = 0;
03453 int tmp_port = misdn_cfg_get_next_port(0);
03454 int bridging;
03455
03456 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03457 if (tmp_port == port)
03458 break;
03459 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03460 }
03461 if (c < 0)
03462 c = 0;
03463
03464 if (callerid) {
03465 ast_callerid_parse(callerid, &cid_name, &cid_num);
03466 }
03467
03468 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03469 if (tmp) {
03470 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03471
03472 tmp->nativeformats = prefformat;
03473
03474 tmp->readformat = format;
03475 tmp->rawreadformat = format;
03476 tmp->writeformat = format;
03477 tmp->rawwriteformat = format;
03478
03479 tmp->tech_pvt = chlist;
03480
03481 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03482
03483 if (bridging)
03484 tmp->tech = &misdn_tech;
03485 else
03486 tmp->tech = &misdn_tech_wo_bridge;
03487
03488 tmp->writeformat = format;
03489 tmp->readformat = format;
03490 tmp->priority=1;
03491
03492 if (exten)
03493 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03494 else
03495 chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03496
03497 if (callerid)
03498
03499
03500 tmp->cid.cid_ani = ast_strdup(cid_num);
03501
03502 if (pipe(chlist->pipe) < 0)
03503 perror("Pipe failed\n");
03504 tmp->fds[0] = chlist->pipe[0];
03505
03506 if (state == AST_STATE_RING)
03507 tmp->rings = 1;
03508 else
03509 tmp->rings = 0;
03510
03511 ast_jb_configure(tmp, misdn_get_global_jbconf());
03512 } else {
03513 chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03514 }
03515
03516 return tmp;
03517 }
03518
03519 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
03520 {
03521 struct chan_list *help = list;
03522 for (; help; help = help->next) {
03523 if (help->bc == bc) return help;
03524 }
03525
03526 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03527
03528 return NULL;
03529 }
03530
03531 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
03532 {
03533 struct chan_list *help = list;
03534 for (; help; help = help->next) {
03535 if ( help->bc && (help->bc->pid == pid) ) return help;
03536 }
03537
03538 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03539
03540 return NULL;
03541 }
03542
03543 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
03544 {
03545 struct chan_list *help = list;
03546
03547 if (bc->pri) return NULL;
03548
03549 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03550 for (;help; help = help->next) {
03551 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state == MISDN_HOLDED, help->hold_info.channel);
03552 if ((help->state == MISDN_HOLDED) &&
03553 (help->hold_info.port == bc->port))
03554 return help;
03555 }
03556 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03557
03558 return NULL;
03559 }
03560
03561
03562 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
03563 {
03564 struct chan_list *help = list;
03565
03566 for (; help; help = help->next) {
03567 if ( (help->state == MISDN_HOLDED) &&
03568 (help->l3id == l3_id)
03569 )
03570 return help;
03571 }
03572
03573 return NULL;
03574 }
03575
03576 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
03577 {
03578 chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03579
03580 ast_mutex_lock(&cl_te_lock);
03581 if (!*list) {
03582 *list = chan;
03583 } else {
03584 struct chan_list *help = *list;
03585 for (; help->next; help = help->next);
03586 help->next = chan;
03587 }
03588 chan->next = NULL;
03589 ast_mutex_unlock(&cl_te_lock);
03590 }
03591
03592 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
03593 {
03594 struct chan_list *help;
03595
03596 if (chan->dsp)
03597 ast_dsp_free(chan->dsp);
03598 if (chan->trans)
03599 ast_translator_free_path(chan->trans);
03600
03601 ast_mutex_lock(&cl_te_lock);
03602 if (!*list) {
03603 ast_mutex_unlock(&cl_te_lock);
03604 return;
03605 }
03606
03607 if (*list == chan) {
03608 *list = (*list)->next;
03609 ast_mutex_unlock(&cl_te_lock);
03610 return;
03611 }
03612
03613 for (help = *list; help->next; help = help->next) {
03614 if (help->next == chan) {
03615 help->next = help->next->next;
03616 ast_mutex_unlock(&cl_te_lock);
03617 return;
03618 }
03619 }
03620
03621 ast_mutex_unlock(&cl_te_lock);
03622 }
03623
03624
03625
03626
03627 static int pbx_start_chan(struct chan_list *ch)
03628 {
03629 int ret = ast_pbx_start(ch->ast);
03630
03631 if (ret >= 0)
03632 ch->need_hangup = 0;
03633 else
03634 ch->need_hangup = 1;
03635
03636 return ret;
03637 }
03638
03639 static void hangup_chan(struct chan_list *ch)
03640 {
03641 int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
03642 if (!ch) {
03643 cb_log(1, 0, "Cannot hangup chan, no ch\n");
03644 return;
03645 }
03646
03647 cb_log(5, port, "hangup_chan called\n");
03648
03649 if (ch->need_hangup) {
03650 cb_log(2, port, " --> hangup\n");
03651 send_cause2ast(ch->ast, ch->bc, ch);
03652 ch->need_hangup = 0;
03653 ch->need_queue_hangup = 0;
03654 if (ch->ast)
03655 ast_hangup(ch->ast);
03656 return;
03657 }
03658
03659 if (!ch->need_queue_hangup) {
03660 cb_log(2, port, " --> No need to queue hangup\n");
03661 }
03662
03663 ch->need_queue_hangup = 0;
03664 if (ch->ast) {
03665 send_cause2ast(ch->ast, ch->bc, ch);
03666
03667 if (ch->ast)
03668 ast_queue_hangup(ch->ast);
03669 cb_log(2, port, " --> queue_hangup\n");
03670 } else {
03671 cb_log(1, port, "Cannot hangup chan, no ast\n");
03672 }
03673 }
03674
03675
03676 static void release_chan(struct misdn_bchannel *bc) {
03677 struct ast_channel *ast = NULL;
03678
03679 ast_mutex_lock(&release_lock);
03680 {
03681 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03682 if (!ch) {
03683 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03684 ast_mutex_unlock(&release_lock);
03685 return;
03686 }
03687
03688 if (ch->ast) {
03689 ast = ch->ast;
03690 }
03691
03692 chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
03693
03694
03695 if (ch->jb ) {
03696 misdn_jb_destroy(ch->jb);
03697 ch->jb = NULL;
03698 } else {
03699 if (!bc->nojitter)
03700 chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03701 }
03702
03703 if (ch->overlap_dial) {
03704 if (ch->overlap_dial_task != -1) {
03705 misdn_tasks_remove(ch->overlap_dial_task);
03706 ch->overlap_dial_task = -1;
03707 }
03708 ast_mutex_destroy(&ch->overlap_tv_lock);
03709 }
03710
03711 if (ch->originator == ORG_AST) {
03712 misdn_out_calls[bc->port]--;
03713 } else {
03714 misdn_in_calls[bc->port]--;
03715 }
03716
03717 if (ch) {
03718 close(ch->pipe[0]);
03719 close(ch->pipe[1]);
03720
03721 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03722 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));
03723 chan_misdn_log(3, bc->port, " --> * State Down\n");
03724 MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03725
03726 if (ast->_state != AST_STATE_RESERVED) {
03727 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03728 ast_setstate(ast, AST_STATE_DOWN);
03729 }
03730 }
03731
03732 ch->state = MISDN_CLEANING;
03733 cl_dequeue_chan(&cl_te, ch);
03734
03735 free(ch);
03736 } else {
03737
03738 }
03739 }
03740 ast_mutex_unlock(&release_lock);
03741
03742 }
03743
03744 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
03745 {
03746 chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
03747
03748 tmp_ch->state = MISDN_HOLD_DISCONNECT;
03749
03750 ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03751
03752 holded_chan->state=MISDN_CONNECTED;
03753
03754 ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03755 }
03756
03757
03758 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
03759 {
03760 char predial[256]="";
03761 char *p = predial;
03762
03763 struct ast_frame fr;
03764
03765 strncpy(predial, ast->exten, sizeof(predial) -1 );
03766
03767 ch->state = MISDN_DIALING;
03768
03769 if (!ch->noautorespond_on_setup) {
03770 if (bc->nt) {
03771 int ret;
03772 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03773 } else {
03774 int ret;
03775 if ( misdn_lib_is_ptp(bc->port)) {
03776 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03777 } else {
03778 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03779 }
03780 }
03781 } else {
03782 ch->state = MISDN_INCOMING_SETUP;
03783 }
03784
03785 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);
03786
03787 strcpy(ast->exten, "s");
03788
03789 if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03790 ast = NULL;
03791 bc->out_cause = AST_CAUSE_UNALLOCATED;
03792 hangup_chan(ch);
03793 hanguptone_indicate(ch);
03794
03795 if (bc->nt)
03796 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03797 else
03798 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03799 }
03800
03801
03802 while (!ast_strlen_zero(p) ) {
03803 fr.frametype = AST_FRAME_DTMF;
03804 fr.subclass = *p;
03805 fr.src = NULL;
03806 fr.data = NULL;
03807 fr.datalen = 0;
03808 fr.samples = 0;
03809 fr.mallocd = 0;
03810 fr.offset = 0;
03811 fr.delivery = ast_tv(0,0);
03812
03813 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03814 ast_queue_frame(ch->ast, &fr);
03815 }
03816 p++;
03817 }
03818 }
03819
03820
03821
03822 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) {
03823 if (!ast) {
03824 chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
03825 return;
03826 }
03827 if (!bc) {
03828 chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
03829 return;
03830 }
03831 if (!ch) {
03832 chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
03833 return;
03834 }
03835
03836 ast->hangupcause = bc->cause;
03837
03838 switch (bc->cause) {
03839
03840 case AST_CAUSE_UNALLOCATED:
03841 case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
03842 case AST_CAUSE_NO_ROUTE_DESTINATION:
03843 case 4:
03844 case AST_CAUSE_NUMBER_CHANGED:
03845 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856 break;
03857
03858 case AST_CAUSE_CALL_REJECTED:
03859 case AST_CAUSE_USER_BUSY:
03860 ch->state = MISDN_BUSY;
03861
03862 if (!ch->need_busy) {
03863 chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
03864 break;
03865 }
03866
03867 chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
03868
03869 ast_queue_control(ast, AST_CONTROL_BUSY);
03870
03871 ch->need_busy = 0;
03872
03873 break;
03874 }
03875 }
03876
03877
03878
03879 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03880 {
03881 const char *tmp;
03882
03883 tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
03884 if (tmp) {
03885 ch->other_pid = atoi(tmp);
03886 chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
03887 if (ch->other_pid > 0) {
03888 ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
03889 if (ch->other_ch)
03890 ch->other_ch->other_ch = ch;
03891 }
03892 }
03893
03894 tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
03895 if (tmp && (atoi(tmp) == 1)) {
03896 bc->sending_complete = 1;
03897 }
03898
03899 tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
03900 if (tmp) {
03901 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
03902 ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
03903 bc->uulen = strlen(bc->uu);
03904 }
03905
03906 tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
03907 if (tmp) {
03908 ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
03909 }
03910 }
03911
03912
03913 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03914 {
03915 char tmp[32];
03916 chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
03917 snprintf(tmp, sizeof(tmp), "%d", bc->pid);
03918 pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
03919
03920 if (bc->sending_complete) {
03921 snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
03922 pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
03923 }
03924
03925 if (bc->urate) {
03926 snprintf(tmp, sizeof(tmp), "%d", bc->urate);
03927 pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
03928 }
03929
03930 if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
03931 bc->uu[bc->uulen] = 0;
03932 pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
03933 }
03934
03935 if (!ast_strlen_zero(bc->keypad))
03936 pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
03937 }
03938
03939 int add_in_calls(int port)
03940 {
03941 int max_in_calls;
03942
03943 misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
03944 misdn_in_calls[port]++;
03945
03946 if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
03947 ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
03948 return misdn_in_calls[port] - max_in_calls;
03949 }
03950
03951 return 0;
03952 }
03953
03954 int add_out_calls(int port)
03955 {
03956 int max_out_calls;
03957
03958 misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
03959
03960 if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
03961 ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
03962 return (misdn_out_calls[port] + 1) - max_out_calls;
03963 }
03964
03965 misdn_out_calls[port]++;
03966
03967 return 0;
03968 }
03969
03970 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03971 if (pbx_start_chan(ch) < 0) {
03972 hangup_chan(ch);
03973 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03974 if (bc->nt) {
03975 hanguptone_indicate(ch);
03976 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
03977 } else
03978 misdn_lib_send_event(bc, EVENT_RELEASE);
03979 }
03980 }
03981
03982 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03983 ch->state=MISDN_WAITING4DIGS;
03984 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03985 if (bc->nt && !bc->dad[0])
03986 dialtone_indicate(ch);
03987 }
03988
03989
03990
03991
03992
03993 static enum event_response_e
03994 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
03995 {
03996 int msn_valid;
03997 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
03998
03999 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
04000 int debuglevel = 1;
04001 if ( event == EVENT_CLEANUP && !user_data)
04002 debuglevel = 5;
04003
04004 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");
04005 if (debuglevel == 1) {
04006 misdn_lib_log_ies(bc);
04007 chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04008 }
04009 }
04010
04011 if (!ch) {
04012 switch(event) {
04013 case EVENT_SETUP:
04014 case EVENT_DISCONNECT:
04015 case EVENT_PORT_ALARM:
04016 case EVENT_RETRIEVE:
04017 case EVENT_NEW_BC:
04018 case EVENT_FACILITY:
04019 break;
04020 case EVENT_RELEASE_COMPLETE:
04021 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
04022 break;
04023 case EVENT_CLEANUP:
04024 case EVENT_TONE_GENERATE:
04025 case EVENT_BCHAN_DATA:
04026 return -1;
04027 default:
04028 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);
04029 return -1;
04030 }
04031 }
04032
04033 if (ch) {
04034 switch (event) {
04035 case EVENT_TONE_GENERATE:
04036 break;
04037 case EVENT_DISCONNECT:
04038 case EVENT_RELEASE:
04039 case EVENT_RELEASE_COMPLETE:
04040 case EVENT_CLEANUP:
04041 case EVENT_TIMEOUT:
04042 if (!ch->ast)
04043 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));
04044 break;
04045 default:
04046 if (!ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04047 if (event != EVENT_BCHAN_DATA)
04048 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04049 return -1;
04050 }
04051 }
04052 }
04053
04054
04055 switch (event) {
04056 case EVENT_PORT_ALARM:
04057 {
04058 int boa = 0;
04059 misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
04060 if (boa) {
04061 cb_log(1, bc->port, " --> blocking\n");
04062 misdn_lib_port_block(bc->port);
04063 }
04064 }
04065 break;
04066 case EVENT_BCHAN_ACTIVATED:
04067 break;
04068
04069 case EVENT_NEW_CHANNEL:
04070 update_name(ch->ast,bc->port,bc->channel);
04071 break;
04072
04073 case EVENT_NEW_L3ID:
04074 ch->l3id=bc->l3_id;
04075 ch->addr=bc->addr;
04076 break;
04077
04078 case EVENT_NEW_BC:
04079 if (!ch) {
04080 ch = find_holded(cl_te,bc);
04081 }
04082
04083 if (!ch) {
04084 ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04085 break;
04086 }
04087
04088 if (bc)
04089 ch->bc = (struct misdn_bchannel *)user_data;
04090 break;
04091
04092 case EVENT_DTMF_TONE:
04093 {
04094
04095 struct ast_frame fr;
04096
04097 memset(&fr, 0, sizeof(fr));
04098 fr.frametype = AST_FRAME_DTMF;
04099 fr.subclass = bc->dtmf ;
04100 fr.src = NULL;
04101 fr.data = NULL;
04102 fr.datalen = 0;
04103 fr.samples = 0;
04104 fr.mallocd = 0;
04105 fr.offset = 0;
04106 fr.delivery = ast_tv(0,0);
04107
04108 if (!ch->ignore_dtmf) {
04109 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04110 ast_queue_frame(ch->ast, &fr);
04111 } else {
04112 chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04113 }
04114 }
04115 break;
04116 case EVENT_STATUS:
04117 break;
04118
04119 case EVENT_INFORMATION:
04120 {
04121 if ( ch->state != MISDN_CONNECTED )
04122 stop_indicate(ch);
04123
04124 if (!ch->ast)
04125 break;
04126
04127 if (ch->state == MISDN_WAITING4DIGS ) {
04128
04129 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04130 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04131 ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04132 }
04133
04134 strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04135 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04136
04137
04138 if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04139 if (ast_pickup_call(ch->ast)) {
04140 hangup_chan(ch);
04141 } else {
04142 struct ast_channel *chan = ch->ast;
04143 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04144 ast_setstate(chan, AST_STATE_DOWN);
04145 hangup_chan(ch);
04146 ch->ast = NULL;
04147 break;
04148 }
04149 }
04150
04151 if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04152 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04153 ast_log(LOG_WARNING,
04154 "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04155 bc->dad, ch->context, bc->port);
04156 strcpy(ch->ast->exten, "i");
04157
04158 ch->state = MISDN_DIALING;
04159 start_pbx(ch, bc, ch->ast);
04160 break;
04161 }
04162
04163 ast_log(LOG_WARNING,
04164 "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04165 "\tMaybe you want to add an 'i' extension to catch this case.\n",
04166 bc->dad, ch->context, bc->port);
04167
04168 if (bc->nt)
04169 hanguptone_indicate(ch);
04170 ch->state = MISDN_EXTCANTMATCH;
04171 bc->out_cause = AST_CAUSE_UNALLOCATED;
04172
04173 misdn_lib_send_event(bc, EVENT_DISCONNECT);
04174 break;
04175 }
04176
04177 if (ch->overlap_dial) {
04178 ast_mutex_lock(&ch->overlap_tv_lock);
04179 ch->overlap_tv = ast_tvnow();
04180 ast_mutex_unlock(&ch->overlap_tv_lock);
04181 if (ch->overlap_dial_task == -1) {
04182 ch->overlap_dial_task =
04183 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04184 }
04185 break;
04186 }
04187
04188 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04189
04190 ch->state = MISDN_DIALING;
04191 start_pbx(ch, bc, ch->ast);
04192 }
04193 } else {
04194
04195 struct ast_frame fr;
04196 int digits;
04197
04198 memset(&fr, 0, sizeof(fr));
04199 fr.frametype = AST_FRAME_DTMF;
04200 fr.subclass = bc->info_dad[0] ;
04201 fr.src = NULL;
04202 fr.data = NULL;
04203 fr.datalen = 0;
04204 fr.samples = 0;
04205 fr.mallocd = 0;
04206 fr.offset = 0;
04207 fr.delivery = ast_tv(0,0);
04208
04209 misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
04210 if (ch->state != MISDN_CONNECTED ) {
04211 if (digits) {
04212 strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04213 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04214 ast_cdr_update(ch->ast);
04215 }
04216
04217 ast_queue_frame(ch->ast, &fr);
04218 }
04219 }
04220 }
04221 break;
04222 case EVENT_SETUP:
04223 {
04224 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04225 struct ast_channel *chan;
04226 int exceed;
04227 int pres, screen;
04228 int ai;
04229 int im;
04230
04231 if (ch) {
04232 switch (ch->state) {
04233 case MISDN_NOTHING:
04234 ch = NULL;
04235 break;
04236 default:
04237 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04238 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE;
04239 }
04240 }
04241
04242 msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04243 if (!bc->nt && ! msn_valid) {
04244 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04245 return RESPONSE_IGNORE_SETUP;
04246 }
04247
04248 if (bc->cw) {
04249 int cause;
04250 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04251 misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04252 bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
04253 return RESPONSE_RELEASE_SETUP;
04254 }
04255
04256 print_bearer(bc);
04257
04258 ch = init_chan_list(ORG_MISDN);
04259
04260 if (!ch) {
04261 chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
04262 return 0;
04263 }
04264
04265 ch->bc = bc;
04266 ch->l3id = bc->l3_id;
04267 ch->addr = bc->addr;
04268 ch->originator = ORG_MISDN;
04269
04270 chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04271 if (!chan) {
04272 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04273 ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
04274 return 0;
04275 }
04276
04277 ch->ast = chan;
04278
04279 if ((exceed = add_in_calls(bc->port))) {
04280 char tmp[16];
04281 snprintf(tmp, sizeof(tmp), "%d", exceed);
04282 pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
04283 }
04284
04285 read_config(ch, ORG_MISDN);
04286
04287 export_ch(chan, bc, ch);
04288
04289 ch->ast->rings = 1;
04290 ast_setstate(ch->ast, AST_STATE_RINGING);
04291
04292 switch (bc->pres) {
04293 case 1:
04294 pres = AST_PRES_RESTRICTED;
04295 chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
04296 break;
04297 case 2:
04298 pres = AST_PRES_UNAVAILABLE;
04299 chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
04300 break;
04301 default:
04302 pres = AST_PRES_ALLOWED;
04303 chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
04304 break;
04305 }
04306
04307 switch (bc->screen) {
04308 default:
04309 case 0:
04310 screen = AST_PRES_USER_NUMBER_UNSCREENED;
04311 chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
04312 break;
04313 case 1:
04314 screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
04315 chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
04316 break;
04317 case 2:
04318 screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
04319 chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
04320 break;
04321 case 3:
04322 screen = AST_PRES_NETWORK_NUMBER;
04323 chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
04324 break;
04325 }
04326
04327 chan->cid.cid_pres = pres | screen;
04328
04329 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04330 chan->transfercapability = bc->capability;
04331
04332 switch (bc->capability) {
04333 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04334 pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
04335 break;
04336 default:
04337 pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
04338 }
04339
04340
04341 cl_queue_chan(&cl_te, ch);
04342
04343 if (!strstr(ch->allowed_bearers, "all")) {
04344 int i;
04345
04346 for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
04347 if (allowed_bearers_array[i].cap == bc->capability) {
04348 if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
04349
04350 if (allowed_bearers_array[i].deprecated) {
04351 chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
04352 allowed_bearers_array[i].name);
04353 }
04354 break;
04355 }
04356 }
04357 }
04358 if (i == ARRAY_LEN(allowed_bearers_array)) {
04359
04360 chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
04361 bearer2str(bc->capability), bc->capability);
04362 bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
04363
04364 ch->state = MISDN_EXTCANTMATCH;
04365 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04366 return RESPONSE_OK;
04367 }
04368 }
04369
04370
04371 if (!strcmp(chan->exten, ast_pickup_ext())) {
04372 if (!ch->noautorespond_on_setup) {
04373 int ret;
04374 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04375 } else {
04376 ch->state = MISDN_INCOMING_SETUP;
04377 }
04378 if (ast_pickup_call(chan)) {
04379 hangup_chan(ch);
04380 } else {
04381 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04382 ast_setstate(chan, AST_STATE_DOWN);
04383 hangup_chan(ch);
04384 ch->ast = NULL;
04385 break;
04386 }
04387 }
04388
04389
04390
04391
04392
04393 misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04394 if (ai) {
04395 do_immediate_setup(bc, ch, chan);
04396 break;
04397 }
04398
04399
04400 misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04401 if (im && ast_strlen_zero(bc->dad)) {
04402 do_immediate_setup(bc, ch, chan);
04403 break;
04404 }
04405
04406 chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
04407 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04408 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04409 ast_log(LOG_WARNING,
04410 "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04411 bc->dad, ch->context, bc->port);
04412 strcpy(ch->ast->exten, "i");
04413 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04414 ch->state = MISDN_DIALING;
04415 start_pbx(ch, bc, chan);
04416 break;
04417 }
04418
04419 ast_log(LOG_WARNING,
04420 "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04421 "\tMaybe you want to add an 'i' extension to catch this case.\n",
04422 bc->dad, ch->context, bc->port);
04423 if (bc->nt)
04424 hanguptone_indicate(ch);
04425
04426 ch->state = MISDN_EXTCANTMATCH;
04427 bc->out_cause = AST_CAUSE_UNALLOCATED;
04428
04429 if (bc->nt)
04430 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04431 else
04432 misdn_lib_send_event(bc, EVENT_RELEASE );
04433
04434 break;
04435 }
04436
04437
04438
04439
04440 if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04441 if (!ch->noautorespond_on_setup) {
04442 ch->state=MISDN_DIALING;
04443 misdn_lib_send_event(bc, EVENT_PROCEEDING );
04444 } else {
04445 ch->state = MISDN_INCOMING_SETUP;
04446 }
04447 start_pbx(ch, bc, chan);
04448 break;
04449 }
04450
04451
04452
04453
04454
04455
04456
04457 if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04458 wait_for_digits(ch, bc, chan);
04459 break;
04460 }
04461
04462
04463
04464
04465
04466 if (ch->overlap_dial) {
04467 ast_mutex_lock(&ch->overlap_tv_lock);
04468 ch->overlap_tv = ast_tvnow();
04469 ast_mutex_unlock(&ch->overlap_tv_lock);
04470
04471 wait_for_digits(ch, bc, chan);
04472 if (ch->overlap_dial_task == -1)
04473 ch->overlap_dial_task =
04474 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04475
04476 break;
04477 }
04478
04479
04480
04481
04482 if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04483 wait_for_digits(ch, bc, chan);
04484 break;
04485 }
04486
04487
04488
04489
04490 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04491 if (bc->need_more_infos)
04492 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04493 else
04494 misdn_lib_send_event(bc, EVENT_PROCEEDING);
04495
04496 ch->state = MISDN_DIALING;
04497 start_pbx(ch, bc, chan);
04498 break;
04499 }
04500 }
04501 break;
04502
04503 case EVENT_SETUP_ACKNOWLEDGE:
04504 {
04505 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04506
04507 if (bc->channel)
04508 update_name(ch->ast,bc->port,bc->channel);
04509
04510 if (!ast_strlen_zero(bc->infos_pending)) {
04511
04512 strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04513
04514 if (!ch->ast)
04515 break;
04516 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04517 ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04518 ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04519
04520 misdn_lib_send_event(bc, EVENT_INFORMATION);
04521 }
04522 }
04523 break;
04524 case EVENT_PROCEEDING:
04525 {
04526 if (bc->channel)
04527 update_name(ch->ast, bc->port, bc->channel);
04528
04529 if (misdn_cap_is_speech(bc->capability) &&
04530 misdn_inband_avail(bc) ) {
04531 start_bc_tones(ch);
04532 }
04533
04534 ch->state = MISDN_PROCEEDING;
04535
04536 if (!ch->ast)
04537 break;
04538
04539 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04540 }
04541 break;
04542 case EVENT_PROGRESS:
04543 if (bc->channel)
04544 update_name(ch->ast, bc->port, bc->channel);
04545
04546 if (!bc->nt ) {
04547 if ( misdn_cap_is_speech(bc->capability) &&
04548 misdn_inband_avail(bc)
04549 ) {
04550 start_bc_tones(ch);
04551 }
04552
04553 ch->state = MISDN_PROGRESS;
04554
04555 if (!ch->ast)
04556 break;
04557 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04558 }
04559 break;
04560
04561
04562 case EVENT_ALERTING:
04563 {
04564 if (bc->channel)
04565 update_name(ch->ast, bc->port, bc->channel);
04566
04567 ch->state = MISDN_ALERTING;
04568
04569 if (!ch->ast)
04570 break;
04571
04572 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04573 ast_setstate(ch->ast, AST_STATE_RINGING);
04574
04575 cb_log(7, bc->port, " --> Set State Ringing\n");
04576
04577 if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04578 cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04579 start_bc_tones(ch);
04580 } else {
04581 cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04582 if (ch->far_alerting) {
04583 cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04584 start_bc_tones(ch);
04585
04586 }
04587 }
04588 }
04589 break;
04590 case EVENT_CONNECT:
04591 {
04592 struct ast_channel *bridged;
04593
04594
04595 misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04596
04597 if (!ch->ast)
04598 break;
04599
04600 bridged = ast_bridged_channel(ch->ast);
04601 stop_indicate(ch);
04602
04603 if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04604 struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04605
04606 chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04607 if (bridged_ch) {
04608 bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04609 ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04610 }
04611 }
04612 }
04613 ch->l3id=bc->l3_id;
04614 ch->addr=bc->addr;
04615
04616 start_bc_tones(ch);
04617
04618 ch->state = MISDN_CONNECTED;
04619
04620 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04621 break;
04622 case EVENT_CONNECT_ACKNOWLEDGE:
04623 {
04624 ch->l3id = bc->l3_id;
04625 ch->addr = bc->addr;
04626
04627 start_bc_tones(ch);
04628
04629 ch->state = MISDN_CONNECTED;
04630 }
04631 break;
04632 case EVENT_DISCONNECT:
04633
04634 if (ch) {
04635 struct chan_list *holded_ch = find_holded(cl_te, bc);
04636
04637 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);
04638 if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04639
04640
04641
04642
04643
04644 chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04645
04646 ch->state = MISDN_DISCONNECTED;
04647 start_bc_tones(ch);
04648
04649 if (ch->ast) {
04650 ch->ast->hangupcause = bc->cause;
04651 if (bc->cause == AST_CAUSE_USER_BUSY)
04652 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04653 }
04654 ch->need_busy = 0;
04655 break;
04656 }
04657
04658
04659 if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
04660 cb_log(1, bc->port, " --> found holded ch\n");
04661 misdn_transfer_bc(ch, holded_ch) ;
04662 }
04663
04664 bc->need_disconnect = 0;
04665
04666 stop_bc_tones(ch);
04667 hangup_chan(ch);
04668 #if 0
04669 } else {
04670 ch = find_holded_l3(cl_te, bc->l3_id,1);
04671 if (ch) {
04672 hangup_chan(ch);
04673 }
04674 #endif
04675 }
04676 bc->out_cause = -1;
04677 if (bc->need_release)
04678 misdn_lib_send_event(bc, EVENT_RELEASE);
04679 break;
04680
04681 case EVENT_RELEASE:
04682 {
04683 bc->need_disconnect = 0;
04684 bc->need_release = 0;
04685
04686 hangup_chan(ch);
04687 release_chan(bc);
04688 }
04689 break;
04690 case EVENT_RELEASE_COMPLETE:
04691 {
04692 bc->need_disconnect = 0;
04693 bc->need_release = 0;
04694 bc->need_release_complete = 0;
04695
04696 stop_bc_tones(ch);
04697 hangup_chan(ch);
04698
04699 if (ch)
04700 ch->state = MISDN_CLEANING;
04701
04702 release_chan(bc);
04703 }
04704 break;
04705 case EVENT_BCHAN_ERROR:
04706 case EVENT_CLEANUP:
04707 {
04708 stop_bc_tones(ch);
04709
04710 switch (ch->state) {
04711 case MISDN_CALLING:
04712 bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04713 break;
04714 default:
04715 break;
04716 }
04717
04718 hangup_chan(ch);
04719 release_chan(bc);
04720 }
04721 break;
04722
04723 case EVENT_TONE_GENERATE:
04724 {
04725 int tone_len = bc->tone_cnt;
04726 struct ast_channel *ast = ch->ast;
04727 void *tmp;
04728 int res;
04729 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04730
04731 chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
04732
04733 if (!ast)
04734 break;
04735
04736 if (!ast->generator)
04737 break;
04738
04739 tmp = ast->generatordata;
04740 ast->generatordata = NULL;
04741 generate = ast->generator->generate;
04742
04743 if (tone_len < 0 || tone_len > 512 ) {
04744 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
04745 tone_len = 128;
04746 }
04747
04748 res = generate(ast, tmp, tone_len, tone_len);
04749 ast->generatordata = tmp;
04750
04751 if (res) {
04752 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04753 ast_deactivate_generator(ast);
04754 } else {
04755 bc->tone_cnt = 0;
04756 }
04757 }
04758 break;
04759
04760 case EVENT_BCHAN_DATA:
04761 {
04762 if (!misdn_cap_is_speech(ch->bc->capability)) {
04763 struct ast_frame frame;
04764
04765 frame.frametype = AST_FRAME_VOICE;
04766 frame.subclass = AST_FORMAT_ALAW;
04767 frame.datalen = bc->bframe_len;
04768 frame.samples = bc->bframe_len;
04769 frame.mallocd = 0;
04770 frame.offset = 0;
04771 frame.delivery = ast_tv(0,0);
04772 frame.src = NULL;
04773 frame.data = bc->bframe;
04774
04775 if (ch->ast)
04776 ast_queue_frame(ch->ast, &frame);
04777 } else {
04778 fd_set wrfs;
04779 struct timeval tv = { 0, 0 };
04780 int t;
04781
04782 FD_ZERO(&wrfs);
04783 FD_SET(ch->pipe[1], &wrfs);
04784
04785 t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
04786
04787 if (!t) {
04788 chan_misdn_log(9, bc->port, "Select Timed out\n");
04789 break;
04790 }
04791
04792 if (t < 0) {
04793 chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
04794 break;
04795 }
04796
04797 if (FD_ISSET(ch->pipe[1], &wrfs)) {
04798 chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
04799 if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
04800 chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
04801
04802 stop_bc_tones(ch);
04803 hangup_chan(ch);
04804 release_chan(bc);
04805 }
04806 } else {
04807 chan_misdn_log(1, bc->port, "Write Pipe full!\n");
04808 }
04809 }
04810 }
04811 break;
04812 case EVENT_TIMEOUT:
04813 {
04814 if (ch && bc)
04815 chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
04816
04817 switch (ch->state) {
04818 case MISDN_DIALING:
04819 case MISDN_PROGRESS:
04820 if (bc->nt && !ch->nttimeout)
04821 break;
04822
04823 case MISDN_CALLING:
04824 case MISDN_ALERTING:
04825 case MISDN_PROCEEDING:
04826 case MISDN_CALLING_ACKNOWLEDGE:
04827 if (bc->nt) {
04828 bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
04829 hanguptone_indicate(ch);
04830 }
04831
04832 bc->out_cause = AST_CAUSE_UNALLOCATED;
04833 misdn_lib_send_event(bc, EVENT_DISCONNECT);
04834 break;
04835
04836 case MISDN_WAITING4DIGS:
04837 if (bc->nt) {
04838 bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
04839 bc->out_cause = AST_CAUSE_UNALLOCATED;
04840 hanguptone_indicate(ch);
04841 misdn_lib_send_event(bc, EVENT_DISCONNECT);
04842 } else {
04843 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
04844 misdn_lib_send_event(bc, EVENT_RELEASE);
04845 }
04846
04847 break;
04848
04849 case MISDN_CLEANING:
04850 chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
04851 break;
04852
04853 default:
04854 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04855 }
04856 }
04857 break;
04858
04859
04860
04861
04862
04863 case EVENT_RETRIEVE:
04864 {
04865 struct ast_channel *hold_ast;
04866
04867 if (!ch) {
04868 chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
04869 ch = find_holded_l3(cl_te, bc->l3_id, 1);
04870 }
04871
04872 if (!ch) {
04873 ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
04874 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04875 break;
04876 }
04877
04878
04879 ch->bc = bc;
04880 ch->state = MISDN_CONNECTED;
04881
04882 ch->hold_info.port = 0;
04883 ch->hold_info.channel = 0;
04884
04885 hold_ast = ast_bridged_channel(ch->ast);
04886
04887 if (hold_ast) {
04888 ast_moh_stop(hold_ast);
04889 }
04890
04891 if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
04892 chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
04893 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04894 }
04895 }
04896 break;
04897
04898 case EVENT_HOLD:
04899 {
04900 int hold_allowed;
04901 struct ast_channel *bridged;
04902
04903 misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04904
04905 if (!hold_allowed) {
04906
04907 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04908 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04909 break;
04910 }
04911
04912 bridged = ast_bridged_channel(ch->ast);
04913 if (bridged) {
04914 chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
04915 ch->state = MISDN_HOLDED;
04916 ch->l3id = bc->l3_id;
04917
04918 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04919
04920
04921
04922 ast_moh_start(bridged, NULL, NULL);
04923
04924
04925 ch->bc = NULL;
04926 ch->hold_info.port = bc->port;
04927 ch->hold_info.channel = bc->channel;
04928
04929 } else {
04930 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04931 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04932 }
04933 }
04934 break;
04935
04936 case EVENT_FACILITY:
04937 if (!ch) {
04938
04939 chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
04940 break;
04941 }
04942
04943 print_facility(&(bc->fac_in), bc);
04944
04945 switch (bc->fac_in.Function) {
04946 case Fac_CD:
04947 {
04948 struct ast_channel *bridged = ast_bridged_channel(ch->ast);
04949 struct chan_list *ch_br;
04950 if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04951 ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
04952
04953 if (ch_br->bc) {
04954 if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
04955 ch_br->state = MISDN_DIALING;
04956 if (pbx_start_chan(ch_br) < 0) {
04957 chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
04958 }
04959 }
04960 }
04961 }
04962 misdn_lib_send_event(bc, EVENT_DISCONNECT);
04963 }
04964 break;
04965 case Fac_AOCDCurrency:
04966 {
04967 bc->AOCDtype = Fac_AOCDCurrency;
04968 memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
04969 export_aoc_vars(ch->originator, ch->ast, bc);
04970 }
04971 break;
04972 case Fac_AOCDChargingUnit:
04973 {
04974 bc->AOCDtype = Fac_AOCDChargingUnit;
04975 memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
04976 export_aoc_vars(ch->originator, ch->ast, bc);
04977 }
04978 break;
04979 default:
04980 chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
04981 }
04982
04983 break;
04984
04985 case EVENT_RESTART:
04986
04987 if (!bc->dummy) {
04988 stop_bc_tones(ch);
04989 release_chan(bc);
04990 }
04991 break;
04992
04993 default:
04994 chan_misdn_log(1, 0, "Got Unknown Event\n");
04995 break;
04996 }
04997
04998 return RESPONSE_OK;
04999 }
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012 static int unload_module(void)
05013 {
05014
05015 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05016
05017 misdn_tasks_destroy();
05018
05019 if (!g_config_initialized)
05020 return 0;
05021
05022 ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05023
05024
05025 ast_unregister_application("misdn_set_opt");
05026 ast_unregister_application("misdn_facility");
05027 ast_unregister_application("misdn_check_l2l1");
05028
05029 ast_channel_unregister(&misdn_tech);
05030
05031 free_robin_list();
05032 misdn_cfg_destroy();
05033 misdn_lib_destroy();
05034
05035 if (misdn_debug)
05036 free(misdn_debug);
05037 if (misdn_debug_only)
05038 free(misdn_debug_only);
05039 free(misdn_ports);
05040
05041 return 0;
05042 }
05043
05044 static int load_module(void)
05045 {
05046 int i, port;
05047 int ntflags = 0, ntkc = 0;
05048 char ports[256] = "";
05049 char tempbuf[BUFFERSIZE + 1];
05050 char ntfile[BUFFERSIZE + 1];
05051 struct misdn_lib_iface iface = {
05052 .cb_event = cb_events,
05053 .cb_log = chan_misdn_log,
05054 .cb_jb_empty = chan_misdn_jb_empty,
05055 };
05056
05057 max_ports = misdn_lib_maxports_get();
05058
05059 if (max_ports <= 0) {
05060 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05061 return AST_MODULE_LOAD_DECLINE;
05062 }
05063
05064 if (misdn_cfg_init(max_ports)) {
05065 ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05066 return AST_MODULE_LOAD_DECLINE;
05067 }
05068 g_config_initialized = 1;
05069
05070 misdn_debug = (int *) malloc(sizeof(int) * (max_ports + 1));
05071 if (!misdn_debug) {
05072 ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05073 return AST_MODULE_LOAD_DECLINE;
05074 }
05075 misdn_ports = (int *) malloc(sizeof(int) * (max_ports + 1));
05076 if (!misdn_ports) {
05077 ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05078 return AST_MODULE_LOAD_DECLINE;
05079 }
05080 misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
05081 for (i = 1; i <= max_ports; i++) {
05082 misdn_debug[i] = misdn_debug[0];
05083 misdn_ports[i] = i;
05084 }
05085 *misdn_ports = 0;
05086 misdn_debug_only = (int *) calloc(max_ports + 1, sizeof(int));
05087
05088 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
05089 if (!ast_strlen_zero(tempbuf))
05090 tracing = 1;
05091
05092 misdn_in_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05093 misdn_out_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05094
05095 for (i = 1; i <= max_ports; i++) {
05096 misdn_in_calls[i] = 0;
05097 misdn_out_calls[i] = 0;
05098 }
05099
05100 ast_mutex_init(&cl_te_lock);
05101 ast_mutex_init(&release_lock);
05102
05103 misdn_cfg_update_ptp();
05104 misdn_cfg_get_ports_string(ports);
05105
05106 if (!ast_strlen_zero(ports))
05107 chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05108 if (misdn_lib_init(ports, &iface, NULL))
05109 chan_misdn_log(0, 0, "No te ports initialized\n");
05110
05111 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
05112 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
05113 misdn_lib_nt_debug_init(ntflags, ntfile);
05114
05115 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(int));
05116 misdn_lib_nt_keepcalls(ntkc);
05117
05118 if (ast_channel_register(&misdn_tech)) {
05119 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05120 unload_module();
05121 return -1;
05122 }
05123
05124 ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05125
05126 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05127 "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05128 "Sets mISDN opts. and optargs\n"
05129 "\n"
05130 "The available options are:\n"
05131 " a - Have Asterisk detect DTMF tones on called channel\n"
05132 " c - Make crypted outgoing call, optarg is keyindex\n"
05133 " d - Send display text to called phone, text is the optarg\n"
05134 " e - Perform echo cancelation on this channel,\n"
05135 " takes taps as optarg (32,64,128,256)\n"
05136 " e! - Disable echo cancelation on this channel\n"
05137 " f - Enable fax detection\n"
05138 " h - Make digital outgoing call\n"
05139 " h1 - Make HDLC mode digital outgoing call\n"
05140 " i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05141 " they will be transported inband.\n"
05142 " jb - Set jitter buffer length, optarg is length\n"
05143 " jt - Set jitter buffer upper threshold, optarg is threshold\n"
05144 " jn - Disable jitter buffer\n"
05145 " n - Disable mISDN DSP on channel.\n"
05146 " Disables: echo cancel, DTMF detection, and volume control.\n"
05147 " p - Caller ID presentation,\n"
05148 " optarg is either 'allowed' or 'restricted'\n"
05149 " s - Send Non-inband DTMF as inband\n"
05150 " vr - Rx gain control, optarg is gain\n"
05151 " vt - Tx gain control, optarg is gain\n"
05152 );
05153
05154
05155 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05156 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05157 "Sends the Facility Message FACILITY_TYPE with \n"
05158 "the given Arguments to the current ISDN Channel\n"
05159 "Supported Facilities are:\n"
05160 "\n"
05161 "type=calldeflect args=Nr where to deflect\n"
05162 );
05163
05164
05165 ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05166 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05167 "Checks if the L2 and L1 are up on either the given <port> or\n"
05168 "on the ports in the group with <groupname>\n"
05169 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05170 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05171 "\n"
05172 "This application, ensures the L1/L2 state of the Ports in a group\n"
05173 "it is intended to make the pmp_l1_check option redundant and to\n"
05174 "fix a buggy switch config from your provider\n"
05175 "\n"
05176 "a sample dialplan would look like:\n\n"
05177 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05178 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05179 "\n"
05180 );
05181
05182
05183 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
05184
05185
05186
05187 for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05188 int l1timeout;
05189 misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05190 if (l1timeout) {
05191 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05192 misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
05193 }
05194 }
05195
05196 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05197
05198 return 0;
05199 }
05200
05201
05202
05203 static int reload(void)
05204 {
05205 reload_config();
05206
05207 return 0;
05208 }
05209
05210
05211
05212 static int misdn_facility_exec(struct ast_channel *chan, void *data)
05213 {
05214 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05215 char *tok, *tokb;
05216
05217 chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05218
05219 if (strcasecmp(chan->tech->type, "mISDN")) {
05220 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05221 return -1;
05222 }
05223
05224 if (ast_strlen_zero((char *)data)) {
05225 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05226 return -1;
05227 }
05228
05229 tok = strtok_r((char*) data, "|", &tokb) ;
05230
05231 if (!tok) {
05232 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05233 return -1;
05234 }
05235
05236 if (!strcasecmp(tok, "calldeflect")) {
05237 tok = strtok_r(NULL, "|", &tokb) ;
05238
05239 if (!tok) {
05240 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05241 }
05242
05243 if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05244 ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05245 return 0;
05246 }
05247 ch->bc->fac_out.Function = Fac_CD;
05248 ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05249 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05250 } else {
05251 chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05252 }
05253
05254 return 0;
05255 }
05256
05257 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
05258 {
05259 char group[BUFFERSIZE + 1];
05260 char *port_str;
05261 int port = 0;
05262 int timeout;
05263 int dowait = 0;
05264 int port_up;
05265
05266 AST_DECLARE_APP_ARGS(args,
05267 AST_APP_ARG(grouppar);
05268 AST_APP_ARG(timeout);
05269 );
05270
05271 if (ast_strlen_zero((char *)data)) {
05272 ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05273 return -1;
05274 }
05275
05276 AST_STANDARD_APP_ARGS(args, data);
05277
05278 if (args.argc != 2) {
05279 ast_log(LOG_WARNING, "Wrong argument count\n");
05280 return 0;
05281 }
05282
05283
05284 timeout = atoi(args.timeout);
05285 port_str = args.grouppar;
05286
05287 if (port_str[0] == 'g' && port_str[1] == ':' ) {
05288
05289 port_str += 2;
05290 ast_copy_string(group, port_str, sizeof(group));
05291 chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05292
05293 for ( port = misdn_cfg_get_next_port(port);
05294 port > 0;
05295 port = misdn_cfg_get_next_port(port)) {
05296 char cfg_group[BUFFERSIZE + 1];
05297
05298 chan_misdn_log(2, 0, "trying port %d\n", port);
05299
05300 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05301
05302 if (!strcasecmp(cfg_group, group)) {
05303 port_up = misdn_lib_port_up(port, 1);
05304
05305 if (!port_up) {
05306 chan_misdn_log(2, 0, " --> port '%d'\n", port);
05307 misdn_lib_get_port_up(port);
05308 dowait = 1;
05309 }
05310 }
05311 }
05312
05313 } else {
05314 port = atoi(port_str);
05315 chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05316 port_up = misdn_lib_port_up(port, 1);
05317 if (!port_up) {
05318 misdn_lib_get_port_up(port);
05319 dowait = 1;
05320 }
05321 }
05322
05323 if (dowait) {
05324 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05325 sleep(timeout);
05326 }
05327
05328 return 0;
05329 }
05330
05331 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
05332 {
05333 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05334 char *tok, *tokb;
05335 int keyidx = 0;
05336 int rxgain = 0;
05337 int txgain = 0;
05338 int change_jitter = 0;
05339
05340 if (strcasecmp(chan->tech->type, "mISDN")) {
05341 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05342 return -1;
05343 }
05344
05345 if (ast_strlen_zero((char *)data)) {
05346 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05347 return -1;
05348 }
05349
05350 for (tok = strtok_r((char*) data, ":", &tokb);
05351 tok;
05352 tok = strtok_r(NULL, ":", &tokb) ) {
05353 int neglect = 0;
05354
05355 if (tok[0] == '!' ) {
05356 neglect = 1;
05357 tok++;
05358 }
05359
05360 switch(tok[0]) {
05361
05362 case 'd' :
05363 ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05364 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05365 break;
05366
05367 case 'n':
05368 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05369 ch->bc->nodsp = 1;
05370 break;
05371
05372 case 'j':
05373 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05374 tok++;
05375 change_jitter = 1;
05376
05377 switch ( tok[0] ) {
05378 case 'b':
05379 ch->jb_len = atoi(++tok);
05380 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05381 break;
05382 case 't' :
05383 ch->jb_upper_threshold = atoi(++tok);
05384 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05385 break;
05386 case 'n':
05387 ch->bc->nojitter = 1;
05388 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05389 break;
05390 default:
05391 ch->jb_len = 4000;
05392 ch->jb_upper_threshold = 0;
05393 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05394 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05395 }
05396 break;
05397 case 'v':
05398 tok++;
05399
05400 switch (tok[0]) {
05401 case 'r' :
05402 rxgain = atoi(++tok);
05403 if (rxgain < -8)
05404 rxgain = -8;
05405 if (rxgain > 8)
05406 rxgain = 8;
05407 ch->bc->rxgain = rxgain;
05408 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05409 break;
05410 case 't':
05411 txgain = atoi(++tok);
05412 if (txgain < -8)
05413 txgain = -8;
05414 if (txgain > 8)
05415 txgain = 8;
05416 ch->bc->txgain = txgain;
05417 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05418 break;
05419 }
05420 break;
05421
05422 case 'c':
05423 keyidx = atoi(++tok);
05424 {
05425 char keys[4096];
05426 char *key = NULL, *tmp = keys;
05427 int i;
05428 misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05429
05430 for (i = 0; i < keyidx; i++) {
05431 key = strsep(&tmp, ",");
05432 }
05433
05434 if (key) {
05435 ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05436 }
05437
05438 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05439 break;
05440 }
05441 case 'e':
05442 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05443
05444 if (neglect) {
05445 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05446 #ifdef MISDN_1_2
05447 *ch->bc->pipeline = 0;
05448 #else
05449 ch->bc->ec_enable = 0;
05450 #endif
05451 } else {
05452 #ifdef MISDN_1_2
05453 update_pipeline_config(ch->bc);
05454 #else
05455 ch->bc->ec_enable = 1;
05456 ch->bc->orig = ch->originator;
05457 tok++;
05458 if (*tok) {
05459 ch->bc->ec_deftaps = atoi(tok);
05460 }
05461 #endif
05462 }
05463
05464 break;
05465 case 'h':
05466 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05467
05468 if (strlen(tok) > 1 && tok[1] == '1') {
05469 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05470 if (!ch->bc->hdlc) {
05471 ch->bc->hdlc = 1;
05472 }
05473 }
05474 ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05475 break;
05476
05477 case 's':
05478 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05479 ch->bc->send_dtmf = 1;
05480 break;
05481
05482 case 'f':
05483 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05484 ch->faxdetect = 1;
05485 misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05486 break;
05487
05488 case 'a':
05489 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05490 ch->ast_dsp = 1;
05491 break;
05492
05493 case 'p':
05494 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05495
05496 if (strstr(tok,"allowed")) {
05497 ch->bc->pres = 0;
05498 } else if (strstr(tok, "restricted")) {
05499 ch->bc->pres = 1;
05500 } else if (strstr(tok, "not_screened")) {
05501 chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05502 ch->bc->pres = 1;
05503 }
05504 break;
05505 case 'i' :
05506 chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05507 ch->ignore_dtmf=1;
05508 break;
05509 default:
05510 break;
05511 }
05512 }
05513
05514 if (change_jitter)
05515 config_jitterbuffer(ch);
05516
05517 if (ch->faxdetect || ch->ast_dsp) {
05518 if (!ch->dsp)
05519 ch->dsp = ast_dsp_new();
05520 if (ch->dsp)
05521 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
05522 if (!ch->trans)
05523 ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05524 }
05525
05526 if (ch->ast_dsp) {
05527 chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05528 ch->bc->nodsp = 1;
05529 }
05530
05531 return 0;
05532 }
05533
05534
05535 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
05536 {
05537 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05538
05539 if (ch && ch->jb) {
05540 return misdn_jb_empty(ch->jb, buf, len);
05541 }
05542
05543 return -1;
05544 }
05545
05546
05547
05548
05549
05550
05551
05552
05553
05554 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
05555 {
05556 int i;
05557 struct misdn_jb *jb;
05558
05559 jb = malloc(sizeof(struct misdn_jb));
05560 if (!jb) {
05561 chan_misdn_log(-1, 0, "No free Mem for jb\n");
05562 return NULL;
05563 }
05564 jb->size = size;
05565 jb->upper_threshold = upper_threshold;
05566 jb->wp = 0;
05567 jb->rp = 0;
05568 jb->state_full = 0;
05569 jb->state_empty = 0;
05570 jb->bytes_wrote = 0;
05571 jb->samples = malloc(size * sizeof(char));
05572 if (!jb->samples) {
05573 free(jb);
05574 chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05575 return NULL;
05576 }
05577
05578 jb->ok = malloc(size * sizeof(char));
05579 if (!jb->ok) {
05580 free(jb->samples);
05581 free(jb);
05582 chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05583 return NULL;
05584 }
05585
05586 for (i = 0; i < size; i++)
05587 jb->ok[i] = 0;
05588
05589 ast_mutex_init(&jb->mutexjb);
05590
05591 return jb;
05592 }
05593
05594
05595 void misdn_jb_destroy(struct misdn_jb *jb)
05596 {
05597 ast_mutex_destroy(&jb->mutexjb);
05598
05599 free(jb->ok);
05600 free(jb->samples);
05601 free(jb);
05602 }
05603
05604
05605
05606 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
05607 {
05608 int i, j, rp, wp;
05609
05610 if (!jb || ! data)
05611 return 0;
05612
05613 ast_mutex_lock(&jb->mutexjb);
05614
05615 wp = jb->wp;
05616 rp = jb->rp;
05617
05618 for (i = 0; i < len; i++) {
05619 jb->samples[wp] = data[i];
05620 jb->ok[wp] = 1;
05621 wp = (wp != jb->size - 1) ? wp + 1 : 0;
05622
05623 if (wp == jb->rp)
05624 jb->state_full = 1;
05625 }
05626
05627 if (wp >= rp)
05628 jb->state_buffer = wp - rp;
05629 else
05630 jb->state_buffer = jb->size - rp + wp;
05631 chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05632
05633 if (jb->state_full) {
05634 jb->wp = wp;
05635
05636 rp = wp;
05637 for (j = 0; j < jb->upper_threshold; j++)
05638 rp = (rp != 0) ? rp - 1 : jb->size - 1;
05639 jb->rp = rp;
05640 jb->state_full = 0;
05641 jb->state_empty = 1;
05642
05643 ast_mutex_unlock(&jb->mutexjb);
05644
05645 return -1;
05646 }
05647
05648 if (!jb->state_empty) {
05649 jb->bytes_wrote += len;
05650 if (jb->bytes_wrote >= jb->upper_threshold) {
05651 jb->state_empty = 1;
05652 jb->bytes_wrote = 0;
05653 }
05654 }
05655 jb->wp = wp;
05656
05657 ast_mutex_unlock(&jb->mutexjb);
05658
05659 return 0;
05660 }
05661
05662
05663
05664
05665 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
05666 {
05667 int i, wp, rp, read = 0;
05668
05669 ast_mutex_lock(&jb->mutexjb);
05670
05671 rp = jb->rp;
05672 wp = jb->wp;
05673
05674 if (jb->state_empty) {
05675 for (i = 0; i < len; i++) {
05676 if (wp == rp) {
05677 jb->rp = rp;
05678 jb->state_empty = 0;
05679
05680 ast_mutex_unlock(&jb->mutexjb);
05681
05682 return read;
05683 } else {
05684 if (jb->ok[rp] == 1) {
05685 data[i] = jb->samples[rp];
05686 jb->ok[rp] = 0;
05687 rp = (rp != jb->size - 1) ? rp + 1 : 0;
05688 read += 1;
05689 }
05690 }
05691 }
05692
05693 if (wp >= rp)
05694 jb->state_buffer = wp - rp;
05695 else
05696 jb->state_buffer = jb->size - rp + wp;
05697 chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05698
05699 jb->rp = rp;
05700 } else
05701 chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05702
05703 ast_mutex_unlock(&jb->mutexjb);
05704
05705 return read;
05706 }
05707
05708
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718 static void chan_misdn_log(int level, int port, char *tmpl, ...)
05719 {
05720 va_list ap;
05721 char buf[1024];
05722 char port_buf[8];
05723
05724 if (! ((0 <= port) && (port <= max_ports))) {
05725 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05726 port = 0;
05727 level = -1;
05728 }
05729
05730 snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05731
05732 va_start(ap, tmpl);
05733 vsnprintf(buf, sizeof(buf), tmpl, ap);
05734 va_end(ap);
05735
05736 if (level == -1)
05737 ast_log(LOG_WARNING, "%s", buf);
05738
05739 else if (misdn_debug_only[port] ?
05740 (level == 1 && misdn_debug[port]) || (level == misdn_debug[port])
05741 : level <= misdn_debug[port]) {
05742
05743 ast_console_puts(port_buf);
05744 ast_console_puts(buf);
05745 }
05746
05747 if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05748 time_t tm = time(NULL);
05749 char *tmp = ctime(&tm), *p;
05750
05751 FILE *fp = fopen(global_tracefile, "a+");
05752
05753 p = strchr(tmp, '\n');
05754 if (p)
05755 *p = ':';
05756
05757 if (!fp) {
05758 ast_console_puts("Error opening Tracefile: [ ");
05759 ast_console_puts(global_tracefile);
05760 ast_console_puts(" ] ");
05761
05762 ast_console_puts(strerror(errno));
05763 ast_console_puts("\n");
05764 return ;
05765 }
05766
05767 fputs(tmp, fp);
05768 fputs(" ", fp);
05769 fputs(port_buf, fp);
05770 fputs(" ", fp);
05771 fputs(buf, fp);
05772
05773 fclose(fp);
05774 }
05775 }
05776
05777 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
05778 .load = load_module,
05779 .unload = unload_module,
05780 .reload = reload,
05781 );