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