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