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