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