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