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: 196118 $")
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_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
02353 else
02354 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_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(ast);
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(ast);
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 p->state = MISDN_CLEANING;
02828
02829
02830
02831 ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02832 release_chan(bc);
02833 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02834 break;
02835 case MISDN_HOLDED:
02836 case MISDN_DIALING:
02837 start_bc_tones(p);
02838 hanguptone_indicate(p);
02839
02840 p->state=MISDN_CLEANING;
02841 if (bc->need_disconnect)
02842 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02843 break;
02844 case MISDN_CALLING_ACKNOWLEDGE:
02845 start_bc_tones(p);
02846 hanguptone_indicate(p);
02847
02848 if (bc->need_disconnect)
02849 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02850 break;
02851
02852 case MISDN_CALLING:
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 = 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)[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, 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, 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 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03626 if (tmp_port == port)
03627 break;
03628 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03629 }
03630 if (c < 0)
03631 c = 0;
03632
03633 ast_string_field_build(tmp, name, "%s/%d-u%d",
03634 misdn_type, chan_offset+c, glob_channel++);
03635
03636 chan_misdn_log(3 , port, " --> updating channel name to [%s]\n", tmp->name);
03637 }
03638
03639 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
03640 {
03641 struct ast_channel *tmp;
03642 char *cid_name = 0, *cid_num = 0;
03643 int chan_offset = 0;
03644 int tmp_port = misdn_cfg_get_next_port(0);
03645 int bridging;
03646
03647 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03648 if (tmp_port == port)
03649 break;
03650 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03651 }
03652 if (c < 0)
03653 c = 0;
03654
03655 if (callerid)
03656 ast_callerid_parse(callerid, &cid_name, &cid_num);
03657
03658 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03659
03660 if (tmp) {
03661 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03662
03663 tmp->nativeformats = prefformat;
03664
03665 tmp->readformat = format;
03666 tmp->rawreadformat = format;
03667 tmp->writeformat = format;
03668 tmp->rawwriteformat = format;
03669
03670 tmp->tech_pvt = chlist;
03671
03672 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
03673
03674 if (bridging)
03675 tmp->tech = &misdn_tech;
03676 else
03677 tmp->tech = &misdn_tech_wo_bridge;
03678
03679 tmp->writeformat = format;
03680 tmp->readformat = format;
03681 tmp->priority=1;
03682
03683 if (exten)
03684 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03685 else
03686 chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03687
03688 if (callerid)
03689
03690
03691 tmp->cid.cid_ani = ast_strdup(cid_num);
03692
03693 if (pipe(chlist->pipe) < 0)
03694 ast_log(LOG_ERROR, "Pipe failed\n");
03695
03696 ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
03697
03698 if (state == AST_STATE_RING)
03699 tmp->rings = 1;
03700 else
03701 tmp->rings = 0;
03702
03703 ast_jb_configure(tmp, misdn_get_global_jbconf());
03704 } else {
03705 chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03706 }
03707
03708 return tmp;
03709 }
03710
03711 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
03712 {
03713 struct chan_list *help = list;
03714 for (; help; help = help->next) {
03715 if (help->bc == bc) return help;
03716 }
03717
03718 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03719
03720 return NULL;
03721 }
03722
03723 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
03724 {
03725 struct chan_list *help = list;
03726 for (; help; help = help->next) {
03727 if ( help->bc && (help->bc->pid == pid) ) return help;
03728 }
03729
03730 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03731
03732 return NULL;
03733 }
03734
03735 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
03736 {
03737 struct chan_list *help = list;
03738
03739 if (bc->pri) return NULL;
03740
03741 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03742 for (;help; help = help->next) {
03743 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state==MISDN_HOLDED, help->hold_info.channel);
03744 if ( (help->state == MISDN_HOLDED) &&
03745 (help->hold_info.port == bc->port) )
03746 return help;
03747 }
03748 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03749
03750 return NULL;
03751 }
03752
03753
03754 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
03755 {
03756 struct chan_list *help = list;
03757
03758 for (; help; help = help->next) {
03759 if ( (help->state == MISDN_HOLDED) &&
03760 (help->l3id == l3_id)
03761 )
03762 return help;
03763 }
03764
03765 return NULL;
03766 }
03767
03768 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
03769 {
03770 chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03771
03772 ast_mutex_lock(&cl_te_lock);
03773 if (!*list) {
03774 *list = chan;
03775 } else {
03776 struct chan_list *help = *list;
03777 for (; help->next; help = help->next);
03778 help->next = chan;
03779 }
03780 chan->next = NULL;
03781 ast_mutex_unlock(&cl_te_lock);
03782 }
03783
03784 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
03785 {
03786 struct chan_list *help;
03787
03788 if (chan->dsp)
03789 ast_dsp_free(chan->dsp);
03790 if (chan->trans)
03791 ast_translator_free_path(chan->trans);
03792
03793 ast_mutex_lock(&cl_te_lock);
03794 if (!*list) {
03795 ast_mutex_unlock(&cl_te_lock);
03796 return;
03797 }
03798
03799 if (*list == chan) {
03800 *list = (*list)->next;
03801 ast_mutex_unlock(&cl_te_lock);
03802 return;
03803 }
03804
03805 for (help = *list; help->next; help = help->next) {
03806 if (help->next == chan) {
03807 help->next = help->next->next;
03808 ast_mutex_unlock(&cl_te_lock);
03809 return;
03810 }
03811 }
03812
03813 ast_mutex_unlock(&cl_te_lock);
03814 }
03815
03816
03817
03818
03819 static int pbx_start_chan(struct chan_list *ch)
03820 {
03821 int ret = ast_pbx_start(ch->ast);
03822
03823 if (ret >= 0)
03824 ch->need_hangup = 0;
03825 else
03826 ch->need_hangup = 1;
03827
03828 return ret;
03829 }
03830
03831 static void hangup_chan(struct chan_list *ch)
03832 {
03833 int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
03834 if (!ch) {
03835 cb_log(1, 0, "Cannot hangup chan, no ch\n");
03836 return;
03837 }
03838
03839 cb_log(5, port, "hangup_chan called\n");
03840
03841 if (ch->need_hangup) {
03842 cb_log(2, port, " --> hangup\n");
03843 send_cause2ast(ch->ast, ch->bc, ch);
03844 ch->need_hangup = 0;
03845 ch->need_queue_hangup = 0;
03846 if (ch->ast)
03847 ast_hangup(ch->ast);
03848 return;
03849 }
03850
03851 if (!ch->need_queue_hangup) {
03852 cb_log(2, port, " --> No need to queue hangup\n");
03853 }
03854
03855 ch->need_queue_hangup = 0;
03856 if (ch->ast) {
03857 send_cause2ast(ch->ast, ch->bc, ch);
03858
03859 if (ch->ast)
03860 ast_queue_hangup(ch->ast);
03861 cb_log(2, port, " --> queue_hangup\n");
03862 } else {
03863 cb_log(1, port, "Cannot hangup chan, no ast\n");
03864 }
03865 }
03866
03867
03868 static void release_chan(struct misdn_bchannel *bc) {
03869 struct ast_channel *ast=NULL;
03870
03871 ast_mutex_lock(&release_lock);
03872 {
03873 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03874 if (!ch) {
03875 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03876 ast_mutex_unlock(&release_lock);
03877 return;
03878 }
03879
03880 if (ch->ast) {
03881 ast = ch->ast;
03882 }
03883
03884 chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
03885
03886
03887 if (ch->jb ) {
03888 misdn_jb_destroy(ch->jb);
03889 ch->jb = NULL;
03890 } else {
03891 if (!bc->nojitter)
03892 chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03893 }
03894
03895 if (ch->overlap_dial) {
03896 if (ch->overlap_dial_task != -1) {
03897 misdn_tasks_remove(ch->overlap_dial_task);
03898 ch->overlap_dial_task = -1;
03899 }
03900 ast_mutex_destroy(&ch->overlap_tv_lock);
03901 }
03902
03903 if (ch->originator == ORG_AST) {
03904 misdn_out_calls[bc->port]--;
03905 } else {
03906 misdn_in_calls[bc->port]--;
03907 }
03908
03909 if (ch) {
03910 close(ch->pipe[0]);
03911 close(ch->pipe[1]);
03912
03913 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03914 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));
03915 chan_misdn_log(3, bc->port, " --> * State Down\n");
03916 MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03917
03918 if (ast->_state != AST_STATE_RESERVED) {
03919 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03920 ast_setstate(ast, AST_STATE_DOWN);
03921 }
03922 }
03923
03924 ch->state = MISDN_CLEANING;
03925 cl_dequeue_chan(&cl_te, ch);
03926
03927 ast_free(ch);
03928 } else {
03929
03930 }
03931
03932 ast_mutex_unlock(&release_lock);
03933 }
03934
03935 }
03936
03937 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
03938 {
03939 chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
03940
03941 tmp_ch->state = MISDN_HOLD_DISCONNECT;
03942
03943 ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03944
03945 holded_chan->state=MISDN_CONNECTED;
03946
03947 ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03948 }
03949
03950
03951 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
03952 {
03953 char *predial;
03954 struct ast_frame fr;
03955
03956 predial = ast_strdupa(ast->exten);
03957
03958 ch->state = MISDN_DIALING;
03959
03960 if (!ch->noautorespond_on_setup) {
03961 if (bc->nt) {
03962 int ret;
03963 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03964 } else {
03965 int ret;
03966 if ( misdn_lib_is_ptp(bc->port)) {
03967 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03968 } else {
03969 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03970 }
03971 }
03972 } else {
03973 ch->state = MISDN_INCOMING_SETUP;
03974 }
03975
03976 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);
03977
03978 strncpy(ast->exten, "s", 2);
03979
03980 if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03981 ast = NULL;
03982 bc->out_cause = AST_CAUSE_UNALLOCATED;
03983 hangup_chan(ch);
03984 hanguptone_indicate(ch);
03985
03986 if (bc->nt)
03987 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03988 else
03989 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03990 }
03991
03992
03993 while (!ast_strlen_zero(predial) ) {
03994 fr.frametype = AST_FRAME_DTMF;
03995 fr.subclass = *predial;
03996 fr.src = NULL;
03997 fr.data = NULL;
03998 fr.datalen = 0;
03999 fr.samples = 0;
04000 fr.mallocd = 0;
04001 fr.offset = 0;
04002 fr.delivery = ast_tv(0,0);
04003
04004 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04005 ast_queue_frame(ch->ast, &fr);
04006 }
04007 predial++;
04008 }
04009 }
04010
04011
04012
04013 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) {
04014 if (!ast) {
04015 chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
04016 return;
04017 }
04018 if (!bc) {
04019 chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
04020 return;
04021 }
04022 if (!ch) {
04023 chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
04024 return;
04025 }
04026
04027 ast->hangupcause = bc->cause;
04028
04029 switch (bc->cause) {
04030
04031 case 1:
04032 case 2:
04033 case 3:
04034 case 4:
04035 case 22:
04036 case 27:
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046 break;
04047
04048 case 21:
04049 case 17:
04050
04051 ch->state = MISDN_BUSY;
04052
04053 if (!ch->need_busy) {
04054 chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
04055 break;
04056 }
04057
04058 chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
04059
04060 ast_queue_control(ast, AST_CONTROL_BUSY);
04061
04062 ch->need_busy = 0;
04063
04064 break;
04065 }
04066 }
04067
04068
04069
04070 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
04071 {
04072 const char *tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
04073 if (tmp) {
04074 ch->other_pid = atoi(tmp);
04075 chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
04076 if (ch->other_pid > 0) {
04077 ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
04078 if (ch->other_ch)
04079 ch->other_ch->other_ch = ch;
04080 }
04081 }
04082
04083 tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
04084 if (tmp && (atoi(tmp) == 1)) {
04085 bc->sending_complete = 1;
04086 }
04087
04088 tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
04089 if (tmp) {
04090 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
04091 ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
04092 bc->uulen = strlen(bc->uu);
04093 }
04094
04095 tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
04096 if (tmp)
04097 ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
04098 }
04099
04100
04101 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
04102 {
04103 char tmp[32];
04104 chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
04105 snprintf(tmp, sizeof(tmp), "%d", bc->pid);
04106 pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
04107
04108 if (bc->sending_complete) {
04109 snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
04110 pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
04111 }
04112
04113 if (bc->urate) {
04114 snprintf(tmp, sizeof(tmp), "%d", bc->urate);
04115 pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
04116 }
04117
04118 if (bc->uulen)
04119 pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
04120
04121 if (!ast_strlen_zero(bc->keypad))
04122 pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
04123 }
04124
04125 int add_in_calls(int port)
04126 {
04127 int max_in_calls;
04128
04129 misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
04130 misdn_in_calls[port]++;
04131
04132 if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
04133 ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
04134 return misdn_in_calls[port] - max_in_calls;
04135 }
04136
04137 return 0;
04138 }
04139
04140 int add_out_calls(int port)
04141 {
04142 int max_out_calls;
04143
04144 misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
04145
04146 if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
04147 ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
04148 return (misdn_out_calls[port] + 1) - max_out_calls;
04149 }
04150
04151 misdn_out_calls[port]++;
04152
04153 return 0;
04154 }
04155
04156 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
04157 if (pbx_start_chan(ch) < 0) {
04158 hangup_chan(ch);
04159 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
04160 if (bc->nt) {
04161 hanguptone_indicate(ch);
04162 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04163 } else
04164 misdn_lib_send_event(bc, EVENT_RELEASE);
04165 }
04166 }
04167
04168 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
04169 ch->state=MISDN_WAITING4DIGS;
04170 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04171 if (bc->nt && !bc->dad[0])
04172 dialtone_indicate(ch);
04173 }
04174
04175
04176
04177
04178
04179 static enum event_response_e
04180 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
04181 {
04182 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04183
04184 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
04185 int debuglevel = 1;
04186 if ( event == EVENT_CLEANUP && !user_data)
04187 debuglevel = 5;
04188
04189 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");
04190 if (debuglevel == 1) {
04191 misdn_lib_log_ies(bc);
04192 chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04193 }
04194 }
04195
04196 if (!ch) {
04197 switch(event) {
04198 case EVENT_SETUP:
04199 case EVENT_DISCONNECT:
04200 case EVENT_PORT_ALARM:
04201 case EVENT_RETRIEVE:
04202 case EVENT_NEW_BC:
04203 case EVENT_FACILITY:
04204 break;
04205 case EVENT_RELEASE_COMPLETE:
04206 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
04207 break;
04208 case EVENT_CLEANUP:
04209 case EVENT_TONE_GENERATE:
04210 case EVENT_BCHAN_DATA:
04211 return -1;
04212 default:
04213 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);
04214 return -1;
04215 }
04216 }
04217
04218 if (ch) {
04219 switch (event) {
04220 case EVENT_TONE_GENERATE:
04221 break;
04222 case EVENT_DISCONNECT:
04223 case EVENT_RELEASE:
04224 case EVENT_RELEASE_COMPLETE:
04225 case EVENT_CLEANUP:
04226 case EVENT_TIMEOUT:
04227 if (!ch->ast)
04228 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));
04229 break;
04230 default:
04231 if (!ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04232 if (event != EVENT_BCHAN_DATA)
04233 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04234 return -1;
04235 }
04236 }
04237 }
04238
04239
04240 switch (event) {
04241 case EVENT_PORT_ALARM:
04242 {
04243 int boa = 0;
04244 misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
04245 if (boa) {
04246 cb_log(1, bc->port, " --> blocking\n");
04247 misdn_lib_port_block(bc->port);
04248 }
04249 }
04250 break;
04251 case EVENT_BCHAN_ACTIVATED:
04252 break;
04253
04254 case EVENT_NEW_CHANNEL:
04255 update_name(ch->ast,bc->port,bc->channel);
04256 break;
04257
04258 case EVENT_NEW_L3ID:
04259 ch->l3id=bc->l3_id;
04260 ch->addr=bc->addr;
04261 break;
04262
04263 case EVENT_NEW_BC:
04264 if (!ch) {
04265 ch = find_holded(cl_te,bc);
04266 }
04267
04268 if (!ch) {
04269 ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04270 break;
04271 }
04272
04273 if (bc)
04274 ch->bc = (struct misdn_bchannel *)user_data;
04275 break;
04276
04277 case EVENT_DTMF_TONE:
04278 {
04279
04280 struct ast_frame fr = { 0, };
04281 fr.frametype = AST_FRAME_DTMF;
04282 fr.subclass = bc->dtmf ;
04283 fr.src = NULL;
04284 fr.data = NULL;
04285 fr.datalen = 0;
04286 fr.samples = 0;
04287 fr.mallocd = 0;
04288 fr.offset = 0;
04289 fr.delivery = ast_tv(0,0);
04290
04291 if (!ch->ignore_dtmf) {
04292 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04293 ast_queue_frame(ch->ast, &fr);
04294 } else {
04295 chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04296 }
04297 }
04298 break;
04299 case EVENT_STATUS:
04300 break;
04301
04302 case EVENT_INFORMATION:
04303 {
04304 if ( ch->state != MISDN_CONNECTED )
04305 stop_indicate(ch);
04306
04307 if (!ch->ast)
04308 break;
04309
04310 if (ch->state == MISDN_WAITING4DIGS ) {
04311
04312 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04313 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04314 ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04315 }
04316
04317 strncat(bc->dad,bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04318 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04319
04320
04321 if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04322 if (ast_pickup_call(ch->ast)) {
04323 hangup_chan(ch);
04324 } else {
04325 struct ast_channel *chan = ch->ast;
04326 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04327 ast_setstate(chan, AST_STATE_DOWN);
04328 hangup_chan(ch);
04329 ch->ast = NULL;
04330 break;
04331 }
04332 }
04333
04334 if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04335 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04336 ast_log(LOG_WARNING,
04337 "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04338 bc->dad, ch->context, bc->port);
04339 strcpy(ch->ast->exten, "i");
04340
04341 ch->state = MISDN_DIALING;
04342 start_pbx(ch, bc, ch->ast);
04343 break;
04344 }
04345
04346 ast_log(LOG_WARNING,
04347 "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04348 "\tMaybe you want to add an 'i' extension to catch this case.\n",
04349 bc->dad, ch->context, 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 = 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,
04609 "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04610 bc->dad, ch->context, bc->port);
04611 strcpy(ch->ast->exten, "i");
04612 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04613 ch->state = MISDN_DIALING;
04614 start_pbx(ch, bc, chan);
04615 break;
04616 }
04617
04618 ast_log(LOG_WARNING,
04619 "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04620 "\tMaybe you want to add an 'i' extension to catch this case.\n",
04621 bc->dad, ch->context, bc->port);
04622 if (bc->nt)
04623 hanguptone_indicate(ch);
04624
04625 ch->state = MISDN_EXTCANTMATCH;
04626 bc->out_cause = AST_CAUSE_UNALLOCATED;
04627
04628 if (bc->nt)
04629 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04630 else
04631 misdn_lib_send_event(bc, EVENT_RELEASE );
04632
04633 break;
04634 }
04635
04636
04637
04638
04639 if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04640 if (!ch->noautorespond_on_setup) {
04641 ch->state=MISDN_DIALING;
04642 misdn_lib_send_event(bc, EVENT_PROCEEDING );
04643 } else {
04644 ch->state = MISDN_INCOMING_SETUP;
04645 }
04646 start_pbx(ch, bc, chan);
04647 break;
04648 }
04649
04650
04651
04652
04653
04654
04655
04656 if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04657 wait_for_digits(ch, bc, chan);
04658 break;
04659 }
04660
04661
04662
04663
04664
04665 if (ch->overlap_dial) {
04666 ast_mutex_lock(&ch->overlap_tv_lock);
04667 ch->overlap_tv = ast_tvnow();
04668 ast_mutex_unlock(&ch->overlap_tv_lock);
04669
04670 wait_for_digits(ch, bc, chan);
04671 if (ch->overlap_dial_task == -1)
04672 ch->overlap_dial_task =
04673 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04674
04675 break;
04676 }
04677
04678
04679
04680
04681 if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04682 wait_for_digits(ch, bc, chan);
04683 break;
04684 }
04685
04686
04687
04688
04689 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04690 if (bc->need_more_infos)
04691 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04692 else
04693 misdn_lib_send_event(bc, EVENT_PROCEEDING);
04694
04695 ch->state = MISDN_DIALING;
04696 start_pbx(ch, bc, chan);
04697 break;
04698 }
04699 }
04700 break;
04701
04702 case EVENT_SETUP_ACKNOWLEDGE:
04703 {
04704 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04705
04706 if (bc->channel)
04707 update_name(ch->ast,bc->port,bc->channel);
04708
04709 if (!ast_strlen_zero(bc->infos_pending)) {
04710
04711 strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04712
04713 if (!ch->ast)
04714 break;
04715 ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04716 ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04717 ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04718
04719 misdn_lib_send_event(bc, EVENT_INFORMATION);
04720 }
04721 }
04722 break;
04723 case EVENT_PROCEEDING:
04724 {
04725
04726 if (misdn_cap_is_speech(bc->capability) &&
04727 misdn_inband_avail(bc) ) {
04728 start_bc_tones(ch);
04729 }
04730
04731 ch->state = MISDN_PROCEEDING;
04732
04733 if (!ch->ast)
04734 break;
04735
04736 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04737 }
04738 break;
04739 case EVENT_PROGRESS:
04740
04741 if (bc->channel)
04742 update_name(ch->ast, bc->port, bc->channel);
04743
04744 if (!bc->nt ) {
04745 if ( misdn_cap_is_speech(bc->capability) &&
04746 misdn_inband_avail(bc)
04747 ) {
04748 start_bc_tones(ch);
04749 }
04750
04751 ch->state = MISDN_PROGRESS;
04752
04753 if (!ch->ast)
04754 break;
04755 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04756 }
04757 break;
04758
04759
04760 case EVENT_ALERTING:
04761 {
04762 ch->state = MISDN_ALERTING;
04763
04764 if (!ch->ast)
04765 break;
04766
04767 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04768 ast_setstate(ch->ast, AST_STATE_RINGING);
04769
04770 cb_log(7, bc->port, " --> Set State Ringing\n");
04771
04772 if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04773 cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04774 start_bc_tones(ch);
04775 } else {
04776 cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04777 if (ch->far_alerting) {
04778 cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04779 start_bc_tones(ch);
04780
04781 }
04782 }
04783 }
04784 break;
04785 case EVENT_CONNECT:
04786 {
04787 struct ast_channel *bridged;
04788
04789
04790 misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04791
04792 if (!ch->ast)
04793 break;
04794
04795 bridged = ast_bridged_channel(ch->ast);
04796 stop_indicate(ch);
04797
04798 if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04799 struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04800
04801 chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04802 if (bridged_ch) {
04803 bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04804 ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04805 }
04806 }
04807 }
04808 ch->l3id=bc->l3_id;
04809 ch->addr=bc->addr;
04810
04811 start_bc_tones(ch);
04812
04813 ch->state = MISDN_CONNECTED;
04814
04815 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04816 break;
04817 case EVENT_CONNECT_ACKNOWLEDGE:
04818 {
04819 ch->l3id = bc->l3_id;
04820 ch->addr = bc->addr;
04821
04822 start_bc_tones(ch);
04823
04824 ch->state = MISDN_CONNECTED;
04825 }
04826 break;
04827 case EVENT_DISCONNECT:
04828
04829 if (ch) {
04830 struct chan_list *holded_ch = find_holded(cl_te, bc);
04831
04832 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);
04833 if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04834
04835
04836
04837
04838
04839 chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04840
04841 ch->state = MISDN_DISCONNECTED;
04842 start_bc_tones(ch);
04843
04844 if (ch->ast) {
04845 ch->ast->hangupcause = bc->cause;
04846 if (bc->cause == AST_CAUSE_USER_BUSY)
04847 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04848 }
04849 ch->need_busy = 0;
04850 break;
04851 }
04852
04853
04854 if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
04855 cb_log(1, bc->port, " --> found holded ch\n");
04856 misdn_transfer_bc(ch, holded_ch) ;
04857 }
04858
04859 bc->need_disconnect = 0;
04860
04861 stop_bc_tones(ch);
04862 hangup_chan(ch);
04863 #if 0
04864 } else {
04865 ch = find_holded_l3(cl_te, bc->l3_id,1);
04866 if (ch) {
04867 hangup_chan(ch);
04868 }
04869 #endif
04870 }
04871 bc->out_cause = -1;
04872 if (bc->need_release)
04873 misdn_lib_send_event(bc, EVENT_RELEASE);
04874 break;
04875
04876 case EVENT_RELEASE:
04877 {
04878 bc->need_disconnect = 0;
04879 bc->need_release = 0;
04880
04881 hangup_chan(ch);
04882 release_chan(bc);
04883 }
04884 break;
04885 case EVENT_RELEASE_COMPLETE:
04886 {
04887 bc->need_disconnect = 0;
04888 bc->need_release = 0;
04889 bc->need_release_complete = 0;
04890
04891 stop_bc_tones(ch);
04892 hangup_chan(ch);
04893
04894 if (ch)
04895 ch->state = MISDN_CLEANING;
04896
04897 release_chan(bc);
04898 }
04899 break;
04900 case EVENT_BCHAN_ERROR:
04901 case EVENT_CLEANUP:
04902 {
04903 stop_bc_tones(ch);
04904
04905 switch (ch->state) {
04906 case MISDN_CALLING:
04907 bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04908 break;
04909 default:
04910 break;
04911 }
04912
04913 hangup_chan(ch);
04914 release_chan(bc);
04915 }
04916 break;
04917
04918 case EVENT_TONE_GENERATE:
04919 {
04920 int tone_len = bc->tone_cnt;
04921 struct ast_channel *ast = ch->ast;
04922 void *tmp;
04923 int res;
04924 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04925
04926 chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
04927
04928 if (!ast)
04929 break;
04930
04931 if (!ast->generator)
04932 break;
04933
04934 tmp = ast->generatordata;
04935 ast->generatordata = NULL;
04936 generate = ast->generator->generate;
04937
04938 if (tone_len < 0 || tone_len > 512 ) {
04939 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
04940 tone_len = 128;
04941 }
04942
04943 res = generate(ast, tmp, tone_len, tone_len);
04944 ast->generatordata = tmp;
04945
04946 if (res) {
04947 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04948 ast_deactivate_generator(ast);
04949 } else {
04950 bc->tone_cnt = 0;
04951 }
04952 }
04953 break;
04954
04955 case EVENT_BCHAN_DATA:
04956 {
04957 if (ch->bc->AOCD_need_export)
04958 export_aoc_vars(ch->originator, ch->ast, ch->bc);
04959 if (!misdn_cap_is_speech(ch->bc->capability) ) {
04960 struct ast_frame frame;
04961
04962 frame.frametype = AST_FRAME_VOICE;
04963 frame.subclass = AST_FORMAT_ALAW;
04964 frame.datalen = bc->bframe_len;
04965 frame.samples = bc->bframe_len;
04966 frame.mallocd = 0;
04967 frame.offset = 0;
04968 frame.delivery = ast_tv(0,0);
04969 frame.src = NULL;
04970 frame.data = bc->bframe;
04971
04972 if (ch->ast)
04973 ast_queue_frame(ch->ast, &frame);
04974 } else {
04975 fd_set wrfs;
04976 struct timeval tv = { 0, 0 };
04977 int t;
04978
04979 FD_ZERO(&wrfs);
04980 FD_SET(ch->pipe[1], &wrfs);
04981
04982 t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
04983
04984 if (!t) {
04985 chan_misdn_log(9, bc->port, "Select Timed out\n");
04986 break;
04987 }
04988
04989 if (t < 0) {
04990 chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
04991 break;
04992 }
04993
04994 if (FD_ISSET(ch->pipe[1], &wrfs)) {
04995 chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n", bc->bframe_len);
04996 if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
04997 chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
04998
04999 stop_bc_tones(ch);
05000 hangup_chan(ch);
05001 release_chan(bc);
05002 }
05003 } else {
05004 chan_misdn_log(1, bc->port, "Write Pipe full!\n");
05005 }
05006 }
05007 }
05008 break;
05009 case EVENT_TIMEOUT:
05010 {
05011 if (ch && bc)
05012 chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
05013
05014 switch (ch->state) {
05015 case MISDN_DIALING:
05016 case MISDN_PROGRESS:
05017 if (bc->nt && !ch->nttimeout)
05018 break;
05019
05020 case MISDN_CALLING:
05021 case MISDN_ALERTING:
05022 case MISDN_PROCEEDING:
05023 case MISDN_CALLING_ACKNOWLEDGE:
05024 if (bc->nt) {
05025 bc->progress_indicator = 8;
05026 hanguptone_indicate(ch);
05027 }
05028
05029 bc->out_cause = AST_CAUSE_UNALLOCATED;
05030 misdn_lib_send_event(bc, EVENT_DISCONNECT);
05031 break;
05032
05033 case MISDN_WAITING4DIGS:
05034 if (bc->nt) {
05035 bc->progress_indicator = 8;
05036 bc->out_cause = AST_CAUSE_UNALLOCATED;
05037 hanguptone_indicate(ch);
05038 misdn_lib_send_event(bc, EVENT_DISCONNECT);
05039 } else {
05040 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
05041 misdn_lib_send_event(bc, EVENT_RELEASE);
05042 }
05043
05044 break;
05045
05046 case MISDN_CLEANING:
05047 chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
05048 break;
05049
05050 default:
05051 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
05052 }
05053 }
05054 break;
05055
05056
05057
05058
05059
05060 case EVENT_RETRIEVE:
05061 {
05062 struct ast_channel *hold_ast;
05063
05064 if (!ch) {
05065 chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
05066 ch = find_holded_l3(cl_te, bc->l3_id, 1);
05067 }
05068
05069 if (!ch) {
05070 ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
05071 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05072 break;
05073 }
05074
05075
05076 ch->bc = bc;
05077 ch->state = MISDN_CONNECTED;
05078
05079 ch->hold_info.port = 0;
05080 ch->hold_info.channel = 0;
05081
05082 hold_ast = ast_bridged_channel(ch->ast);
05083
05084 if (hold_ast) {
05085 ast_moh_stop(hold_ast);
05086 }
05087
05088 if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
05089 chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
05090 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
05091 }
05092 }
05093 break;
05094
05095 case EVENT_HOLD:
05096 {
05097 int hold_allowed;
05098 struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05099
05100 misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
05101
05102 if (!hold_allowed) {
05103
05104 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
05105 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05106 break;
05107 }
05108
05109 if (bridged) {
05110 chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
05111 ch->state = MISDN_HOLDED;
05112 ch->l3id = bc->l3_id;
05113
05114 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
05115
05116
05117
05118 ast_moh_start(bridged, NULL, NULL);
05119
05120
05121 ch->bc = NULL;
05122 ch->hold_info.port = bc->port;
05123 ch->hold_info.channel = bc->channel;
05124
05125 } else {
05126 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
05127 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
05128 }
05129 }
05130 break;
05131
05132 case EVENT_FACILITY:
05133 print_facility(&(bc->fac_in), bc);
05134
05135 switch (bc->fac_in.Function) {
05136 #ifdef HAVE_MISDN_FAC_RESULT
05137 case Fac_RESULT:
05138 break;
05139 #endif
05140 case Fac_CD:
05141 if (ch) {
05142 struct ast_channel *bridged = ast_bridged_channel(ch->ast);
05143 struct chan_list *ch_br;
05144 if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
05145 ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
05146
05147 if (ch_br->bc) {
05148 if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
05149 ch_br->state = MISDN_DIALING;
05150 if (pbx_start_chan(ch_br) < 0) {
05151 chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
05152 }
05153 }
05154 }
05155 }
05156 misdn_lib_send_event(bc, EVENT_DISCONNECT);
05157 }
05158 break;
05159 case Fac_AOCDCurrency:
05160 if (ch) {
05161 bc->AOCDtype = Fac_AOCDCurrency;
05162 memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(bc->AOCD.currency));
05163 bc->AOCD_need_export = 1;
05164 export_aoc_vars(ch->originator, ch->ast, bc);
05165 }
05166 break;
05167 case Fac_AOCDChargingUnit:
05168 if (ch) {
05169 bc->AOCDtype = Fac_AOCDChargingUnit;
05170 memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(bc->AOCD.chargingUnit));
05171 bc->AOCD_need_export = 1;
05172 export_aoc_vars(ch->originator, ch->ast, bc);
05173 }
05174 break;
05175 case Fac_None:
05176 #ifdef HAVE_MISDN_FAC_ERROR
05177 case Fac_ERROR:
05178 #endif
05179 break;
05180 default:
05181 chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
05182 }
05183
05184 break;
05185
05186 case EVENT_RESTART:
05187
05188 if (!bc->dummy) {
05189 stop_bc_tones(ch);
05190 release_chan(bc);
05191 }
05192 break;
05193
05194 default:
05195 chan_misdn_log(1, 0, "Got Unknown Event\n");
05196 break;
05197 }
05198
05199 return RESPONSE_OK;
05200 }
05201
05202
05203
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213 static int unload_module(void)
05214 {
05215
05216 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05217
05218 misdn_tasks_destroy();
05219
05220 if (!g_config_initialized)
05221 return 0;
05222
05223 ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05224
05225
05226 ast_unregister_application("misdn_set_opt");
05227 ast_unregister_application("misdn_facility");
05228 ast_unregister_application("misdn_check_l2l1");
05229
05230 ast_channel_unregister(&misdn_tech);
05231
05232 free_robin_list();
05233 misdn_cfg_destroy();
05234 misdn_lib_destroy();
05235
05236 if (misdn_debug)
05237 ast_free(misdn_debug);
05238 if (misdn_debug_only)
05239 ast_free(misdn_debug_only);
05240 ast_free(misdn_ports);
05241
05242 return 0;
05243 }
05244
05245 static int load_module(void)
05246 {
05247 int i, port;
05248 int ntflags = 0, ntkc = 0;
05249 char ports[256] = "";
05250 char tempbuf[BUFFERSIZE + 1];
05251 char ntfile[BUFFERSIZE + 1];
05252 struct misdn_lib_iface iface = {
05253 .cb_event = cb_events,
05254 .cb_log = chan_misdn_log,
05255 .cb_jb_empty = chan_misdn_jb_empty,
05256 };
05257
05258 max_ports = misdn_lib_maxports_get();
05259
05260 if (max_ports <= 0) {
05261 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05262 return AST_MODULE_LOAD_DECLINE;
05263 }
05264
05265 if (misdn_cfg_init(max_ports, 0)) {
05266 ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05267 return AST_MODULE_LOAD_DECLINE;
05268 }
05269 g_config_initialized = 1;
05270
05271 misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
05272 if (!misdn_debug) {
05273 ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05274 return AST_MODULE_LOAD_DECLINE;
05275 }
05276 misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
05277 if (!misdn_ports) {
05278 ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05279 return AST_MODULE_LOAD_DECLINE;
05280 }
05281 misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
05282 for (i = 1; i <= max_ports; i++) {
05283 misdn_debug[i] = misdn_debug[0];
05284 misdn_ports[i] = i;
05285 }
05286 *misdn_ports = 0;
05287 misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
05288
05289 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
05290 if (!ast_strlen_zero(tempbuf))
05291 tracing = 1;
05292
05293 misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05294 misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
05295
05296 for (i = 1; i <= max_ports; i++) {
05297 misdn_in_calls[i] = 0;
05298 misdn_out_calls[i] = 0;
05299 }
05300
05301 ast_mutex_init(&cl_te_lock);
05302 ast_mutex_init(&release_lock);
05303
05304 misdn_cfg_update_ptp();
05305 misdn_cfg_get_ports_string(ports);
05306
05307 if (!ast_strlen_zero(ports))
05308 chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05309 if (misdn_lib_init(ports, &iface, NULL))
05310 chan_misdn_log(0, 0, "No te ports initialized\n");
05311
05312 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
05313 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
05314 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
05315
05316 misdn_lib_nt_keepcalls(ntkc);
05317 misdn_lib_nt_debug_init(ntflags, ntfile);
05318
05319 if (ast_channel_register(&misdn_tech)) {
05320 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05321 unload_module();
05322 return AST_MODULE_LOAD_DECLINE;
05323 }
05324
05325 ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05326
05327 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05328 "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05329 "Sets mISDN opts. and optargs\n"
05330 "\n"
05331 "The available options are:\n"
05332 " a - Have Asterisk detect DTMF tones on called channel\n"
05333 " c - Make crypted outgoing call, optarg is keyindex\n"
05334 " d - Send display text to called phone, text is the optarg\n"
05335 " e - Perform echo cancelation on this channel,\n"
05336 " takes taps as optarg (32,64,128,256)\n"
05337 " e! - Disable echo cancelation on this channel\n"
05338 " f - Enable fax detection\n"
05339 " h - Make digital outgoing call\n"
05340 " h1 - Make HDLC mode digital outgoing call\n"
05341 " i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05342 " they will be transported inband.\n"
05343 " jb - Set jitter buffer length, optarg is length\n"
05344 " jt - Set jitter buffer upper threshold, optarg is threshold\n"
05345 " jn - Disable jitter buffer\n"
05346 " n - Disable mISDN DSP on channel.\n"
05347 " Disables: echo cancel, DTMF detection, and volume control.\n"
05348 " p - Caller ID presentation,\n"
05349 " optarg is either 'allowed' or 'restricted'\n"
05350 " s - Send Non-inband DTMF as inband\n"
05351 " vr - Rx gain control, optarg is gain\n"
05352 " vt - Tx gain control, optarg is gain\n"
05353 );
05354
05355
05356 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05357 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05358 "Sends the Facility Message FACILITY_TYPE with \n"
05359 "the given Arguments to the current ISDN Channel\n"
05360 "Supported Facilities are:\n"
05361 "\n"
05362 "type=calldeflect args=Nr where to deflect\n"
05363 );
05364
05365
05366 ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05367 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05368 "Checks if the L2 and L1 are up on either the given <port> or\n"
05369 "on the ports in the group with <groupname>\n"
05370 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05371 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05372 "\n"
05373 "This application, ensures the L1/L2 state of the Ports in a group\n"
05374 "it is intended to make the pmp_l1_check option redundant and to\n"
05375 "fix a buggy switch config from your provider\n"
05376 "\n"
05377 "a sample dialplan would look like:\n\n"
05378 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05379 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05380 "\n"
05381 );
05382
05383
05384 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
05385
05386
05387
05388 for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05389 int l1timeout;
05390 misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05391 if (l1timeout) {
05392 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05393 misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
05394 }
05395 }
05396
05397 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05398
05399 return 0;
05400 }
05401
05402
05403
05404 static int reload(void)
05405 {
05406 reload_config();
05407
05408 return 0;
05409 }
05410
05411
05412
05413 static int misdn_facility_exec(struct ast_channel *chan, void *data)
05414 {
05415 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05416 char *parse, *tok, *tokb;
05417
05418 chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05419
05420 if (strcasecmp(chan->tech->type, "mISDN")) {
05421 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05422 return -1;
05423 }
05424
05425 if (ast_strlen_zero((char *)data)) {
05426 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05427 return -1;
05428 }
05429
05430 parse = ast_strdupa(data);
05431 tok = strtok_r(parse, "|", &tokb) ;
05432
05433 if (!tok) {
05434 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05435 return -1;
05436 }
05437
05438 if (!strcasecmp(tok, "calldeflect")) {
05439 tok = strtok_r(NULL, "|", &tokb) ;
05440
05441 if (!tok) {
05442 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05443 }
05444
05445 if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05446 ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05447 return 0;
05448 }
05449 ch->bc->fac_out.Function = Fac_CD;
05450 ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05451 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05452 } else {
05453 chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05454 }
05455
05456 return 0;
05457 }
05458
05459 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
05460 {
05461 char *parse;
05462 char group[BUFFERSIZE + 1];
05463 char *port_str;
05464 int port = 0;
05465 int timeout;
05466 int dowait = 0;
05467 int port_up;
05468
05469 AST_DECLARE_APP_ARGS(args,
05470 AST_APP_ARG(grouppar);
05471 AST_APP_ARG(timeout);
05472 );
05473
05474 if (ast_strlen_zero((char *)data)) {
05475 ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05476 return -1;
05477 }
05478
05479 parse = ast_strdupa(data);
05480 AST_STANDARD_APP_ARGS(args, parse);
05481
05482 if (args.argc != 2) {
05483 ast_log(LOG_WARNING, "Wrong argument count\n");
05484 return 0;
05485 }
05486
05487
05488 timeout = atoi(args.timeout);
05489 port_str = args.grouppar;
05490
05491 if (port_str[0] == 'g' && port_str[1] == ':' ) {
05492
05493 port_str += 2;
05494 ast_copy_string(group, port_str, sizeof(group));
05495 chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05496
05497 for ( port = misdn_cfg_get_next_port(port);
05498 port > 0;
05499 port = misdn_cfg_get_next_port(port)) {
05500 char cfg_group[BUFFERSIZE + 1];
05501
05502 chan_misdn_log(2, 0, "trying port %d\n", port);
05503
05504 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
05505
05506 if (!strcasecmp(cfg_group, group)) {
05507 port_up = misdn_lib_port_up(port, 1);
05508
05509 if (!port_up) {
05510 chan_misdn_log(2, 0, " --> port '%d'\n", port);
05511 misdn_lib_get_port_up(port);
05512 dowait = 1;
05513 }
05514 }
05515 }
05516
05517 } else {
05518 port = atoi(port_str);
05519 chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05520 port_up = misdn_lib_port_up(port, 1);
05521 if (!port_up) {
05522 misdn_lib_get_port_up(port);
05523 dowait = 1;
05524 }
05525 }
05526
05527 if (dowait) {
05528 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05529 ast_safe_sleep(chan, timeout * 1000);
05530 }
05531
05532 return 0;
05533 }
05534
05535 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
05536 {
05537 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05538 char *tok, *tokb, *parse;
05539 int keyidx = 0;
05540 int rxgain = 0;
05541 int txgain = 0;
05542 int change_jitter = 0;
05543
05544 if (strcasecmp(chan->tech->type, "mISDN")) {
05545 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05546 return -1;
05547 }
05548
05549 if (ast_strlen_zero((char *)data)) {
05550 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05551 return -1;
05552 }
05553
05554 parse = ast_strdupa(data);
05555 for (tok = strtok_r(parse, ":", &tokb);
05556 tok;
05557 tok = strtok_r(NULL, ":", &tokb) ) {
05558 int neglect = 0;
05559
05560 if (tok[0] == '!' ) {
05561 neglect = 1;
05562 tok++;
05563 }
05564
05565 switch(tok[0]) {
05566
05567 case 'd' :
05568 ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05569 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05570 break;
05571
05572 case 'n':
05573 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05574 ch->bc->nodsp = 1;
05575 break;
05576
05577 case 'j':
05578 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05579 tok++;
05580 change_jitter = 1;
05581
05582 switch ( tok[0] ) {
05583 case 'b':
05584 ch->jb_len = atoi(++tok);
05585 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05586 break;
05587 case 't' :
05588 ch->jb_upper_threshold = atoi(++tok);
05589 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05590 break;
05591 case 'n':
05592 ch->bc->nojitter = 1;
05593 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05594 break;
05595 default:
05596 ch->jb_len = 4000;
05597 ch->jb_upper_threshold = 0;
05598 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05599 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05600 }
05601 break;
05602 case 'v':
05603 tok++;
05604
05605 switch (tok[0]) {
05606 case 'r' :
05607 rxgain = atoi(++tok);
05608 if (rxgain < -8)
05609 rxgain = -8;
05610 if (rxgain > 8)
05611 rxgain = 8;
05612 ch->bc->rxgain = rxgain;
05613 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05614 break;
05615 case 't':
05616 txgain = atoi(++tok);
05617 if (txgain < -8)
05618 txgain = -8;
05619 if (txgain > 8)
05620 txgain = 8;
05621 ch->bc->txgain = txgain;
05622 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05623 break;
05624 }
05625 break;
05626
05627 case 'c':
05628 keyidx = atoi(++tok);
05629 {
05630 char keys[4096];
05631 char *key = NULL, *tmp = keys;
05632 int i;
05633 misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05634
05635 for (i = 0; i < keyidx; i++) {
05636 key = strsep(&tmp, ",");
05637 }
05638
05639 if (key) {
05640 ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05641 }
05642
05643 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05644 break;
05645 }
05646 case 'e':
05647 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05648
05649 if (neglect) {
05650 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05651 #ifdef MISDN_1_2
05652 *ch->bc->pipeline = 0;
05653 #else
05654 ch->bc->ec_enable = 0;
05655 #endif
05656 } else {
05657 #ifdef MISDN_1_2
05658 update_pipeline_config(ch->bc);
05659 #else
05660 ch->bc->ec_enable = 1;
05661 ch->bc->orig = ch->originator;
05662 tok++;
05663 if (*tok) {
05664 ch->bc->ec_deftaps = atoi(tok);
05665 }
05666 #endif
05667 }
05668
05669 break;
05670 case 'h':
05671 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05672
05673 if (strlen(tok) > 1 && tok[1] == '1') {
05674 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05675 if (!ch->bc->hdlc) {
05676 ch->bc->hdlc = 1;
05677 }
05678 }
05679 ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05680 break;
05681
05682 case 's':
05683 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05684 ch->bc->send_dtmf = 1;
05685 break;
05686
05687 case 'f':
05688 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05689 ch->faxdetect = 1;
05690 misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05691 break;
05692
05693 case 'a':
05694 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05695 ch->ast_dsp = 1;
05696 break;
05697
05698 case 'p':
05699 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05700
05701 if (strstr(tok,"allowed")) {
05702 ch->bc->pres = 0;
05703 } else if (strstr(tok, "not_screened")) {
05704 ch->bc->pres = 1;
05705 }
05706 break;
05707 case 'i' :
05708 chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05709 ch->ignore_dtmf=1;
05710 break;
05711 default:
05712 break;
05713 }
05714 }
05715
05716 if (change_jitter)
05717 config_jitterbuffer(ch);
05718
05719 if (ch->faxdetect || ch->ast_dsp) {
05720 if (!ch->dsp)
05721 ch->dsp = ast_dsp_new();
05722 if (ch->dsp)
05723 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT);
05724 if (!ch->trans)
05725 ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05726 }
05727
05728 if (ch->ast_dsp) {
05729 chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05730 ch->bc->nodsp = 1;
05731 }
05732
05733 return 0;
05734 }
05735
05736
05737 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
05738 {
05739 struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05740
05741 if (ch && ch->jb) {
05742 return misdn_jb_empty(ch->jb, buf, len);
05743 }
05744
05745 return -1;
05746 }
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
05757 {
05758 int i;
05759 struct misdn_jb *jb;
05760
05761 jb = ast_malloc(sizeof(*jb));
05762 if (!jb) {
05763 chan_misdn_log(-1, 0, "No free Mem for jb\n");
05764 return NULL;
05765 }
05766 jb->size = size;
05767 jb->upper_threshold = upper_threshold;
05768 jb->wp = 0;
05769 jb->rp = 0;
05770 jb->state_full = 0;
05771 jb->state_empty = 0;
05772 jb->bytes_wrote = 0;
05773 jb->samples = ast_malloc(size * sizeof(char));
05774
05775 if (!jb->samples) {
05776 ast_free(jb);
05777 chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05778 return NULL;
05779 }
05780
05781 jb->ok = ast_malloc(size * sizeof(char));
05782
05783 if (!jb->ok) {
05784 ast_free(jb->samples);
05785 ast_free(jb);
05786 chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05787 return NULL;
05788 }
05789
05790 for (i = 0; i < size; i++)
05791 jb->ok[i] = 0;
05792
05793 ast_mutex_init(&jb->mutexjb);
05794
05795 return jb;
05796 }
05797
05798
05799 void misdn_jb_destroy(struct misdn_jb *jb)
05800 {
05801 ast_mutex_destroy(&jb->mutexjb);
05802
05803 ast_free(jb->ok);
05804 ast_free(jb->samples);
05805 ast_free(jb);
05806 }
05807
05808
05809
05810 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
05811 {
05812 int i, j, rp, wp;
05813
05814 if (!jb || ! data)
05815 return 0;
05816
05817 ast_mutex_lock(&jb->mutexjb);
05818
05819 wp = jb->wp;
05820 rp = jb->rp;
05821
05822 for (i = 0; i < len; i++) {
05823 jb->samples[wp] = data[i];
05824 jb->ok[wp] = 1;
05825 wp = (wp != jb->size - 1) ? wp + 1 : 0;
05826
05827 if (wp == jb->rp)
05828 jb->state_full = 1;
05829 }
05830
05831 if (wp >= rp)
05832 jb->state_buffer = wp - rp;
05833 else
05834 jb->state_buffer = jb->size - rp + wp;
05835 chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05836
05837 if (jb->state_full) {
05838 jb->wp = wp;
05839
05840 rp = wp;
05841 for (j = 0; j < jb->upper_threshold; j++)
05842 rp = rp != 0 ? rp - 1 : jb->size - 1;
05843 jb->rp = rp;
05844 jb->state_full = 0;
05845 jb->state_empty = 1;
05846
05847 ast_mutex_unlock(&jb->mutexjb);
05848
05849 return -1;
05850 }
05851
05852 if (!jb->state_empty) {
05853 jb->bytes_wrote += len;
05854 if (jb->bytes_wrote >= jb->upper_threshold) {
05855 jb->state_empty = 1;
05856 jb->bytes_wrote = 0;
05857 }
05858 }
05859 jb->wp = wp;
05860
05861 ast_mutex_unlock(&jb->mutexjb);
05862
05863 return 0;
05864 }
05865
05866
05867
05868
05869 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
05870 {
05871 int i, wp, rp, read = 0;
05872
05873 ast_mutex_lock(&jb->mutexjb);
05874
05875 rp = jb->rp;
05876 wp = jb->wp;
05877
05878 if (jb->state_empty) {
05879 for (i = 0; i < len; i++) {
05880 if (wp == rp) {
05881 jb->rp = rp;
05882 jb->state_empty = 0;
05883
05884 ast_mutex_unlock(&jb->mutexjb);
05885
05886 return read;
05887 } else {
05888 if (jb->ok[rp] == 1) {
05889 data[i] = jb->samples[rp];
05890 jb->ok[rp] = 0;
05891 rp = (rp != jb->size - 1) ? rp + 1 : 0;
05892 read += 1;
05893 }
05894 }
05895 }
05896
05897 if (wp >= rp)
05898 jb->state_buffer = wp - rp;
05899 else
05900 jb->state_buffer = jb->size - rp + wp;
05901 chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05902
05903 jb->rp = rp;
05904 } else
05905 chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05906
05907 ast_mutex_unlock(&jb->mutexjb);
05908
05909 return read;
05910 }
05911
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921
05922 static void chan_misdn_log(int level, int port, char *tmpl, ...)
05923 {
05924 va_list ap;
05925 char buf[1024];
05926 char port_buf[8];
05927
05928 if (! ((0 <= port) && (port <= max_ports))) {
05929 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05930 port = 0;
05931 level = -1;
05932 }
05933
05934 snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05935
05936 va_start(ap, tmpl);
05937 vsnprintf(buf, sizeof(buf), tmpl, ap);
05938 va_end(ap);
05939
05940 if (level == -1)
05941 ast_log(LOG_WARNING, "%s", buf);
05942
05943 else if (misdn_debug_only[port] ?
05944 (level == 1 && misdn_debug[port]) || (level == misdn_debug[port])
05945 : level <= misdn_debug[port]) {
05946
05947 ast_console_puts(port_buf);
05948 ast_console_puts(buf);
05949 }
05950
05951 if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05952 char ctimebuf[30];
05953 time_t tm = time(NULL);
05954 char *tmp = ctime_r(&tm, ctimebuf), *p;
05955
05956 FILE *fp = fopen(global_tracefile, "a+");
05957
05958 p = strchr(tmp, '\n');
05959 if (p)
05960 *p = ':';
05961
05962 if (!fp) {
05963 ast_console_puts("Error opening Tracefile: [ ");
05964 ast_console_puts(global_tracefile);
05965 ast_console_puts(" ] ");
05966
05967 ast_console_puts(strerror(errno));
05968 ast_console_puts("\n");
05969 return ;
05970 }
05971
05972 fputs(tmp, fp);
05973 fputs(" ", fp);
05974 fputs(port_buf, fp);
05975 fputs(" ", fp);
05976 fputs(buf, fp);
05977
05978 fclose(fp);
05979 }
05980 }
05981
05982 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
05983 .load = load_module,
05984 .unload = unload_module,
05985 .reload = reload,
05986 );