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