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