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