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