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