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