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: 107464 $")
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 char newname[255];
03338 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
03339 if (tmp_port == port) break;
03340 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;
03341 }
03342 if (c<0) c=0;
03343
03344 snprintf(newname,sizeof(newname),"%s/%d-",misdn_type,chan_offset+c);
03345 if (strncmp(tmp->name,newname,strlen(newname))) {
03346 snprintf(newname,sizeof(newname),"%s/%d-u%d", misdn_type, chan_offset+c, glob_channel++);
03347 ast_change_name(tmp,newname);
03348 chan_misdn_log(3,port," --> updating channel name to [%s]\n",tmp->name);
03349 }
03350 }
03351
03352 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
03353 {
03354 struct ast_channel *tmp;
03355 char *cid_name = 0, *cid_num = 0;
03356 int chan_offset=0;
03357 int tmp_port = misdn_cfg_get_next_port(0);
03358
03359 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
03360 if (tmp_port == port) break;
03361 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;
03362 }
03363 if (c<0) c=0;
03364
03365
03366 if (callerid)
03367 ast_callerid_parse(callerid, &cid_name, &cid_num);
03368
03369 if (c)
03370 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03371 else
03372 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/tmp%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03373
03374 if (tmp) {
03375 int bridging;
03376 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
03377
03378 tmp->nativeformats = prefformat;
03379
03380 tmp->readformat = format;
03381 tmp->rawreadformat = format;
03382 tmp->writeformat = format;
03383 tmp->rawwriteformat = format;
03384
03385 tmp->tech_pvt = chlist;
03386
03387 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03388
03389 if (bridging)
03390 tmp->tech = &misdn_tech;
03391 else
03392 tmp->tech = &misdn_tech_wo_bridge;
03393
03394 tmp->writeformat = format;
03395 tmp->readformat = format;
03396 tmp->priority=1;
03397
03398 if (exten)
03399 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03400 else
03401 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
03402
03403 if (callerid)
03404
03405
03406 tmp->cid.cid_ani = ast_strdup(cid_num);
03407
03408 {
03409 if (pipe(chlist->pipe)<0)
03410 perror("Pipe failed\n");
03411
03412 tmp->fds[0]=chlist->pipe[0];
03413
03414 }
03415
03416 if (state == AST_STATE_RING)
03417 tmp->rings = 1;
03418 else
03419 tmp->rings = 0;
03420
03421
03422 } else {
03423 chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
03424 }
03425
03426 return tmp;
03427 }
03428
03429 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
03430 {
03431 struct chan_list *help=list;
03432 for (;help; help=help->next) {
03433 if (help->bc == bc) return help;
03434 }
03435
03436 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03437
03438 return NULL;
03439 }
03440
03441 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
03442 {
03443 struct chan_list *help=list;
03444 for (;help; help=help->next) {
03445 if ( help->bc && (help->bc->pid == pid) ) return help;
03446 }
03447
03448 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
03449
03450 return NULL;
03451 }
03452
03453 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
03454 {
03455 struct chan_list *help=list;
03456
03457 if (bc->pri) return NULL;
03458
03459 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
03460 for (;help; help=help->next) {
03461 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel);
03462 if ( (help->state == MISDN_HOLDED) &&
03463 (help->hold_info.port == bc->port) )
03464 return help;
03465 }
03466 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03467
03468 return NULL;
03469 }
03470
03471
03472 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
03473
03474 {
03475 struct chan_list *help=list;
03476
03477 for (;help; help=help->next) {
03478 if ( (help->state == MISDN_HOLDED) &&
03479 (help->l3id == l3_id)
03480 )
03481 return help;
03482 }
03483
03484 return NULL;
03485 }
03486
03487 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
03488 {
03489 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
03490
03491 ast_mutex_lock(&cl_te_lock);
03492 if (!*list) {
03493 *list = chan;
03494 } else {
03495 struct chan_list *help=*list;
03496 for (;help->next; help=help->next);
03497 help->next=chan;
03498 }
03499 chan->next=NULL;
03500 ast_mutex_unlock(&cl_te_lock);
03501 }
03502
03503 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
03504 {
03505 if (chan->dsp)
03506 ast_dsp_free(chan->dsp);
03507 if (chan->trans)
03508 ast_translator_free_path(chan->trans);
03509
03510
03511
03512 ast_mutex_lock(&cl_te_lock);
03513 if (!*list) {
03514 ast_mutex_unlock(&cl_te_lock);
03515 return;
03516 }
03517
03518 if (*list == chan) {
03519 *list=(*list)->next;
03520 ast_mutex_unlock(&cl_te_lock);
03521 return ;
03522 }
03523
03524 {
03525 struct chan_list *help=*list;
03526 for (;help->next; help=help->next) {
03527 if (help->next == chan) {
03528 help->next=help->next->next;
03529 ast_mutex_unlock(&cl_te_lock);
03530 return;
03531 }
03532 }
03533 }
03534
03535 ast_mutex_unlock(&cl_te_lock);
03536 }
03537
03538
03539
03540
03541 int pbx_start_chan(struct chan_list *ch)
03542 {
03543 int ret=ast_pbx_start(ch->ast);
03544
03545 if (ret>=0)
03546 ch->need_hangup=0;
03547 else
03548 ch->need_hangup=1;
03549
03550 return ret;
03551 }
03552
03553 static void hangup_chan(struct chan_list *ch)
03554 {
03555 int port=ch?ch->bc?ch->bc->port:0:0;
03556 if (!ch) {
03557 cb_log(1,0,"Cannot hangup chan, no ch\n");
03558 return;
03559 }
03560
03561 cb_log(5,port,"hangup_chan called\n");
03562
03563 if (ch->need_hangup)
03564 {
03565 cb_log(2,port," --> hangup\n");
03566 send_cause2ast(ch->ast,ch->bc,ch);
03567 ch->need_hangup=0;
03568 ch->need_queue_hangup=0;
03569 if (ch->ast)
03570 ast_hangup(ch->ast);
03571 return;
03572 }
03573
03574 if (!ch->need_queue_hangup) {
03575 cb_log(2,port," --> No need to queue hangup\n");
03576 }
03577
03578 ch->need_queue_hangup=0;
03579 if (ch->ast) {
03580 send_cause2ast(ch->ast,ch->bc,ch);
03581
03582 if (ch->ast)
03583 ast_queue_hangup(ch->ast);
03584 cb_log(2,port," --> queue_hangup\n");
03585 } else {
03586 cb_log(1,port,"Cannot hangup chan, no ast\n");
03587 }
03588 }
03589
03590
03591 static void release_chan(struct misdn_bchannel *bc) {
03592 struct ast_channel *ast=NULL;
03593
03594 ast_mutex_lock(&release_lock);
03595 {
03596 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03597 if (!ch) {
03598 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03599 ast_mutex_unlock(&release_lock);
03600 return;
03601 }
03602
03603 if (ch->ast) {
03604 ast=ch->ast;
03605 }
03606
03607 chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
03608
03609
03610 if (ch->jb ) {
03611 misdn_jb_destroy(ch->jb);
03612 ch->jb=NULL;
03613 } else {
03614 if (!bc->nojitter)
03615 chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
03616 }
03617
03618 if (ch->overlap_dial) {
03619 if (ch->overlap_dial_task != -1) {
03620 misdn_tasks_remove(ch->overlap_dial_task);
03621 ch->overlap_dial_task = -1;
03622 }
03623 ast_mutex_destroy(&ch->overlap_tv_lock);
03624 }
03625
03626 if (ch->originator == ORG_AST) {
03627 misdn_out_calls[bc->port]--;
03628 } else {
03629 misdn_in_calls[bc->port]--;
03630 }
03631
03632 if (ch) {
03633
03634 close(ch->pipe[0]);
03635 close(ch->pipe[1]);
03636
03637
03638 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03639 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));
03640 chan_misdn_log(3, bc->port, " --> * State Down\n");
03641 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
03642
03643
03644 if (ast->_state != AST_STATE_RESERVED) {
03645 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03646 ast_setstate(ast, AST_STATE_DOWN);
03647 }
03648 }
03649
03650 ch->state=MISDN_CLEANING;
03651 cl_dequeue_chan(&cl_te, ch);
03652
03653 free(ch);
03654 } else {
03655
03656 }
03657 }
03658
03659 ast_mutex_unlock(&release_lock);
03660 }
03661
03662
03663 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
03664 {
03665 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
03666
03667 tmp_ch->state=MISDN_HOLD_DISCONNECT;
03668
03669 ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03670
03671 holded_chan->state=MISDN_CONNECTED;
03672
03673 ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03674 }
03675
03676
03677 static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
03678 {
03679 char predial[256]="";
03680 char *p = predial;
03681
03682 struct ast_frame fr;
03683
03684 strncpy(predial, ast->exten, sizeof(predial) -1 );
03685
03686 ch->state=MISDN_DIALING;
03687
03688 if (!ch->noautorespond_on_setup) {
03689 if (bc->nt) {
03690 int ret;
03691 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03692 } else {
03693 int ret;
03694 if ( misdn_lib_is_ptp(bc->port)) {
03695 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03696 } else {
03697 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03698 }
03699 }
03700 } else {
03701 ch->state = MISDN_INCOMING_SETUP;
03702 }
03703
03704 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);
03705
03706 strncpy(ast->exten,"s", 2);
03707
03708 if (pbx_start_chan(ch)<0) {
03709 ast=NULL;
03710 hangup_chan(ch);
03711 hanguptone_indicate(ch);
03712
03713 if (bc->nt)
03714 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03715 else
03716 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03717 }
03718
03719
03720 while (!ast_strlen_zero(p) ) {
03721 fr.frametype = AST_FRAME_DTMF;
03722 fr.subclass = *p ;
03723 fr.src=NULL;
03724 fr.data = NULL ;
03725 fr.datalen = 0;
03726 fr.samples = 0 ;
03727 fr.mallocd =0 ;
03728 fr.offset= 0 ;
03729 fr.delivery= ast_tv(0,0) ;
03730
03731 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03732 ast_queue_frame(ch->ast, &fr);
03733 }
03734 p++;
03735 }
03736 }
03737
03738
03739
03740 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
03741 if (!ast) {
03742 chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
03743 return;
03744 }
03745 if (!bc) {
03746 chan_misdn_log(1,0,"send_cause2ast: No BC\n");
03747 return;
03748 }
03749 if (!ch) {
03750 chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
03751 return;
03752 }
03753
03754 ast->hangupcause=bc->cause;
03755
03756 switch ( bc->cause) {
03757
03758 case 1:
03759 case 2:
03760 case 3:
03761 case 4:
03762 case 22:
03763 case 27:
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773 break;
03774
03775 case 21:
03776 case 17:
03777
03778 ch->state=MISDN_BUSY;
03779
03780 if (!ch->need_busy) {
03781 chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
03782 break;
03783 }
03784
03785 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
03786
03787 ast_queue_control(ast, AST_CONTROL_BUSY);
03788
03789 ch->need_busy=0;
03790
03791 break;
03792 }
03793 }
03794
03795
03796
03797
03798 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03799 {
03800 const char *tmp;
03801 tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
03802 if (tmp) {
03803 ch->other_pid=atoi(tmp);
03804 chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp);
03805 if (ch->other_pid >0) {
03806 ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
03807 if (ch->other_ch) ch->other_ch->other_ch=ch;
03808 }
03809 }
03810
03811 tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
03812 if (tmp && (atoi(tmp) == 1)) {
03813 bc->sending_complete=1;
03814 }
03815
03816 tmp=pbx_builtin_getvar_helper(chan,"MISDN_USERUSER");
03817 if (tmp) {
03818 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
03819 strcpy(bc->uu, tmp);
03820 bc->uulen=strlen(bc->uu);
03821 }
03822
03823 tmp=pbx_builtin_getvar_helper(chan,"MISDN_KEYPAD");
03824 if (tmp) {
03825 strncpy(bc->keypad,tmp,sizeof(bc->keypad));
03826 bc->keypad[sizeof(bc->keypad)-1]=0;
03827 }
03828
03829
03830 }
03831
03832 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03833 {
03834 char tmp[32];
03835 chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
03836 sprintf(tmp,"%d",bc->pid);
03837 pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
03838
03839 if (bc->sending_complete) {
03840 sprintf(tmp,"%d",bc->sending_complete);
03841 pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
03842 }
03843
03844 if (bc->urate) {
03845 sprintf(tmp,"%d",bc->urate);
03846 pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp);
03847 }
03848
03849 if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
03850 bc->uu[bc->uulen]=0;
03851 pbx_builtin_setvar_helper(chan,"MISDN_USERUSER",bc->uu);
03852 }
03853
03854 if (bc->keypad[0])
03855 pbx_builtin_setvar_helper(chan,"MISDN_KEYPAD",bc->keypad);
03856 }
03857
03858 int add_in_calls(int port)
03859 {
03860 int max_in_calls;
03861
03862 misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
03863 misdn_in_calls[port]++;
03864
03865 if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) {
03866 ast_log(LOG_NOTICE,"Marking Incoming Call on port[%d]\n",port);
03867 return misdn_in_calls[port]-max_in_calls;
03868 }
03869
03870 return 0;
03871 }
03872
03873 int add_out_calls(int port)
03874 {
03875 int max_out_calls;
03876
03877 misdn_cfg_get( port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
03878
03879
03880 if (max_out_calls >=0 && max_out_calls<=misdn_out_calls[port]) {
03881 ast_log(LOG_NOTICE,"Rejecting Outgoing Call on port[%d]\n",port);
03882 return (misdn_out_calls[port]+1)-max_out_calls;
03883 }
03884
03885 misdn_out_calls[port]++;
03886
03887 return 0;
03888 }
03889
03890 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03891 if (pbx_start_chan(ch)<0) {
03892 hangup_chan(ch);
03893 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03894 if (bc->nt) {
03895 hanguptone_indicate(ch);
03896 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03897 } else
03898 misdn_lib_send_event(bc, EVENT_RELEASE);
03899 }
03900 }
03901
03902 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03903 ch->state=MISDN_WAITING4DIGS;
03904 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03905 if (bc->nt && !bc->dad[0])
03906 dialtone_indicate(ch);
03907 }
03908
03909
03910
03911
03912
03913 static enum event_response_e
03914 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
03915 {
03916 int msn_valid;
03917 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03918
03919 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
03920 int debuglevel=1;
03921 if ( event==EVENT_CLEANUP && !user_data)
03922 debuglevel=5;
03923
03924 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");
03925 if (debuglevel==1) {
03926 misdn_lib_log_ies(bc);
03927 chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
03928 }
03929 }
03930
03931 if (!ch) {
03932 switch(event) {
03933 case EVENT_SETUP:
03934 case EVENT_DISCONNECT:
03935 case EVENT_PORT_ALARM:
03936 case EVENT_RETRIEVE:
03937 case EVENT_NEW_BC:
03938 case EVENT_FACILITY:
03939 break;
03940 case EVENT_RELEASE_COMPLETE:
03941 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
03942 break;
03943 case EVENT_CLEANUP:
03944 case EVENT_TONE_GENERATE:
03945 case EVENT_BCHAN_DATA:
03946 return -1;
03947
03948 default:
03949 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);
03950 return -1;
03951 }
03952 }
03953
03954 if (ch ) {
03955 switch (event) {
03956 case EVENT_TONE_GENERATE:
03957 break;
03958 case EVENT_DISCONNECT:
03959 case EVENT_RELEASE:
03960 case EVENT_RELEASE_COMPLETE:
03961 case EVENT_CLEANUP:
03962 case EVENT_TIMEOUT:
03963 if (!ch->ast)
03964 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));
03965 break;
03966 default:
03967 if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03968 if (event!=EVENT_BCHAN_DATA)
03969 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
03970 return -1;
03971 }
03972 }
03973 }
03974
03975
03976 switch (event) {
03977 case EVENT_PORT_ALARM:
03978 {
03979 int boa=0;
03980 misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
03981 if (boa) {
03982 cb_log(1,bc->port," --> blocking\n");
03983 misdn_lib_port_block(bc->port);
03984 }
03985 }
03986 break;
03987 case EVENT_BCHAN_ACTIVATED:
03988 break;
03989
03990 case EVENT_NEW_CHANNEL:
03991 update_name(ch->ast,bc->port,bc->channel);
03992 break;
03993
03994 case EVENT_NEW_L3ID:
03995 ch->l3id=bc->l3_id;
03996 ch->addr=bc->addr;
03997 break;
03998
03999 case EVENT_NEW_BC:
04000 if (!ch) {
04001 ch=find_holded(cl_te,bc);
04002 }
04003
04004 if (!ch) {
04005 ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
04006 break;
04007 }
04008
04009 if (bc)
04010 ch->bc=(struct misdn_bchannel*)user_data;
04011 break;
04012
04013 case EVENT_DTMF_TONE:
04014 {
04015
04016 struct ast_frame fr;
04017 memset(&fr, 0 , sizeof(fr));
04018 fr.frametype = AST_FRAME_DTMF;
04019 fr.subclass = bc->dtmf ;
04020 fr.src=NULL;
04021 fr.data = NULL ;
04022 fr.datalen = 0;
04023 fr.samples = 0 ;
04024 fr.mallocd =0 ;
04025 fr.offset= 0 ;
04026 fr.delivery= ast_tv(0,0) ;
04027
04028 if (!ch->ignore_dtmf) {
04029 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04030 ast_queue_frame(ch->ast, &fr);
04031 } else {
04032 chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
04033 }
04034 }
04035 break;
04036 case EVENT_STATUS:
04037 break;
04038
04039 case EVENT_INFORMATION:
04040 {
04041 int l;
04042
04043 if ( ch->state != MISDN_CONNECTED )
04044 stop_indicate(ch);
04045
04046 if (!ch->ast) break;
04047
04048 if (ch->state == MISDN_WAITING4DIGS ) {
04049
04050 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04051 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04052 strcpy(bc->info_dad,bc->keypad);
04053 }
04054
04055 l = sizeof(bc->dad);
04056 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad) - 1);
04057
04058 l = sizeof(ch->ast->exten);
04059 strncpy(ch->ast->exten, bc->dad, l);
04060 ch->ast->exten[l-1] = 0;
04061
04062
04063 if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04064 if (ast_pickup_call(ch->ast)) {
04065 hangup_chan(ch);
04066 } else {
04067 struct ast_channel *chan=ch->ast;
04068 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04069 ast_setstate(chan, AST_STATE_DOWN);
04070 hangup_chan(ch);
04071 ch->ast=NULL;
04072 break;
04073 }
04074 }
04075
04076 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04077 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04078 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
04079 strcpy(ch->ast->exten, "i");
04080
04081 ch->state = MISDN_DIALING;
04082 start_pbx(ch, bc, ch->ast);
04083 break;
04084 }
04085
04086 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
04087 "maybe you want to add an 'i' extension to catch this case.\n",
04088 bc->port);
04089
04090 if (bc->nt)
04091 hanguptone_indicate(ch);
04092 ch->state=MISDN_EXTCANTMATCH;
04093 bc->out_cause=1;
04094
04095 misdn_lib_send_event(bc, EVENT_DISCONNECT );
04096 break;
04097 }
04098
04099 if (ch->overlap_dial) {
04100 ast_mutex_lock(&ch->overlap_tv_lock);
04101 ch->overlap_tv = ast_tvnow();
04102 ast_mutex_unlock(&ch->overlap_tv_lock);
04103 if (ch->overlap_dial_task == -1) {
04104 ch->overlap_dial_task =
04105 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04106 }
04107 break;
04108 }
04109
04110 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04111
04112 ch->state = MISDN_DIALING;
04113 start_pbx(ch, bc, ch->ast);
04114 }
04115 } else {
04116
04117 int digits;
04118 struct ast_frame fr;
04119 memset(&fr, 0, sizeof(fr));
04120 fr.frametype = AST_FRAME_DTMF;
04121 fr.subclass = bc->info_dad[0] ;
04122 fr.src=NULL;
04123 fr.data = NULL ;
04124 fr.datalen = 0;
04125 fr.samples = 0 ;
04126 fr.mallocd =0 ;
04127 fr.offset= 0 ;
04128 fr.delivery= ast_tv(0,0) ;
04129
04130 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
04131 if (ch->state != MISDN_CONNECTED ) {
04132 if (digits) {
04133 int l = sizeof(bc->dad);
04134 strncat(bc->dad, bc->info_dad, l - strlen(bc->dad) - 1);
04135 l = sizeof(ch->ast->exten);
04136 strncpy(ch->ast->exten, bc->dad, l);
04137 ch->ast->exten[l-1] = 0;
04138
04139 ast_cdr_update(ch->ast);
04140 }
04141
04142 ast_queue_frame(ch->ast, &fr);
04143 }
04144 }
04145 }
04146 break;
04147 case EVENT_SETUP:
04148 {
04149 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
04150 if (ch) {
04151 switch (ch->state) {
04152 case MISDN_NOTHING:
04153 ch=NULL;
04154 break;
04155 default:
04156 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04157 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE;
04158 }
04159 }
04160 }
04161
04162 msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04163 if (!bc->nt && ! msn_valid) {
04164 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04165 return RESPONSE_IGNORE_SETUP;
04166 }
04167
04168
04169 if (bc->cw) {
04170 int cause;
04171 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04172 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04173 bc->out_cause=cause?cause:16;
04174 return RESPONSE_RELEASE_SETUP;
04175 }
04176
04177 print_bearer(bc);
04178
04179 {
04180 struct chan_list *ch;
04181 struct ast_channel *chan;
04182 int exceed;
04183 int pres,screen;
04184 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04185 int ai, im;
04186 if (!bc->nt && ! msn_valid) {
04187 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04188 return RESPONSE_IGNORE_SETUP;
04189 }
04190
04191 if (bc->cw) {
04192 int cause;
04193 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04194 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04195 bc->out_cause=cause?cause:16;
04196 return RESPONSE_RELEASE_SETUP;
04197 }
04198
04199 print_bearer(bc);
04200
04201 ch=init_chan_list(ORG_MISDN);
04202
04203 if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
04204
04205 ch->bc = bc;
04206 ch->l3id=bc->l3_id;
04207 ch->addr=bc->addr;
04208 ch->originator = ORG_MISDN;
04209
04210 chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04211
04212 if (!chan) {
04213 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04214 ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
04215 return 0;
04216 }
04217
04218 ch->ast = chan;
04219
04220 if ((exceed=add_in_calls(bc->port))) {
04221 char tmp[16];
04222 sprintf(tmp,"%d",exceed);
04223 pbx_builtin_setvar_helper(chan,"MAX_OVERFLOW",tmp);
04224 }
04225
04226 read_config(ch, ORG_MISDN);
04227
04228 export_ch(chan, bc, ch);
04229
04230 ch->ast->rings=1;
04231 ast_setstate(ch->ast, AST_STATE_RINGING);
04232
04233 switch (bc->pres) {
04234 case 1:
04235 pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
04236 break;
04237 case 2:
04238 pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
04239 break;
04240 default:
04241 pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
04242 }
04243
04244 switch (bc->screen) {
04245 case 0:
04246 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
04247 break;
04248 case 1:
04249 screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
04250 break;
04251 case 2:
04252 screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
04253 break;
04254 case 3:
04255 screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
04256 break;
04257 default:
04258 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
04259 }
04260
04261 chan->cid.cid_pres=pres+screen;
04262
04263 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04264 chan->transfercapability=bc->capability;
04265
04266 switch (bc->capability) {
04267 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04268 pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
04269 break;
04270 default:
04271 pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
04272 }
04273
04274
04275 cl_queue_chan(&cl_te, ch) ;
04276
04277 if (!strstr(ch->allowed_bearers,"all")) {
04278 int i;
04279 for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
04280 if (allowed_bearers_array[i].cap == bc->capability) {
04281 if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
04282 chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
04283 bc->out_cause=88;
04284
04285 ch->state=MISDN_EXTCANTMATCH;
04286 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04287 return RESPONSE_OK;
04288 }
04289 }
04290
04291 }
04292 }
04293
04294
04295 if (!strcmp(chan->exten, ast_pickup_ext())) {
04296 if (!ch->noautorespond_on_setup) {
04297 int ret;
04298 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04299 } else {
04300 ch->state = MISDN_INCOMING_SETUP;
04301 }
04302 if (ast_pickup_call(chan)) {
04303 hangup_chan(ch);
04304 } else {
04305 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04306 ast_setstate(chan, AST_STATE_DOWN);
04307 hangup_chan(ch);
04308 ch->ast=NULL;
04309 break;
04310 }
04311 }
04312
04313
04314
04315
04316
04317 misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04318 if ( ai ) {
04319 do_immediate_setup(bc, ch , chan);
04320 break;
04321 }
04322
04323
04324 misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04325 if ( im && ast_strlen_zero(bc->dad) ) {
04326 do_immediate_setup(bc, ch , chan);
04327 break;
04328 }
04329
04330 chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
04331 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04332 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04333 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
04334 strcpy(ch->ast->exten, "i");
04335 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04336 ch->state=MISDN_DIALING;
04337 start_pbx(ch, bc, chan);
04338 break;
04339 }
04340
04341 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
04342 "maybe you want to add an 'i' extension to catch this case.\n",
04343 bc->port);
04344 if (bc->nt)
04345 hanguptone_indicate(ch);
04346
04347 ch->state=MISDN_EXTCANTMATCH;
04348 bc->out_cause=1;
04349
04350 if (bc->nt)
04351 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04352 else
04353 misdn_lib_send_event(bc, EVENT_RELEASE );
04354
04355 break;
04356 }
04357
04358
04359
04360
04361 if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04362 if (!ch->noautorespond_on_setup) {
04363 ch->state=MISDN_DIALING;
04364 misdn_lib_send_event(bc, EVENT_PROCEEDING );
04365 } else {
04366 ch->state = MISDN_INCOMING_SETUP;
04367 }
04368 start_pbx(ch, bc, chan);
04369 break;
04370 }
04371
04372
04373
04374
04375
04376
04377
04378 if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04379 wait_for_digits(ch, bc, chan);
04380 break;
04381 }
04382
04383
04384
04385
04386
04387 if (ch->overlap_dial) {
04388 ast_mutex_lock(&ch->overlap_tv_lock);
04389 ch->overlap_tv = ast_tvnow();
04390 ast_mutex_unlock(&ch->overlap_tv_lock);
04391
04392 wait_for_digits(ch, bc, chan);
04393 if (ch->overlap_dial_task == -1)
04394 ch->overlap_dial_task =
04395 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04396
04397 break;
04398 }
04399
04400
04401
04402
04403 if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04404 wait_for_digits(ch, bc, chan);
04405 break;
04406 }
04407
04408
04409
04410
04411 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04412 if (bc->need_more_infos)
04413 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04414 else
04415 misdn_lib_send_event(bc, EVENT_PROCEEDING);
04416
04417 ch->state=MISDN_DIALING;
04418 start_pbx(ch, bc, chan);
04419 break;
04420 }
04421 }
04422 break;
04423
04424 case EVENT_SETUP_ACKNOWLEDGE:
04425 {
04426 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04427
04428 if (bc->channel)
04429 update_name(ch->ast,bc->port,bc->channel);
04430
04431 if (!ast_strlen_zero(bc->infos_pending)) {
04432
04433
04434 {
04435 int l = sizeof(bc->dad);
04436 strncat(bc->dad, bc->infos_pending, l - strlen(bc->dad) - 1);
04437 }
04438
04439 if (!ch->ast) break;
04440 {
04441 int l = sizeof(ch->ast->exten);
04442 strncpy(ch->ast->exten, bc->dad, l);
04443 ch->ast->exten[l-1] = 0;
04444 }
04445 {
04446 int l = sizeof(bc->info_dad);
04447 strncpy(bc->info_dad, bc->infos_pending, l);
04448 bc->info_dad[l-1] = 0;
04449 }
04450 strncpy(bc->infos_pending,"", 1);
04451
04452 misdn_lib_send_event(bc, EVENT_INFORMATION);
04453 }
04454 }
04455 break;
04456 case EVENT_PROCEEDING:
04457 {
04458 if (bc->channel)
04459 update_name(ch->ast,bc->port,bc->channel);
04460
04461 if ( misdn_cap_is_speech(bc->capability) &&
04462 misdn_inband_avail(bc) ) {
04463 start_bc_tones(ch);
04464 }
04465
04466 ch->state = MISDN_PROCEEDING;
04467
04468 if (!ch->ast) break;
04469
04470 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04471 }
04472 break;
04473 case EVENT_PROGRESS:
04474 if (bc->channel)
04475 update_name(ch->ast,bc->port,bc->channel);
04476
04477 if (!bc->nt ) {
04478 if ( misdn_cap_is_speech(bc->capability) &&
04479 misdn_inband_avail(bc)
04480 ) {
04481 start_bc_tones(ch);
04482 }
04483
04484 ch->state=MISDN_PROGRESS;
04485
04486 if (!ch->ast) break;
04487 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04488 }
04489 break;
04490
04491
04492 case EVENT_ALERTING:
04493 {
04494 if (bc->channel)
04495 update_name(ch->ast,bc->port,bc->channel);
04496
04497 ch->state = MISDN_ALERTING;
04498
04499 if (!ch->ast) break;
04500
04501 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04502 ast_setstate(ch->ast, AST_STATE_RINGING);
04503
04504 cb_log(7,bc->port," --> Set State Ringing\n");
04505
04506 if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04507 cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
04508 start_bc_tones(ch);
04509 } else {
04510 cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
04511 if (ch->far_alerting) {
04512 cb_log(1,bc->port," --> The other end can not do ringing eh ?.. we must do all ourself..");
04513 start_bc_tones(ch);
04514
04515 }
04516 }
04517 }
04518 break;
04519 case EVENT_CONNECT:
04520 {
04521 struct ast_channel *bridged;
04522
04523 misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
04524
04525 if (!ch->ast) break;
04526
04527 bridged=ast_bridged_channel(ch->ast);
04528 stop_indicate(ch);
04529
04530 if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
04531 struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
04532
04533 chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
04534 if (bridged_ch) {
04535 bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
04536 ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
04537 }
04538 }
04539 }
04540 ch->l3id=bc->l3_id;
04541 ch->addr=bc->addr;
04542
04543 start_bc_tones(ch);
04544
04545 ch->state = MISDN_CONNECTED;
04546
04547 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04548 break;
04549 case EVENT_CONNECT_ACKNOWLEDGE:
04550 {
04551 ch->l3id=bc->l3_id;
04552 ch->addr=bc->addr;
04553
04554 start_bc_tones(ch);
04555
04556 ch->state = MISDN_CONNECTED;
04557 }
04558 break;
04559 case EVENT_DISCONNECT:
04560
04561 if (ch) {
04562 struct chan_list *holded_ch=find_holded(cl_te, bc);
04563
04564 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);
04565 if ( ch->originator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04566
04567
04568
04569
04570
04571 chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04572
04573 ch->state=MISDN_DISCONNECTED;
04574 start_bc_tones(ch);
04575
04576 if (ch->ast) {
04577 ch->ast->hangupcause=bc->cause;
04578 if (bc->cause == 17)
04579 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04580 }
04581 ch->need_busy=0;
04582 break;
04583 }
04584
04585
04586 if ( holded_ch &&
04587 holded_ch != ch &&
04588 ch->ast &&
04589 ch->state == MISDN_CONNECTED ) {
04590 cb_log(1,bc->port," --> found holded ch\n");
04591 misdn_transfer_bc(ch, holded_ch) ;
04592 }
04593
04594 bc->need_disconnect=0;
04595
04596 stop_bc_tones(ch);
04597 hangup_chan(ch);
04598 } else {
04599
04600
04601
04602
04603
04604 }
04605 bc->out_cause=-1;
04606 if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
04607 break;
04608
04609 case EVENT_RELEASE:
04610 {
04611 bc->need_disconnect=0;
04612 bc->need_release=0;
04613
04614 hangup_chan(ch);
04615 release_chan(bc);
04616 }
04617 break;
04618 case EVENT_RELEASE_COMPLETE:
04619 {
04620 bc->need_disconnect=0;
04621 bc->need_release=0;
04622 bc->need_release_complete=0;
04623
04624 stop_bc_tones(ch);
04625 hangup_chan(ch);
04626
04627 if(ch)
04628 ch->state=MISDN_CLEANING;
04629
04630 release_chan(bc);
04631 }
04632 break;
04633 case EVENT_BCHAN_ERROR:
04634 case EVENT_CLEANUP:
04635 {
04636 stop_bc_tones(ch);
04637
04638 switch(ch->state) {
04639 case MISDN_CALLING:
04640 bc->cause=27;
04641 break;
04642 default:
04643 break;
04644 }
04645
04646 hangup_chan(ch);
04647 release_chan(bc);
04648 }
04649 break;
04650
04651 case EVENT_TONE_GENERATE:
04652 {
04653 int tone_len=bc->tone_cnt;
04654 struct ast_channel *ast=ch->ast;
04655 void *tmp;
04656 int res;
04657 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04658
04659 chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
04660
04661 if (!ast) break;
04662
04663 if (!ast->generator) break;
04664
04665
04666
04667 tmp = ast->generatordata;
04668 ast->generatordata = NULL;
04669 generate = ast->generator->generate;
04670
04671 if (tone_len <0 || tone_len > 512 ) {
04672 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
04673 tone_len=128;
04674 }
04675
04676 res = generate(ast, tmp, tone_len, tone_len);
04677 ast->generatordata = tmp;
04678
04679 if (res) {
04680 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04681 ast_deactivate_generator(ast);
04682 } else {
04683 bc->tone_cnt=0;
04684 }
04685 }
04686 break;
04687
04688 case EVENT_BCHAN_DATA:
04689 {
04690 if ( !misdn_cap_is_speech(ch->bc->capability) ) {
04691 struct ast_frame frame;
04692
04693 frame.frametype = AST_FRAME_VOICE;
04694 frame.subclass = AST_FORMAT_ALAW;
04695 frame.datalen = bc->bframe_len;
04696 frame.samples = bc->bframe_len ;
04697 frame.mallocd =0 ;
04698 frame.offset= 0 ;
04699 frame.delivery= ast_tv(0,0) ;
04700 frame.src = NULL;
04701 frame.data = bc->bframe ;
04702
04703 if (ch->ast)
04704 ast_queue_frame(ch->ast,&frame);
04705 } else {
04706 int t;
04707 fd_set wrfs;
04708 struct timeval tv;
04709 tv.tv_sec=0;
04710 tv.tv_usec=0;
04711
04712
04713 FD_ZERO(&wrfs);
04714 FD_SET(ch->pipe[1],&wrfs);
04715
04716 t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
04717
04718 if (!t) {
04719 chan_misdn_log(9, bc->port, "Select Timed out\n");
04720 break;
04721 }
04722
04723 if (t<0) {
04724 chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
04725 break;
04726 }
04727
04728 if (FD_ISSET(ch->pipe[1],&wrfs)) {
04729 int ret;
04730 chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
04731 ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
04732
04733 if (ret<=0) {
04734 chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno));
04735
04736 stop_bc_tones(ch);
04737 hangup_chan(ch);
04738 release_chan(bc);
04739 }
04740 } else {
04741 chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
04742 }
04743 }
04744 }
04745 break;
04746 case EVENT_TIMEOUT:
04747 {
04748 if (ch && bc)
04749 chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
04750
04751 switch (ch->state) {
04752 case MISDN_DIALING:
04753 case MISDN_PROGRESS:
04754 if (bc->nt && !ch->nttimeout) break;
04755
04756 case MISDN_CALLING:
04757 case MISDN_ALERTING:
04758 case MISDN_PROCEEDING:
04759 case MISDN_CALLING_ACKNOWLEDGE:
04760 if (bc->nt) {
04761 bc->progress_indicator=8;
04762 hanguptone_indicate(ch);
04763 }
04764
04765 bc->out_cause=1;
04766 misdn_lib_send_event(bc,EVENT_DISCONNECT);
04767 break;
04768
04769 case MISDN_WAITING4DIGS:
04770 if (bc->nt) {
04771 bc->progress_indicator=8;
04772 bc->out_cause=1;
04773 hanguptone_indicate(ch);
04774 misdn_lib_send_event(bc,EVENT_DISCONNECT);
04775 } else {
04776 bc->out_cause=16;
04777 misdn_lib_send_event(bc,EVENT_RELEASE);
04778 }
04779
04780 break;
04781
04782
04783 case MISDN_CLEANING:
04784 chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
04785 break;
04786
04787 default:
04788 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04789 }
04790 }
04791 break;
04792
04793
04794
04795
04796
04797 case EVENT_RETRIEVE:
04798 {
04799 struct ast_channel *hold_ast;
04800 if (!ch) {
04801 chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
04802 ch=find_holded_l3(cl_te, bc->l3_id,1);
04803 }
04804
04805 if (!ch) {
04806 ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
04807 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04808 break;
04809 }
04810
04811
04812 ch->bc=bc;
04813 ch->state = MISDN_CONNECTED;
04814
04815 ch->hold_info.port=0;
04816 ch->hold_info.channel=0;
04817
04818 hold_ast=ast_bridged_channel(ch->ast);
04819
04820 if (hold_ast) {
04821 ast_moh_stop(hold_ast);
04822 }
04823
04824 if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
04825 chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
04826 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04827 }
04828 }
04829 break;
04830
04831 case EVENT_HOLD:
04832 {
04833 int hold_allowed;
04834 struct ast_channel *bridged;
04835 misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04836
04837 if (!hold_allowed) {
04838
04839 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04840 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04841 break;
04842 }
04843
04844 bridged=ast_bridged_channel(ch->ast);
04845
04846 if (bridged) {
04847 chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
04848 ch->state = MISDN_HOLDED;
04849 ch->l3id = bc->l3_id;
04850
04851 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04852
04853
04854
04855 ast_moh_start(bridged, NULL, NULL);
04856
04857
04858 ch->bc=NULL;
04859 ch->hold_info.port=bc->port;
04860 ch->hold_info.channel=bc->channel;
04861
04862 } else {
04863 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04864 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04865 }
04866 }
04867 break;
04868
04869 case EVENT_FACILITY:
04870 if (!ch) {
04871
04872 chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
04873 break;
04874 }
04875
04876 print_facility(&(bc->fac_in), bc);
04877
04878 switch (bc->fac_in.Function) {
04879 case Fac_CD:
04880 {
04881 struct ast_channel *bridged=ast_bridged_channel(ch->ast);
04882 struct chan_list *ch_br;
04883 if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04884 ch_br=MISDN_ASTERISK_TECH_PVT(bridged);
04885
04886 if (ch_br->bc) {
04887 if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
04888 ch_br->state=MISDN_DIALING;
04889 if (pbx_start_chan(ch_br) < 0) {
04890 chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
04891 }
04892 }
04893 }
04894
04895 }
04896 misdn_lib_send_event(bc, EVENT_DISCONNECT);
04897 }
04898 break;
04899 case Fac_AOCDCurrency:
04900 bc->AOCDtype = Fac_AOCDCurrency;
04901 memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
04902 export_aoc_vars(ch->originator, ch->ast, bc);
04903 break;
04904 case Fac_AOCDChargingUnit:
04905 bc->AOCDtype = Fac_AOCDChargingUnit;
04906 memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
04907 export_aoc_vars(ch->originator, ch->ast, bc);
04908 break;
04909 default:
04910 chan_misdn_log(0, bc->port," --> not yet handled: facility type:%p\n", bc->fac_in.Function);
04911 }
04912
04913 break;
04914
04915 case EVENT_RESTART:
04916
04917 if (!bc->dummy) {
04918 stop_bc_tones(ch);
04919 release_chan(bc);
04920 }
04921
04922 break;
04923
04924 default:
04925 chan_misdn_log(1,0, "Got Unknown Event\n");
04926 break;
04927 }
04928
04929 return RESPONSE_OK;
04930 }
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943 static int unload_module(void)
04944 {
04945
04946 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
04947
04948 misdn_tasks_destroy();
04949
04950 if (!g_config_initialized) return 0;
04951
04952 ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
04953
04954
04955 ast_unregister_application("misdn_set_opt");
04956 ast_unregister_application("misdn_facility");
04957 ast_unregister_application("misdn_check_l2l1");
04958
04959 ast_channel_unregister(&misdn_tech);
04960
04961
04962 free_robin_list();
04963 misdn_cfg_destroy();
04964 misdn_lib_destroy();
04965
04966 if (misdn_debug)
04967 free(misdn_debug);
04968 if (misdn_debug_only)
04969 free(misdn_debug_only);
04970 free(misdn_ports);
04971
04972 return 0;
04973 }
04974
04975 static int load_module(void)
04976 {
04977 int i, port;
04978
04979 char ports[256]="";
04980
04981 max_ports=misdn_lib_maxports_get();
04982
04983 if (max_ports<=0) {
04984 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
04985 return AST_MODULE_LOAD_DECLINE;
04986 }
04987
04988 if (misdn_cfg_init(max_ports)) {
04989 ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
04990 return AST_MODULE_LOAD_DECLINE;
04991 }
04992 g_config_initialized=1;
04993
04994 misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
04995 misdn_ports = (int *)malloc(sizeof(int) * (max_ports+1));
04996 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
04997 for (i = 1; i <= max_ports; i++) {
04998 misdn_debug[i] = misdn_debug[0];
04999 misdn_ports[i] = i;
05000 }
05001 *misdn_ports = 0;
05002 misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
05003
05004 {
05005 char tempbuf[BUFFERSIZE+1];
05006 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
05007 if (strlen(tempbuf))
05008 tracing = 1;
05009 }
05010
05011 misdn_in_calls = (int *)malloc(sizeof(int) * (max_ports+1));
05012 misdn_out_calls = (int *)malloc(sizeof(int) * (max_ports+1));
05013
05014 for (i=1; i <= max_ports; i++) {
05015 misdn_in_calls[i]=0;
05016 misdn_out_calls[i]=0;
05017 }
05018
05019 ast_mutex_init(&cl_te_lock);
05020 ast_mutex_init(&release_lock);
05021
05022 misdn_cfg_update_ptp();
05023 misdn_cfg_get_ports_string(ports);
05024
05025 if (strlen(ports))
05026 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
05027
05028 {
05029 int ntflags=0, ntkc=0;
05030 char ntfile[BUFFERSIZE+1];
05031 struct misdn_lib_iface iface = {
05032 .cb_event = cb_events,
05033 .cb_log = chan_misdn_log,
05034 .cb_jb_empty = chan_misdn_jb_empty,
05035 };
05036
05037 if (misdn_lib_init(ports, &iface, NULL))
05038 chan_misdn_log(0, 0, "No te ports initialized\n");
05039
05040 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
05041 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
05042 misdn_lib_nt_debug_init(ntflags,ntfile);
05043
05044 misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(int));
05045 misdn_lib_nt_keepcalls(ntkc);
05046 }
05047
05048 {
05049 if (ast_channel_register(&misdn_tech)) {
05050 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05051 unload_module();
05052 return -1;
05053 }
05054 }
05055
05056 ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05057
05058 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05059 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
05060 "Sets mISDN opts. and optargs\n"
05061 "\n"
05062 "The available options are:\n"
05063 " d - Send display text on called phone, text is the optparam\n"
05064 " n - don't detect dtmf tones on called channel\n"
05065 " h - make digital outgoing call\n"
05066 " c - make crypted outgoing call, param is keyindex\n"
05067 " e - perform echo cancelation on this channel,\n"
05068 " takes taps as arguments (32,64,128,256)\n"
05069 " s - send Non Inband DTMF as inband\n"
05070 " vr - rxgain control\n"
05071 " vt - txgain control\n"
05072 " i - Ignore detected dtmf tones, don't signal them to asterisk, they will be transported inband.\n"
05073 );
05074
05075
05076 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05077 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05078 "Sends the Facility Message FACILITY_TYPE with \n"
05079 "the given Arguments to the current ISDN Channel\n"
05080 "Supported Facilities are:\n"
05081 "\n"
05082 "type=calldeflect args=Nr where to deflect\n"
05083 );
05084
05085
05086 ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05087 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05088 "Checks if the L2 and L1 are up on either the given <port> or\n"
05089 "on the ports in the group with <groupname>\n"
05090 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05091 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05092 "\n"
05093 "This application, ensures the L1/L2 state of the Ports in a group\n"
05094 "it is intended to make the pmp_l1_check option redundant and to\n"
05095 "fix a buggy switch config from your provider\n"
05096 "\n"
05097 "a sample dialplan would look like:\n\n"
05098 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05099 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05100 "\n"
05101 );
05102
05103
05104 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
05105
05106
05107
05108 for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05109 int l1timeout;
05110 misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05111 if (l1timeout) {
05112 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05113 misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
05114 }
05115 }
05116
05117 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05118
05119 return 0;
05120 }
05121
05122
05123
05124 static int reload(void)
05125 {
05126 reload_config();
05127
05128 return 0;
05129 }
05130
05131
05132
05133 static int misdn_facility_exec(struct ast_channel *chan, void *data)
05134 {
05135 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05136 char *tok, *tokb;
05137
05138 chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
05139
05140 if (strcasecmp(chan->tech->type,"mISDN")) {
05141 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05142 return -1;
05143 }
05144
05145 if (ast_strlen_zero((char *)data)) {
05146 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05147 return -1;
05148 }
05149
05150 tok=strtok_r((char*)data,"|", &tokb) ;
05151
05152 if (!tok) {
05153 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05154 return -1;
05155 }
05156
05157 if (!strcasecmp(tok,"calldeflect")) {
05158 tok=strtok_r(NULL,"|", &tokb) ;
05159
05160 if (!tok) {
05161 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05162 }
05163
05164 if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05165 ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05166 return 0;
05167 }
05168 ch->bc->fac_out.Function = Fac_CD;
05169 strncpy((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05170 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05171 } else {
05172 chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n",tok);
05173 }
05174
05175 return 0;
05176
05177 }
05178
05179 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
05180 {
05181 char group[BUFFERSIZE+1];
05182 char *port_str;
05183 int port_up;
05184 int timeout;
05185 int dowait=0;
05186 int port=0;
05187
05188 AST_DECLARE_APP_ARGS(args,
05189 AST_APP_ARG(grouppar);
05190 AST_APP_ARG(timeout);
05191 );
05192
05193 if (ast_strlen_zero((char *)data)) {
05194 ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05195 return -1;
05196 }
05197
05198 AST_STANDARD_APP_ARGS(args, data);
05199
05200 if (args.argc != 2) {
05201 ast_log(LOG_WARNING, "Wrong argument count\n");
05202 return 0;
05203 }
05204
05205
05206 timeout=atoi(args.timeout);
05207 port_str=args.grouppar;
05208 if (port_str[0]=='g' && port_str[1]==':' ) {
05209
05210 port_str += 2;
05211 strncpy(group, port_str, BUFFERSIZE);
05212 group[BUFFERSIZE-1] = 0;
05213 chan_misdn_log(2, 0, "Checking Ports in group: %s\n",group);
05214
05215 for ( port = misdn_cfg_get_next_port(port);
05216 port > 0;
05217 port = misdn_cfg_get_next_port(port))
05218 {
05219 char cfg_group[BUFFERSIZE+1];
05220
05221 chan_misdn_log(2,0,"trying port %d\n",port);
05222
05223 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05224
05225 if (!strcasecmp(cfg_group, group)) {
05226 port_up = misdn_lib_port_up(port, 1);
05227
05228 if (!port_up) {
05229 chan_misdn_log(2, 0, " --> port '%d'\n", port);
05230 misdn_lib_get_port_up(port);
05231 dowait=1;
05232 }
05233 }
05234 }
05235
05236 } else {
05237 port = atoi(port_str);
05238 chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05239 port_up = misdn_lib_port_up(port, 1);
05240 if (!port_up) {
05241 misdn_lib_get_port_up(port);
05242 dowait=1;
05243 }
05244
05245 }
05246
05247 if (dowait) {
05248 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n",timeout);
05249 sleep(timeout);
05250 }
05251
05252 return 0;
05253 }
05254
05255 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
05256 {
05257 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05258 char *tok,*tokb;
05259 int keyidx=0;
05260 int rxgain=0;
05261 int txgain=0;
05262 int change_jitter=0;
05263
05264 if (strcasecmp(chan->tech->type,"mISDN")) {
05265 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05266 return -1;
05267 }
05268
05269 if (ast_strlen_zero((char *)data)) {
05270 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05271 return -1;
05272 }
05273
05274 for (tok=strtok_r((char*)data, ":",&tokb);
05275 tok;
05276 tok=strtok_r(NULL,":",&tokb) ) {
05277 char keys[4096];
05278 char *key, *tmp;
05279 int i;
05280 int neglect=0;
05281
05282 if (tok[0] == '!' ) {
05283 neglect=1;
05284 tok++;
05285 }
05286
05287 switch(tok[0]) {
05288
05289 case 'd' :
05290 ast_copy_string(ch->bc->display,++tok,84);
05291 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
05292 break;
05293
05294 case 'n':
05295 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05296 ch->bc->nodsp=1;
05297 break;
05298
05299 case 'j':
05300 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05301 tok++;
05302 change_jitter=1;
05303
05304 switch ( tok[0] ) {
05305 case 'b' :
05306 ch->jb_len=atoi(++tok);
05307 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
05308 break;
05309 case 't' :
05310 ch->jb_upper_threshold=atoi(++tok);
05311 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
05312 break;
05313
05314 case 'n':
05315 ch->bc->nojitter=1;
05316 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05317 break;
05318
05319 default:
05320 ch->jb_len=4000;
05321 ch->jb_upper_threshold=0;
05322 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
05323 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
05324 }
05325
05326 break;
05327
05328 case 'v':
05329 tok++;
05330
05331 switch ( tok[0] ) {
05332 case 'r' :
05333 rxgain=atoi(++tok);
05334 if (rxgain<-8) rxgain=-8;
05335 if (rxgain>8) rxgain=8;
05336 ch->bc->rxgain=rxgain;
05337 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
05338 break;
05339 case 't':
05340 txgain=atoi(++tok);
05341 if (txgain<-8) txgain=-8;
05342 if (txgain>8) txgain=8;
05343 ch->bc->txgain=txgain;
05344 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
05345 break;
05346 }
05347 break;
05348
05349 case 'c':
05350 keyidx=atoi(++tok);
05351 key=NULL;
05352 misdn_cfg_get( 0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05353
05354 tmp=keys;
05355
05356 for (i=0; i<keyidx; i++) {
05357 key=strsep(&tmp,",");
05358 }
05359
05360 if (key) {
05361 ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05362 }
05363
05364 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",ch->bc->crypt_key);
05365 break;
05366
05367 case 'e':
05368 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05369
05370 if (neglect) {
05371 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05372 #ifdef MISDN_1_2
05373 *ch->bc->pipeline=0;
05374 #else
05375 ch->bc->ec_enable=0;
05376 #endif
05377 } else {
05378 #ifdef MISDN_1_2
05379 update_pipeline_config(ch->bc);
05380 #else
05381 ch->bc->ec_enable=1;
05382 ch->bc->orig=ch->originator;
05383 tok++;
05384 if (*tok) {
05385 ch->bc->ec_deftaps=atoi(tok);
05386 }
05387 #endif
05388 }
05389
05390 break;
05391
05392 case 'h':
05393 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05394
05395 if (strlen(tok) > 1 && tok[1]=='1') {
05396 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05397 if (!ch->bc->hdlc) {
05398 ch->bc->hdlc=1;
05399 }
05400 }
05401 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05402 break;
05403
05404 case 's':
05405 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05406 ch->bc->send_dtmf=1;
05407 break;
05408
05409 case 'f':
05410 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05411 ch->faxdetect=1;
05412 misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05413 break;
05414
05415 case 'a':
05416 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05417 ch->ast_dsp=1;
05418 break;
05419
05420 case 'p':
05421 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
05422
05423 if (strstr(tok,"allowed") ) {
05424 ch->bc->pres=0;
05425 } else if (strstr(tok,"not_screened")) {
05426 ch->bc->pres=1;
05427 }
05428 break;
05429 case 'i' :
05430 chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05431 ch->ignore_dtmf=1;
05432 break;
05433 default:
05434 break;
05435 }
05436 }
05437
05438 if (change_jitter)
05439 config_jitterbuffer(ch);
05440
05441
05442 if (ch->faxdetect || ch->ast_dsp) {
05443 if (!ch->dsp) ch->dsp = ast_dsp_new();
05444 if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
05445 if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05446 }
05447
05448 if (ch->ast_dsp) {
05449 chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05450 ch->bc->nodsp=1;
05451 ch->bc->nojitter=1;
05452 }
05453
05454 return 0;
05455 }
05456
05457
05458 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
05459 {
05460 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
05461
05462 if (ch && ch->jb) {
05463 return misdn_jb_empty(ch->jb, buf, len);
05464 }
05465
05466 return -1;
05467 }
05468
05469
05470
05471
05472
05473
05474
05475
05476
05477 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
05478 {
05479 int i;
05480 struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
05481 jb->size = size;
05482 jb->upper_threshold = upper_threshold;
05483 jb->wp = 0;
05484 jb->rp = 0;
05485 jb->state_full = 0;
05486 jb->state_empty = 0;
05487 jb->bytes_wrote = 0;
05488 jb->samples = (char *)malloc(size*sizeof(char));
05489
05490 if (!jb->samples) {
05491 chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
05492 return NULL;
05493 }
05494
05495 jb->ok = (char *)malloc(size*sizeof(char));
05496
05497 if (!jb->ok) {
05498 chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
05499 return NULL;
05500 }
05501
05502 for(i=0; i<size; i++)
05503 jb->ok[i]=0;
05504
05505 ast_mutex_init(&jb->mutexjb);
05506
05507 return jb;
05508 }
05509
05510
05511 void misdn_jb_destroy(struct misdn_jb *jb)
05512 {
05513 ast_mutex_destroy(&jb->mutexjb);
05514
05515 free(jb->samples);
05516 free(jb);
05517 }
05518
05519
05520
05521 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
05522 {
05523 int i, j, rp, wp;
05524
05525 if (!jb || ! data) return 0;
05526
05527 ast_mutex_lock (&jb->mutexjb);
05528
05529 wp=jb->wp;
05530 rp=jb->rp;
05531
05532 for(i=0; i<len; i++)
05533 {
05534 jb->samples[wp]=data[i];
05535 jb->ok[wp]=1;
05536 wp = (wp!=jb->size-1 ? wp+1 : 0);
05537
05538 if(wp==jb->rp)
05539 jb->state_full=1;
05540 }
05541
05542 if(wp>=rp)
05543 jb->state_buffer=wp-rp;
05544 else
05545 jb->state_buffer= jb->size-rp+wp;
05546 chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05547
05548 if(jb->state_full)
05549 {
05550 jb->wp=wp;
05551
05552 rp=wp;
05553 for(j=0; j<jb->upper_threshold; j++)
05554 rp = (rp!=0 ? rp-1 : jb->size-1);
05555 jb->rp=rp;
05556 jb->state_full=0;
05557 jb->state_empty=1;
05558
05559 ast_mutex_unlock (&jb->mutexjb);
05560
05561 return -1;
05562 }
05563
05564 if(!jb->state_empty)
05565 {
05566 jb->bytes_wrote+=len;
05567 if(jb->bytes_wrote>=jb->upper_threshold)
05568 {
05569 jb->state_empty=1;
05570 jb->bytes_wrote=0;
05571 }
05572 }
05573 jb->wp=wp;
05574
05575 ast_mutex_unlock (&jb->mutexjb);
05576
05577 return 0;
05578 }
05579
05580
05581
05582
05583 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
05584 {
05585 int i, wp, rp, read=0;
05586
05587 ast_mutex_lock (&jb->mutexjb);
05588
05589 rp=jb->rp;
05590 wp=jb->wp;
05591
05592 if(jb->state_empty)
05593 {
05594 for(i=0; i<len; i++)
05595 {
05596 if(wp==rp)
05597 {
05598 jb->rp=rp;
05599 jb->state_empty=0;
05600
05601 ast_mutex_unlock (&jb->mutexjb);
05602
05603 return read;
05604 }
05605 else
05606 {
05607 if(jb->ok[rp]==1)
05608 {
05609 data[i]=jb->samples[rp];
05610 jb->ok[rp]=0;
05611 rp=(rp!=jb->size-1 ? rp+1 : 0);
05612 read+=1;
05613 }
05614 }
05615 }
05616
05617 if(wp >= rp)
05618 jb->state_buffer=wp-rp;
05619 else
05620 jb->state_buffer= jb->size-rp+wp;
05621 chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05622
05623 jb->rp=rp;
05624 }
05625 else
05626 chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
05627
05628 ast_mutex_unlock (&jb->mutexjb);
05629
05630 return read;
05631 }
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643 void chan_misdn_log(int level, int port, char *tmpl, ...)
05644 {
05645 va_list ap;
05646 char buf[1024];
05647 char port_buf[8];
05648
05649 if (! ((0 <= port) && (port <= max_ports))) {
05650 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05651 port=0;
05652 level=-1;
05653 }
05654
05655 sprintf(port_buf,"P[%2d] ",port);
05656
05657 va_start(ap, tmpl);
05658 vsnprintf( buf, 1023, tmpl, ap );
05659 va_end(ap);
05660
05661 if (level == -1)
05662 ast_log(LOG_WARNING, buf);
05663
05664 else if (misdn_debug_only[port] ?
05665 (level==1 && misdn_debug[port]) || (level==misdn_debug[port])
05666 : level <= misdn_debug[port]) {
05667
05668 ast_console_puts(port_buf);
05669 ast_console_puts(buf);
05670 }
05671
05672 if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05673 time_t tm = time(NULL);
05674 char *tmp=ctime(&tm),*p;
05675
05676 FILE *fp= fopen(global_tracefile, "a+");
05677
05678 p=strchr(tmp,'\n');
05679 if (p) *p=':';
05680
05681 if (!fp) {
05682 ast_console_puts("Error opening Tracefile: [ ");
05683 ast_console_puts(global_tracefile);
05684 ast_console_puts(" ] ");
05685
05686 ast_console_puts(strerror(errno));
05687 ast_console_puts("\n");
05688 return ;
05689 }
05690
05691 fputs(tmp,fp);
05692 fputs(" ", fp);
05693 fputs(port_buf,fp);
05694 fputs(" ", fp);
05695 fputs(buf, fp);
05696
05697 fclose(fp);
05698 }
05699 }
05700
05701 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
05702 .load = load_module,
05703 .unload = unload_module,
05704 .reload = reload,
05705 );