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