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: 73208 $")
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 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02420 p->ast=NULL;
02421
02422 if (ast->_state == AST_STATE_RESERVED ||
02423 p->state == MISDN_NOTHING ||
02424 p->state == MISDN_HOLDED ||
02425 p->state == MISDN_HOLD_DISCONNECT ) {
02426
02427 CLEAN_CH:
02428
02429 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
02430 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02431
02432 ast_mutex_lock(&release_lock);
02433 cl_dequeue_chan(&cl_te, p);
02434 close(p->pipe[0]);
02435 close(p->pipe[1]);
02436 free(p);
02437 ast_mutex_unlock(&release_lock);
02438
02439 if (bc)
02440 misdn_lib_release(bc);
02441
02442 return 0;
02443 }
02444
02445 if (!bc) {
02446 ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02447 goto CLEAN_CH;
02448 }
02449
02450
02451 p->need_hangup=0;
02452 p->need_queue_hangup=0;
02453 p->need_busy=0;
02454
02455
02456 if (!p->bc->nt)
02457 stop_bc_tones(p);
02458
02459
02460 {
02461 const char *varcause=NULL;
02462 bc->out_cause=ast->hangupcause?ast->hangupcause:16;
02463
02464 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02465 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02466 int tmpcause=atoi(varcause);
02467 bc->out_cause=tmpcause?tmpcause:16;
02468 }
02469
02470 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));
02471 chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id);
02472 chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause);
02473 chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause);
02474 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02475
02476 switch (p->state) {
02477 case MISDN_CALLING:
02478 case MISDN_INCOMING_SETUP:
02479
02480
02481
02482 ast_log(LOG_NOTICE, "release channel, in CALLING/INCOMING_SETUP state.. no other events happened\n");
02483 release_chan(bc);
02484
02485 p->state=MISDN_CLEANING;
02486 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02487 break;
02488 case MISDN_HOLDED:
02489 case MISDN_DIALING:
02490 start_bc_tones(p);
02491 hanguptone_indicate(p);
02492
02493 if (bc->need_disconnect)
02494 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02495 break;
02496
02497 case MISDN_CALLING_ACKNOWLEDGE:
02498 start_bc_tones(p);
02499 hanguptone_indicate(p);
02500
02501 if (bc->need_disconnect)
02502 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02503 break;
02504
02505 case MISDN_ALERTING:
02506 case MISDN_PROGRESS:
02507 case MISDN_PROCEEDING:
02508 if (p->originator != ORG_AST)
02509 hanguptone_indicate(p);
02510
02511
02512 if (bc->need_disconnect)
02513 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02514 break;
02515 case MISDN_CONNECTED:
02516 case MISDN_PRECONNECTED:
02517
02518 if (p->bc->nt) {
02519 start_bc_tones(p);
02520 hanguptone_indicate(p);
02521 p->bc->progress_indicator=8;
02522 }
02523 if (bc->need_disconnect)
02524 misdn_lib_send_event( bc, EVENT_DISCONNECT);
02525
02526
02527 break;
02528 case MISDN_DISCONNECTED:
02529 misdn_lib_send_event( bc, EVENT_RELEASE);
02530 p->state=MISDN_CLEANING;
02531 break;
02532
02533 case MISDN_RELEASED:
02534 case MISDN_CLEANING:
02535 p->state=MISDN_CLEANING;
02536 break;
02537
02538 case MISDN_BUSY:
02539 break;
02540
02541 case MISDN_HOLD_DISCONNECT:
02542
02543 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
02544 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
02545
02546 bc->out_cause=-1;
02547 misdn_lib_send_event(bc,EVENT_RELEASE);
02548 p->state=MISDN_CLEANING;
02549 break;
02550 default:
02551 if (bc->nt) {
02552 bc->out_cause=-1;
02553 misdn_lib_send_event(bc, EVENT_RELEASE);
02554 p->state=MISDN_CLEANING;
02555 } else {
02556 if (bc->need_disconnect)
02557 misdn_lib_send_event(bc, EVENT_DISCONNECT);
02558 }
02559 }
02560
02561 p->state=MISDN_CLEANING;
02562
02563 }
02564
02565
02566 chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p));
02567
02568 return 0;
02569 }
02570
02571
02572 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
02573 {
02574 struct ast_frame *f,*f2;
02575
02576 if (tmp->trans) {
02577 f2 = ast_translate(tmp->trans, frame, 0);
02578 f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02579 } else {
02580 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02581 return NULL;
02582 }
02583
02584
02585 if (!f || (f->frametype != AST_FRAME_DTMF))
02586 return frame;
02587
02588 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
02589
02590 if (tmp->faxdetect && (f->subclass == 'f')) {
02591
02592 if (!tmp->faxhandled) {
02593 struct ast_channel *ast = tmp->ast;
02594 tmp->faxhandled++;
02595 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02596 tmp->bc->rxgain = 0;
02597 isdn_lib_update_rxgain(tmp->bc);
02598 tmp->bc->txgain = 0;
02599 isdn_lib_update_txgain(tmp->bc);
02600 #ifdef MISDN_1_2
02601 *tmp->bc->pipeline = 0;
02602 #else
02603 tmp->bc->ec_enable = 0;
02604 #endif
02605 isdn_lib_update_ec(tmp->bc);
02606 isdn_lib_stop_dtmf(tmp->bc);
02607 switch (tmp->faxdetect) {
02608 case 1:
02609 if (strcmp(ast->exten, "fax")) {
02610 char *context;
02611 char context_tmp[BUFFERSIZE];
02612 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02613 context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02614 if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02615 if (option_verbose > 2)
02616 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02617
02618 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02619 if (ast_async_goto(ast, context, "fax", 1))
02620 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02621 } else
02622 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02623 } else
02624 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02625 break;
02626 case 2:
02627 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02628 break;
02629 }
02630 } else
02631 ast_log(LOG_DEBUG, "Fax already handled\n");
02632 }
02633
02634 if (tmp->ast_dsp && (f->subclass != 'f')) {
02635 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02636 }
02637
02638 return frame;
02639 }
02640
02641
02642 static struct ast_frame *misdn_read(struct ast_channel *ast)
02643 {
02644 struct chan_list *tmp;
02645 int len;
02646
02647 if (!ast) {
02648 chan_misdn_log(1,0,"misdn_read called without ast\n");
02649 return NULL;
02650 }
02651 if (!(tmp=MISDN_ASTERISK_TECH_PVT(ast))) {
02652 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n");
02653 return NULL;
02654 }
02655
02656 if (!tmp->bc && !(tmp->state==MISDN_HOLDED)) {
02657 chan_misdn_log(1,0,"misdn_read called without bc\n");
02658 return NULL;
02659 }
02660
02661 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
02662
02663 if (len<=0) {
02664
02665 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
02666 return NULL;
02667 }
02668
02669 tmp->frame.frametype = AST_FRAME_VOICE;
02670 tmp->frame.subclass = AST_FORMAT_ALAW;
02671 tmp->frame.datalen = len;
02672 tmp->frame.samples = len;
02673 tmp->frame.mallocd = 0;
02674 tmp->frame.offset = 0;
02675 tmp->frame.delivery= ast_tv(0,0) ;
02676 tmp->frame.src = NULL;
02677 tmp->frame.data = tmp->ast_rd_buf;
02678
02679 if (tmp->faxdetect && !tmp->faxhandled) {
02680 if (tmp->faxdetect_timeout) {
02681 if (ast_tvzero(tmp->faxdetect_tv)) {
02682 tmp->faxdetect_tv = ast_tvnow();
02683 chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
02684 return process_ast_dsp(tmp, &tmp->frame);
02685 } else {
02686 struct timeval tv_now = ast_tvnow();
02687 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
02688 if (diff <= (tmp->faxdetect_timeout * 1000)) {
02689 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n");
02690 return process_ast_dsp(tmp, &tmp->frame);
02691 } else {
02692 chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n");
02693 tmp->faxdetect = 0;
02694 return &tmp->frame;
02695 }
02696 }
02697 } else {
02698 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n");
02699 return process_ast_dsp(tmp, &tmp->frame);
02700 }
02701 } else {
02702 if (tmp->ast_dsp)
02703 return process_ast_dsp(tmp, &tmp->frame);
02704 else
02705 return &tmp->frame;
02706 }
02707 }
02708
02709
02710 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
02711 {
02712 struct chan_list *ch;
02713 int i = 0;
02714
02715 if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02716
02717 if (ch->state == MISDN_HOLDED) {
02718 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
02719 return 0;
02720 }
02721
02722 if (!ch->bc ) {
02723 ast_log(LOG_WARNING, "private but no bc\n");
02724 return -1;
02725 }
02726
02727 if (ch->notxtone) {
02728 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxone\n");
02729 return 0;
02730 }
02731
02732
02733 if ( !frame->subclass) {
02734 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
02735 return 0;
02736 }
02737
02738 if ( !(frame->subclass & prefformat)) {
02739
02740 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
02741 return 0;
02742 }
02743
02744
02745 if ( !frame->samples ) {
02746 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
02747
02748 if (!strcmp(frame->src,"ast_prod")) {
02749 chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
02750
02751 if (ch->ts) {
02752 chan_misdn_log(4,ch->bc->port,"Starting Playtones\n");
02753 misdn_lib_tone_generator_start(ch->bc);
02754 }
02755 return 0;
02756 }
02757
02758 return -1;
02759 }
02760
02761 if ( ! ch->bc->addr ) {
02762 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
02763 return 0;
02764 }
02765
02766 #if MISDN_DEBUG
02767 {
02768 int i, max=5>frame->samples?frame->samples:5;
02769
02770 printf("write2mISDN %p %d bytes: ", p, frame->samples);
02771
02772 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
02773 printf ("\n");
02774 }
02775 #endif
02776
02777
02778 switch (ch->bc->bc_state) {
02779 case BCHAN_ACTIVATED:
02780 case BCHAN_BRIDGED:
02781 break;
02782 default:
02783 if (!ch->dropped_frame_cnt)
02784 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);
02785
02786 ch->dropped_frame_cnt++;
02787 if (ch->dropped_frame_cnt > 100) {
02788 ch->dropped_frame_cnt=0;
02789 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);
02790
02791 }
02792
02793 return 0;
02794 }
02795
02796 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples);
02797 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
02798
02799 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) {
02800 if (ch->bc->active)
02801 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n");
02802 }
02803
02804 } else {
02805
02806 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
02807 }
02808
02809
02810
02811 return 0;
02812 }
02813
02814
02815
02816
02817 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0,
02818 struct ast_channel *c1, int flags,
02819 struct ast_frame **fo,
02820 struct ast_channel **rc,
02821 int timeoutms)
02822
02823 {
02824 struct chan_list *ch1,*ch2;
02825 struct ast_channel *carr[2], *who;
02826 int to=-1;
02827 struct ast_frame *f;
02828
02829 ch1=get_chan_by_ast(c0);
02830 ch2=get_chan_by_ast(c1);
02831
02832 carr[0]=c0;
02833 carr[1]=c1;
02834
02835 if (ch1 && ch2 ) ;
02836 else
02837 return -1;
02838
02839 int p1_b, p2_b;
02840
02841 misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(int));
02842 misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(int));
02843
02844 if ( ! p1_b || ! p2_b) {
02845 ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
02846 return AST_BRIDGE_FAILED;
02847 }
02848
02849 int bridging;
02850 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02851 if (bridging) {
02852
02853 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1);
02854 misdn_lib_bridge(ch1->bc,ch2->bc);
02855 }
02856
02857 if (option_verbose > 2)
02858 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
02859
02860 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
02861
02862 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) )
02863 ch1->ignore_dtmf=1;
02864
02865 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) )
02866 ch2->ignore_dtmf=1;
02867
02868 while(1) {
02869 to=-1;
02870 who = ast_waitfor_n(carr, 2, &to);
02871
02872 if (!who) {
02873 ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n");
02874 break;
02875 }
02876 f = ast_read(who);
02877
02878 if (!f || f->frametype == AST_FRAME_CONTROL) {
02879
02880
02881 if (!f)
02882 chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n");
02883 else
02884 chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass);
02885
02886 *fo=f;
02887 *rc=who;
02888
02889 break;
02890 }
02891
02892 if ( f->frametype == AST_FRAME_DTMF ) {
02893 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten);
02894
02895 *fo=f;
02896 *rc=who;
02897 break;
02898 }
02899
02900 #if 0
02901 if (f->frametype == AST_FRAME_VOICE) {
02902 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
02903
02904 continue;
02905 }
02906 #endif
02907
02908 if (who == c0) {
02909 ast_write(c1,f);
02910 }
02911 else {
02912 ast_write(c0,f);
02913 }
02914
02915 }
02916
02917 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
02918
02919 misdn_lib_split_bridge(ch1->bc,ch2->bc);
02920
02921
02922 return AST_BRIDGE_COMPLETE;
02923 }
02924
02925
02926
02927 static int dialtone_indicate(struct chan_list *cl)
02928 {
02929 const struct tone_zone_sound *ts= NULL;
02930 struct ast_channel *ast=cl->ast;
02931
02932 if (!ast) {
02933 chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n");
02934 return -1;
02935 }
02936
02937 int nd=0;
02938 misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
02939
02940 if (nd) {
02941 chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n");
02942 return 0;
02943 }
02944
02945 chan_misdn_log(3,cl->bc->port," --> Dial\n");
02946 ts=ast_get_indication_tone(ast->zone,"dial");
02947 cl->ts=ts;
02948
02949 if (ts) {
02950 cl->notxtone=0;
02951 cl->norxtone=0;
02952
02953 ast_playtones_start(ast,0, ts->data, 0);
02954 }
02955
02956 return 0;
02957 }
02958
02959 static int hanguptone_indicate(struct chan_list *cl)
02960 {
02961 misdn_lib_send_tone(cl->bc,TONE_HANGUP);
02962 return 0;
02963 }
02964
02965 static int stop_indicate(struct chan_list *cl)
02966 {
02967 struct ast_channel *ast=cl->ast;
02968
02969 if (!ast) {
02970 chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n");
02971 return -1;
02972 }
02973
02974 chan_misdn_log(3,cl->bc->port," --> None\n");
02975 misdn_lib_tone_generator_stop(cl->bc);
02976 ast_playtones_stop(ast);
02977
02978 cl->ts=NULL;
02979
02980
02981 return 0;
02982 }
02983
02984
02985 static int start_bc_tones(struct chan_list* cl)
02986 {
02987 misdn_lib_tone_generator_stop(cl->bc);
02988 cl->notxtone=0;
02989 cl->norxtone=0;
02990 return 0;
02991 }
02992
02993 static int stop_bc_tones(struct chan_list *cl)
02994 {
02995 if (!cl) return -1;
02996
02997 cl->notxtone=1;
02998 cl->norxtone=1;
02999
03000 return 0;
03001 }
03002
03003
03004 static struct chan_list *init_chan_list(int orig)
03005 {
03006 struct chan_list *cl=malloc(sizeof(struct chan_list));
03007
03008 if (!cl) {
03009 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03010 return NULL;
03011 }
03012
03013 memset(cl,0,sizeof(struct chan_list));
03014
03015 cl->originator=orig;
03016 cl->need_queue_hangup=1;
03017 cl->need_hangup=1;
03018 cl->need_busy=1;
03019 cl->overlap_dial_task=-1;
03020
03021 return cl;
03022
03023 }
03024
03025 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
03026
03027 {
03028 struct ast_channel *tmp = NULL;
03029 char group[BUFFERSIZE+1]="";
03030 char buf[128];
03031 char buf2[128], *ext=NULL, *port_str;
03032 char *tokb=NULL, *p=NULL;
03033 int channel=0, port=0;
03034 struct misdn_bchannel *newbc = NULL;
03035 int dec=0;
03036
03037 struct chan_list *cl=init_chan_list(ORG_AST);
03038
03039 sprintf(buf,"%s/%s",misdn_type,(char*)data);
03040 ast_copy_string(buf2,data, 128);
03041
03042 port_str=strtok_r(buf2,"/", &tokb);
03043
03044 ext=strtok_r(NULL,"/", &tokb);
03045
03046 if (port_str) {
03047 if (port_str[0]=='g' && port_str[1]==':' ) {
03048
03049 port_str += 2;
03050 strncpy(group, port_str, BUFFERSIZE);
03051 group[127] = 0;
03052 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
03053 }
03054 else if ((p = strchr(port_str, ':'))) {
03055
03056 *p = 0;
03057 channel = atoi(++p);
03058 port = atoi(port_str);
03059 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03060 }
03061 else {
03062 port = atoi(port_str);
03063 }
03064 } else {
03065 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
03066 return NULL;
03067 }
03068
03069 if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03070 chan_misdn_log(4, port, " --> STARTING STANDARDDEC...\n");
03071 dec=1;
03072 }
03073
03074 if (!ast_strlen_zero(group)) {
03075
03076 char cfg_group[BUFFERSIZE+1];
03077 struct robin_list *rr = NULL;
03078
03079 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03080 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03081 rr = get_robin_position(group);
03082 }
03083
03084
03085 if (rr) {
03086 int robin_channel = rr->channel;
03087 int port_start;
03088 int next_chan = 1;
03089
03090 do {
03091 port_start = 0;
03092 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
03093 port = misdn_cfg_get_next_port_spin(port)) {
03094
03095 if (!port_start)
03096 port_start = port;
03097
03098 if (port >= port_start)
03099 next_chan = 1;
03100
03101 if (port <= port_start && next_chan) {
03102 int maxbchans=misdn_lib_get_maxchans(port);
03103 if (++robin_channel >= maxbchans) {
03104 robin_channel = 1;
03105 }
03106 next_chan = 0;
03107 }
03108
03109 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03110
03111 if (!strcasecmp(cfg_group, group)) {
03112 int port_up;
03113 int check;
03114 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03115 port_up = misdn_lib_port_up(port, check);
03116
03117 if (check && !port_up)
03118 chan_misdn_log(1,port,"L1 is not Up on this Port\n");
03119
03120 if (check && port_up<0) {
03121 ast_log(LOG_WARNING,"This port (%d) is blocked\n", port);
03122 }
03123
03124
03125 if ( port_up>0 ) {
03126 newbc = misdn_lib_get_free_bc(port, robin_channel,0, 0);
03127 if (newbc) {
03128 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03129 if (port_up)
03130 chan_misdn_log(4, port, "portup:%d\n", port_up);
03131 rr->port = newbc->port;
03132 rr->channel = newbc->channel;
03133 break;
03134 }
03135 }
03136 }
03137 }
03138 } while (!newbc && robin_channel != rr->channel);
03139
03140 } else {
03141 for (port=misdn_cfg_get_next_port(0); port > 0;
03142 port=misdn_cfg_get_next_port(port)) {
03143
03144 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03145
03146 chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port);
03147 if (!strcasecmp(cfg_group, group)) {
03148 int port_up;
03149 int check;
03150 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03151 port_up = misdn_lib_port_up(port, check);
03152
03153 chan_misdn_log(4, port, "portup:%d\n", port_up);
03154
03155 if ( port_up>0 ) {
03156 newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03157 if (newbc)
03158 break;
03159 }
03160 }
03161 }
03162 }
03163
03164
03165 if (!newbc) {
03166 ast_log(LOG_WARNING,
03167 "Could not Dial out on group '%s'.\n"
03168 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03169 "\tOr there was no free channel on none of the ports\n\n"
03170 , group);
03171 return NULL;
03172 }
03173 } else {
03174 if (channel)
03175 chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
03176 newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03177
03178 if (!newbc) {
03179 ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n",port,ext);
03180 return NULL;
03181 }
03182 }
03183
03184
03185
03186 cl->bc=newbc;
03187
03188 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03189 if (!tmp) {
03190 ast_log(LOG_ERROR,"Could not create Asterisk object\n");
03191 return NULL;
03192 }
03193
03194 cl->ast=tmp;
03195
03196
03197 cl_queue_chan(&cl_te, cl) ;
03198
03199
03200 read_config(cl, ORG_AST);
03201
03202
03203 cl->need_hangup=0;
03204
03205 return tmp;
03206 }
03207
03208
03209 static int misdn_send_text (struct ast_channel *chan, const char *text)
03210 {
03211 struct chan_list *tmp=chan->tech_pvt;
03212
03213 if (tmp && tmp->bc) {
03214 ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display));
03215 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03216 } else {
03217 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03218 return -1;
03219 }
03220
03221 return 0;
03222 }
03223
03224 static struct ast_channel_tech misdn_tech = {
03225 .type="mISDN",
03226 .description="Channel driver for mISDN Support (Bri/Pri)",
03227 .capabilities= AST_FORMAT_ALAW ,
03228 .requester=misdn_request,
03229 .send_digit_begin=misdn_digit_begin,
03230 .send_digit_end=misdn_digit_end,
03231 .call=misdn_call,
03232 .bridge=misdn_bridge,
03233 .hangup=misdn_hangup,
03234 .answer=misdn_answer,
03235 .read=misdn_read,
03236 .write=misdn_write,
03237 .indicate=misdn_indication,
03238 .fixup=misdn_fixup,
03239 .send_text=misdn_send_text,
03240 .properties=0
03241 };
03242
03243 static struct ast_channel_tech misdn_tech_wo_bridge = {
03244 .type="mISDN",
03245 .description="Channel driver for mISDN Support (Bri/Pri)",
03246 .capabilities=AST_FORMAT_ALAW ,
03247 .requester=misdn_request,
03248 .send_digit_begin=misdn_digit_begin,
03249 .send_digit_end=misdn_digit_end,
03250 .call=misdn_call,
03251 .hangup=misdn_hangup,
03252 .answer=misdn_answer,
03253 .read=misdn_read,
03254 .write=misdn_write,
03255 .indicate=misdn_indication,
03256 .fixup=misdn_fixup,
03257 .send_text=misdn_send_text,
03258 .properties=0
03259 };
03260
03261
03262 static int glob_channel=0;
03263
03264 static void update_name(struct ast_channel *tmp, int port, int c)
03265 {
03266 int chan_offset=0;
03267 int tmp_port = misdn_cfg_get_next_port(0);
03268 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
03269 if (tmp_port == port) break;
03270 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;
03271 }
03272 if (c<0) c=0;
03273
03274 ast_string_field_build(tmp, name, "%s/%d-u%d",
03275 misdn_type, chan_offset+c, glob_channel++);
03276
03277 chan_misdn_log(3,port," --> updating channel name to [%s]\n",tmp->name);
03278
03279 }
03280
03281 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c)
03282 {
03283 struct ast_channel *tmp;
03284 char *cid_name = 0, *cid_num = 0;
03285 int chan_offset=0;
03286 int tmp_port = misdn_cfg_get_next_port(0);
03287
03288 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) {
03289 if (tmp_port == port) break;
03290 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2;
03291 }
03292 if (c<0) c=0;
03293
03294
03295 if (callerid)
03296 ast_callerid_parse(callerid, &cid_name, &cid_num);
03297
03298 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03299
03300 if (tmp) {
03301 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid);
03302
03303 tmp->nativeformats = prefformat;
03304
03305 tmp->readformat = format;
03306 tmp->rawreadformat = format;
03307 tmp->writeformat = format;
03308 tmp->rawwriteformat = format;
03309
03310 tmp->tech_pvt = chlist;
03311
03312 int bridging;
03313 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03314
03315 if (bridging)
03316 tmp->tech = &misdn_tech;
03317 else
03318 tmp->tech = &misdn_tech_wo_bridge;
03319
03320 tmp->writeformat = format;
03321 tmp->readformat = format;
03322 tmp->priority=1;
03323
03324 if (exten)
03325 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03326 else
03327 chan_misdn_log(1,0,"misdn_new: no exten given.\n");
03328
03329 if (callerid) {
03330 char *cid_name, *cid_num;
03331
03332 ast_callerid_parse(callerid, &cid_name, &cid_num);
03333
03334
03335 tmp->cid.cid_num = ast_strdup(cid_num);
03336 tmp->cid.cid_ani = ast_strdup(cid_num);
03337 tmp->cid.cid_name = ast_strdup(cid_name);
03338 }
03339
03340 {
03341 if (pipe(chlist->pipe)<0)
03342 perror("Pipe failed\n");
03343
03344 tmp->fds[0]=chlist->pipe[0];
03345
03346 }
03347
03348 if (state == AST_STATE_RING)
03349 tmp->rings = 1;
03350 else
03351 tmp->rings = 0;
03352
03353
03354 } else {
03355 chan_misdn_log(-1,0,"Unable to allocate channel structure\n");
03356 }
03357
03358 return tmp;
03359 }
03360
03361 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
03362 {
03363 struct chan_list *help=list;
03364 for (;help; help=help->next) {
03365 if (help->bc == bc) return help;
03366 }
03367
03368 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03369
03370 return NULL;
03371 }
03372
03373 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
03374 {
03375 struct chan_list *help=list;
03376 for (;help; help=help->next) {
03377 if ( help->bc && (help->bc->pid == pid) ) return help;
03378 }
03379
03380 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid);
03381
03382 return NULL;
03383 }
03384
03385 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
03386 {
03387 struct chan_list *help=list;
03388
03389 if (bc->pri) return NULL;
03390
03391 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
03392 for (;help; help=help->next) {
03393 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel);
03394 if ( (help->state == MISDN_HOLDED) &&
03395 (help->hold_info.port == bc->port) )
03396 return help;
03397 }
03398 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
03399
03400 return NULL;
03401 }
03402
03403
03404 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w)
03405
03406 {
03407 struct chan_list *help=list;
03408
03409 for (;help; help=help->next) {
03410 if ( (help->state == MISDN_HOLDED) &&
03411 (help->l3id == l3_id)
03412 )
03413 return help;
03414 }
03415
03416 return NULL;
03417 }
03418
03419 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
03420 {
03421 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
03422
03423 ast_mutex_lock(&cl_te_lock);
03424 if (!*list) {
03425 *list = chan;
03426 } else {
03427 struct chan_list *help=*list;
03428 for (;help->next; help=help->next);
03429 help->next=chan;
03430 }
03431 chan->next=NULL;
03432 ast_mutex_unlock(&cl_te_lock);
03433 }
03434
03435 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan)
03436 {
03437 if (chan->dsp)
03438 ast_dsp_free(chan->dsp);
03439 if (chan->trans)
03440 ast_translator_free_path(chan->trans);
03441
03442
03443
03444 ast_mutex_lock(&cl_te_lock);
03445 if (!*list) {
03446 ast_mutex_unlock(&cl_te_lock);
03447 return;
03448 }
03449
03450 if (*list == chan) {
03451 *list=(*list)->next;
03452 ast_mutex_unlock(&cl_te_lock);
03453 return ;
03454 }
03455
03456 {
03457 struct chan_list *help=*list;
03458 for (;help->next; help=help->next) {
03459 if (help->next == chan) {
03460 help->next=help->next->next;
03461 ast_mutex_unlock(&cl_te_lock);
03462 return;
03463 }
03464 }
03465 }
03466
03467 ast_mutex_unlock(&cl_te_lock);
03468 }
03469
03470
03471
03472
03473 int pbx_start_chan(struct chan_list *ch)
03474 {
03475 int ret=ast_pbx_start(ch->ast);
03476
03477 if (ret>=0)
03478 ch->need_hangup=0;
03479 else
03480 ch->need_hangup=1;
03481
03482 return ret;
03483 }
03484
03485 static void hangup_chan(struct chan_list *ch)
03486 {
03487 int port=ch?ch->bc?ch->bc->port:0:0;
03488 if (!ch) {
03489 cb_log(1,0,"Cannot hangup chan, no ch\n");
03490 return;
03491 }
03492
03493 cb_log(5,port,"hangup_chan called\n");
03494
03495 if (ch->need_hangup)
03496 {
03497 cb_log(2,port," --> hangup\n");
03498 send_cause2ast(ch->ast,ch->bc,ch);
03499 ch->need_hangup=0;
03500 ch->need_queue_hangup=0;
03501 if (ch->ast)
03502 ast_hangup(ch->ast);
03503 return;
03504 }
03505
03506 if (!ch->need_queue_hangup) {
03507 cb_log(2,port," --> No need to queue hangup\n");
03508 }
03509
03510 ch->need_queue_hangup=0;
03511 if (ch->ast) {
03512 send_cause2ast(ch->ast,ch->bc,ch);
03513
03514 if (ch->ast)
03515 ast_queue_hangup(ch->ast);
03516 cb_log(2,port," --> queue_hangup\n");
03517 } else {
03518 cb_log(1,port,"Cannot hangup chan, no ast\n");
03519 }
03520 }
03521
03522
03523 static void release_chan(struct misdn_bchannel *bc) {
03524 struct ast_channel *ast=NULL;
03525
03526 ast_mutex_lock(&release_lock);
03527 {
03528 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03529 if (!ch) {
03530 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03531 ast_mutex_unlock(&release_lock);
03532 return;
03533 }
03534
03535 if (ch->ast) {
03536 ast=ch->ast;
03537 }
03538
03539 chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id);
03540
03541
03542 if (ch->jb ) {
03543 misdn_jb_destroy(ch->jb);
03544 ch->jb=NULL;
03545 } else {
03546 if (!bc->nojitter)
03547 chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n");
03548 }
03549
03550 if (ch->overlap_dial) {
03551 if (ch->overlap_dial_task != -1) {
03552 misdn_tasks_remove(ch->overlap_dial_task);
03553 ch->overlap_dial_task = -1;
03554 }
03555 ast_mutex_destroy(&ch->overlap_tv_lock);
03556 }
03557
03558 if (ch->originator == ORG_AST) {
03559 misdn_out_calls[bc->port]--;
03560 } else {
03561 misdn_in_calls[bc->port]--;
03562 }
03563
03564 if (ch) {
03565
03566 close(ch->pipe[0]);
03567 close(ch->pipe[1]);
03568
03569
03570 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03571 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));
03572 chan_misdn_log(3, bc->port, " --> * State Down\n");
03573 MISDN_ASTERISK_TECH_PVT(ast)=NULL;
03574
03575
03576 if (ast->_state != AST_STATE_RESERVED) {
03577 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03578 ast_setstate(ast, AST_STATE_DOWN);
03579 }
03580 }
03581
03582 ch->state=MISDN_CLEANING;
03583 cl_dequeue_chan(&cl_te, ch);
03584
03585 free(ch);
03586 } else {
03587
03588 }
03589 }
03590
03591 ast_mutex_unlock(&release_lock);
03592 }
03593
03594
03595 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
03596 {
03597 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
03598
03599 tmp_ch->state=MISDN_HOLD_DISCONNECT;
03600
03601 ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03602
03603 holded_chan->state=MISDN_CONNECTED;
03604
03605 ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03606 }
03607
03608
03609 static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
03610 {
03611 char predial[256]="";
03612 char *p = predial;
03613
03614 struct ast_frame fr;
03615
03616 strncpy(predial, ast->exten, sizeof(predial) -1 );
03617
03618 ch->state=MISDN_DIALING;
03619
03620 if (!ch->noautorespond_on_setup) {
03621 if (bc->nt) {
03622 int ret;
03623 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03624 } else {
03625 int ret;
03626 if ( misdn_lib_is_ptp(bc->port)) {
03627 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03628 } else {
03629 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03630 }
03631 }
03632 } else {
03633 ch->state = MISDN_INCOMING_SETUP;
03634 }
03635
03636 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);
03637
03638 strncpy(ast->exten,"s", 2);
03639
03640 if (pbx_start_chan(ch)<0) {
03641 ast=NULL;
03642 hangup_chan(ch);
03643 hanguptone_indicate(ch);
03644
03645 if (bc->nt)
03646 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03647 else
03648 misdn_lib_send_event(bc, EVENT_DISCONNECT );
03649 }
03650
03651
03652 while (!ast_strlen_zero(p) ) {
03653 fr.frametype = AST_FRAME_DTMF;
03654 fr.subclass = *p ;
03655 fr.src=NULL;
03656 fr.data = NULL ;
03657 fr.datalen = 0;
03658 fr.samples = 0 ;
03659 fr.mallocd =0 ;
03660 fr.offset= 0 ;
03661 fr.delivery= ast_tv(0,0) ;
03662
03663 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03664 ast_queue_frame(ch->ast, &fr);
03665 }
03666 p++;
03667 }
03668 }
03669
03670
03671
03672 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) {
03673 if (!ast) {
03674 chan_misdn_log(1,0,"send_cause2ast: No Ast\n");
03675 return;
03676 }
03677 if (!bc) {
03678 chan_misdn_log(1,0,"send_cause2ast: No BC\n");
03679 return;
03680 }
03681 if (!ch) {
03682 chan_misdn_log(1,0,"send_cause2ast: No Ch\n");
03683 return;
03684 }
03685
03686 ast->hangupcause=bc->cause;
03687
03688 switch ( bc->cause) {
03689
03690 case 1:
03691 case 2:
03692 case 3:
03693 case 4:
03694 case 22:
03695 case 27:
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705 break;
03706
03707 case 21:
03708 case 17:
03709
03710 ch->state=MISDN_BUSY;
03711
03712 if (!ch->need_busy) {
03713 chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n");
03714 break;
03715 }
03716
03717 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
03718
03719 ast_queue_control(ast, AST_CONTROL_BUSY);
03720
03721 ch->need_busy=0;
03722
03723 break;
03724 }
03725 }
03726
03727
03728
03729
03730 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03731 {
03732 const char *tmp;
03733 tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID");
03734 if (tmp) {
03735 ch->other_pid=atoi(tmp);
03736 chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp);
03737 if (ch->other_pid >0) {
03738 ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid);
03739 if (ch->other_ch) ch->other_ch->other_ch=ch;
03740 }
03741 }
03742
03743 tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE");
03744 if (tmp && (atoi(tmp) == 1)) {
03745 bc->sending_complete=1;
03746 }
03747
03748 tmp=pbx_builtin_getvar_helper(chan,"MISDN_USERUSER");
03749 if (tmp) {
03750 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
03751 strcpy(bc->uu, tmp);
03752 bc->uulen=strlen(bc->uu);
03753 }
03754
03755 tmp=pbx_builtin_getvar_helper(chan,"MISDN_KEYPAD");
03756 if (tmp) {
03757 strncpy(bc->keypad,tmp,sizeof(bc->keypad));
03758 bc->keypad[sizeof(bc->keypad)-1]=0;
03759 }
03760
03761
03762 }
03763
03764 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03765 {
03766 char tmp[32];
03767 chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid);
03768 sprintf(tmp,"%d",bc->pid);
03769 pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp);
03770
03771 if (bc->sending_complete) {
03772 sprintf(tmp,"%d",bc->sending_complete);
03773 pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp);
03774 }
03775
03776 if (bc->urate) {
03777 sprintf(tmp,"%d",bc->urate);
03778 pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp);
03779 }
03780
03781 if (bc->uulen) {
03782 pbx_builtin_setvar_helper(chan,"MISDN_USERUSER",bc->uu);
03783 }
03784
03785 if (bc->keypad[0])
03786 pbx_builtin_setvar_helper(chan,"MISDN_KEYPAD",bc->keypad);
03787 }
03788
03789 int add_in_calls(int port)
03790 {
03791 int max_in_calls;
03792
03793 misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
03794 misdn_in_calls[port]++;
03795
03796 if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) {
03797 ast_log(LOG_NOTICE,"Marking Incoming Call on port[%d]\n",port);
03798 return misdn_in_calls[port]-max_in_calls;
03799 }
03800
03801 return 0;
03802 }
03803
03804 int add_out_calls(int port)
03805 {
03806 int max_out_calls;
03807
03808 misdn_cfg_get( port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
03809
03810
03811 if (max_out_calls >=0 && max_out_calls<=misdn_out_calls[port]) {
03812 ast_log(LOG_NOTICE,"Rejecting Outgoing Call on port[%d]\n",port);
03813 return (misdn_out_calls[port]+1)-max_out_calls;
03814 }
03815
03816 misdn_out_calls[port]++;
03817
03818 return 0;
03819 }
03820
03821 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03822 if (pbx_start_chan(ch)<0) {
03823 hangup_chan(ch);
03824 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03825 if (bc->nt) {
03826 hanguptone_indicate(ch);
03827 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03828 } else
03829 misdn_lib_send_event(bc, EVENT_RELEASE);
03830 }
03831 }
03832
03833 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03834 ch->state=MISDN_WAITING4DIGS;
03835 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03836 if (bc->nt && !bc->dad[0])
03837 dialtone_indicate(ch);
03838 }
03839
03840
03841
03842
03843
03844 static enum event_response_e
03845 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
03846 {
03847 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03848
03849 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
03850 int debuglevel=1;
03851 if ( event==EVENT_CLEANUP && !user_data)
03852 debuglevel=5;
03853
03854 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");
03855 if (debuglevel==1) {
03856 misdn_lib_log_ies(bc);
03857 chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state));
03858 }
03859 }
03860
03861 if (!ch) {
03862 switch(event) {
03863 case EVENT_SETUP:
03864 case EVENT_DISCONNECT:
03865 case EVENT_PORT_ALARM:
03866 case EVENT_RETRIEVE:
03867 case EVENT_NEW_BC:
03868 case EVENT_FACILITY:
03869 break;
03870 case EVENT_RELEASE_COMPLETE:
03871 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
03872 break;
03873 case EVENT_CLEANUP:
03874 case EVENT_TONE_GENERATE:
03875 case EVENT_BCHAN_DATA:
03876 return -1;
03877
03878 default:
03879 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);
03880 return -1;
03881 }
03882 }
03883
03884 if (ch ) {
03885 switch (event) {
03886 case EVENT_TONE_GENERATE:
03887 break;
03888 case EVENT_DISCONNECT:
03889 case EVENT_RELEASE:
03890 case EVENT_RELEASE_COMPLETE:
03891 case EVENT_CLEANUP:
03892 case EVENT_TIMEOUT:
03893 if (!ch->ast)
03894 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));
03895 break;
03896 default:
03897 if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03898 if (event!=EVENT_BCHAN_DATA)
03899 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
03900 return -1;
03901 }
03902 }
03903 }
03904
03905
03906 switch (event) {
03907 case EVENT_PORT_ALARM:
03908 {
03909 int boa=0;
03910 misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
03911 if (boa) {
03912 cb_log(1,bc->port," --> blocking\n");
03913 misdn_lib_port_block(bc->port);
03914 }
03915 }
03916 break;
03917 case EVENT_BCHAN_ACTIVATED:
03918 break;
03919
03920 case EVENT_NEW_CHANNEL:
03921 update_name(ch->ast,bc->port,bc->channel);
03922 break;
03923
03924 case EVENT_NEW_L3ID:
03925 ch->l3id=bc->l3_id;
03926 ch->addr=bc->addr;
03927 break;
03928
03929 case EVENT_NEW_BC:
03930 if (!ch) {
03931 ch=find_holded(cl_te,bc);
03932 }
03933
03934 if (!ch) {
03935 ast_log(LOG_WARNING,"NEW_BC without chan_list?\n");
03936 break;
03937 }
03938
03939 if (bc)
03940 ch->bc=(struct misdn_bchannel*)user_data;
03941 break;
03942
03943 case EVENT_DTMF_TONE:
03944 {
03945
03946 struct ast_frame fr;
03947 memset(&fr, 0 , sizeof(fr));
03948 fr.frametype = AST_FRAME_DTMF;
03949 fr.subclass = bc->dtmf ;
03950 fr.src=NULL;
03951 fr.data = NULL ;
03952 fr.datalen = 0;
03953 fr.samples = 0 ;
03954 fr.mallocd =0 ;
03955 fr.offset= 0 ;
03956 fr.delivery= ast_tv(0,0) ;
03957
03958 if (!ch->ignore_dtmf) {
03959 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
03960 ast_queue_frame(ch->ast, &fr);
03961 } else {
03962 chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf);
03963 }
03964 }
03965 break;
03966 case EVENT_STATUS:
03967 break;
03968
03969 case EVENT_INFORMATION:
03970 {
03971 int l;
03972
03973 if ( ch->state != MISDN_CONNECTED )
03974 stop_indicate(ch);
03975
03976 if (!ch->ast) break;
03977
03978 if (ch->state == MISDN_WAITING4DIGS ) {
03979
03980 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
03981 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
03982 strcpy(bc->info_dad,bc->keypad);
03983 }
03984
03985 l = sizeof(bc->dad);
03986 strncat(bc->dad,bc->info_dad, l);
03987 bc->dad[l-1] = 0;
03988
03989 l = sizeof(ch->ast->exten);
03990 strncpy(ch->ast->exten, bc->dad, l);
03991 ch->ast->exten[l-1] = 0;
03992
03993
03994 if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
03995 if (ast_pickup_call(ch->ast)) {
03996 hangup_chan(ch);
03997 } else {
03998 struct ast_channel *chan=ch->ast;
03999 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04000 ast_setstate(chan, AST_STATE_DOWN);
04001 hangup_chan(ch);
04002 ch->ast=NULL;
04003 break;
04004 }
04005 }
04006
04007 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04008 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04009 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
04010 strcpy(ch->ast->exten, "i");
04011
04012 ch->state = MISDN_DIALING;
04013 start_pbx(ch, bc, ch->ast);
04014 break;
04015 }
04016
04017 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
04018 "maybe you want to add an 'i' extension to catch this case.\n",
04019 bc->port);
04020
04021 if (bc->nt)
04022 hanguptone_indicate(ch);
04023 ch->state=MISDN_EXTCANTMATCH;
04024 bc->out_cause=1;
04025
04026 misdn_lib_send_event(bc, EVENT_DISCONNECT );
04027 break;
04028 }
04029
04030 if (ch->overlap_dial) {
04031 ast_mutex_lock(&ch->overlap_tv_lock);
04032 ch->overlap_tv = ast_tvnow();
04033 ast_mutex_unlock(&ch->overlap_tv_lock);
04034 if (ch->overlap_dial_task == -1) {
04035 ch->overlap_dial_task =
04036 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04037 }
04038 break;
04039 }
04040
04041 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04042
04043 ch->state = MISDN_DIALING;
04044 start_pbx(ch, bc, ch->ast);
04045 }
04046 } else {
04047
04048 struct ast_frame fr;
04049 fr.frametype = AST_FRAME_DTMF;
04050 fr.subclass = bc->info_dad[0] ;
04051 fr.src=NULL;
04052 fr.data = NULL ;
04053 fr.datalen = 0;
04054 fr.samples = 0 ;
04055 fr.mallocd =0 ;
04056 fr.offset= 0 ;
04057 fr.delivery= ast_tv(0,0) ;
04058
04059
04060 int digits;
04061 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
04062 if (ch->state != MISDN_CONNECTED ) {
04063 if (digits) {
04064 int l = sizeof(bc->dad);
04065 strncat(bc->dad,bc->info_dad, l);
04066 bc->dad[l-1] = 0;
04067 l = sizeof(ch->ast->exten);
04068 strncpy(ch->ast->exten, bc->dad, l);
04069 ch->ast->exten[l-1] = 0;
04070
04071 ast_cdr_update(ch->ast);
04072 }
04073
04074 ast_queue_frame(ch->ast, &fr);
04075 }
04076 }
04077 }
04078 break;
04079 case EVENT_SETUP:
04080 {
04081 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
04082 if (ch) {
04083 switch (ch->state) {
04084 case MISDN_NOTHING:
04085 ch=NULL;
04086 break;
04087 default:
04088 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04089 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE;
04090 }
04091 }
04092 }
04093
04094 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04095 if (!bc->nt && ! msn_valid) {
04096 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04097 return RESPONSE_IGNORE_SETUP;
04098 }
04099
04100
04101 if (bc->cw) {
04102 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04103 int cause;
04104 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04105 bc->out_cause=cause?cause:16;
04106 return RESPONSE_RELEASE_SETUP;
04107 }
04108
04109 print_bearer(bc);
04110
04111 {
04112 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04113 if (!bc->nt && ! msn_valid) {
04114 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04115 return RESPONSE_IGNORE_SETUP;
04116 }
04117
04118 if (bc->cw) {
04119 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04120 int cause;
04121 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04122 bc->out_cause=cause?cause:16;
04123 return RESPONSE_RELEASE_SETUP;
04124 }
04125
04126 print_bearer(bc);
04127
04128 struct chan_list *ch=init_chan_list(ORG_MISDN);
04129 struct ast_channel *chan;
04130 int exceed;
04131
04132 if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
04133
04134 ch->bc = bc;
04135 ch->l3id=bc->l3_id;
04136 ch->addr=bc->addr;
04137 ch->originator = ORG_MISDN;
04138
04139 chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04140
04141 if (!chan) {
04142 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04143 ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n");
04144 return 0;
04145 }
04146
04147 ch->ast = chan;
04148
04149 if ((exceed=add_in_calls(bc->port))) {
04150 char tmp[16];
04151 sprintf(tmp,"%d",exceed);
04152 pbx_builtin_setvar_helper(chan,"MAX_OVERFLOW",tmp);
04153 }
04154
04155 read_config(ch, ORG_MISDN);
04156
04157 export_ch(chan, bc, ch);
04158
04159 ch->ast->rings=1;
04160 ast_setstate(ch->ast, AST_STATE_RINGING);
04161
04162 int pres,screen;
04163
04164 switch (bc->pres) {
04165 case 1:
04166 pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n");
04167 break;
04168 case 2:
04169 pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n");
04170 break;
04171 default:
04172 pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres);
04173 }
04174
04175 switch (bc->screen) {
04176 case 0:
04177 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n");
04178 break;
04179 case 1:
04180 screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n");
04181 break;
04182 case 2:
04183 screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n");
04184 break;
04185 case 3:
04186 screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n");
04187 break;
04188 default:
04189 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen);
04190 }
04191
04192 chan->cid.cid_pres=pres+screen;
04193
04194 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04195 chan->transfercapability=bc->capability;
04196
04197 switch (bc->capability) {
04198 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04199 pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
04200 break;
04201 default:
04202 pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
04203 }
04204
04205
04206 cl_queue_chan(&cl_te, ch) ;
04207
04208 if (!strstr(ch->allowed_bearers,"all")) {
04209 int i;
04210 for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) {
04211 if (allowed_bearers_array[i].cap == bc->capability) {
04212 if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) {
04213 chan_misdn_log(0,bc->port,"Bearer Not allowed\b");
04214 bc->out_cause=88;
04215
04216 ch->state=MISDN_EXTCANTMATCH;
04217 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04218 return RESPONSE_OK;
04219 }
04220 }
04221
04222 }
04223 }
04224
04225
04226 if (!strcmp(chan->exten, ast_pickup_ext())) {
04227 if (!ch->noautorespond_on_setup) {
04228 int ret;
04229 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04230 } else {
04231 ch->state = MISDN_INCOMING_SETUP;
04232 }
04233 if (ast_pickup_call(chan)) {
04234 hangup_chan(ch);
04235 } else {
04236 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04237 ast_setstate(chan, AST_STATE_DOWN);
04238 hangup_chan(ch);
04239 ch->ast=NULL;
04240 break;
04241 }
04242 }
04243
04244
04245
04246
04247
04248 int ai;
04249 misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04250 if ( ai ) {
04251 do_immediate_setup(bc, ch , chan);
04252 break;
04253 }
04254
04255
04256 int im;
04257 misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04258 if ( im && ast_strlen_zero(bc->dad) ) {
04259 do_immediate_setup(bc, ch , chan);
04260 break;
04261 }
04262
04263 chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context);
04264 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04265 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04266 ast_log(LOG_WARNING, "Extension can never match, So jumping to 'i' extension. port(%d)\n",bc->port);
04267 strcpy(ch->ast->exten, "i");
04268 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04269 ch->state=MISDN_DIALING;
04270 start_pbx(ch, bc, chan);
04271 break;
04272 }
04273
04274 ast_log(LOG_WARNING, "Extension can never match, so disconnecting on port(%d)."
04275 "maybe you want to add an 'i' extension to catch this case.\n",
04276 bc->port);
04277 if (bc->nt)
04278 hanguptone_indicate(ch);
04279
04280 ch->state=MISDN_EXTCANTMATCH;
04281 bc->out_cause=1;
04282
04283 if (bc->nt)
04284 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04285 else
04286 misdn_lib_send_event(bc, EVENT_RELEASE );
04287
04288 break;
04289 }
04290
04291
04292
04293
04294 if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04295 if (!ch->noautorespond_on_setup) {
04296 ch->state=MISDN_DIALING;
04297 misdn_lib_send_event(bc, EVENT_PROCEEDING );
04298 } else {
04299 ch->state = MISDN_INCOMING_SETUP;
04300 }
04301 start_pbx(ch, bc, chan);
04302 break;
04303 }
04304
04305
04306
04307
04308
04309 if (ch->overlap_dial) {
04310 ast_mutex_lock(&ch->overlap_tv_lock);
04311 ch->overlap_tv = ast_tvnow();
04312 ast_mutex_unlock(&ch->overlap_tv_lock);
04313
04314 if (ch->overlap_dial_task == -1)
04315 ch->overlap_dial_task =
04316 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04317
04318 wait_for_digits(ch, bc, chan);
04319 break;
04320 }
04321
04322
04323
04324
04325 if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04326 wait_for_digits(ch, bc, chan);
04327 break;
04328 }
04329
04330
04331
04332
04333 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04334 if (bc->need_more_infos)
04335 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04336 else
04337 misdn_lib_send_event(bc, EVENT_PROCEEDING);
04338
04339 ch->state=MISDN_DIALING;
04340 start_pbx(ch, bc, chan);
04341 break;
04342 }
04343 }
04344 break;
04345
04346 case EVENT_SETUP_ACKNOWLEDGE:
04347 {
04348 ch->state = MISDN_CALLING_ACKNOWLEDGE;
04349
04350 if (bc->channel)
04351 update_name(ch->ast,bc->port,bc->channel);
04352
04353 if (!ast_strlen_zero(bc->infos_pending)) {
04354
04355
04356 {
04357 int l = sizeof(bc->dad);
04358 strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
04359 bc->dad[l-1] = 0;
04360 }
04361
04362 if (!ch->ast) break;
04363 {
04364 int l = sizeof(ch->ast->exten);
04365 strncpy(ch->ast->exten, bc->dad, l);
04366 ch->ast->exten[l-1] = 0;
04367 }
04368 {
04369 int l = sizeof(bc->info_dad);
04370 strncpy(bc->info_dad, bc->infos_pending, l);
04371 bc->info_dad[l-1] = 0;
04372 }
04373 strncpy(bc->infos_pending,"", 1);
04374
04375 misdn_lib_send_event(bc, EVENT_INFORMATION);
04376 }
04377 }
04378 break;
04379 case EVENT_PROCEEDING:
04380 {
04381 if (bc->channel)
04382 update_name(ch->ast,bc->port,bc->channel);
04383
04384 if ( misdn_cap_is_speech(bc->capability) &&
04385 misdn_inband_avail(bc) ) {
04386 start_bc_tones(ch);
04387 }
04388
04389 ch->state = MISDN_PROCEEDING;
04390
04391 if (!ch->ast) break;
04392
04393 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04394 }
04395 break;
04396 case EVENT_PROGRESS:
04397 if (bc->channel)
04398 update_name(ch->ast,bc->port,bc->channel);
04399
04400 if (!bc->nt ) {
04401 if ( misdn_cap_is_speech(bc->capability) &&
04402 misdn_inband_avail(bc)
04403 ) {
04404 start_bc_tones(ch);
04405 }
04406
04407 ch->state=MISDN_PROGRESS;
04408
04409 if (!ch->ast) break;
04410 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04411 }
04412 break;
04413
04414
04415 case EVENT_ALERTING:
04416 {
04417 if (bc->channel)
04418 update_name(ch->ast,bc->port,bc->channel);
04419
04420 ch->state = MISDN_ALERTING;
04421
04422 if (!ch->ast) break;
04423
04424 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04425 ast_setstate(ch->ast, AST_STATE_RINGING);
04426
04427 cb_log(7,bc->port," --> Set State Ringing\n");
04428
04429 if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04430 cb_log(1,bc->port,"Starting Tones, we have inband Data\n");
04431 start_bc_tones(ch);
04432 } else {
04433 cb_log(3,bc->port," --> We have no inband Data, the other end must create ringing\n");
04434 if (ch->far_alerting) {
04435 cb_log(1,bc->port," --> The other end can not do ringing eh ?.. we must do all ourself..");
04436 start_bc_tones(ch);
04437
04438 }
04439 }
04440 }
04441 break;
04442 case EVENT_CONNECT:
04443 {
04444
04445 misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
04446
04447 if (!ch->ast) break;
04448
04449 struct ast_channel *bridged=ast_bridged_channel(ch->ast);
04450 stop_indicate(ch);
04451
04452 if (bridged && !strcasecmp(bridged->tech->type,"mISDN")) {
04453 struct chan_list *bridged_ch=MISDN_ASTERISK_TECH_PVT(bridged);
04454
04455 chan_misdn_log(1,bc->port," --> copying cpndialplan:%d and cad:%s to the A-Channel\n",bc->cpnnumplan,bc->cad);
04456 if (bridged_ch) {
04457 bridged_ch->bc->cpnnumplan=bc->cpnnumplan;
04458 ast_copy_string(bridged_ch->bc->cad,bc->cad,sizeof(bc->cad));
04459 }
04460 }
04461 }
04462
04463
04464 case EVENT_CONNECT_ACKNOWLEDGE:
04465 {
04466 ch->l3id=bc->l3_id;
04467 ch->addr=bc->addr;
04468
04469 start_bc_tones(ch);
04470
04471 ch->state = MISDN_CONNECTED;
04472
04473 if (!ch->ast) break;
04474
04475 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04476 }
04477 break;
04478 case EVENT_DISCONNECT:
04479
04480 if (ch) {
04481 struct chan_list *holded_ch=find_holded(cl_te, bc);
04482
04483 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);
04484 if ( ch->originator==ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04485
04486
04487
04488
04489
04490 chan_misdn_log(1,bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04491
04492 ch->state=MISDN_DISCONNECTED;
04493 start_bc_tones(ch);
04494
04495 if (ch->ast) {
04496 ch->ast->hangupcause=bc->cause;
04497 if (bc->cause == 17)
04498 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04499 }
04500 ch->need_busy=0;
04501 break;
04502 }
04503
04504
04505 if ( holded_ch &&
04506 holded_ch != ch &&
04507 ch->ast &&
04508 ch->state == MISDN_CONNECTED ) {
04509 cb_log(1,bc->port," --> found holded ch\n");
04510 misdn_transfer_bc(ch, holded_ch) ;
04511 }
04512
04513 bc->need_disconnect=0;
04514
04515 stop_bc_tones(ch);
04516 hangup_chan(ch);
04517 } else {
04518
04519
04520
04521
04522
04523 }
04524 bc->out_cause=-1;
04525 if (bc->need_release) misdn_lib_send_event(bc,EVENT_RELEASE);
04526 break;
04527
04528 case EVENT_RELEASE:
04529 {
04530 bc->need_disconnect=0;
04531 bc->need_release=0;
04532
04533 hangup_chan(ch);
04534 release_chan(bc);
04535
04536 if (bc->need_release_complete)
04537 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04538 }
04539 break;
04540 case EVENT_RELEASE_COMPLETE:
04541 {
04542 bc->need_disconnect=0;
04543 bc->need_release=0;
04544 bc->need_release_complete=0;
04545
04546 stop_bc_tones(ch);
04547 hangup_chan(ch);
04548
04549 if(ch)
04550 ch->state=MISDN_CLEANING;
04551
04552 release_chan(bc);
04553 }
04554 break;
04555 case EVENT_BCHAN_ERROR:
04556 case EVENT_CLEANUP:
04557 {
04558 stop_bc_tones(ch);
04559
04560 switch(ch->state) {
04561 case MISDN_CALLING:
04562 bc->cause=27;
04563 break;
04564 default:
04565 break;
04566 }
04567
04568 hangup_chan(ch);
04569 release_chan(bc);
04570 }
04571 break;
04572
04573 case EVENT_TONE_GENERATE:
04574 {
04575 int tone_len=bc->tone_cnt;
04576 struct ast_channel *ast=ch->ast;
04577 void *tmp;
04578 int res;
04579 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04580
04581 chan_misdn_log(9,bc->port,"TONE_GEN: len:%d\n");
04582
04583 if (!ast) break;
04584
04585 if (!ast->generator) break;
04586
04587
04588
04589 tmp = ast->generatordata;
04590 ast->generatordata = NULL;
04591 generate = ast->generator->generate;
04592
04593 if (tone_len <0 || tone_len > 512 ) {
04594 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n",tone_len);
04595 tone_len=128;
04596 }
04597
04598 res = generate(ast, tmp, tone_len, tone_len);
04599 ast->generatordata = tmp;
04600
04601 if (res) {
04602 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04603 ast_deactivate_generator(ast);
04604 } else {
04605 bc->tone_cnt=0;
04606 }
04607 }
04608 break;
04609
04610 case EVENT_BCHAN_DATA:
04611 {
04612 if ( !misdn_cap_is_speech(ch->bc->capability) ) {
04613 struct ast_frame frame;
04614
04615 frame.frametype = AST_FRAME_VOICE;
04616 frame.subclass = AST_FORMAT_ALAW;
04617 frame.datalen = bc->bframe_len;
04618 frame.samples = bc->bframe_len ;
04619 frame.mallocd =0 ;
04620 frame.offset= 0 ;
04621 frame.delivery= ast_tv(0,0) ;
04622 frame.src = NULL;
04623 frame.data = bc->bframe ;
04624
04625 if (ch->ast)
04626 ast_queue_frame(ch->ast,&frame);
04627 } else {
04628 fd_set wrfs;
04629 struct timeval tv;
04630 tv.tv_sec=0;
04631 tv.tv_usec=0;
04632
04633
04634 FD_ZERO(&wrfs);
04635 FD_SET(ch->pipe[1],&wrfs);
04636
04637 int t=select(FD_SETSIZE,NULL,&wrfs,NULL,&tv);
04638
04639 if (!t) {
04640 chan_misdn_log(9, bc->port, "Select Timed out\n");
04641 break;
04642 }
04643
04644 if (t<0) {
04645 chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n",strerror(errno));
04646 break;
04647 }
04648
04649 if (FD_ISSET(ch->pipe[1],&wrfs)) {
04650 chan_misdn_log(9, bc->port, "writing %d bytes 2 asterisk\n",bc->bframe_len);
04651 int ret=write(ch->pipe[1], bc->bframe, bc->bframe_len);
04652
04653 if (ret<=0) {
04654 chan_misdn_log(-1, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n",strerror(errno));
04655
04656 stop_bc_tones(ch);
04657 hangup_chan(ch);
04658 release_chan(bc);
04659 }
04660 } else {
04661 chan_misdn_log(1, bc->port, "Wripe Pipe full!\n");
04662 }
04663 }
04664 }
04665 break;
04666 case EVENT_TIMEOUT:
04667 {
04668 if (ch && bc)
04669 chan_misdn_log(1,bc->port,"--> state: %s\n",misdn_get_ch_state(ch));
04670
04671 switch (ch->state) {
04672 case MISDN_DIALING:
04673 case MISDN_PROGRESS:
04674 if (bc->nt && !ch->nttimeout) break;
04675
04676 case MISDN_CALLING:
04677 case MISDN_ALERTING:
04678 case MISDN_PROCEEDING:
04679 case MISDN_CALLING_ACKNOWLEDGE:
04680 if (bc->nt) {
04681 bc->progress_indicator=8;
04682 hanguptone_indicate(ch);
04683 }
04684
04685 bc->out_cause=1;
04686 misdn_lib_send_event(bc,EVENT_DISCONNECT);
04687 break;
04688
04689 case MISDN_WAITING4DIGS:
04690 if (bc->nt) {
04691 bc->progress_indicator=8;
04692 bc->out_cause=1;
04693 hanguptone_indicate(ch);
04694 misdn_lib_send_event(bc,EVENT_DISCONNECT);
04695 } else {
04696 bc->out_cause=16;
04697 misdn_lib_send_event(bc,EVENT_RELEASE);
04698 }
04699
04700 break;
04701
04702
04703 case MISDN_CLEANING:
04704 chan_misdn_log(1,bc->port," --> in state cleaning .. so ingoring, the stack should clean it for us\n");
04705 break;
04706
04707 default:
04708 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04709 }
04710 }
04711 break;
04712
04713
04714
04715
04716
04717 case EVENT_RETRIEVE:
04718 {
04719 if (!ch) {
04720 chan_misdn_log(4, bc->port, " --> no CH, searching in holded");
04721 ch=find_holded_l3(cl_te, bc->l3_id,1);
04722 }
04723
04724 if (!ch) {
04725 ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
04726 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04727 break;
04728 }
04729
04730
04731 ch->bc=bc;
04732 ch->state = MISDN_CONNECTED;
04733
04734 ch->hold_info.port=0;
04735 ch->hold_info.channel=0;
04736
04737 struct ast_channel *hold_ast=ast_bridged_channel(ch->ast);
04738
04739 if (hold_ast) {
04740 ast_moh_stop(hold_ast);
04741 }
04742
04743 if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
04744 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04745 }
04746 break;
04747
04748 case EVENT_HOLD:
04749 {
04750 int hold_allowed;
04751 misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04752
04753 if (!hold_allowed) {
04754
04755 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04756 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04757 break;
04758 }
04759
04760 struct ast_channel *bridged=ast_bridged_channel(ch->ast);
04761
04762 if (bridged) {
04763 chan_misdn_log(2,bc->port,"Bridge Partner is of type: %s\n",bridged->tech->type);
04764 ch->state = MISDN_HOLDED;
04765 ch->l3id = bc->l3_id;
04766
04767 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04768
04769
04770
04771 ast_moh_start(bridged, NULL, NULL);
04772
04773
04774 ch->bc=NULL;
04775 ch->hold_info.port=bc->port;
04776 ch->hold_info.channel=bc->channel;
04777
04778 } else {
04779 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04780 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04781 }
04782 }
04783 break;
04784
04785 case EVENT_FACILITY:
04786 if (!ch) {
04787
04788 chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
04789 break;
04790 }
04791
04792 print_facility(&(bc->fac_in), bc);
04793
04794 switch (bc->fac_in.Function) {
04795 case Fac_CD:
04796 {
04797 struct ast_channel *bridged=ast_bridged_channel(ch->ast);
04798 struct chan_list *ch_br;
04799 if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04800 ch_br=MISDN_ASTERISK_TECH_PVT(bridged);
04801
04802 if (ch_br->bc) {
04803 if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
04804 ch_br->state=MISDN_DIALING;
04805 if (pbx_start_chan(ch_br) < 0) {
04806 chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
04807 }
04808 }
04809 }
04810
04811 }
04812 misdn_lib_send_event(bc, EVENT_DISCONNECT);
04813 }
04814 break;
04815 case Fac_AOCDCurrency:
04816 bc->AOCDtype = Fac_AOCDCurrency;
04817 memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
04818 export_aoc_vars(ch->originator, ch->ast, bc);
04819 break;
04820 case Fac_AOCDChargingUnit:
04821 bc->AOCDtype = Fac_AOCDChargingUnit;
04822 memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
04823 export_aoc_vars(ch->originator, ch->ast, bc);
04824 break;
04825 default:
04826 chan_misdn_log(0, bc->port," --> not yet handled: facility type:%p\n", bc->fac_in.Function);
04827 }
04828
04829 break;
04830
04831 case EVENT_RESTART:
04832
04833 if (!bc->dummy) {
04834 stop_bc_tones(ch);
04835 release_chan(bc);
04836 }
04837
04838 break;
04839
04840 default:
04841 chan_misdn_log(1,0, "Got Unknown Event\n");
04842 break;
04843 }
04844
04845 return RESPONSE_OK;
04846 }
04847
04848
04849
04850
04851
04852
04853
04854
04855
04856
04857
04858
04859 static int unload_module(void)
04860 {
04861
04862 ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
04863
04864 misdn_tasks_destroy();
04865
04866 if (!g_config_initialized) return 0;
04867
04868 ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
04869
04870
04871 ast_unregister_application("misdn_set_opt");
04872 ast_unregister_application("misdn_facility");
04873 ast_unregister_application("misdn_check_l2l1");
04874
04875 ast_channel_unregister(&misdn_tech);
04876
04877
04878 free_robin_list();
04879 misdn_cfg_destroy();
04880 misdn_lib_destroy();
04881
04882 if (misdn_debug)
04883 free(misdn_debug);
04884 if (misdn_debug_only)
04885 free(misdn_debug_only);
04886 free(misdn_ports);
04887
04888 return 0;
04889 }
04890
04891 static int load_module(void)
04892 {
04893 int i, port;
04894
04895 char ports[256]="";
04896
04897 max_ports=misdn_lib_maxports_get();
04898
04899 if (max_ports<=0) {
04900 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
04901 return AST_MODULE_LOAD_DECLINE;
04902 }
04903
04904 if (misdn_cfg_init(max_ports)) {
04905 ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
04906 return AST_MODULE_LOAD_DECLINE;
04907 }
04908 g_config_initialized=1;
04909
04910 misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
04911 misdn_ports = (int *)malloc(sizeof(int) * (max_ports+1));
04912 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
04913 for (i = 1; i <= max_ports; i++) {
04914 misdn_debug[i] = misdn_debug[0];
04915 misdn_ports[i] = i;
04916 }
04917 *misdn_ports = 0;
04918 misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
04919
04920 {
04921 char tempbuf[BUFFERSIZE+1];
04922 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
04923 if (strlen(tempbuf))
04924 tracing = 1;
04925 }
04926
04927 misdn_in_calls = (int *)malloc(sizeof(int) * (max_ports+1));
04928 misdn_out_calls = (int *)malloc(sizeof(int) * (max_ports+1));
04929
04930 for (i=1; i <= max_ports; i++) {
04931 misdn_in_calls[i]=0;
04932 misdn_out_calls[i]=0;
04933 }
04934
04935 ast_mutex_init(&cl_te_lock);
04936 ast_mutex_init(&release_lock);
04937
04938 misdn_cfg_update_ptp();
04939 misdn_cfg_get_ports_string(ports);
04940
04941 if (strlen(ports))
04942 chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
04943
04944 {
04945 struct misdn_lib_iface iface = {
04946 .cb_event = cb_events,
04947 .cb_log = chan_misdn_log,
04948 .cb_jb_empty = chan_misdn_jb_empty,
04949 };
04950
04951 if (misdn_lib_init(ports, &iface, NULL))
04952 chan_misdn_log(0, 0, "No te ports initialized\n");
04953
04954 int ntflags=0;
04955 char ntfile[BUFFERSIZE+1];
04956
04957 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
04958 misdn_cfg_get( 0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
04959
04960 misdn_lib_nt_debug_init(ntflags,ntfile);
04961
04962 }
04963
04964 {
04965 if (ast_channel_register(&misdn_tech)) {
04966 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
04967 unload_module();
04968 return -1;
04969 }
04970 }
04971
04972 ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
04973
04974 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
04975 "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
04976 "Sets mISDN opts. and optargs\n"
04977 "\n"
04978 "The available options are:\n"
04979 " d - Send display text on called phone, text is the optparam\n"
04980 " n - don't detect dtmf tones on called channel\n"
04981 " h - make digital outgoing call\n"
04982 " c - make crypted outgoing call, param is keyindex\n"
04983 " e - perform echo cancelation on this channel,\n"
04984 " takes taps as arguments (32,64,128,256)\n"
04985 " s - send Non Inband DTMF as inband\n"
04986 " vr - rxgain control\n"
04987 " vt - txgain control\n"
04988 );
04989
04990
04991 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
04992 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
04993 "Sends the Facility Message FACILITY_TYPE with \n"
04994 "the given Arguments to the current ISDN Channel\n"
04995 "Supported Facilities are:\n"
04996 "\n"
04997 "type=calldeflect args=Nr where to deflect\n"
04998 );
04999
05000
05001 ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05002 "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05003 "Checks if the L2 and L1 are up on either the given <port> or\n"
05004 "on the ports in the group with <groupname>\n"
05005 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05006 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05007 "\n"
05008 "This application, ensures the L1/L2 state of the Ports in a group\n"
05009 "it is intended to make the pmp_l1_check option redundant and to\n"
05010 "fix a buggy switch config from your provider\n"
05011 "\n"
05012 "a sample dialplan would look like:\n\n"
05013 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05014 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05015 "\n"
05016 );
05017
05018
05019 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
05020
05021
05022
05023 for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05024 int l1timeout;
05025 misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05026 if (l1timeout) {
05027 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05028 misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
05029 }
05030 }
05031
05032 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05033
05034 return 0;
05035 }
05036
05037
05038
05039 static int reload(void)
05040 {
05041 reload_config();
05042
05043 return 0;
05044 }
05045
05046
05047
05048 static int misdn_facility_exec(struct ast_channel *chan, void *data)
05049 {
05050 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05051 char *tok, *tokb;
05052
05053 chan_misdn_log(0,0,"TYPE: %s\n",chan->tech->type);
05054
05055 if (strcasecmp(chan->tech->type,"mISDN")) {
05056 ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05057 return -1;
05058 }
05059
05060 if (ast_strlen_zero((char *)data)) {
05061 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05062 return -1;
05063 }
05064
05065 tok=strtok_r((char*)data,"|", &tokb) ;
05066
05067 if (!tok) {
05068 ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05069 return -1;
05070 }
05071
05072 if (!strcasecmp(tok,"calldeflect")) {
05073 tok=strtok_r(NULL,"|", &tokb) ;
05074
05075 if (!tok) {
05076 ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05077 }
05078
05079 if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05080 ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05081 return 0;
05082 }
05083 ch->bc->fac_out.Function = Fac_CD;
05084 strncpy((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05085 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05086 } else {
05087 chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n",tok);
05088 }
05089
05090 return 0;
05091
05092 }
05093
05094 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
05095 {
05096 AST_DECLARE_APP_ARGS(args,
05097 AST_APP_ARG(grouppar);
05098 AST_APP_ARG(timeout);
05099 );
05100
05101 if (ast_strlen_zero((char *)data)) {
05102 ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05103 return -1;
05104 }
05105
05106 AST_STANDARD_APP_ARGS(args, data);
05107
05108 if (args.argc != 2) {
05109 ast_log(LOG_WARNING, "Wrong argument count\n");
05110 return 0;
05111 }
05112
05113
05114 char group[BUFFERSIZE+1];
05115 char *port_str;
05116
05117 int port=0;
05118 int timeout=atoi(args.timeout);
05119 int dowait=0;
05120
05121 port_str=args.grouppar;
05122
05123 int port_up;
05124 if (port_str[0]=='g' && port_str[1]==':' ) {
05125
05126 port_str += 2;
05127 strncpy(group, port_str, BUFFERSIZE);
05128 group[BUFFERSIZE-1] = 0;
05129 chan_misdn_log(2, 0, "Checking Ports in group: %s\n",group);
05130
05131 for ( port = misdn_cfg_get_next_port(port);
05132 port > 0;
05133 port = misdn_cfg_get_next_port(port)) {
05134
05135 chan_misdn_log(2,0,"trying port %d\n",port);
05136
05137 char cfg_group[BUFFERSIZE+1];
05138 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05139
05140 if (!strcasecmp(cfg_group, group)) {
05141 port_up = misdn_lib_port_up(port, 1);
05142
05143 if (!port_up) {
05144 chan_misdn_log(2, 0, " --> port '%d'\n", port);
05145 misdn_lib_get_port_up(port);
05146 dowait=1;
05147 }
05148 }
05149 }
05150
05151 } else {
05152 port = atoi(port_str);
05153 chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05154 port_up = misdn_lib_port_up(port, 1);
05155 if (!port_up) {
05156 misdn_lib_get_port_up(port);
05157 dowait=1;
05158 }
05159
05160 }
05161
05162 if (dowait) {
05163 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n",timeout);
05164 sleep(timeout);
05165 }
05166
05167 return 0;
05168 }
05169
05170 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
05171 {
05172 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05173 char *tok,*tokb;
05174 int keyidx=0;
05175 int rxgain=0;
05176 int txgain=0;
05177 int change_jitter=0;
05178
05179 if (strcasecmp(chan->tech->type,"mISDN")) {
05180 ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05181 return -1;
05182 }
05183
05184 if (ast_strlen_zero((char *)data)) {
05185 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05186 return -1;
05187 }
05188
05189 for (tok=strtok_r((char*)data, ":",&tokb);
05190 tok;
05191 tok=strtok_r(NULL,":",&tokb) ) {
05192 int neglect=0;
05193
05194 if (tok[0] == '!' ) {
05195 neglect=1;
05196 tok++;
05197 }
05198
05199 switch(tok[0]) {
05200
05201 case 'd' :
05202 ast_copy_string(ch->bc->display,++tok,84);
05203 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
05204 break;
05205
05206 case 'n':
05207 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05208 ch->bc->nodsp=1;
05209 break;
05210
05211 case 'j':
05212 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05213 tok++;
05214 change_jitter=1;
05215
05216 switch ( tok[0] ) {
05217 case 'b' :
05218 ch->jb_len=atoi(++tok);
05219 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n",ch->jb_len);
05220 break;
05221 case 't' :
05222 ch->jb_upper_threshold=atoi(++tok);
05223 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n",ch->jb_upper_threshold);
05224 break;
05225
05226 case 'n':
05227 ch->bc->nojitter=1;
05228 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05229 break;
05230
05231 default:
05232 ch->jb_len=4000;
05233 ch->jb_upper_threshold=0;
05234 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n",ch->jb_len);
05235 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n",ch->jb_upper_threshold);
05236 }
05237
05238 break;
05239
05240 case 'v':
05241 tok++;
05242
05243 switch ( tok[0] ) {
05244 case 'r' :
05245 rxgain=atoi(++tok);
05246 if (rxgain<-8) rxgain=-8;
05247 if (rxgain>8) rxgain=8;
05248 ch->bc->rxgain=rxgain;
05249 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
05250 break;
05251 case 't':
05252 txgain=atoi(++tok);
05253 if (txgain<-8) txgain=-8;
05254 if (txgain>8) txgain=8;
05255 ch->bc->txgain=txgain;
05256 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
05257 break;
05258 }
05259 break;
05260
05261 case 'c':
05262 keyidx=atoi(++tok);
05263
05264 char keys[4096];
05265 char *key=NULL, *tmp;
05266 int i;
05267 misdn_cfg_get( 0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05268
05269 tmp=keys;
05270
05271 for (i=0; i<keyidx; i++) {
05272 key=strsep(&tmp,",");
05273 }
05274
05275 if (key) {
05276 ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05277 }
05278
05279 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",ch->bc->crypt_key);
05280 break;
05281
05282 case 'e':
05283 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05284
05285 if (neglect) {
05286 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05287 #ifdef MISDN_1_2
05288 *ch->bc->pipeline=0;
05289 #else
05290 ch->bc->ec_enable=0;
05291 #endif
05292 } else {
05293 #ifdef MISDN_1_2
05294 update_pipeline_config(ch->bc);
05295 #else
05296 ch->bc->ec_enable=1;
05297 ch->bc->orig=ch->originator;
05298 tok++;
05299 if (*tok) {
05300 ch->bc->ec_deftaps=atoi(tok);
05301 }
05302 #endif
05303 }
05304
05305 break;
05306
05307 case 'h':
05308 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05309
05310 if (strlen(tok) > 1 && tok[1]=='1') {
05311 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05312 if (!ch->bc->hdlc) {
05313 ch->bc->hdlc=1;
05314 }
05315 }
05316 ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05317 break;
05318
05319 case 's':
05320 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05321 ch->bc->send_dtmf=1;
05322 break;
05323
05324 case 'f':
05325 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05326 ch->faxdetect=1;
05327 misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05328 break;
05329
05330 case 'a':
05331 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05332 ch->ast_dsp=1;
05333 break;
05334
05335 case 'p':
05336 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
05337
05338 if (strstr(tok,"allowed") ) {
05339 ch->bc->pres=0;
05340 } else if (strstr(tok,"not_screened")) {
05341 ch->bc->pres=1;
05342 }
05343
05344
05345 break;
05346
05347
05348 default:
05349 break;
05350 }
05351 }
05352
05353 if (change_jitter)
05354 config_jitterbuffer(ch);
05355
05356
05357 if (ch->faxdetect || ch->ast_dsp) {
05358 if (!ch->dsp) ch->dsp = ast_dsp_new();
05359 if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
05360 if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05361 }
05362
05363 if (ch->ast_dsp) {
05364 chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05365 ch->bc->nodsp=1;
05366 ch->bc->nojitter=1;
05367 }
05368
05369 return 0;
05370 }
05371
05372
05373 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len)
05374 {
05375 struct chan_list *ch=find_chan_by_bc(cl_te, bc);
05376
05377 if (ch && ch->jb) {
05378 return misdn_jb_empty(ch->jb, buf, len);
05379 }
05380
05381 return -1;
05382 }
05383
05384
05385
05386
05387
05388
05389
05390
05391
05392 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
05393 {
05394 int i;
05395 struct misdn_jb *jb = (struct misdn_jb*) malloc(sizeof(struct misdn_jb));
05396 jb->size = size;
05397 jb->upper_threshold = upper_threshold;
05398 jb->wp = 0;
05399 jb->rp = 0;
05400 jb->state_full = 0;
05401 jb->state_empty = 0;
05402 jb->bytes_wrote = 0;
05403 jb->samples = (char *)malloc(size*sizeof(char));
05404
05405 if (!jb->samples) {
05406 chan_misdn_log(-1,0,"No free Mem for jb->samples\n");
05407 return NULL;
05408 }
05409
05410 jb->ok = (char *)malloc(size*sizeof(char));
05411
05412 if (!jb->ok) {
05413 chan_misdn_log(-1,0,"No free Mem for jb->ok\n");
05414 return NULL;
05415 }
05416
05417 for(i=0; i<size; i++)
05418 jb->ok[i]=0;
05419
05420 ast_mutex_init(&jb->mutexjb);
05421
05422 return jb;
05423 }
05424
05425
05426 void misdn_jb_destroy(struct misdn_jb *jb)
05427 {
05428 ast_mutex_destroy(&jb->mutexjb);
05429
05430 free(jb->samples);
05431 free(jb);
05432 }
05433
05434
05435
05436 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
05437 {
05438 int i, j, rp, wp;
05439
05440 if (!jb || ! data) return 0;
05441
05442 ast_mutex_lock (&jb->mutexjb);
05443
05444 wp=jb->wp;
05445 rp=jb->rp;
05446
05447 for(i=0; i<len; i++)
05448 {
05449 jb->samples[wp]=data[i];
05450 jb->ok[wp]=1;
05451 wp = (wp!=jb->size-1 ? wp+1 : 0);
05452
05453 if(wp==jb->rp)
05454 jb->state_full=1;
05455 }
05456
05457 if(wp>=rp)
05458 jb->state_buffer=wp-rp;
05459 else
05460 jb->state_buffer= jb->size-rp+wp;
05461 chan_misdn_log(9,0,"misdn_jb_fill: written:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05462
05463 if(jb->state_full)
05464 {
05465 jb->wp=wp;
05466
05467 rp=wp;
05468 for(j=0; j<jb->upper_threshold; j++)
05469 rp = (rp!=0 ? rp-1 : jb->size-1);
05470 jb->rp=rp;
05471 jb->state_full=0;
05472 jb->state_empty=1;
05473
05474 ast_mutex_unlock (&jb->mutexjb);
05475
05476 return -1;
05477 }
05478
05479 if(!jb->state_empty)
05480 {
05481 jb->bytes_wrote+=len;
05482 if(jb->bytes_wrote>=jb->upper_threshold)
05483 {
05484 jb->state_empty=1;
05485 jb->bytes_wrote=0;
05486 }
05487 }
05488 jb->wp=wp;
05489
05490 ast_mutex_unlock (&jb->mutexjb);
05491
05492 return 0;
05493 }
05494
05495
05496
05497
05498 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
05499 {
05500 int i, wp, rp, read=0;
05501
05502 ast_mutex_lock (&jb->mutexjb);
05503
05504 rp=jb->rp;
05505 wp=jb->wp;
05506
05507 if(jb->state_empty)
05508 {
05509 for(i=0; i<len; i++)
05510 {
05511 if(wp==rp)
05512 {
05513 jb->rp=rp;
05514 jb->state_empty=0;
05515
05516 ast_mutex_unlock (&jb->mutexjb);
05517
05518 return read;
05519 }
05520 else
05521 {
05522 if(jb->ok[rp]==1)
05523 {
05524 data[i]=jb->samples[rp];
05525 jb->ok[rp]=0;
05526 rp=(rp!=jb->size-1 ? rp+1 : 0);
05527 read+=1;
05528 }
05529 }
05530 }
05531
05532 if(wp >= rp)
05533 jb->state_buffer=wp-rp;
05534 else
05535 jb->state_buffer= jb->size-rp+wp;
05536 chan_misdn_log(9,0,"misdn_jb_empty: read:%d | Bufferstatus:%d p:%x\n",len,jb->state_buffer,jb);
05537
05538 jb->rp=rp;
05539 }
05540 else
05541 chan_misdn_log(9,0,"misdn_jb_empty: Wait...requested:%d p:%x\n",len,jb);
05542
05543 ast_mutex_unlock (&jb->mutexjb);
05544
05545 return read;
05546 }
05547
05548
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558 void chan_misdn_log(int level, int port, char *tmpl, ...)
05559 {
05560 if (! ((0 <= port) && (port <= max_ports))) {
05561 ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05562 port=0;
05563 level=-1;
05564 }
05565
05566 va_list ap;
05567 char buf[1024];
05568 char port_buf[8];
05569 sprintf(port_buf,"P[%2d] ",port);
05570
05571 va_start(ap, tmpl);
05572 vsnprintf( buf, 1023, tmpl, ap );
05573 va_end(ap);
05574
05575 if (level == -1)
05576 ast_log(LOG_WARNING, buf);
05577
05578 else if (misdn_debug_only[port] ?
05579 (level==1 && misdn_debug[port]) || (level==misdn_debug[port])
05580 : level <= misdn_debug[port]) {
05581
05582 ast_console_puts(port_buf);
05583 ast_console_puts(buf);
05584 }
05585
05586 if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05587 time_t tm = time(NULL);
05588 char *tmp=ctime(&tm),*p;
05589
05590 FILE *fp= fopen(global_tracefile, "a+");
05591
05592 p=strchr(tmp,'\n');
05593 if (p) *p=':';
05594
05595 if (!fp) {
05596 ast_console_puts("Error opening Tracefile: [ ");
05597 ast_console_puts(global_tracefile);
05598 ast_console_puts(" ] ");
05599
05600 ast_console_puts(strerror(errno));
05601 ast_console_puts("\n");
05602 return ;
05603 }
05604
05605 fputs(tmp,fp);
05606 fputs(" ", fp);
05607 fputs(port_buf,fp);
05608 fputs(" ", fp);
05609 fputs(buf, fp);
05610
05611 fclose(fp);
05612 }
05613 }
05614
05615 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
05616 .load = load_module,
05617 .unload = unload_module,
05618 .reload = reload,
05619 );