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