![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
chan_misdn.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 2004 - 2006, Christian Richter 00005 * 00006 * Christian Richter <crich@beronet.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 * 00018 */ 00019 00020 /*! 00021 * \file 00022 * 00023 * \brief the chan_misdn channel driver for Asterisk 00024 * \author Christian Richter <crich@beronet.com> 00025 * 00026 * \ingroup channel_drivers 00027 */ 00028 00029 /*** MODULEINFO 00030 <depend>isdnnet</depend> 00031 <depend>misdn</depend> 00032 <depend>suppserv</depend> 00033 ***/ 00034 #include "asterisk.h" 00035 00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 51385 $") 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 /* allocates the jb-structure and initialise the elements*/ 00098 struct misdn_jb *misdn_jb_init(int size, int upper_threshold); 00099 00100 /* frees the data and destroys the given jitterbuffer struct */ 00101 void misdn_jb_destroy(struct misdn_jb *jb); 00102 00103 /* fills the jitterbuffer with len data returns < 0 if there was an 00104 error (bufferoverun). */ 00105 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len); 00106 00107 /* gets len bytes out of the jitterbuffer if available, else only the 00108 available data is returned and the return value indicates the number 00109 of data. */ 00110 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len); 00111 00112 00113 enum misdn_chan_state { 00114 MISDN_NOTHING=0, /*!< at beginning */ 00115 MISDN_WAITING4DIGS, /*!< when waiting for infos */ 00116 MISDN_EXTCANTMATCH, /*!< when asterisk couldnt match our ext */ 00117 MISDN_DIALING, /*!< when pbx_start */ 00118 MISDN_PROGRESS, /*!< we got a progress */ 00119 MISDN_PROCEEDING, /*!< we got a progress */ 00120 MISDN_CALLING, /*!< when misdn_call is called */ 00121 MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */ 00122 MISDN_ALERTING, /*!< when Alerting */ 00123 MISDN_BUSY, /*!< when BUSY */ 00124 MISDN_CONNECTED, /*!< when connected */ 00125 MISDN_PRECONNECTED, /*!< when connected */ 00126 MISDN_DISCONNECTED, /*!< when connected */ 00127 MISDN_RELEASED, /*!< when connected */ 00128 MISDN_BRIDGED, /*!< when bridged */ 00129 MISDN_CLEANING, /*!< when hangup from * but we were connected before */ 00130 MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP cam from misdn */ 00131 MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */ 00132 /* misdn_hangup */ 00133 MISDN_HOLDED, /*!< if this chan is holded */ 00134 MISDN_HOLD_DISCONNECT, /*!< if this chan is holded */ 00135 00136 }; 00137 00138 #define ORG_AST 1 00139 #define ORG_MISDN 2 00140 00141 struct hold_info { 00142 int port; 00143 int channel; 00144 }; 00145 00146 struct chan_list { 00147 00148 char allowed_bearers[BUFFERSIZE+1]; 00149 00150 enum misdn_chan_state state; 00151 int need_queue_hangup; 00152 int need_hangup; 00153 int need_busy; 00154 00155 int orginator; 00156 00157 int norxtone; 00158 int notxtone; 00159 00160 int toggle_ec; 00161 00162 int incoming_early_audio; 00163 00164 int ignore_dtmf; 00165 00166 int pipe[2]; 00167 char ast_rd_buf[4096]; 00168 struct ast_frame frame; 00169 00170 int faxdetect; /* 0:no 1:yes 2:yes+nojump */ 00171 int faxdetect_timeout; 00172 struct timeval faxdetect_tv; 00173 int faxhandled; 00174 00175 int ast_dsp; 00176 00177 int jb_len; 00178 int jb_upper_threshold; 00179 struct misdn_jb *jb; 00180 00181 struct ast_dsp *dsp; 00182 struct ast_trans_pvt *trans; 00183 00184 struct ast_channel * ast; 00185 00186 int dummy; 00187 00188 struct misdn_bchannel *bc; 00189 00190 struct hold_info hold_info; 00191 00192 unsigned int l3id; 00193 int addr; 00194 00195 char context[BUFFERSIZE]; 00196 00197 int zero_read_cnt; 00198 int dropped_frame_cnt; 00199 00200 int far_alerting; 00201 00202 int nttimeout; 00203 00204 int other_pid; 00205 struct chan_list *other_ch; 00206 00207 const struct ind_tone_zone_sound *ts; 00208 00209 int overlap_dial; 00210 int overlap_dial_task; 00211 ast_mutex_t overlap_tv_lock; 00212 struct timeval overlap_tv; 00213 00214 struct chan_list *peer; 00215 struct chan_list *next; 00216 struct chan_list *prev; 00217 struct chan_list *first; 00218 }; 00219 00220 00221 00222 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch); 00223 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch); 00224 00225 struct robin_list { 00226 char *group; 00227 int port; 00228 int channel; 00229 struct robin_list *next; 00230 struct robin_list *prev; 00231 }; 00232 static struct robin_list *robin = NULL; 00233 00234 00235 00236 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame); 00237 00238 00239 00240 static inline void free_robin_list_r (struct robin_list *r) 00241 { 00242 if (r) { 00243 if (r->next) free_robin_list_r(r->next); 00244 if (r->group) free(r->group); 00245 free(r); 00246 } 00247 } 00248 00249 static void free_robin_list ( void ) 00250 { 00251 free_robin_list_r(robin); 00252 robin = NULL; 00253 } 00254 00255 static struct robin_list* get_robin_position (char *group) 00256 { 00257 struct robin_list *iter = robin; 00258 for (; iter; iter = iter->next) { 00259 if (!strcasecmp(iter->group, group)) 00260 return iter; 00261 } 00262 struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list)); 00263 new->group = strndup(group, strlen(group)); 00264 new->channel = 1; 00265 if (robin) { 00266 new->next = robin; 00267 robin->prev = new; 00268 } 00269 robin = new; 00270 return robin; 00271 } 00272 00273 00274 /* the main schedule context for stuff like l1 watcher, overlap dial, ... */ 00275 static struct sched_context *misdn_tasks = NULL; 00276 static pthread_t misdn_tasks_thread; 00277 00278 static int *misdn_ports; 00279 00280 static void chan_misdn_log(int level, int port, char *tmpl, ...); 00281 00282 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, int format, int port, int c); 00283 static void send_digit_to_chan(struct chan_list *cl, char digit ); 00284 00285 static void hangup_chan(struct chan_list *ch); 00286 static int pbx_start_chan(struct chan_list *ch); 00287 00288 00289 #define AST_CID_P(ast) ast->cid.cid_num 00290 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast) 00291 #define AST_LOAD_CFG ast_config_load 00292 #define AST_DESTROY_CFG ast_config_destroy 00293 00294 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt 00295 #define MISDN_ASTERISK_PVT(ast) 1 00296 00297 #include <asterisk/strings.h> 00298 00299 /* #define MISDN_DEBUG 1 */ 00300 00301 static const char misdn_type[] = "mISDN"; 00302 00303 static int tracing = 0 ; 00304 00305 static char **misdn_key_vector=NULL; 00306 static int misdn_key_vector_size=0; 00307 00308 /* Only alaw and mulaw is allowed for now */ 00309 static int prefformat = AST_FORMAT_ALAW ; /* AST_FORMAT_SLINEAR ; AST_FORMAT_ULAW | */ 00310 00311 static int *misdn_debug; 00312 static int *misdn_debug_only; 00313 static int max_ports; 00314 00315 static int *misdn_in_calls; 00316 static int *misdn_out_calls; 00317 00318 00319 struct chan_list dummy_cl; 00320 00321 struct chan_list *cl_te=NULL; 00322 ast_mutex_t cl_te_lock; 00323 00324 static enum event_response_e 00325 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data); 00326 00327 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch); 00328 00329 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan); 00330 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan); 00331 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc); 00332 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid); 00333 00334 00335 00336 static int dialtone_indicate(struct chan_list *cl); 00337 static int hanguptone_indicate(struct chan_list *cl); 00338 static int stop_indicate(struct chan_list *cl); 00339 00340 static int start_bc_tones(struct chan_list *cl); 00341 static int stop_bc_tones(struct chan_list *cl); 00342 static void release_chan(struct misdn_bchannel *bc); 00343 00344 static int misdn_set_opt_exec(struct ast_channel *chan, void *data); 00345 static int misdn_facility_exec(struct ast_channel *chan, void *data); 00346 00347 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len); 00348 00349 00350 void debug_numplan(int port, int numplan, char *type); 00351 00352 00353 int add_out_calls(int port); 00354 int add_in_calls(int port); 00355 00356 00357 static int update_ec_config(struct misdn_bchannel *bc); 00358 00359 00360 00361 00362 /*protos*/ 00363 00364 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len); 00365 00366 /*************** Helpers *****************/ 00367 00368 static struct chan_list * get_chan_by_ast(struct ast_channel *ast) 00369 { 00370 struct chan_list *tmp; 00371 00372 for (tmp=cl_te; tmp; tmp = tmp->next) { 00373 if ( tmp->ast == ast ) return tmp; 00374 } 00375 00376 return NULL; 00377 } 00378 00379 static struct chan_list * get_chan_by_ast_name(char *name) 00380 { 00381 struct chan_list *tmp; 00382 00383 for (tmp=cl_te; tmp; tmp = tmp->next) { 00384 if ( tmp->ast && strcmp(tmp->ast->name,name) == 0) return tmp; 00385 } 00386 00387 return NULL; 00388 } 00389 00390 00391 00392 struct allowed_bearers { 00393 int cap; 00394 int val; 00395 char *name; 00396 }; 00397 00398 struct allowed_bearers allowed_bearers_array[]={ 00399 {INFO_CAPABILITY_SPEECH,1,"speech"}, 00400 {INFO_CAPABILITY_AUDIO_3_1K,2,"3_1khz"}, 00401 {INFO_CAPABILITY_DIGITAL_UNRESTRICTED,4,"digital_unrestricted"}, 00402 {INFO_CAPABILITY_DIGITAL_RESTRICTED,8,"digital_restriced"}, 00403 {INFO_CAPABILITY_VIDEO,16,"video"} 00404 }; 00405 00406 static char *bearer2str(int cap) { 00407 static char *bearers[]={ 00408 "Speech", 00409 "Audio 3.1k", 00410 "Unres Digital", 00411 "Res Digital", 00412 "Video", 00413 "Unknown Bearer" 00414 }; 00415 00416 switch (cap) { 00417 case INFO_CAPABILITY_SPEECH: 00418 return bearers[0]; 00419 break; 00420 case INFO_CAPABILITY_AUDIO_3_1K: 00421 return bearers[1]; 00422 break; 00423 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: 00424 return bearers[2]; 00425 break; 00426 case INFO_CAPABILITY_DIGITAL_RESTRICTED: 00427 return bearers[3]; 00428 break; 00429 case INFO_CAPABILITY_VIDEO: 00430 return bearers[4]; 00431 break; 00432 default: 00433 return bearers[5]; 00434 break; 00435 } 00436 } 00437 00438 00439 static void print_facility(struct FacParm *fac, struct misdn_bchannel *bc) 00440 { 00441 switch (fac->Function) { 00442 case Fac_CD: 00443 chan_misdn_log(0,bc->port," --> calldeflect to: %s, screened: %s\n", fac->u.CDeflection.DeflectedToNumber, 00444 fac->u.CDeflection.PresentationAllowed ? "yes" : "no"); 00445 break; 00446 case Fac_AOCDCurrency: 00447 if (fac->u.AOCDcur.chargeNotAvailable) 00448 chan_misdn_log(0,bc->port," --> AOCD currency: charge not available\n"); 00449 else if (fac->u.AOCDcur.freeOfCharge) 00450 chan_misdn_log(0,bc->port," --> AOCD currency: free of charge\n"); 00451 else if (fac->u.AOCDchu.billingId >= 0) 00452 chan_misdn_log(0,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d billingId:%d\n", 00453 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier, 00454 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId); 00455 else 00456 chan_misdn_log(0,bc->port," --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%d\n", 00457 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier, 00458 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total"); 00459 break; 00460 case Fac_AOCDChargingUnit: 00461 if (fac->u.AOCDchu.chargeNotAvailable) 00462 chan_misdn_log(0,bc->port," --> AOCD charging unit: charge not available\n"); 00463 else if (fac->u.AOCDchu.freeOfCharge) 00464 chan_misdn_log(0,bc->port," --> AOCD charging unit: free of charge\n"); 00465 else if (fac->u.AOCDchu.billingId >= 0) 00466 chan_misdn_log(0,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n", 00467 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId); 00468 else 00469 chan_misdn_log(0,bc->port," --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n", 00470 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total"); 00471 break; 00472 default: 00473 chan_misdn_log(0,bc->port," --> unknown\n"); 00474 } 00475 } 00476 00477 static void print_bearer(struct misdn_bchannel *bc) 00478 { 00479 00480 chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability)); 00481 00482 switch(bc->law) { 00483 case INFO_CODEC_ALAW: 00484 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n"); 00485 break; 00486 case INFO_CODEC_ULAW: 00487 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n"); 00488 break; 00489 } 00490 } 00491 /*************** Helpers END *************/ 00492 00493 static void sighandler(int sig) 00494 {} 00495 00496 static void* misdn_tasks_thread_func (void *data) 00497 { 00498 int wait; 00499 struct sigaction sa; 00500 00501 sa.sa_handler = sighandler; 00502 sa.sa_flags = SA_NODEFER; 00503 sigemptyset(&sa.sa_mask); 00504 sigaddset(&sa.sa_mask, SIGUSR1); 00505 sigaction(SIGUSR1, &sa, NULL); 00506 00507 sem_post((sem_t *)data); 00508 00509 while (1) { 00510 wait = ast_sched_wait(misdn_tasks); 00511 if (wait < 0) 00512 wait = 8000; 00513 if (poll(NULL, 0, wait) < 0) 00514 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n"); 00515 ast_sched_runq(misdn_tasks); 00516 } 00517 return NULL; 00518 } 00519 00520 static void misdn_tasks_init (void) 00521 { 00522 sem_t blocker; 00523 int i = 5; 00524 00525 if (sem_init(&blocker, 0, 0)) { 00526 perror("chan_misdn: Failed to initialize semaphore!"); 00527 exit(1); 00528 } 00529 00530 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n"); 00531 00532 misdn_tasks = sched_context_create(); 00533 pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker); 00534 00535 while (sem_wait(&blocker) && --i); 00536 sem_destroy(&blocker); 00537 } 00538 00539 static void misdn_tasks_destroy (void) 00540 { 00541 if (misdn_tasks) { 00542 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n"); 00543 if ( pthread_cancel(misdn_tasks_thread) == 0 ) { 00544 cb_log(4, 0, "Joining misdn_tasks thread\n"); 00545 pthread_join(misdn_tasks_thread, NULL); 00546 } 00547 sched_context_destroy(misdn_tasks); 00548 } 00549 } 00550 00551 static inline void misdn_tasks_wakeup (void) 00552 { 00553 pthread_kill(misdn_tasks_thread, SIGUSR1); 00554 } 00555 00556 static inline int _misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data, int variable) 00557 { 00558 int task_id; 00559 00560 if (!misdn_tasks) { 00561 misdn_tasks_init(); 00562 } 00563 task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable); 00564 misdn_tasks_wakeup(); 00565 00566 return task_id; 00567 } 00568 00569 static int misdn_tasks_add (int timeout, ast_sched_cb callback, void *data) 00570 { 00571 return _misdn_tasks_add_variable(timeout, callback, data, 0); 00572 } 00573 00574 static int misdn_tasks_add_variable (int timeout, ast_sched_cb callback, void *data) 00575 { 00576 return _misdn_tasks_add_variable(timeout, callback, data, 1); 00577 } 00578 00579 static void misdn_tasks_remove (int task_id) 00580 { 00581 ast_sched_del(misdn_tasks, task_id); 00582 } 00583 00584 static int misdn_l1_task (void *data) 00585 { 00586 misdn_lib_isdn_l1watcher(*(int *)data); 00587 chan_misdn_log(5, *(int *)data, "L1watcher timeout\n"); 00588 return 1; 00589 } 00590 00591 static int misdn_overlap_dial_task (void *data) 00592 { 00593 struct timeval tv_end, tv_now; 00594 int diff; 00595 struct chan_list *ch = (struct chan_list *)data; 00596 00597 chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state); 00598 00599 if (ch->state != MISDN_WAITING4DIGS) { 00600 ch->overlap_dial_task = -1; 00601 return 0; 00602 } 00603 00604 ast_mutex_lock(&ch->overlap_tv_lock); 00605 tv_end = ch->overlap_tv; 00606 ast_mutex_unlock(&ch->overlap_tv_lock); 00607 00608 tv_end.tv_sec += ch->overlap_dial; 00609 tv_now = ast_tvnow(); 00610 00611 diff = ast_tvdiff_ms(tv_end, tv_now); 00612 00613 if (diff <= 100) { 00614 /* if we are 100ms near the timeout, we are satisfied.. */ 00615 stop_indicate(ch); 00616 if (ast_exists_extension(ch->ast, ch->context, ch->bc->dad, 1, ch->bc->oad)) { 00617 ch->state=MISDN_DIALING; 00618 if (pbx_start_chan(ch) < 0) { 00619 chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n"); 00620 goto misdn_overlap_dial_task_disconnect; 00621 } 00622 } else { 00623 misdn_overlap_dial_task_disconnect: 00624 hanguptone_indicate(ch); 00625 if (ch->bc->nt) 00626 misdn_lib_send_event(ch->bc, EVENT_RELEASE_COMPLETE ); 00627 else 00628 misdn_lib_send_event(ch->bc, EVENT_RELEASE); 00629 } 00630 ch->overlap_dial_task = -1; 00631 return 0; 00632 } else 00633 return diff; 00634 } 00635 00636 static void send_digit_to_chan(struct chan_list *cl, char digit ) 00637 { 00638 static const char* dtmf_tones[] = { 00639 "!941+1336/100,!0/100", /* 0 */ 00640 "!697+1209/100,!0/100", /* 1 */ 00641 "!697+1336/100,!0/100", /* 2 */ 00642 "!697+1477/100,!0/100", /* 3 */ 00643 "!770+1209/100,!0/100", /* 4 */ 00644 "!770+1336/100,!0/100", /* 5 */ 00645 "!770+1477/100,!0/100", /* 6 */ 00646 "!852+1209/100,!0/100", /* 7 */ 00647 "!852+1336/100,!0/100", /* 8 */ 00648 "!852+1477/100,!0/100", /* 9 */ 00649 "!697+1633/100,!0/100", /* A */ 00650 "!770+1633/100,!0/100", /* B */ 00651 "!852+1633/100,!0/100", /* C */ 00652 "!941+1633/100,!0/100", /* D */ 00653 "!941+1209/100,!0/100", /* * */ 00654 "!941+1477/100,!0/100" }; /* # */ 00655 struct ast_channel *chan=cl->ast; 00656 00657 if (digit >= '0' && digit <='9') 00658 ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0); 00659 else if (digit >= 'A' && digit <= 'D') 00660 ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0); 00661 else if (digit == '*') 00662 ast_playtones_start(chan,0,dtmf_tones[14], 0); 00663 else if (digit == '#') 00664 ast_playtones_start(chan,0,dtmf_tones[15], 0); 00665 else { 00666 /* not handled */ 00667 if (option_debug) 00668 ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name); 00669 } 00670 } 00671 /*** CLI HANDLING ***/ 00672 static int misdn_set_debug(int fd, int argc, char *argv[]) 00673 { 00674 if (argc != 4 && argc != 5 && argc != 6 && argc != 7) 00675 return RESULT_SHOWUSAGE; 00676 00677 int level = atoi(argv[3]); 00678 00679 switch (argc) { 00680 case 4: 00681 case 5: { 00682 int only = 0; 00683 if (argc == 5) { 00684 if (strncasecmp(argv[4], "only", strlen(argv[4]))) 00685 return RESULT_SHOWUSAGE; 00686 else 00687 only = 1; 00688 } 00689 int i; 00690 for (i=0; i<=max_ports; i++) { 00691 misdn_debug[i] = level; 00692 misdn_debug_only[i] = only; 00693 } 00694 ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":""); 00695 } 00696 break; 00697 case 6: 00698 case 7: { 00699 if (strncasecmp(argv[4], "port", strlen(argv[4]))) 00700 return RESULT_SHOWUSAGE; 00701 int port = atoi(argv[5]); 00702 if (port <= 0 || port > max_ports) { 00703 switch (max_ports) { 00704 case 0: 00705 ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n"); 00706 break; 00707 case 1: 00708 ast_cli(fd, "port number not valid! only port 1 is availble.\n"); 00709 break; 00710 default: 00711 ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports); 00712 } 00713 return 0; 00714 } 00715 if (argc == 7) { 00716 if (strncasecmp(argv[6], "only", strlen(argv[6]))) 00717 return RESULT_SHOWUSAGE; 00718 else 00719 misdn_debug_only[port] = 1; 00720 } else 00721 misdn_debug_only[port] = 0; 00722 misdn_debug[port] = level; 00723 ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port); 00724 } 00725 } 00726 return 0; 00727 } 00728 00729 static int misdn_set_crypt_debug(int fd, int argc, char *argv[]) 00730 { 00731 if (argc != 5) return RESULT_SHOWUSAGE; 00732 00733 return 0; 00734 } 00735 00736 00737 static int misdn_port_block(int fd, int argc, char *argv[]) 00738 { 00739 int port; 00740 00741 if (argc != 4) 00742 return RESULT_SHOWUSAGE; 00743 00744 port = atoi(argv[3]); 00745 00746 misdn_lib_port_block(port); 00747 00748 return 0; 00749 } 00750 00751 static int misdn_port_unblock(int fd, int argc, char *argv[]) 00752 { 00753 int port; 00754 00755 if (argc != 4) 00756 return RESULT_SHOWUSAGE; 00757 00758 port = atoi(argv[3]); 00759 00760 misdn_lib_port_unblock(port); 00761 00762 return 0; 00763 } 00764 00765 00766 static int misdn_restart_port (int fd, int argc, char *argv[]) 00767 { 00768 int port; 00769 00770 if (argc != 4) 00771 return RESULT_SHOWUSAGE; 00772 00773 port = atoi(argv[3]); 00774 00775 misdn_lib_port_restart(port); 00776 00777 return 0; 00778 } 00779 00780 static int misdn_restart_pid (int fd, int argc, char *argv[]) 00781 { 00782 int pid; 00783 00784 if (argc != 4) 00785 return RESULT_SHOWUSAGE; 00786 00787 pid = atoi(argv[3]); 00788 00789 misdn_lib_pid_restart(pid); 00790 00791 return 0; 00792 } 00793 00794 static int misdn_port_up (int fd, int argc, char *argv[]) 00795 { 00796 int port; 00797 00798 if (argc != 4) 00799 return RESULT_SHOWUSAGE; 00800 00801 port = atoi(argv[3]); 00802 00803 misdn_lib_get_port_up(port); 00804 00805 return 0; 00806 } 00807 00808 static int misdn_port_down (int fd, int argc, char *argv[]) 00809 { 00810 int port; 00811 00812 if (argc != 4) 00813 return RESULT_SHOWUSAGE; 00814 00815 port = atoi(argv[3]); 00816 00817 misdn_lib_get_port_down(port); 00818 00819 return 0; 00820 } 00821 00822 static inline void show_config_description (int fd, enum misdn_cfg_elements elem) 00823 { 00824 char section[BUFFERSIZE]; 00825 char name[BUFFERSIZE]; 00826 char desc[BUFFERSIZE]; 00827 char def[BUFFERSIZE]; 00828 char tmp[BUFFERSIZE]; 00829 00830 misdn_cfg_get_name(elem, tmp, sizeof(tmp)); 00831 term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp)); 00832 misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def)); 00833 00834 if (elem < MISDN_CFG_LAST) 00835 term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section)); 00836 else 00837 term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section)); 00838 00839 if (*def) 00840 ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc); 00841 else 00842 ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc); 00843 } 00844 00845 static int misdn_show_config (int fd, int argc, char *argv[]) 00846 { 00847 char buffer[BUFFERSIZE]; 00848 enum misdn_cfg_elements elem; 00849 int linebreak; 00850 int onlyport = -1; 00851 int ok = 0; 00852 00853 if (argc >= 4) { 00854 if (!strcmp(argv[3], "description")) { 00855 if (argc == 5) { 00856 enum misdn_cfg_elements elem = misdn_cfg_get_elem (argv[4]); 00857 if (elem == MISDN_CFG_FIRST) 00858 ast_cli(fd, "Unknown element: %s\n", argv[4]); 00859 else 00860 show_config_description(fd, elem); 00861 return 0; 00862 } 00863 return RESULT_SHOWUSAGE; 00864 } 00865 if (!strcmp(argv[3], "descriptions")) { 00866 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "general"))) { 00867 for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) { 00868 show_config_description(fd, elem); 00869 ast_cli(fd, "\n"); 00870 } 00871 ok = 1; 00872 } 00873 if ((argc == 4) || ((argc == 5) && !strcmp(argv[4], "ports"))) { 00874 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 /* the ptp hack, remove the -1 when ptp is gone */; ++elem) { 00875 show_config_description(fd, elem); 00876 ast_cli(fd, "\n"); 00877 } 00878 ok = 1; 00879 } 00880 return ok ? 0 : RESULT_SHOWUSAGE; 00881 } 00882 if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) { 00883 ast_cli(fd, "Unknown option: %s\n", argv[3]); 00884 return RESULT_SHOWUSAGE; 00885 } 00886 } 00887 00888 if (argc == 3 || onlyport == 0) { 00889 ast_cli(fd,"Misdn General-Config: \n"); 00890 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) { 00891 misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE); 00892 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : ""); 00893 } 00894 ast_cli(fd, "\n"); 00895 } 00896 00897 if (onlyport < 0) { 00898 int port = misdn_cfg_get_next_port(0); 00899 for (; port > 0; port = misdn_cfg_get_next_port(port)) { 00900 ast_cli(fd, "\n[PORT %d]\n", port); 00901 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) { 00902 misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE); 00903 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : ""); 00904 } 00905 ast_cli(fd, "\n"); 00906 } 00907 } 00908 00909 if (onlyport > 0) { 00910 if (misdn_cfg_is_port_valid(onlyport)) { 00911 ast_cli(fd, "[PORT %d]\n", onlyport); 00912 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) { 00913 misdn_cfg_get_config_string(onlyport, elem, buffer, BUFFERSIZE); 00914 ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : ""); 00915 } 00916 ast_cli(fd, "\n"); 00917 } else { 00918 ast_cli(fd, "Port %d is not active!\n", onlyport); 00919 } 00920 } 00921 return 0; 00922 } 00923 00924 struct state_struct { 00925 enum misdn_chan_state state; 00926 char txt[255] ; 00927 } ; 00928 00929 static struct state_struct state_array[] = { 00930 {MISDN_NOTHING,"NOTHING"}, /* at beginning */ 00931 {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /* when waiting for infos */ 00932 {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /* when asterisk couldnt match our ext */ 00933 {MISDN_DIALING,"DIALING"}, /* when pbx_start */ 00934 {MISDN_PROGRESS,"PROGRESS"}, /* when pbx_start */ 00935 {MISDN_PROCEEDING,"PROCEEDING"}, /* when pbx_start */ 00936 {MISDN_CALLING,"CALLING"}, /* when misdn_call is called */ 00937 {MISDN_CALLING_ACKNOWLEDGE,"CALLING_ACKNOWLEDGE"}, /* when misdn_call is called */ 00938 {MISDN_ALERTING,"ALERTING"}, /* when Alerting */ 00939 {MISDN_BUSY,"BUSY"}, /* when BUSY */ 00940 {MISDN_CONNECTED,"CONNECTED"}, /* when connected */ 00941 {MISDN_PRECONNECTED,"PRECONNECTED"}, /* when connected */ 00942 {MISDN_DISCONNECTED,"DISCONNECTED"}, /* when connected */ 00943 {MISDN_RELEASED,"RELEASED"}, /* when connected */ 00944 {MISDN_BRIDGED,"BRIDGED"}, /* when bridged */ 00945 {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */ 00946 {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */ 00947 {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */ 00948 {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP cam from misdn */ 00949 {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */ 00950 /* misdn_hangup */ 00951 }; 00952 00953 static char *misdn_get_ch_state(struct chan_list *p) 00954 { 00955 int i; 00956 static char state[8]; 00957 00958 if( !p) return NULL; 00959 00960 for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) { 00961 if ( state_array[i].state == p->state) return state_array[i].txt; 00962 } 00963 00964 sprintf(state,"%d",p->state) ; 00965 00966 return state; 00967 } 00968 00969 00970 00971 static void reload_config(void) 00972 { 00973 int i, cfg_debug; 00974 00975 if (!g_config_initialized) { 00976 ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n"); 00977 return ; 00978 } 00979 00980 free_robin_list(); 00981 misdn_cfg_reload(); 00982 misdn_cfg_update_ptp(); 00983 misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE); 00984 misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int)); 00985 00986 for (i = 0; i <= max_ports; i++) { 00987 misdn_debug[i] = cfg_debug; 00988 misdn_debug_only[i] = 0; 00989 } 00990 } 00991 00992 static int misdn_reload (int fd, int argc, char *argv[]) 00993 { 00994 ast_cli(fd, "Reloading mISDN Config\n"); 00995 reload_config(); 00996 return 0; 00997 } 00998 00999 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc) 01000 { 01001 struct ast_channel *ast=help->ast; 01002 ast_cli(fd, 01003 "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s rad:%s ctx:%s state:%s\n", 01004 01005 bc->pid, bc->port, bc->channel, 01006 bc->nt?"NT":"TE", 01007 help->orginator == ORG_AST?"*":"I", 01008 ast?ast->exten:NULL, 01009 ast?AST_CID_P(ast):NULL, 01010 bc->rad, 01011 ast?ast->context:NULL, 01012 misdn_get_ch_state(help) 01013 ); 01014 if (misdn_debug[bc->port] > 0) 01015 ast_cli(fd, 01016 " --> astname: %s\n" 01017 " --> ch_l3id: %x\n" 01018 " --> ch_addr: %x\n" 01019 " --> bc_addr: %x\n" 01020 " --> bc_l3id: %x\n" 01021 " --> display: %s\n" 01022 " --> activated: %d\n" 01023 " --> state: %s\n" 01024 " --> capability: %s\n" 01025 " --> echo_cancel: %d\n" 01026 " --> notone : rx %d tx:%d\n" 01027 " --> bc_hold: %d\n", 01028 help->ast->name, 01029 help->l3id, 01030 help->addr, 01031 bc->addr, 01032 bc?bc->l3_id:-1, 01033 bc->display, 01034 01035 bc->active, 01036 bc_state2str(bc->bc_state), 01037 bearer2str(bc->capability), 01038 bc->ec_enable, 01039 01040 help->norxtone,help->notxtone, 01041 bc->holded 01042 ); 01043 01044 } 01045 01046 static int misdn_show_cls (int fd, int argc, char *argv[]) 01047 { 01048 struct chan_list *help=cl_te; 01049 01050 ast_cli(fd,"Chan List: %p\n",cl_te); 01051 01052 for (;help; help=help->next) { 01053 struct misdn_bchannel *bc=help->bc; 01054 struct ast_channel *ast=help->ast; 01055 if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast); 01056 if (bc) { 01057 print_bc_info(fd, help, bc); 01058 } else { 01059 if (help->state == MISDN_HOLDED) { 01060 chan_misdn_log(2, 0, "ITS A HOLDED BC:\n"); 01061 chan_misdn_log(2,0," --> l3_id: %x\n" 01062 " --> dad:%s oad:%s\n" 01063 " --> hold_port: %d\n" 01064 " --> hold_channel: %d\n" 01065 01066 ,help->l3id 01067 ,ast->exten 01068 ,AST_CID_P(ast) 01069 ,help->hold_info.port 01070 ,help->hold_info.channel 01071 ); 01072 } else { 01073 ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast)); 01074 } 01075 } 01076 } 01077 01078 01079 return 0; 01080 } 01081 01082 static int misdn_show_cl (int fd, int argc, char *argv[]) 01083 { 01084 struct chan_list *help=cl_te; 01085 01086 if (argc != 4) 01087 return RESULT_SHOWUSAGE; 01088 01089 for (;help; help=help->next) { 01090 struct misdn_bchannel *bc=help->bc; 01091 struct ast_channel *ast=help->ast; 01092 01093 if (bc && ast) { 01094 if (!strcasecmp(ast->name,argv[3])) { 01095 print_bc_info(fd, help, bc); 01096 break; 01097 } 01098 } 01099 } 01100 01101 01102 return 0; 01103 } 01104 01105 ast_mutex_t lock; 01106 int MAXTICS=8; 01107 01108 static int misdn_set_tics (int fd, int argc, char *argv[]) 01109 { 01110 if (argc != 4) 01111 return RESULT_SHOWUSAGE; 01112 01113 MAXTICS=atoi(argv[3]); 01114 01115 return 0; 01116 } 01117 01118 static int misdn_show_stacks (int fd, int argc, char *argv[]) 01119 { 01120 int port; 01121 01122 ast_cli(fd, "BEGIN STACK_LIST:\n"); 01123 01124 for (port=misdn_cfg_get_next_port(0); port > 0; 01125 port=misdn_cfg_get_next_port(port)) { 01126 char buf[128]; 01127 get_show_stack_details(port,buf); 01128 ast_cli(fd," %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":""); 01129 } 01130 01131 return 0; 01132 } 01133 01134 01135 static int misdn_show_ports_stats (int fd, int argc, char *argv[]) 01136 { 01137 int port; 01138 01139 ast_cli(fd, "Port\tin_calls\tout_calls\n"); 01140 01141 for (port=misdn_cfg_get_next_port(0); port > 0; 01142 port=misdn_cfg_get_next_port(port)) { 01143 ast_cli(fd,"%d\t%d\t\t%d\n",port,misdn_in_calls[port],misdn_out_calls[port]); 01144 } 01145 ast_cli(fd,"\n"); 01146 01147 return 0; 01148 01149 } 01150 01151 01152 static int misdn_show_port (int fd, int argc, char *argv[]) 01153 { 01154 int port; 01155 01156 if (argc != 4) 01157 return RESULT_SHOWUSAGE; 01158 01159 port = atoi(argv[3]); 01160 01161 ast_cli(fd, "BEGIN STACK_LIST:\n"); 01162 01163 char buf[128]; 01164 get_show_stack_details(port,buf); 01165 ast_cli(fd," %s Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":""); 01166 01167 01168 return 0; 01169 } 01170 01171 static int misdn_send_cd (int fd, int argc, char *argv[]) 01172 { 01173 char *channame; 01174 char *nr; 01175 01176 if (argc != 5) 01177 return RESULT_SHOWUSAGE; 01178 01179 channame = argv[3]; 01180 nr = argv[4]; 01181 01182 ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame); 01183 01184 { 01185 struct chan_list *tmp=get_chan_by_ast_name(channame); 01186 01187 if (!tmp) { 01188 ast_cli(fd, "Sending CD with nr %s to %s failed: Channel does not exist.\n",nr, channame); 01189 return 0; 01190 } else { 01191 if (strlen(nr) >= 15) { 01192 ast_cli(fd, "Sending CD with nr %s to %s failed: Number too long (up to 15 digits are allowed).\n",nr, channame); 01193 return 0; 01194 } 01195 tmp->bc->fac_out.Function = Fac_CD; 01196 strncpy((char *)tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr, sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber)); 01197 misdn_lib_send_event(tmp->bc, EVENT_FACILITY); 01198 } 01199 } 01200 01201 return 0; 01202 } 01203 01204 static int misdn_send_digit (int fd, int argc, char *argv[]) 01205 { 01206 char *channame; 01207 char *msg; 01208 01209 if (argc != 5) 01210 return RESULT_SHOWUSAGE; 01211 01212 channame = argv[3]; 01213 msg = argv[4]; 01214 01215 ast_cli(fd, "Sending %s to %s\n",msg, channame); 01216 01217 { 01218 struct chan_list *tmp=get_chan_by_ast_name(channame); 01219 01220 if (!tmp) { 01221 ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame); 01222 return 0; 01223 } else { 01224 #if 1 01225 int i; 01226 int msglen = strlen(msg); 01227 for (i=0; i<msglen; i++) { 01228 ast_cli(fd, "Sending: %c\n",msg[i]); 01229 send_digit_to_chan(tmp, msg[i]); 01230 /* res = ast_safe_sleep(tmp->ast, 250); */ 01231 usleep(250000); 01232 /* res = ast_waitfor(tmp->ast,100); */ 01233 } 01234 #else 01235 int res; 01236 res = ast_dtmf_stream(tmp->ast,NULL,msg,250); 01237 #endif 01238 } 01239 } 01240 01241 return 0; 01242 } 01243 01244 static int misdn_toggle_echocancel (int fd, int argc, char *argv[]) 01245 { 01246 char *channame; 01247 01248 if (argc != 4) 01249 return RESULT_SHOWUSAGE; 01250 01251 channame = argv[3]; 01252 01253 ast_cli(fd, "Toggling EchoCancel on %s\n", channame); 01254 01255 { 01256 struct chan_list *tmp=get_chan_by_ast_name(channame); 01257 01258 if (!tmp) { 01259 ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame); 01260 return 0; 01261 } else { 01262 01263 tmp->toggle_ec=tmp->toggle_ec?0:1; 01264 01265 if (tmp->toggle_ec) { 01266 update_ec_config(tmp->bc); 01267 manager_ec_enable(tmp->bc); 01268 } else { 01269 manager_ec_disable(tmp->bc); 01270 } 01271 } 01272 } 01273 01274 return 0; 01275 } 01276 01277 static int misdn_send_display (int fd, int argc, char *argv[]) 01278 { 01279 char *channame; 01280 char *msg; 01281 01282 if (argc != 5) 01283 return RESULT_SHOWUSAGE; 01284 01285 channame = argv[3]; 01286 msg = argv[4]; 01287 01288 ast_cli(fd, "Sending %s to %s\n",msg, channame); 01289 { 01290 struct chan_list *tmp; 01291 tmp=get_chan_by_ast_name(channame); 01292 01293 if (tmp && tmp->bc) { 01294 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display)); 01295 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION); 01296 } else { 01297 ast_cli(fd,"No such channel %s\n",channame); 01298 return RESULT_FAILURE; 01299 } 01300 } 01301 01302 return RESULT_SUCCESS ; 01303 } 01304 01305 static char *complete_ch_helper(const char *line, const char *word, int pos, int state, int rpos) 01306 { 01307 struct ast_channel *c; 01308 int which=0; 01309 char *ret; 01310 if (pos != rpos) 01311 return NULL; 01312 c = ast_channel_walk_locked(NULL); 01313 while(c) { 01314 if (!strncasecmp(word, c->name, strlen(word))) { 01315 if (++which > state) 01316 break; 01317 } 01318 ast_mutex_unlock(&c->lock); 01319 c = ast_channel_walk_locked(c); 01320 } 01321 if (c) { 01322 ret = strdup(c->name); 01323 ast_mutex_unlock(&c->lock); 01324 } else 01325 ret = NULL; 01326 return ret; 01327 } 01328 01329 static char *complete_ch(const char *line, const char *word, int pos, int state) 01330 { 01331 return complete_ch_helper(line, word, pos, state, 3); 01332 } 01333 01334 static char *complete_debug_port (const char *line, const char *word, int pos, int state) 01335 { 01336 if (state) 01337 return NULL; 01338 01339 switch (pos) { 01340 case 4: if (*word == 'p') 01341 return strdup("port"); 01342 else if (*word == 'o') 01343 return strdup("only"); 01344 break; 01345 case 6: if (*word == 'o') 01346 return strdup("only"); 01347 break; 01348 } 01349 return NULL; 01350 } 01351 01352 static char *complete_show_config (const char *line, const char *word, int pos, int state) 01353 { 01354 char buffer[BUFFERSIZE]; 01355 enum misdn_cfg_elements elem; 01356 int wordlen = strlen(word); 01357 int which = 0; 01358 int port = 0; 01359 01360 switch (pos) { 01361 case 3: if ((!strncmp(word, "description", wordlen)) && (++which > state)) 01362 return strdup("description"); 01363 if ((!strncmp(word, "descriptions", wordlen)) && (++which > state)) 01364 return strdup("descriptions"); 01365 if ((!strncmp(word, "0", wordlen)) && (++which > state)) 01366 return strdup("0"); 01367 while ((port = misdn_cfg_get_next_port(port)) != -1) { 01368 snprintf(buffer, sizeof(buffer), "%d", port); 01369 if ((!strncmp(word, buffer, wordlen)) && (++which > state)) { 01370 return strdup(buffer); 01371 } 01372 } 01373 break; 01374 case 4: 01375 if (strstr(line, "description ")) { 01376 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) { 01377 if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) 01378 continue; 01379 misdn_cfg_get_name(elem, buffer, BUFFERSIZE); 01380 if (!wordlen || !strncmp(word, buffer, wordlen)) { 01381 if (++which > state) 01382 return strdup(buffer); 01383 } 01384 } 01385 } else if (strstr(line, "descriptions ")) { 01386 if ((!wordlen || !strncmp(word, "general", wordlen)) && (++which > state)) 01387 return strdup("general"); 01388 if ((!wordlen || !strncmp(word, "ports", wordlen)) && (++which > state)) 01389 return strdup("ports"); 01390 } 01391 break; 01392 } 01393 return NULL; 01394 } 01395 01396 static struct ast_cli_entry chan_misdn_clis[] = { 01397 { {"misdn","send","calldeflect", NULL}, misdn_send_cd, "Sends CallDeflection to mISDN Channel", 01398 "Usage: misdn send calldeflect <channel> \"<nr>\" \n", complete_ch }, 01399 { {"misdn","send","digit", NULL}, misdn_send_digit, "Sends DTMF Digit to mISDN Channel", 01400 "Usage: misdn send digit <channel> \"<msg>\" \n" 01401 " Send <digit> to <channel> as DTMF Tone\n" 01402 " when channel is a mISDN channel\n", complete_ch }, 01403 { {"misdn","toggle","echocancel", NULL}, misdn_toggle_echocancel, "Toggles EchoCancel on mISDN Channel", 01404 "Usage: misdn toggle echocancel <channel>\n", complete_ch }, 01405 { {"misdn","send","display", NULL}, misdn_send_display, "Sends Text to mISDN Channel", 01406 "Usage: misdn send display <channel> \"<msg>\" \n" 01407 " Send <msg> to <channel> as Display Message\n" 01408 " when channel is a mISDN channel\n", complete_ch }, 01409 { {"misdn","show","config", NULL}, misdn_show_config, "Shows internal mISDN config, read from cfg-file", 01410 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n" 01411 " Use 0 for <port> to only print the general config.\n", complete_show_config }, 01412 { {"misdn","reload", NULL}, misdn_reload, "Reloads internal mISDN config, read from cfg-file", 01413 "Usage: misdn reload\n" }, 01414 { {"misdn","set","tics", NULL}, misdn_set_tics, "", 01415 "\n" }, 01416 { {"misdn","show","channels", NULL}, misdn_show_cls, "Shows internal mISDN chan_list", 01417 "Usage: misdn show channels\n" }, 01418 { {"misdn","show","channel", NULL}, misdn_show_cl, "Shows internal mISDN chan_list", 01419 "Usage: misdn show channels\n", complete_ch }, 01420 { {"misdn","port","block", NULL}, misdn_port_block, "Blocks the given port", 01421 "Usage: misdn port block\n" }, 01422 { {"misdn","port","unblock", NULL}, misdn_port_unblock, "Unblocks the given port", 01423 "Usage: misdn port unblock\n" }, 01424 { {"misdn","restart","port", NULL}, misdn_restart_port, "Restarts the given port", 01425 "Usage: misdn restart port\n" }, 01426 { {"misdn","restart","pid", NULL}, misdn_restart_pid, "Restarts the given pid", 01427 "Usage: misdn restart pid\n" }, 01428 { {"misdn","port","up", NULL}, misdn_port_up, "Tries to establish L1 on the given port", 01429 "Usage: misdn port up <port>\n" }, 01430 { {"misdn","port","down", NULL}, misdn_port_down, "Tries to deacivate the L1 on the given port", 01431 "Usage: misdn port down <port>\n" }, 01432 { {"misdn","show","stacks", NULL}, misdn_show_stacks, "Shows internal mISDN stack_list", 01433 "Usage: misdn show stacks\n" }, 01434 { {"misdn","show","ports","stats", NULL}, misdn_show_ports_stats, "Shows chan_misdns call statistics per port", 01435 "Usage: misdn show port stats\n" }, 01436 { {"misdn","show","port", NULL}, misdn_show_port, "Shows detailed information for given port", 01437 "Usage: misdn show port <port>\n" }, 01438 { {"misdn","set","debug", NULL}, misdn_set_debug, "Sets Debuglevel of chan_misdn", 01439 "Usage: misdn set debug <level> [only] | [port <port> [only]]\n", complete_debug_port }, 01440 { {"misdn","set","crypt","debug", NULL}, misdn_set_crypt_debug, "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}", 01441 "Usage: misdn set crypt debug <level>\n" } 01442 }; 01443 01444 static int update_config (struct chan_list *ch, int orig) 01445 { 01446 if (!ch) { 01447 ast_log(LOG_WARNING, "Cannot configure without chanlist\n"); 01448 return -1; 01449 } 01450 01451 struct ast_channel *ast=ch->ast; 01452 struct misdn_bchannel *bc=ch->bc; 01453 if (! ast || ! bc ) { 01454 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n"); 01455 return -1; 01456 } 01457 01458 int port=bc->port; 01459 01460 chan_misdn_log(7,port,"update_config: Getting Config\n"); 01461 01462 int hdlc=0; 01463 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int)); 01464 01465 if (hdlc) { 01466 switch (bc->capability) { 01467 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: 01468 case INFO_CAPABILITY_DIGITAL_RESTRICTED: 01469 chan_misdn_log(1,bc->port," --> CONF HDLC\n"); 01470 bc->hdlc=1; 01471 break; 01472 } 01473 01474 } 01475 01476 01477 int pres, screen; 01478 01479 misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int)); 01480 misdn_cfg_get( port, MISDN_CFG_SCREEN, &screen, sizeof(int)); 01481 chan_misdn_log(2,port," --> pres: %d screen: %d\n",pres, screen); 01482 01483 if ( (pres + screen) < 0 ) { 01484 01485 chan_misdn_log(2,port," --> pres: %x\n", ast->cid.cid_pres); 01486 01487 switch (ast->cid.cid_pres & 0x60){ 01488 01489 case AST_PRES_RESTRICTED: 01490 bc->pres=1; 01491 chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n"); 01492 break; 01493 01494 01495 case AST_PRES_UNAVAILABLE: 01496 bc->pres=2; 01497 chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n"); 01498 break; 01499 01500 default: 01501 bc->pres=0; 01502 chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n"); 01503 } 01504 01505 switch (ast->cid.cid_pres & 0x3){ 01506 01507 case AST_PRES_USER_NUMBER_UNSCREENED: 01508 bc->screen=0; 01509 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n"); 01510 break; 01511 01512 case AST_PRES_USER_NUMBER_PASSED_SCREEN: 01513 bc->screen=1; 01514 chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n"); 01515 break; 01516 case AST_PRES_USER_NUMBER_FAILED_SCREEN: 01517 bc->screen=2; 01518 chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n"); 01519 break; 01520 01521 case AST_PRES_NETWORK_NUMBER: 01522 bc->screen=3; 01523 chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n"); 01524 break; 01525 01526 default: 01527 bc->screen=0; 01528 chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n"); 01529 } 01530 01531 01532 } else { 01533 bc->screen=screen; 01534 bc->pres=pres; 01535 } 01536 01537 return 0; 01538 01539 } 01540 01541 01542 01543 01544 static void config_jitterbuffer(struct chan_list *ch) 01545 { 01546 struct misdn_bchannel *bc=ch->bc; 01547 int len=ch->jb_len, threshold=ch->jb_upper_threshold; 01548 01549 chan_misdn_log(5,bc->port, "config_jb: Called\n"); 01550 01551 if ( ! len ) { 01552 chan_misdn_log(1,bc->port, "config_jb: Deactivating Jitterbuffer\n"); 01553 bc->nojitter=1; 01554 } else { 01555 01556 if (len <=100 || len > 8000) { 01557 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer out of Bounds, setting to 1000\n"); 01558 len=1000; 01559 } 01560 01561 if ( threshold > len ) { 01562 chan_misdn_log(0,bc->port,"config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n"); 01563 } 01564 01565 if ( ch->jb) { 01566 cb_log(0,bc->port,"config_jb: We've got a Jitterbuffer Already on this port.\n"); 01567 misdn_jb_destroy(ch->jb); 01568 ch->jb=NULL; 01569 } 01570 01571 ch->jb=misdn_jb_init(len, threshold); 01572 01573 if (!ch->jb ) 01574 bc->nojitter=1; 01575 } 01576 } 01577 01578 01579 void debug_numplan(int port, int numplan, char *type) 01580 { 01581 switch (numplan) { 01582 case NUMPLAN_INTERNATIONAL: 01583 chan_misdn_log(2, port, " --> %s: International\n",type); 01584 break; 01585 case NUMPLAN_NATIONAL: 01586 chan_misdn_log(2, port, " --> %s: National\n",type); 01587 break; 01588 case NUMPLAN_SUBSCRIBER: 01589 chan_misdn_log(2, port, " --> %s: Subscriber\n",type); 01590 break; 01591 case NUMPLAN_UNKNOWN: 01592 chan_misdn_log(2, port, " --> %s: Unknown\n",type); 01593 break; 01594 /* Maybe we should cut off the prefix if present ? */ 01595 default: 01596 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n "); 01597 break; 01598 } 01599 } 01600 01601 01602 01603 01604 static int update_ec_config(struct misdn_bchannel *bc) 01605 { 01606 int ec; 01607 int port=bc->port; 01608 01609 misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int)); 01610 01611 if (ec == 1 ) { 01612 bc->ec_enable=1; 01613 } else if ( ec > 1 ) { 01614 bc->ec_enable=1; 01615 bc->ec_deftaps=ec; 01616 } 01617 #ifdef WITH_ECHOTRAINING 01618 int ectr; 01619 misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int)); 01620 01621 if ( ectr >= 0 ) { 01622 bc->ec_training=ectr; 01623 } 01624 #endif 01625 01626 return 0; 01627 } 01628 01629 01630 static int read_config(struct chan_list *ch, int orig) { 01631 01632 if (!ch) { 01633 ast_log(LOG_WARNING, "Cannot configure without chanlist\n"); 01634 return -1; 01635 } 01636 01637 struct ast_channel *ast=ch->ast; 01638 struct misdn_bchannel *bc=ch->bc; 01639 if (! ast || ! bc ) { 01640 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n"); 01641 return -1; 01642 } 01643 01644 int port=bc->port; 01645 01646 chan_misdn_log(1,port,"read_config: Getting Config\n"); 01647 01648 char lang[BUFFERSIZE+1]; 01649 01650 01651 misdn_cfg_get( port, MISDN_CFG_LANGUAGE, lang, BUFFERSIZE); 01652 ast_string_field_set(ast, language, lang); 01653 01654 char localmusicclass[BUFFERSIZE+1]; 01655 01656 misdn_cfg_get( port, MISDN_CFG_MUSICCLASS, localmusicclass, BUFFERSIZE); 01657 ast_string_field_set(ast, musicclass, localmusicclass); 01658 01659 01660 misdn_cfg_get( port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(int)); 01661 misdn_cfg_get( port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(int)); 01662 01663 misdn_cfg_get( port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(int)); 01664 01665 misdn_cfg_get( port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(int)); 01666 01667 misdn_cfg_get( port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(int)); 01668 misdn_cfg_get( port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(int)); 01669 01670 misdn_cfg_get( port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(int)); 01671 01672 misdn_cfg_get( port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, BUFFERSIZE); 01673 01674 char faxdetect[BUFFERSIZE+1]; 01675 misdn_cfg_get( port, MISDN_CFG_FAXDETECT, faxdetect, BUFFERSIZE); 01676 01677 int hdlc=0; 01678 misdn_cfg_get( port, MISDN_CFG_HDLC, &hdlc, sizeof(int)); 01679 01680 if (hdlc) { 01681 switch (bc->capability) { 01682 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: 01683 case INFO_CAPABILITY_DIGITAL_RESTRICTED: 01684 chan_misdn_log(1,bc->port," --> CONF HDLC\n"); 01685 bc->hdlc=1; 01686 break; 01687 } 01688 01689 } 01690 /*Initialize new Jitterbuffer*/ 01691 { 01692 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(int)); 01693 misdn_cfg_get( port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(int)); 01694 01695 config_jitterbuffer(ch); 01696 } 01697 01698 misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context)); 01699 01700 ast_copy_string (ast->context,ch->context,sizeof(ast->context)); 01701 01702 update_ec_config(bc); 01703 01704 { 01705 int eb3; 01706 01707 misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int)); 01708 bc->early_bconnect=eb3; 01709 } 01710 01711 port=bc->port; 01712 01713 { 01714 char buf[256]; 01715 ast_group_t pg,cg; 01716 01717 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg)); 01718 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg)); 01719 01720 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg)); 01721 ast->pickupgroup=pg; 01722 ast->callgroup=cg; 01723 } 01724 01725 if ( orig == ORG_AST) { 01726 misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(int)); 01727 01728 if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) { 01729 if (strstr(faxdetect, "nojump")) 01730 ch->faxdetect=2; 01731 else 01732 ch->faxdetect=1; 01733 } 01734 01735 { 01736 char callerid[BUFFERSIZE+1]; 01737 misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE); 01738 if ( ! ast_strlen_zero(callerid) ) { 01739 chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid); 01740 { 01741 int l = sizeof(bc->oad); 01742 strncpy(bc->oad,callerid, l); 01743 bc->oad[l-1] = 0; 01744 } 01745 01746 } 01747 01748 01749 misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &bc->dnumplan, sizeof(int)); 01750 misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &bc->onumplan, sizeof(int)); 01751 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int)); 01752 debug_numplan(port, bc->dnumplan,"TON"); 01753 debug_numplan(port, bc->onumplan,"LTON"); 01754 debug_numplan(port, bc->cpnnumplan,"CTON"); 01755 } 01756 01757 ch->overlap_dial = 0; 01758 } else { /** ORIGINATOR MISDN **/ 01759 if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) { 01760 if (strstr(faxdetect, "nojump")) 01761 ch->faxdetect=2; 01762 else 01763 ch->faxdetect=1; 01764 } 01765 01766 misdn_cfg_get( port, MISDN_CFG_CPNDIALPLAN, &bc->cpnnumplan, sizeof(int)); 01767 debug_numplan(port, bc->cpnnumplan,"CTON"); 01768 01769 char prefix[BUFFERSIZE+1]=""; 01770 switch( bc->onumplan ) { 01771 case NUMPLAN_INTERNATIONAL: 01772 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE); 01773 break; 01774 01775 case NUMPLAN_NATIONAL: 01776 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE); 01777 break; 01778 default: 01779 break; 01780 } 01781 01782 { 01783 int l = strlen(prefix) + strlen(bc->oad); 01784 char tmp[l+1]; 01785 strcpy(tmp,prefix); 01786 strcat(tmp,bc->oad); 01787 strcpy(bc->oad,tmp); 01788 } 01789 01790 if (!ast_strlen_zero(bc->dad)) { 01791 ast_copy_string(bc->orig_dad,bc->dad, sizeof(bc->orig_dad)); 01792 } 01793 01794 if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) { 01795 ast_copy_string(bc->dad,bc->keypad, sizeof(bc->dad)); 01796 } 01797 01798 prefix[0] = 0; 01799 01800 switch( bc->dnumplan ) { 01801 case NUMPLAN_INTERNATIONAL: 01802 misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE); 01803 break; 01804 case NUMPLAN_NATIONAL: 01805 misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE); 01806 break; 01807 default: 01808 break; 01809 } 01810 01811 { 01812 int l = strlen(prefix) + strlen(bc->dad); 01813 char tmp[l+1]; 01814 strcpy(tmp,prefix); 01815 strcat(tmp,bc->dad); 01816 strcpy(bc->dad,tmp); 01817 } 01818 01819 if ( strcmp(bc->dad,ast->exten)) { 01820 ast_copy_string(ast->exten, bc->dad, sizeof(ast->exten)); 01821 } 01822 01823 ast_set_callerid(ast, bc->oad, NULL, bc->oad); 01824 01825 if ( !ast_strlen_zero(bc->rad) ) { 01826 if (ast->cid.cid_rdnis) 01827 free(ast->cid.cid_rdnis); 01828 ast->cid.cid_rdnis = strdup(bc->rad); 01829 } 01830 01831 misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial)); 01832 ast_mutex_init(&ch->overlap_tv_lock); 01833 } /* ORIG MISDN END */ 01834 01835 ch->overlap_dial_task = -1; 01836 01837 if (ch->faxdetect) { 01838 misdn_cfg_get( port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout)); 01839 if (!ch->dsp) 01840 ch->dsp = ast_dsp_new(); 01841 if (ch->dsp) 01842 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT | DSP_FEATURE_FAX_DETECT); 01843 if (!ch->trans) 01844 ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW); 01845 } 01846 01847 /* AOCD initialization */ 01848 bc->AOCDtype = Fac_None; 01849 01850 return 0; 01851 } 01852 01853 01854 /*****************************/ 01855 /*** AST Indications Start ***/ 01856 /*****************************/ 01857 01858 static int misdn_call(struct ast_channel *ast, char *dest, int timeout) 01859 { 01860 int port=0; 01861 int r; 01862 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast); 01863 struct misdn_bchannel *newbc; 01864 char *opts=NULL, *ext,*tokb; 01865 char dest_cp[256]; 01866 01867 { 01868 strncpy(dest_cp,dest,sizeof(dest_cp)-1); 01869 dest_cp[sizeof(dest_cp)]=0; 01870 01871 ext=strtok_r(dest_cp,"/",&tokb); 01872 01873 if (ext) { 01874 ext=strtok_r(NULL,"/",&tokb); 01875 if (ext) { 01876 opts=strtok_r(NULL,"/",&tokb); 01877 } else { 01878 chan_misdn_log(0,0,"misdn_call: No Extension given!\n"); 01879 return -1; 01880 } 01881 } 01882 } 01883 01884 if (!ast) { 01885 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n"); 01886 return -1; 01887 } 01888 01889 if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest ) { 01890 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); 01891 ast->hangupcause=41; 01892 ast_setstate(ast, AST_STATE_DOWN); 01893 return -1; 01894 } 01895 01896 if (!ch) { 01897 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); 01898 ast->hangupcause=41; 01899 ast_setstate(ast, AST_STATE_DOWN); 01900 return -1; 01901 } 01902 01903 newbc=ch->bc; 01904 01905 if (!newbc) { 01906 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name); 01907 ast->hangupcause=41; 01908 ast_setstate(ast, AST_STATE_DOWN); 01909 return -1; 01910 } 01911 01912 port=newbc->port; 01913 strncpy(newbc->dad,ext,sizeof( newbc->dad)); 01914 strncpy(ast->exten,ext,sizeof(ast->exten)); 01915 01916 int exceed; 01917 if ((exceed=add_out_calls(port))) { 01918 char tmp[16]; 01919 sprintf(tmp,"%d",exceed); 01920 pbx_builtin_setvar_helper(ast,"MAX_OVERFLOW",tmp); 01921 return -1; 01922 } 01923 01924 chan_misdn_log(1, port, "* CALL: %s\n",dest); 01925 01926 chan_misdn_log(2, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context); 01927 01928 chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten); 01929 if (ast->exten) { 01930 int l = sizeof(newbc->dad); 01931 strncpy(newbc->dad,ast->exten, l); 01932 newbc->dad[l-1] = 0; 01933 } 01934 newbc->rad[0]=0; 01935 chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast)); 01936 if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) { 01937 01938 if (AST_CID_P(ast)) { 01939 int l = sizeof(newbc->oad); 01940 strncpy(newbc->oad,AST_CID_P(ast), l); 01941 newbc->oad[l-1] = 0; 01942 } 01943 } 01944 01945 { 01946 struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast); 01947 if (!ch) { ast_verbose("No chan_list in misdn_call\n"); return -1;} 01948 01949 newbc->capability=ast->transfercapability; 01950 pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability)); 01951 if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) { 01952 chan_misdn_log(2, port, " --> * Call with flag Digital\n"); 01953 } 01954 01955 01956 /* update screening and presentation */ 01957 update_config(ch,ORG_AST); 01958 01959 /* fill in some ies from channel vary*/ 01960 import_ch(ast, newbc, ch); 01961 01962 /* Finally The Options Override Everything */ 01963 if (opts) 01964 misdn_set_opt_exec(ast,opts); 01965 else 01966 chan_misdn_log(2,port,"NO OPTS GIVEN\n"); 01967 01968 /*check for bridging*/ 01969 int bridging; 01970 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int)); 01971 if (bridging && ch->other_ch) { 01972 chan_misdn_log(0, port, "Disabling EC on both Sides\n"); 01973 ch->bc->ec_enable=0; 01974 ch->other_ch->bc->ec_enable=0; 01975 } 01976 01977 r=misdn_lib_send_event( newbc, EVENT_SETUP ); 01978 01979 /** we should have l3id after sending setup **/ 01980 ch->l3id=newbc->l3_id; 01981 } 01982 01983 if ( r == -ENOCHAN ) { 01984 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n"); 01985 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1); 01986 ast->hangupcause=34; 01987 ast_setstate(ast, AST_STATE_DOWN); 01988 return -1; 01989 } 01990 01991 chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1); 01992 01993 ast_setstate(ast, AST_STATE_DIALING); 01994 ast->hangupcause=16; 01995 01996 if (newbc->nt) stop_bc_tones(ch); 01997 01998 ch->state=MISDN_CALLING; 01999 02000 return 0; 02001 } 02002 02003 02004 static int misdn_answer(struct ast_channel *ast) 02005 { 02006 struct chan_list *p; 02007 02008 02009 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1; 02010 02011 chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n"); 02012 02013 if (!p) { 02014 ast_log(LOG_WARNING, " --> Channel not connected ??\n"); 02015 ast_queue_hangup(ast); 02016 } 02017 02018 if (!p->bc) { 02019 chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n"); 02020 02021 ast_queue_hangup(ast); 02022 } 02023 02024 { 02025 const char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY"); 02026 02027 if (tmp_key ) { 02028 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n"); 02029 { 02030 int l = sizeof(p->bc->crypt_key); 02031 strncpy(p->bc->crypt_key,tmp_key, l); 02032 p->bc->crypt_key[l-1] = 0; 02033 } 02034 } else { 02035 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n"); 02036 } 02037 02038 } 02039 02040 { 02041 const char *nodsp=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS"); 02042 if (nodsp) { 02043 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n"); 02044 p->bc->nodsp=1; 02045 p->bc->hdlc=0; 02046 p->bc->nojitter=1; 02047 } 02048 } 02049 02050 p->state = MISDN_CONNECTED; 02051 stop_indicate(p); 02052 02053 if ( ast_strlen_zero(p->bc->cad) ) { 02054 chan_misdn_log(2,p->bc->port," --> empty cad using dad\n"); 02055 ast_copy_string(p->bc->cad,p->bc->dad,sizeof(p->bc->cad)); 02056 } 02057 02058 misdn_lib_send_event( p->bc, EVENT_CONNECT); 02059 start_bc_tones(p); 02060 02061 return 0; 02062 } 02063 02064 static int misdn_digit_begin(struct ast_channel *chan, char digit) 02065 { 02066 /* XXX Modify this callback to support Asterisk controlling the length of DTMF */ 02067 return 0; 02068 } 02069 02070 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration) 02071 { 02072 struct chan_list *p; 02073 02074 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) return -1; 02075 02076 struct misdn_bchannel *bc=p->bc; 02077 chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit); 02078 02079 if (!bc) { 02080 ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n"); 02081 return -1; 02082 } 02083 02084 switch (p->state ) { 02085 case MISDN_CALLING: 02086 { 02087 02088 char buf[8]; 02089 buf[0]=digit; 02090 buf[1]=0; 02091 02092 int l = sizeof(bc->infos_pending); 02093 strncat(bc->infos_pending,buf,l); 02094 bc->infos_pending[l-1] = 0; 02095 } 02096 break; 02097 case MISDN_CALLING_ACKNOWLEDGE: 02098 { 02099 bc->info_dad[0]=digit; 02100 bc->info_dad[1]=0; 02101 02102 { 02103 int l = sizeof(bc->dad); 02104 strncat(bc->dad,bc->info_dad, l - strlen(bc->dad)); 02105 bc->dad[l-1] = 0; 02106 } 02107 { 02108 int l = sizeof(p->ast->exten); 02109 strncpy(p->ast->exten, bc->dad, l); 02110 p->ast->exten[l-1] = 0; 02111 } 02112 02113 misdn_lib_send_event( bc, EVENT_INFORMATION); 02114 } 02115 break; 02116 02117 default: 02118 if ( bc->send_dtmf ) { 02119 send_digit_to_chan(p,digit); 02120 } 02121 break; 02122 } 02123 02124 return 0; 02125 } 02126 02127 02128 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast) 02129 { 02130 struct chan_list *p; 02131 02132 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) )) return -1; 02133 02134 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); 02135 02136 p->ast = ast ; 02137 02138 return 0; 02139 } 02140 02141 02142 02143 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen) 02144 { 02145 struct chan_list *p; 02146 02147 02148 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast))) { 02149 ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n"); 02150 return -1; 02151 } 02152 02153 if (!p->bc ) { 02154 chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten); 02155 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n"); 02156 return -1; 02157 } 02158 02159 chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] from %s\n",cond, ast->exten); 02160 02161 switch (cond) { 02162 case AST_CONTROL_BUSY: 02163 chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n",p->bc?p->bc->pid:-1); 02164 ast_setstate(ast,AST_STATE_BUSY); 02165 02166 p->bc->out_cause=17; 02167 if (p->state != MISDN_CONNECTED) { 02168 start_bc_tones(p); 02169 misdn_lib_send_event( p->bc, EVENT_DISCONNECT); 02170 } else { 02171 chan_misdn_log(-1, p->bc->port, " --> !! Got Busy in Connected State !?! ast:%s\n", ast->name); 02172 } 02173 return -1; 02174 break; 02175 case AST_CONTROL_RING: 02176 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n",p->bc?p->bc->pid:-1); 02177 return -1; 02178 break; 02179 02180 case AST_CONTROL_RINGING: 02181 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1); 02182 switch (p->state) { 02183 case MISDN_ALERTING: 02184 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); 02185 break; 02186 case MISDN_CONNECTED: 02187 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); 02188 return -1; 02189 break; 02190 default: 02191 p->state=MISDN_ALERTING; 02192 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1); 02193 misdn_lib_send_event( p->bc, EVENT_ALERTING); 02194 02195 if (p->other_ch && p->other_ch->bc) { 02196 if (misdn_inband_avail(p->other_ch->bc)) { 02197 chan_misdn_log(2,p->bc->port, " --> other End is mISDN and has inband info available\n"); 02198 break; 02199 } 02200 02201 if (!p->other_ch->bc->nt) { 02202 chan_misdn_log(2,p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n"); 02203 break; 02204 } 02205 } 02206 02207 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1); 02208 ast_setstate(ast,AST_STATE_RINGING); 02209 02210 if ( !p->bc->nt && (p->orginator==ORG_MISDN) && !p->incoming_early_audio ) 02211 chan_misdn_log(2,p->bc->port, " --> incoming_early_audio off\n"); 02212 else 02213 return -1; 02214 } 02215 break; 02216 case AST_CONTROL_ANSWER: 02217 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1); 02218 start_bc_tones(p); 02219 break; 02220 case AST_CONTROL_TAKEOFFHOOK: 02221 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1); 02222 return -1; 02223 break; 02224 case AST_CONTROL_OFFHOOK: 02225 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1); 02226 return -1; 02227 break; 02228 case AST_CONTROL_FLASH: 02229 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1); 02230 break; 02231 case AST_CONTROL_PROGRESS: 02232 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1); 02233 misdn_lib_send_event( p->bc, EVENT_PROGRESS); 02234 break; 02235 case AST_CONTROL_PROCEEDING: 02236 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n",p->bc?p->bc->pid:-1); 02237 misdn_lib_send_event( p->bc, EVENT_PROCEEDING); 02238 break; 02239 case AST_CONTROL_CONGESTION: 02240 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1); 02241 02242 p->bc->out_cause=42; 02243 if (p->state != MISDN_CONNECTED) { 02244 start_bc_tones(p); 02245 misdn_lib_send_event( p->bc, EVENT_RELEASE); 02246 } else { 02247 misdn_lib_send_event( p->bc, EVENT_DISCONNECT); 02248 } 02249 02250 if (p->bc->nt) { 02251 hanguptone_indicate(p); 02252 } 02253 break; 02254 case -1 : 02255 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n",p->bc?p->bc->pid:-1); 02256 02257 stop_indicate(p); 02258 02259 if (p->state == MISDN_CONNECTED) 02260 start_bc_tones(p); 02261 02262 break; 02263 02264 case AST_CONTROL_HOLD: 02265 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1); 02266 break; 02267 case AST_CONTROL_UNHOLD: 02268 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1); 02269 break; 02270 default: 02271 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1); 02272 } 02273 02274 return 0; 02275 } 02276 02277 static int misdn_hangup(struct ast_channel *ast) 02278 { 02279 struct chan_list *p; 02280 struct misdn_bchannel *bc=NULL; 02281 02282 if (option_debug) 02283 ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name); 02284 02285 if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1; 02286 02287 if (!p) { 02288 chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n"); 02289 return 0 ; 02290 } 02291 02292 bc=p->bc; 02293 02294 02295 02296 MISDN_ASTERISK_TECH_PVT(ast)=NULL; 02297 p->ast=NULL; 02298 02299 bc=p->bc; 02300 02301 if (ast->_state == AST_STATE_RESERVED || 02302 p->state == MISDN_NOTHING || 02303 p->state == MISDN_HOLDED || 02304 p->state == MISDN_HOLD_DISCONNECT ) { 02305 02306 CLEAN_CH: 02307 /* between request and call */ 02308 if (option_debug) 02309 ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n"); 02310 MISDN_ASTERISK_TECH_PVT(ast)=NULL; 02311 02312 cl_dequeue_chan(&cl_te, p); 02313 close(p->pipe[0]); 02314 close(p->pipe[1]); 02315 free(p); 02316 02317 if (bc) 02318 misdn_lib_release(bc); 02319 02320 return 0; 02321 } 02322 02323 if (!bc) { 02324 ast_log(LOG_WARNING,"Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id); 02325 goto CLEAN_CH; 02326 } 02327 02328 02329 p->need_hangup=0; 02330 p->need_queue_hangup=0; 02331 p->need_busy=0; 02332 02333 02334 if (!p->bc->nt) 02335 stop_bc_tones(p); 02336 02337 02338 { 02339 const char *varcause=NULL; 02340 bc->out_cause=ast->hangupcause?ast->hangupcause:16; 02341 02342 if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) || 02343 (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) { 02344 int tmpcause=atoi(varcause); 02345 bc->out_cause=tmpcause?tmpcause:16; 02346 } 02347 02348 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_P(ast), misdn_get_ch_state(p)); 02349 chan_misdn_log(3, bc->port, " --> l3id:%x\n",p->l3id); 02350 chan_misdn_log(3, bc->port, " --> cause:%d\n",bc->cause); 02351 chan_misdn_log(2, bc->port, " --> out_cause:%d\n",bc->out_cause); 02352 chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p)); 02353 02354 switch (p->state) { 02355 case MISDN_CALLING: 02356 p->state=MISDN_CLEANING; 02357 misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE); 02358 break; 02359 case MISDN_HOLDED: 02360 case MISDN_DIALING: 02361 start_bc_tones(p); 02362 hanguptone_indicate(p); 02363 02364 if (bc->need_disconnect) 02365 misdn_lib_send_event( bc, EVENT_DISCONNECT); 02366 break; 02367 02368 case MISDN_CALLING_ACKNOWLEDGE: 02369 start_bc_tones(p); 02370 hanguptone_indicate(p); 02371 02372 if (bc->need_disconnect) 02373 misdn_lib_send_event( bc, EVENT_DISCONNECT); 02374 break; 02375 02376 case MISDN_ALERTING: 02377 case MISDN_PROGRESS: 02378 case MISDN_PROCEEDING: 02379 if (p->orginator != ORG_AST) 02380 hanguptone_indicate(p); 02381 02382 /*p->state=MISDN_CLEANING;*/ 02383 if (bc->need_disconnect) 02384 misdn_lib_send_event( bc, EVENT_DISCONNECT); 02385 break; 02386 case MISDN_CONNECTED: 02387 case MISDN_PRECONNECTED: 02388 /* Alerting or Disconect */ 02389 if (p->bc->nt) { 02390 start_bc_tones(p); 02391 hanguptone_indicate(p); 02392 p->bc->progress_indicator=8; 02393 } 02394 if (bc->need_disconnect) 02395 misdn_lib_send_event( bc, EVENT_DISCONNECT); 02396 02397 /*p->state=MISDN_CLEANING;*/ 02398 break; 02399 case MISDN_DISCONNECTED: 02400 misdn_lib_send_event( bc, EVENT_RELEASE); 02401 p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */ 02402 break; 02403 02404 case MISDN_RELEASED: 02405 case MISDN_CLEANING: 02406 p->state=MISDN_CLEANING; 02407 break; 02408 02409 case MISDN_BUSY: 02410 break; 02411 02412 case MISDN_HOLD_DISCONNECT: 02413 /* need to send release here */ 02414 chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause); 02415 chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause); 02416 02417 bc->out_cause=-1; 02418 misdn_lib_send_event(bc,EVENT_RELEASE); 02419 p->state=MISDN_CLEANING; 02420 break; 02421 default: 02422 if (bc->nt) { 02423 bc->out_cause=-1; 02424 misdn_lib_send_event(bc, EVENT_RELEASE); 02425 p->state=MISDN_CLEANING; 02426 } else { 02427 if (bc->need_disconnect) 02428 misdn_lib_send_event(bc, EVENT_DISCONNECT); 02429 } 02430 } 02431 02432 p->state=MISDN_CLEANING; 02433 02434 } 02435 02436 02437 chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n",ast->name,misdn_get_ch_state(p)); 02438 02439 return 0; 02440 } 02441 02442 02443 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame) 02444 { 02445 struct ast_frame *f,*f2; 02446 02447 if (tmp->trans) { 02448 f2 = ast_translate(tmp->trans, frame, 0); 02449 f = ast_dsp_process(tmp->ast, tmp->dsp, f2); 02450 } else { 02451 chan_misdn_log(0, tmp->bc->port, "No T-Path found\n"); 02452 return NULL; 02453 } 02454 02455 02456 if (!f || (f->frametype != AST_FRAME_DTMF)) 02457 return frame; 02458 02459 if (option_debug) 02460 ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass); 02461 02462 if (tmp->faxdetect && (f->subclass == 'f')) { 02463 /* Fax tone -- Handle and return NULL */ 02464 if (!tmp->faxhandled) { 02465 struct ast_channel *ast = tmp->ast; 02466 tmp->faxhandled++; 02467 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name); 02468 tmp->bc->rxgain = 0; 02469 isdn_lib_update_rxgain(tmp->bc); 02470 tmp->bc->txgain = 0; 02471 isdn_lib_update_txgain(tmp->bc); 02472 tmp->bc->ec_enable = 0; 02473 isdn_lib_update_ec(tmp->bc); 02474 isdn_lib_stop_dtmf(tmp->bc); 02475 switch (tmp->faxdetect) { 02476 case 1: 02477 if (strcmp(ast->exten, "fax")) { 02478 char *context; 02479 char context_tmp[BUFFERSIZE]; 02480 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp)); 02481 context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp; 02482 if (ast_exists_extension(ast, context, "fax", 1, AST_CID_P(ast))) { 02483 if (option_verbose > 2) 02484 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context); 02485 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */ 02486 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten); 02487 if (ast_async_goto(ast, context, "fax", 1)) 02488 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context); 02489 } else 02490 ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten); 02491 } else { 02492 if (option_debug) 02493 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n"); 02494 } 02495 break; 02496 case 2: 02497 ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name); 02498 break; 02499 } 02500 } else { 02501 if (option_debug) 02502 ast_log(LOG_DEBUG, "Fax already handled\n"); 02503 } 02504 } 02505 02506 if (tmp->ast_dsp && (f->subclass != 'f')) { 02507 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass); 02508 } 02509 02510 return frame; 02511 } 02512 02513 02514 static struct ast_frame *misdn_read(struct ast_channel *ast) 02515 { 02516 struct chan_list *tmp; 02517 int len; 02518 02519 if (!ast) { 02520 chan_misdn_log(1,0,"misdn_read called without ast\n"); 02521 return NULL; 02522 } 02523 if (!(tmp=MISDN_ASTERISK_TECH_PVT(ast))) { 02524 chan_misdn_log(1,0,"misdn_read called without ast->pvt\n"); 02525 return NULL; 02526 } 02527 if (!tmp->bc) { 02528 chan_misdn_log(1,0,"misdn_read called without bc\n"); 02529 return NULL; 02530 } 02531 02532 len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf)); 02533 02534 if (len<=0) { 02535 /* we hangup here, since our pipe is closed */ 02536 chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n"); 02537 return NULL; 02538 } 02539 02540 tmp->frame.frametype = AST_FRAME_VOICE; 02541 tmp->frame.subclass = AST_FORMAT_ALAW; 02542 tmp->frame.datalen = len; 02543 tmp->frame.samples = len; 02544 tmp->frame.mallocd = 0; 02545 tmp->frame.offset = 0; 02546 tmp->frame.delivery= ast_tv(0,0) ; 02547 tmp->frame.src = NULL; 02548 tmp->frame.data = tmp->ast_rd_buf; 02549 02550 if (tmp->faxdetect && !tmp->faxhandled) { 02551 if (tmp->faxdetect_timeout) { 02552 if (ast_tvzero(tmp->faxdetect_tv)) { 02553 tmp->faxdetect_tv = ast_tvnow(); 02554 chan_misdn_log(2,tmp->bc->port,"faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout); 02555 return process_ast_dsp(tmp, &tmp->frame); 02556 } else { 02557 struct timeval tv_now = ast_tvnow(); 02558 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv); 02559 if (diff <= (tmp->faxdetect_timeout * 1000)) { 02560 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ...\n"); 02561 return process_ast_dsp(tmp, &tmp->frame); 02562 } else { 02563 chan_misdn_log(2,tmp->bc->port,"faxdetect: stopping detection (time ran out) ...\n"); 02564 tmp->faxdetect = 0; 02565 return &tmp->frame; 02566 } 02567 } 02568 } else { 02569 chan_misdn_log(5,tmp->bc->port,"faxdetect: detecting ... (no timeout)\n"); 02570 return process_ast_dsp(tmp, &tmp->frame); 02571 } 02572 } else { 02573 if (tmp->ast_dsp) 02574 return process_ast_dsp(tmp, &tmp->frame); 02575 else 02576 return &tmp->frame; 02577 } 02578 } 02579 02580 02581 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame) 02582 { 02583 struct chan_list *ch; 02584 int i = 0; 02585 02586 if (!ast || ! (ch=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1; 02587 02588 if (ch->state == MISDN_HOLDED) { 02589 chan_misdn_log(7, 0, "misdn_write: Returning because holded\n"); 02590 return 0; 02591 } 02592 02593 if (!ch->bc ) { 02594 ast_log(LOG_WARNING, "private but no bc\n"); 02595 return -1; 02596 } 02597 02598 if (ch->notxtone) { 02599 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxone\n"); 02600 return 0; 02601 } 02602 02603 02604 if ( !frame->subclass) { 02605 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n"); 02606 return 0; 02607 } 02608 02609 if ( !(frame->subclass & prefformat)) { 02610 02611 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass); 02612 return 0; 02613 } 02614 02615 02616 if ( !frame->samples ) { 02617 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n"); 02618 return 0; 02619 } 02620 02621 if ( ! ch->bc->addr ) { 02622 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples); 02623 return 0; 02624 } 02625 02626 #if MISDN_DEBUG 02627 { 02628 int i, max=5>frame->samples?frame->samples:5; 02629 02630 printf("write2mISDN %p %d bytes: ", p, frame->samples); 02631 02632 for (i=0; i< max ; i++) printf("%2.2x ",((char*) frame->data)[i]); 02633 printf ("\n"); 02634 } 02635 #endif 02636 02637 02638 switch (ch->bc->bc_state) { 02639 case BCHAN_ACTIVATED: 02640 case BCHAN_BRIDGED: 02641 break; 02642 default: 02643 if (!ch->dropped_frame_cnt) 02644 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); 02645 02646 ch->dropped_frame_cnt++; 02647 if (ch->dropped_frame_cnt > 100) { 02648 ch->dropped_frame_cnt=0; 02649 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); 02650 02651 } 02652 02653 return 0; 02654 } 02655 02656 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes 2 MISDN\n",frame->samples); 02657 if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) { 02658 /* Buffered Transmit (triggert by read from isdn side)*/ 02659 if (misdn_jb_fill(ch->jb,frame->data,frame->samples) < 0) { 02660 if (ch->bc->active) 02661 cb_log(0,ch->bc->port,"Misdn Jitterbuffer Overflow.\n"); 02662 } 02663 02664 } else { 02665 /*transmit without jitterbuffer*/ 02666 i=misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples); 02667 } 02668 02669 02670 02671 return 0; 02672 } 02673 02674 02675 02676 02677 static enum ast_bridge_result misdn_bridge (struct ast_channel *c0, 02678 struct ast_channel *c1, int flags, 02679 struct ast_frame **fo, 02680 struct ast_channel **rc, 02681 int timeoutms) 02682 02683 { 02684 struct chan_list *ch1,*ch2; 02685 struct ast_channel *carr[2], *who; 02686 int to=-1; 02687 struct ast_frame *f; 02688 02689 ch1=get_chan_by_ast(c0); 02690 ch2=get_chan_by_ast(c1); 02691 02692 carr[0]=c0; 02693 carr[1]=c1; 02694 02695 if (ch1 && ch2 ) ; 02696 else 02697 return -1; 02698 02699 int bridging; 02700 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int)); 02701 if (bridging) { 02702 /* trying to make a mISDN_dsp conference */ 02703 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid +1); 02704 misdn_lib_bridge(ch1->bc,ch2->bc); 02705 } 02706 02707 if (option_verbose > 2) 02708 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name); 02709 02710 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad); 02711 02712 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_0) ) 02713 ch1->ignore_dtmf=1; 02714 02715 if (! (flags&AST_BRIDGE_DTMF_CHANNEL_1) ) 02716 ch2->ignore_dtmf=1; 02717 02718 while(1) { 02719 to=-1; 02720 who = ast_waitfor_n(carr, 2, &to); 02721 02722 if (!who) { 02723 ast_log(LOG_NOTICE,"misdn_bridge: empty read, breaking out\n"); 02724 break; 02725 } 02726 f = ast_read(who); 02727 02728 if (!f || f->frametype == AST_FRAME_CONTROL) { 02729 /* got hangup .. */ 02730 02731 if (!f) 02732 chan_misdn_log(4,ch1->bc->port,"Read Null Frame\n"); 02733 else 02734 chan_misdn_log(4,ch1->bc->port,"Read Frame Controll class:%d\n",f->subclass); 02735 02736 *fo=f; 02737 *rc=who; 02738 02739 break; 02740 } 02741 02742 if ( f->frametype == AST_FRAME_DTMF ) { 02743 chan_misdn_log(1,0,"Read DTMF %d from %s\n",f->subclass, who->exten); 02744 02745 *fo=f; 02746 *rc=who; 02747 break; 02748 } 02749 02750 #if 0 02751 if (f->frametype == AST_FRAME_VOICE) { 02752 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1); 02753 02754 continue; 02755 } 02756 #endif 02757 02758 if (who == c0) { 02759 ast_write(c1,f); 02760 } 02761 else { 02762 ast_write(c0,f); 02763 } 02764 02765 } 02766 02767 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1); 02768 02769 misdn_lib_split_bridge(ch1->bc,ch2->bc); 02770 02771 02772 return AST_BRIDGE_COMPLETE; 02773 } 02774 02775 /** AST INDICATIONS END **/ 02776 02777 static int dialtone_indicate(struct chan_list *cl) 02778 { 02779 const struct ind_tone_zone_sound *ts= NULL; 02780 struct ast_channel *ast=cl->ast; 02781 02782 if (!ast) { 02783 chan_misdn_log(0,cl->bc->port,"No Ast in dialtone_indicate\n"); 02784 return -1; 02785 } 02786 02787 int nd=0; 02788 misdn_cfg_get( cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd)); 02789 02790 if (nd) { 02791 chan_misdn_log(1,cl->bc->port,"Not sending Dialtone, because config wants it\n"); 02792 return 0; 02793 } 02794 02795 chan_misdn_log(3,cl->bc->port," --> Dial\n"); 02796 ts=ast_get_indication_tone(ast->zone,"dial"); 02797 cl->ts=ts; 02798 02799 if (ts) { 02800 cl->notxtone=0; 02801 cl->norxtone=0; 02802 ast_playtones_start(ast,0, ts->data, 0); 02803 chan_misdn_log(4,cl->bc->port,"Starting Playtones\n"); 02804 misdn_lib_tone_generator_start(cl->bc); 02805 } 02806 02807 return 0; 02808 } 02809 02810 static int hanguptone_indicate(struct chan_list *cl) 02811 { 02812 misdn_lib_send_tone(cl->bc,TONE_HANGUP); 02813 return 0; 02814 } 02815 02816 static int stop_indicate(struct chan_list *cl) 02817 { 02818 struct ast_channel *ast=cl->ast; 02819 02820 if (!ast) { 02821 chan_misdn_log(0,cl->bc->port,"No Ast in stop_indicate\n"); 02822 return -1; 02823 } 02824 02825 chan_misdn_log(3,cl->bc->port," --> None\n"); 02826 misdn_lib_tone_generator_stop(cl->bc); 02827 ast_playtones_stop(ast); 02828 /*ast_deactivate_generator(ast);*/ 02829 02830 return 0; 02831 } 02832 02833 02834 static int start_bc_tones(struct chan_list* cl) 02835 { 02836 misdn_lib_tone_generator_stop(cl->bc); 02837 cl->notxtone=0; 02838 cl->norxtone=0; 02839 return 0; 02840 } 02841 02842 static int stop_bc_tones(struct chan_list *cl) 02843 { 02844 if (!cl) return -1; 02845 02846 cl->notxtone=1; 02847 cl->norxtone=1; 02848 02849 return 0; 02850 } 02851 02852 02853 static struct chan_list *init_chan_list(int orig) 02854 { 02855 struct chan_list *cl=malloc(sizeof(struct chan_list)); 02856 02857 if (!cl) { 02858 chan_misdn_log(-1, 0, "misdn_request: malloc failed!"); 02859 return NULL; 02860 } 02861 02862 memset(cl,0,sizeof(struct chan_list)); 02863 02864 cl->orginator=orig; 02865 cl->need_queue_hangup=1; 02866 cl->need_hangup=1; 02867 cl->need_busy=1; 02868 cl->overlap_dial_task=-1; 02869 02870 return cl; 02871 02872 } 02873 02874 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause) 02875 02876 { 02877 struct ast_channel *tmp = NULL; 02878 char group[BUFFERSIZE+1]=""; 02879 char buf[128]; 02880 char buf2[128], *ext=NULL, *port_str; 02881 char *tokb=NULL, *p=NULL; 02882 int channel=0, port=0; 02883 struct misdn_bchannel *newbc = NULL; 02884 02885 struct chan_list *cl=init_chan_list(ORG_AST); 02886 02887 sprintf(buf,"%s/%s",misdn_type,(char*)data); 02888 ast_copy_string(buf2,data, 128); 02889 02890 port_str=strtok_r(buf2,"/", &tokb); 02891 02892 ext=strtok_r(NULL,"/", &tokb); 02893 02894 if (port_str) { 02895 if (port_str[0]=='g' && port_str[1]==':' ) { 02896 /* We make a group call lets checkout which ports are in my group */ 02897 port_str += 2; 02898 strncpy(group, port_str, BUFFERSIZE); 02899 group[127] = 0; 02900 chan_misdn_log(2, 0, " --> Group Call group: %s\n",group); 02901 } 02902 else if ((p = strchr(port_str, ':'))) { 02903 /* we have a preselected channel */ 02904 *p = 0; 02905 channel = atoi(++p); 02906 port = atoi(port_str); 02907 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel); 02908 } 02909 else { 02910 port = atoi(port_str); 02911 } 02912 02913 02914 } else { 02915 ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext); 02916 return NULL; 02917 } 02918 02919 if (!ast_strlen_zero(group)) { 02920 02921 char cfg_group[BUFFERSIZE+1]; 02922 struct robin_list *rr = NULL; 02923 02924 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) { 02925 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN..."); 02926 rr = get_robin_position(group); 02927 } 02928 02929 if (rr) { 02930 int robin_channel = rr->channel; 02931 int port_start; 02932 int next_chan = 1; 02933 02934 do { 02935 port_start = 0; 02936 for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start; 02937 port = misdn_cfg_get_next_port_spin(port)) { 02938 02939 if (!port_start) 02940 port_start = port; 02941 02942 if (port >= port_start) 02943 next_chan = 1; 02944 02945 if (port <= port_start && next_chan) { 02946 int maxbchans=misdn_lib_get_maxchans(port); 02947 if (++robin_channel >= maxbchans) { 02948 robin_channel = 1; 02949 } 02950 next_chan = 0; 02951 } 02952 02953 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE); 02954 02955 if (!strcasecmp(cfg_group, group)) { 02956 int port_up; 02957 int check; 02958 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int)); 02959 port_up = misdn_lib_port_up(port, check); 02960 02961 if (check && !port_up) 02962 chan_misdn_log(1,port,"L1 is not Up on this Port\n"); 02963 02964 if (check && port_up<0) { 02965 ast_log(LOG_WARNING,"This port (%d) is blocked\n", port); 02966 } 02967 02968 02969 if ( port_up>0 ) { 02970 newbc = misdn_lib_get_free_bc(port, robin_channel,0); 02971 if (newbc) { 02972 chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel); 02973 if (port_up) 02974 chan_misdn_log(4, port, "portup:%d\n", port_up); 02975 rr->port = newbc->port; 02976 rr->channel = newbc->channel; 02977 break; 02978 } 02979 } 02980 } 02981 } 02982 } while (!newbc && robin_channel != rr->channel); 02983 02984 if (!newbc) 02985 chan_misdn_log(-1, port, " Failed! No free channel in group %d!", group); 02986 } 02987 02988 else { 02989 for (port=misdn_cfg_get_next_port(0); port > 0; 02990 port=misdn_cfg_get_next_port(port)) { 02991 02992 misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE); 02993 02994 chan_misdn_log(3,port, "Group [%s] Port [%d]\n", group, port); 02995 if (!strcasecmp(cfg_group, group)) { 02996 int port_up; 02997 int check; 02998 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int)); 02999 port_up = misdn_lib_port_up(port, check); 03000 03001 chan_misdn_log(4, port, "portup:%d\n", port_up); 03002 03003 if ( port_up>0 ) { 03004 newbc = misdn_lib_get_free_bc(port, 0, 0); 03005 if (newbc) 03006 break; 03007 } 03008 } 03009 } 03010 } 03011 03012 } else { 03013 if (channel) 03014 chan_misdn_log(1, port," --> preselected_channel: %d\n",channel); 03015 newbc = misdn_lib_get_free_bc(port, channel, 0); 03016 } 03017 03018 if (!newbc) { 03019 chan_misdn_log(-1, 0, "Could not create channel on port:%d with extensions:%s\n",port,ext); 03020 return NULL; 03021 } 03022 03023 /* create ast_channel and link all the objects together */ 03024 cl->bc=newbc; 03025 03026 tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel); 03027 cl->ast=tmp; 03028 03029 /* register chan in local list */ 03030 cl_queue_chan(&cl_te, cl) ; 03031 03032 /* fill in the config into the objects */ 03033 read_config(cl, ORG_AST); 03034 03035 /* important */ 03036 cl->need_hangup=0; 03037 03038 return tmp; 03039 } 03040 03041 03042 static int misdn_send_text (struct ast_channel *chan, const char *text) 03043 { 03044 struct chan_list *tmp=chan->tech_pvt; 03045 03046 if (tmp && tmp->bc) { 03047 ast_copy_string(tmp->bc->display,text,sizeof(tmp->bc->display)); 03048 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION); 03049 } else { 03050 ast_log(LOG_WARNING, "No chan_list but send_text request?\n"); 03051 return -1; 03052 } 03053 03054 return 0; 03055 } 03056 03057 static struct ast_channel_tech misdn_tech = { 03058 .type="mISDN", 03059 .description="Channel driver for mISDN Support (Bri/Pri)", 03060 .capabilities= AST_FORMAT_ALAW , 03061 .requester=misdn_request, 03062 .send_digit_begin=misdn_digit_begin, 03063 .send_digit_end=misdn_digit_end, 03064 .call=misdn_call, 03065 .bridge=misdn_bridge, 03066 .hangup=misdn_hangup, 03067 .answer=misdn_answer, 03068 .read=misdn_read, 03069 .write=misdn_write, 03070 .indicate=misdn_indication, 03071 .fixup=misdn_fixup, 03072 .send_text=misdn_send_text, 03073 .properties=0 03074 }; 03075 03076 static struct ast_channel_tech misdn_tech_wo_bridge = { 03077 .type="mISDN", 03078 .description="Channel driver for mISDN Support (Bri/Pri)", 03079 .capabilities=AST_FORMAT_ALAW , 03080 .requester=misdn_request, 03081 .send_digit_begin=misdn_digit_begin, 03082 .send_digit_end=misdn_digit_end, 03083 .call=misdn_call, 03084 .hangup=misdn_hangup, 03085 .answer=misdn_answer, 03086 .read=misdn_read, 03087 .write=misdn_write, 03088 .indicate=misdn_indication, 03089 .fixup=misdn_fixup, 03090 .send_text=misdn_send_text, 03091 .properties=0 03092 }; 03093 03094 03095 static int glob_channel=0; 03096 03097 static void update_name(struct ast_channel *tmp, int port, int c) 03098 { 03099 int chan_offset=0; 03100 int tmp_port = misdn_cfg_get_next_port(0); 03101 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) { 03102 if (tmp_port == port) break; 03103 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2; 03104 } 03105 if (c<0) c=0; 03106 03107 ast_string_field_build(tmp, name, "%s/%d-u%d", 03108 misdn_type, chan_offset+c, glob_channel++); 03109 03110 chan_misdn_log(3,port," --> updating channel name to [%s]\n",tmp->name); 03111 03112 } 03113 03114 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, int format, int port, int c) 03115 { 03116 struct ast_channel *tmp; 03117 char *cid_name = 0, *cid_num = 0; 03118 int chan_offset=0; 03119 int tmp_port = misdn_cfg_get_next_port(0); 03120 03121 for (; tmp_port > 0; tmp_port=misdn_cfg_get_next_port(tmp_port)) { 03122 if (tmp_port == port) break; 03123 chan_offset+=misdn_lib_port_is_pri(tmp_port)?30:2; 03124 } 03125 if (c<0) c=0; 03126 03127 03128 if (callerid) 03129 ast_callerid_parse(callerid, &cid_name, &cid_num); 03130 03131 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++); 03132 03133 if (tmp) { 03134 chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n",exten,callerid); 03135 03136 tmp->nativeformats = prefformat; 03137 03138 tmp->readformat = format; 03139 tmp->rawreadformat = format; 03140 tmp->writeformat = format; 03141 tmp->rawwriteformat = format; 03142 03143 tmp->tech_pvt = chlist; 03144 03145 int bridging; 03146 misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int)); 03147 if (bridging) 03148 tmp->tech = &misdn_tech; 03149 else 03150 tmp->tech = &misdn_tech_wo_bridge; 03151 03152 tmp->writeformat = format; 03153 tmp->readformat = format; 03154 tmp->priority=1; 03155 03156 if (exten) 03157 ast_copy_string(tmp->exten, exten, sizeof(tmp->exten)); 03158 else 03159 chan_misdn_log(1,0,"misdn_new: no exten given.\n"); 03160 03161 if (callerid) { 03162 char *cid_name, *cid_num; 03163 03164 ast_callerid_parse(callerid, &cid_name, &cid_num); 03165 /* Don't use ast_set_callerid() here because it will 03166 * generate a needless NewCallerID event */ 03167 tmp->cid.cid_num = ast_strdup(cid_num); 03168 tmp->cid.cid_ani = ast_strdup(cid_num); 03169 tmp->cid.cid_name = ast_strdup(cid_name); 03170 } 03171 03172 { 03173 if (pipe(chlist->pipe)<0) 03174 perror("Pipe failed\n"); 03175 03176 tmp->fds[0]=chlist->pipe[0]; 03177 03178 } 03179 03180 if (state == AST_STATE_RING) 03181 tmp->rings = 1; 03182 else 03183 tmp->rings = 0; 03184 03185 03186 } else { 03187 chan_misdn_log(-1,0,"Unable to allocate channel structure\n"); 03188 } 03189 03190 return tmp; 03191 } 03192 03193 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc) 03194 { 03195 struct chan_list *help=list; 03196 for (;help; help=help->next) { 03197 if (help->bc == bc) return help; 03198 } 03199 03200 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad); 03201 03202 return NULL; 03203 } 03204 03205 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid) 03206 { 03207 struct chan_list *help=list; 03208 for (;help; help=help->next) { 03209 if ( help->bc && (help->bc->pid == pid) ) return help; 03210 } 03211 03212 chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n",pid); 03213 03214 return NULL; 03215 } 03216 03217 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc) 03218 { 03219 struct chan_list *help=list; 03220 03221 chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad); 03222 for (;help; help=help->next) { 03223 chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->state==MISDN_HOLDED, help->hold_info.channel); 03224 if ( (help->state == MISDN_HOLDED) && 03225 (help->hold_info.port == bc->port) ) 03226 return help; 03227 } 03228 chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad); 03229 03230 return NULL; 03231 } 03232 03233 03234 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w) 03235 03236 { 03237 struct chan_list *help=list; 03238 03239 for (;help; help=help->next) { 03240 if ( (help->state == MISDN_HOLDED) && 03241 (help->l3id == l3_id) 03242 ) 03243 return help; 03244 } 03245 03246 return NULL; 03247 } 03248 03249 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan) 03250 { 03251 chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan); 03252 03253 ast_mutex_lock(&cl_te_lock); 03254 if (!*list) { 03255 *list = chan; 03256 } else { 03257 struct chan_list *help=*list; 03258 for (;help->next; help=help->next); 03259 help->next=chan; 03260 } 03261 chan->next=NULL; 03262 ast_mutex_unlock(&cl_te_lock); 03263 } 03264 03265 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 03266 { 03267 if (chan->dsp) 03268 ast_dsp_free(chan->dsp); 03269 if (chan->trans) 03270 ast_translator_free_path(chan->trans); 03271 03272 03273 03274 ast_mutex_lock(&cl_te_lock); 03275 if (!*list) { 03276 ast_mutex_unlock(&cl_te_lock); 03277 return; 03278 } 03279 03280 if (*list == chan) { 03281 *list=(*list)->next; 03282 ast_mutex_unlock(&cl_te_lock); 03283 return ; 03284 } 03285 03286 { 03287 struct chan_list *help=*list; 03288 for (;help->next; help=help->next) { 03289 if (help->next == chan) { 03290 help->next=help->next->next; 03291 ast_mutex_unlock(&cl_te_lock); 03292 return; 03293 } 03294 } 03295 } 03296 03297 ast_mutex_unlock(&cl_te_lock); 03298 } 03299 03300 /** Channel Queue End **/ 03301 03302 03303 int pbx_start_chan(struct chan_list *ch) 03304 { 03305 int ret=ast_pbx_start(ch->ast); 03306 03307 if (ret>=0) 03308 ch->need_hangup=0; 03309 else 03310 ch->need_hangup=1; 03311 03312 return ret; 03313 } 03314 03315 static void hangup_chan(struct chan_list *ch) 03316 { 03317 int port=ch?ch->bc?ch->bc->port:0:0; 03318 if (!ch) { 03319 cb_log(1,0,"Cannot hangup chan, no ch\n"); 03320 return; 03321 } 03322 03323 cb_log(5,port,"hangup_chan called\n"); 03324 03325 if (ch->need_hangup) 03326 { 03327 cb_log(2,port," --> hangup\n"); 03328 send_cause2ast(ch->ast,ch->bc,ch); 03329 ch->need_hangup=0; 03330 ch->need_queue_hangup=0; 03331 if (ch->ast) 03332 ast_hangup(ch->ast); 03333 return; 03334 } 03335 03336 if (!ch->need_queue_hangup) { 03337 cb_log(2,port," --> No need to queue hangup\n"); 03338 } 03339 03340 ch->need_queue_hangup=0; 03341 if (ch->ast) { 03342 send_cause2ast(ch->ast,ch->bc,ch); 03343 03344 if (ch->ast) 03345 ast_queue_hangup(ch->ast); 03346 cb_log(2,port," --> queue_hangup\n"); 03347 } else { 03348 cb_log(1,port,"Cannot hangup chan, no ast\n"); 03349 } 03350 } 03351 03352 /** Isdn asks us to release channel, pendant to misdn_hangup **/ 03353 static void release_chan(struct misdn_bchannel *bc) { 03354 struct ast_channel *ast=NULL; 03355 { 03356 struct chan_list *ch=find_chan_by_bc(cl_te, bc); 03357 if (!ch) { 03358 chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n"); 03359 return; 03360 } 03361 03362 if (ch->ast) { 03363 ast=ch->ast; 03364 } 03365 03366 chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n",bc->l3_id); 03367 03368 /*releaseing jitterbuffer*/ 03369 if (ch->jb ) { 03370 misdn_jb_destroy(ch->jb); 03371 ch->jb=NULL; 03372 } else { 03373 if (!bc->nojitter) 03374 chan_misdn_log(5,bc->port,"Jitterbuffer already destroyed.\n"); 03375 } 03376 03377 if (ch->overlap_dial) { 03378 if (ch->overlap_dial_task != -1) { 03379 misdn_tasks_remove(ch->overlap_dial_task); 03380 ch->overlap_dial_task = -1; 03381 } 03382 ast_mutex_destroy(&ch->overlap_tv_lock); 03383 } 03384 03385 if (ch->orginator == ORG_AST) { 03386 misdn_out_calls[bc->port]--; 03387 } else { 03388 misdn_in_calls[bc->port]--; 03389 } 03390 03391 if (ch) { 03392 03393 close(ch->pipe[0]); 03394 close(ch->pipe[1]); 03395 03396 03397 if (ast && MISDN_ASTERISK_TECH_PVT(ast)) { 03398 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_P(ast),misdn_get_ch_state(ch)); 03399 chan_misdn_log(3, bc->port, " --> * State Down\n"); 03400 MISDN_ASTERISK_TECH_PVT(ast)=NULL; 03401 03402 03403 if (ast->_state != AST_STATE_RESERVED) { 03404 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n"); 03405 ast_setstate(ast, AST_STATE_DOWN); 03406 } 03407 } 03408 03409 ch->state=MISDN_CLEANING; 03410 cl_dequeue_chan(&cl_te, ch); 03411 03412 free(ch); 03413 } else { 03414 /* chan is already cleaned, so exiting */ 03415 } 03416 } 03417 } 03418 /*** release end **/ 03419 03420 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan) 03421 { 03422 chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name); 03423 03424 tmp_ch->state=MISDN_HOLD_DISCONNECT; 03425 03426 ast_moh_stop(AST_BRIDGED_P(holded_chan->ast)); 03427 03428 holded_chan->state=MISDN_CONNECTED; 03429 //misdn_lib_transfer(holded_chan->bc); 03430 ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast)); 03431 } 03432 03433 03434 static void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast) 03435 { 03436 char predial[256]=""; 03437 char *p = predial; 03438 03439 struct ast_frame fr; 03440 03441 strncpy(predial, ast->exten, sizeof(predial) -1 ); 03442 03443 ch->state=MISDN_DIALING; 03444 03445 if (bc->nt) { 03446 int ret; 03447 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); 03448 } else { 03449 int ret; 03450 if ( misdn_lib_is_ptp(bc->port)) { 03451 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); 03452 } else { 03453 ret = misdn_lib_send_event(bc, EVENT_PROCEEDING ); 03454 } 03455 } 03456 03457 if ( !bc->nt && (ch->orginator==ORG_MISDN) && !ch->incoming_early_audio ) 03458 chan_misdn_log(1,bc->port, " --> incoming_early_audio off\n"); 03459 else 03460 dialtone_indicate(ch); 03461 03462 chan_misdn_log(1, bc->port, "* Starting Ast ctx:%s dad:%s oad:%s with 's' extension\n", ast->context, ast->exten, AST_CID_P(ast)); 03463 03464 strncpy(ast->exten,"s", 2); 03465 03466 if (pbx_start_chan(ch)<0) { 03467 ast=NULL; 03468 hangup_chan(ch); 03469 hanguptone_indicate(ch); 03470 03471 if (bc->nt) 03472 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); 03473 else 03474 misdn_lib_send_event(bc, EVENT_DISCONNECT ); 03475 } 03476 03477 03478 while (!ast_strlen_zero(p) ) { 03479 fr.frametype = AST_FRAME_DTMF; 03480 fr.subclass = *p ; 03481 fr.src=NULL; 03482 fr.data = NULL ; 03483 fr.datalen = 0; 03484 fr.samples = 0 ; 03485 fr.mallocd =0 ; 03486 fr.offset= 0 ; 03487 fr.delivery= ast_tv(0,0) ; 03488 03489 if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) { 03490 ast_queue_frame(ch->ast, &fr); 03491 } 03492 p++; 03493 } 03494 } 03495 03496 03497 03498 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc, struct chan_list *ch) { 03499 if (!ast) { 03500 chan_misdn_log(1,0,"send_cause2ast: No Ast\n"); 03501 return; 03502 } 03503 if (!bc) { 03504 chan_misdn_log(1,0,"send_cause2ast: No BC\n"); 03505 return; 03506 } 03507 if (!ch) { 03508 chan_misdn_log(1,0,"send_cause2ast: No Ch\n"); 03509 return; 03510 } 03511 03512 ast->hangupcause=bc->cause; 03513 03514 switch ( bc->cause) { 03515 03516 case 1: /** Congestion Cases **/ 03517 case 2: 03518 case 3: 03519 case 4: 03520 case 22: 03521 case 27: 03522 /* 03523 * Not Queueing the Congestion anymore, since we want to hear 03524 * the inband message 03525 * 03526 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1); 03527 ch->state=MISDN_BUSY; 03528 03529 ast_queue_control(ast, AST_CONTROL_CONGESTION); 03530 */ 03531 break; 03532 03533 case 21: 03534 case 17: /* user busy */ 03535 03536 ch->state=MISDN_BUSY; 03537 03538 if (!ch->need_busy) { 03539 chan_misdn_log(1,bc?bc->port:0, "Queued busy already\n"); 03540 break; 03541 } 03542 03543 chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1); 03544 03545 ast_queue_control(ast, AST_CONTROL_BUSY); 03546 03547 ch->need_busy=0; 03548 03549 break; 03550 } 03551 } 03552 03553 03554 03555 03556 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch) 03557 { 03558 const char *tmp; 03559 tmp=pbx_builtin_getvar_helper(chan,"MISDN_PID"); 03560 if (tmp) { 03561 ch->other_pid=atoi(tmp); 03562 chan_misdn_log(3,bc->port," --> IMPORT_PID: importing pid:%s\n",tmp); 03563 if (ch->other_pid >0) { 03564 ch->other_ch=find_chan_by_pid(cl_te,ch->other_pid); 03565 if (ch->other_ch) ch->other_ch->other_ch=ch; 03566 } 03567 } 03568 03569 tmp=pbx_builtin_getvar_helper(chan,"MISDN_ADDRESS_COMPLETE"); 03570 if (tmp && (atoi(tmp) == 1)) { 03571 bc->sending_complete=1; 03572 } 03573 } 03574 03575 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch) 03576 { 03577 char tmp[32]; 03578 chan_misdn_log(3,bc->port," --> EXPORT_PID: pid:%d\n",bc->pid); 03579 sprintf(tmp,"%d",bc->pid); 03580 pbx_builtin_setvar_helper(chan,"_MISDN_PID",tmp); 03581 03582 if (bc->sending_complete) { 03583 sprintf(tmp,"%d",bc->sending_complete); 03584 pbx_builtin_setvar_helper(chan,"MISDN_ADDRESS_COMPLETE",tmp); 03585 } 03586 03587 if (bc->urate) { 03588 sprintf(tmp,"%d",bc->urate); 03589 pbx_builtin_setvar_helper(chan,"MISDN_URATE",tmp); 03590 } 03591 } 03592 03593 int add_in_calls(int port) 03594 { 03595 int max_in_calls; 03596 03597 misdn_cfg_get( port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls)); 03598 03599 misdn_in_calls[port]++; 03600 03601 if (max_in_calls >=0 && max_in_calls<misdn_in_calls[port]) { 03602 ast_log(LOG_NOTICE,"Marking Incoming Call on port[%d]\n",port); 03603 return misdn_in_calls[port]-max_in_calls; 03604 } 03605 03606 return 0; 03607 } 03608 03609 int add_out_calls(int port) 03610 { 03611 int max_out_calls; 03612 03613 misdn_cfg_get( port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls)); 03614 03615 03616 if (max_out_calls >=0 && max_out_calls<=misdn_out_calls[port]) { 03617 ast_log(LOG_NOTICE,"Rejecting Outgoing Call on port[%d]\n",port); 03618 return (misdn_out_calls[port]+1)-max_out_calls; 03619 } 03620 03621 misdn_out_calls[port]++; 03622 03623 return 0; 03624 } 03625 03626 03627 03628 /************************************************************/ 03629 /* Receive Events from isdn_lib here */ 03630 /************************************************************/ 03631 static enum event_response_e 03632 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data) 03633 { 03634 struct chan_list *ch=find_chan_by_bc(cl_te, bc); 03635 03636 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /* Debug Only Non-Bchan */ 03637 int debuglevel=1; 03638 if ( event==EVENT_CLEANUP && !user_data) 03639 debuglevel=5; 03640 03641 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"); 03642 if (debuglevel==1) { 03643 misdn_lib_log_ies(bc); 03644 chan_misdn_log(4,bc->port," --> bc_state:%s\n",bc_state2str(bc->bc_state)); 03645 } 03646 } 03647 03648 if (!ch) { 03649 switch(event) { 03650 case EVENT_SETUP: 03651 case EVENT_DISCONNECT: 03652 case EVENT_PORT_ALARM: 03653 case EVENT_RETRIEVE: 03654 case EVENT_NEW_BC: 03655 case EVENT_FACILITY: 03656 break; 03657 case EVENT_RELEASE_COMPLETE: 03658 chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n"); 03659 break; 03660 case EVENT_CLEANUP: 03661 case EVENT_TONE_GENERATE: 03662 case EVENT_BCHAN_DATA: 03663 return -1; 03664 03665 default: 03666 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); 03667 return -1; 03668 } 03669 } 03670 03671 if (ch ) { 03672 switch (event) { 03673 case EVENT_TONE_GENERATE: 03674 break; 03675 case EVENT_DISCONNECT: 03676 case EVENT_RELEASE: 03677 case EVENT_RELEASE_COMPLETE: 03678 case EVENT_CLEANUP: 03679 case EVENT_TIMEOUT: 03680 if (!ch->ast) 03681 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)); 03682 break; 03683 default: 03684 if ( !ch->ast || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) { 03685 if (event!=EVENT_BCHAN_DATA) 03686 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event)); 03687 return -1; 03688 } 03689 } 03690 } 03691 03692 03693 switch (event) { 03694 case EVENT_PORT_ALARM: 03695 { 03696 int boa=0; 03697 misdn_cfg_get( bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int)); 03698 if (boa) { 03699 cb_log(1,bc->port," --> blocking\n"); 03700 misdn_lib_port_block(bc->port); 03701 } 03702 } 03703 break; 03704 case EVENT_BCHAN_ACTIVATED: 03705 break; 03706 03707 case EVENT_NEW_CHANNEL: 03708 update_name(ch->ast,bc->port,bc->channel); 03709 break; 03710 03711 case EVENT_NEW_L3ID: 03712 ch->l3id=bc->l3_id; 03713 ch->addr=bc->addr; 03714 break; 03715 03716 case EVENT_NEW_BC: 03717 if (!ch) { 03718 ch=find_holded(cl_te,bc); 03719 } 03720 03721 if (!ch) { 03722 ast_log(LOG_WARNING,"NEW_BC without chan_list?\n"); 03723 break; 03724 } 03725 03726 if (bc) 03727 ch->bc=(struct misdn_bchannel*)user_data; 03728 break; 03729 03730 case EVENT_DTMF_TONE: 03731 { 03732 /* sending INFOS as DTMF-Frames :) */ 03733 struct ast_frame fr; 03734 memset(&fr, 0 , sizeof(fr)); 03735 fr.frametype = AST_FRAME_DTMF; 03736 fr.subclass = bc->dtmf ; 03737 fr.src=NULL; 03738 fr.data = NULL ; 03739 fr.datalen = 0; 03740 fr.samples = 0 ; 03741 fr.mallocd =0 ; 03742 fr.offset= 0 ; 03743 fr.delivery= ast_tv(0,0) ; 03744 03745 if (!ch->ignore_dtmf) { 03746 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf); 03747 ast_queue_frame(ch->ast, &fr); 03748 } else { 03749 chan_misdn_log(2, bc->port, " --> Ingoring DTMF:%c due to bridge flags\n", bc->dtmf); 03750 } 03751 } 03752 break; 03753 case EVENT_STATUS: 03754 break; 03755 03756 case EVENT_INFORMATION: 03757 { 03758 int stop_tone; 03759 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int)); 03760 if ( stop_tone ) { 03761 stop_indicate(ch); 03762 } 03763 03764 if (ch->state == MISDN_WAITING4DIGS ) { 03765 /* Ok, incomplete Setup, waiting till extension exists */ 03766 03767 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) { 03768 chan_misdn_log(1, bc->port, " --> using keypad as info\n"); 03769 strcpy(bc->info_dad,bc->keypad); 03770 } 03771 03772 { 03773 int l = sizeof(bc->dad); 03774 strncat(bc->dad,bc->info_dad, l); 03775 bc->dad[l-1] = 0; 03776 } 03777 03778 03779 { 03780 int l = sizeof(ch->ast->exten); 03781 strncpy(ch->ast->exten, bc->dad, l); 03782 ch->ast->exten[l-1] = 0; 03783 } 03784 /* chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/ 03785 03786 /* Check for Pickup Request first */ 03787 if (!strcmp(ch->ast->exten, ast_pickup_ext())) { 03788 int ret;/** Sending SETUP_ACK**/ 03789 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); 03790 if (ast_pickup_call(ch->ast)) { 03791 hangup_chan(ch); 03792 } else { 03793 struct ast_channel *chan=ch->ast; 03794 ch->state = MISDN_CALLING_ACKNOWLEDGE; 03795 ast_setstate(chan, AST_STATE_DOWN); 03796 hangup_chan(ch); 03797 ch->ast=NULL; 03798 break; 03799 } 03800 } 03801 03802 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { 03803 03804 chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n"); 03805 if (bc->nt) 03806 hanguptone_indicate(ch); 03807 ch->state=MISDN_EXTCANTMATCH; 03808 bc->out_cause=1; 03809 03810 misdn_lib_send_event(bc, EVENT_DISCONNECT ); 03811 03812 break; 03813 } 03814 03815 if (ch->overlap_dial) { 03816 ast_mutex_lock(&ch->overlap_tv_lock); 03817 ch->overlap_tv = ast_tvnow(); 03818 ast_mutex_unlock(&ch->overlap_tv_lock); 03819 if (ch->overlap_dial_task == -1) { 03820 ch->overlap_dial_task = 03821 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch); 03822 } 03823 break; 03824 } 03825 03826 if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { 03827 ch->state=MISDN_DIALING; 03828 03829 stop_indicate(ch); 03830 /* chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->context);*/ 03831 if (pbx_start_chan(ch)<0) { 03832 hangup_chan(ch); 03833 03834 chan_misdn_log(-1, bc->port, "ast_pbx_start returned < 0 in INFO\n"); 03835 if (bc->nt) hanguptone_indicate(ch); 03836 03837 misdn_lib_send_event(bc, EVENT_DISCONNECT ); 03838 } 03839 } 03840 03841 } else { 03842 /* sending INFOS as DTMF-Frames :) */ 03843 struct ast_frame fr; 03844 fr.frametype = AST_FRAME_DTMF; 03845 fr.subclass = bc->info_dad[0] ; 03846 fr.src=NULL; 03847 fr.data = NULL ; 03848 fr.datalen = 0; 03849 fr.samples = 0 ; 03850 fr.mallocd =0 ; 03851 fr.offset= 0 ; 03852 fr.delivery= ast_tv(0,0) ; 03853 03854 03855 int digits; 03856 misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int)); 03857 if (ch->state != MISDN_CONNECTED ) { 03858 if (digits) { 03859 int l = sizeof(bc->dad); 03860 strncat(bc->dad,bc->info_dad, l); 03861 bc->dad[l-1] = 0; 03862 l = sizeof(ch->ast->exten); 03863 strncpy(ch->ast->exten, bc->dad, l); 03864 ch->ast->exten[l-1] = 0; 03865 03866 ast_cdr_update(ch->ast); 03867 } 03868 03869 ast_queue_frame(ch->ast, &fr); 03870 } 03871 } 03872 } 03873 break; 03874 case EVENT_SETUP: 03875 { 03876 struct chan_list *ch=find_chan_by_bc(cl_te, bc); 03877 if (ch) { 03878 switch (ch->state) { 03879 case MISDN_NOTHING: 03880 ch=NULL; 03881 break; 03882 default: 03883 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n"); 03884 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /* Ignore MSNs which are not in our List */ 03885 } 03886 } 03887 } 03888 03889 03890 int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad); 03891 if (!bc->nt && ! msn_valid) { 03892 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n"); 03893 return RESPONSE_IGNORE_SETUP; /* Ignore MSNs which are not in our List */ 03894 } 03895 03896 03897 if (bc->cw) { 03898 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n"); 03899 int cause; 03900 misdn_cfg_get( bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause)); 03901 bc->out_cause=cause?cause:16; 03902 return RESPONSE_RELEASE_SETUP; 03903 } 03904 03905 print_bearer(bc); 03906 03907 { 03908 struct chan_list *ch=init_chan_list(ORG_MISDN); 03909 struct ast_channel *chan; 03910 int exceed; 03911 03912 if (!ch) { chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;} 03913 03914 ch->bc = bc; 03915 ch->l3id=bc->l3_id; 03916 ch->addr=bc->addr; 03917 ch->orginator = ORG_MISDN; 03918 03919 chan=misdn_new(ch, AST_STATE_RESERVED,bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel); 03920 ch->ast = chan; 03921 03922 if ((exceed=add_in_calls(bc->port))) { 03923 char tmp[16]; 03924 sprintf(tmp,"%d",exceed); 03925 pbx_builtin_setvar_helper(chan,"MAX_OVERFLOW",tmp); 03926 } 03927 03928 read_config(ch, ORG_MISDN); 03929 03930 export_ch(chan, bc, ch); 03931 03932 ch->ast->rings=1; 03933 ast_setstate(ch->ast, AST_STATE_RINGING); 03934 03935 int pres,screen; 03936 03937 switch (bc->pres) { 03938 case 1: 03939 pres=AST_PRES_RESTRICTED; chan_misdn_log(2,bc->port," --> PRES: Restricted (1)\n"); 03940 break; 03941 case 2: 03942 pres=AST_PRES_UNAVAILABLE; chan_misdn_log(2,bc->port," --> PRES: Restricted (2)\n"); 03943 break; 03944 default: 03945 pres=AST_PRES_ALLOWED; chan_misdn_log(2,bc->port," --> PRES: Restricted (%d)\n", bc->pres); 03946 } 03947 03948 switch (bc->screen) { 03949 case 0: 03950 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (0)\n"); 03951 break; 03952 case 1: 03953 screen=AST_PRES_USER_NUMBER_PASSED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: Passed screen (1)\n"); 03954 break; 03955 case 2: 03956 screen=AST_PRES_USER_NUMBER_FAILED_SCREEN; chan_misdn_log(2,bc->port," --> SCREEN: failed screen (2)\n"); 03957 break; 03958 case 3: 03959 screen=AST_PRES_NETWORK_NUMBER; chan_misdn_log(2,bc->port," --> SCREEN: Network Number (3)\n"); 03960 break; 03961 default: 03962 screen=AST_PRES_USER_NUMBER_UNSCREENED; chan_misdn_log(2,bc->port," --> SCREEN: Unscreened (%d)\n",bc->screen); 03963 } 03964 03965 chan->cid.cid_pres=pres+screen; 03966 03967 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability)); 03968 chan->transfercapability=bc->capability; 03969 03970 switch (bc->capability) { 03971 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: 03972 pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL"); 03973 break; 03974 default: 03975 pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH"); 03976 } 03977 03978 /** queue new chan **/ 03979 cl_queue_chan(&cl_te, ch) ; 03980 03981 03982 if (!strstr(ch->allowed_bearers,"all")) { 03983 int i; 03984 for (i=0; i< sizeof(allowed_bearers_array)/sizeof(struct allowed_bearers); i++) { 03985 if (allowed_bearers_array[i].cap == bc->capability) { 03986 if ( !strstr( ch->allowed_bearers, allowed_bearers_array[i].name)) { 03987 chan_misdn_log(0,bc->port,"Bearer Not allowed\b"); 03988 bc->out_cause=88; 03989 03990 ch->state=MISDN_EXTCANTMATCH; 03991 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); 03992 return RESPONSE_OK; 03993 } 03994 } 03995 03996 } 03997 } 03998 03999 /* Check for Pickup Request first */ 04000 if (!strcmp(chan->exten, ast_pickup_ext())) { 04001 int ret;/** Sending SETUP_ACK**/ 04002 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); 04003 if (ast_pickup_call(chan)) { 04004 hangup_chan(ch); 04005 } else { 04006 ch->state = MISDN_CALLING_ACKNOWLEDGE; 04007 ast_setstate(chan, AST_STATE_DOWN); 04008 hangup_chan(ch); 04009 ch->ast=NULL; 04010 break; 04011 } 04012 } 04013 04014 /* 04015 added support for s extension hope it will help those poor cretains 04016 which haven't overlap dial. 04017 */ 04018 { 04019 int ai; 04020 misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai)); 04021 if ( ai ) { 04022 do_immediate_setup(bc, ch , chan); 04023 break; 04024 } 04025 04026 04027 04028 } 04029 04030 /* check if we should jump into s when we have no dad */ 04031 { 04032 int im; 04033 misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im)); 04034 if ( im && ast_strlen_zero(bc->dad) ) { 04035 do_immediate_setup(bc, ch , chan); 04036 break; 04037 } 04038 } 04039 04040 04041 chan_misdn_log(5,bc->port,"CONTEXT:%s\n",ch->context); 04042 if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { 04043 04044 chan_misdn_log(-1, bc->port, "Extension can never match, so disconnecting\n"); 04045 04046 if (bc->nt) 04047 hanguptone_indicate(ch); 04048 ch->state=MISDN_EXTCANTMATCH; 04049 bc->out_cause=1; 04050 04051 if (bc->nt) 04052 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); 04053 else 04054 misdn_lib_send_event(bc, EVENT_RELEASE ); 04055 04056 break; 04057 } 04058 04059 if (!ch->overlap_dial && ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) { 04060 ch->state=MISDN_DIALING; 04061 04062 if (bc->nt || (bc->need_more_infos && misdn_lib_is_ptp(bc->port)) ) { 04063 int ret; 04064 ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); 04065 } else { 04066 int ret; 04067 ret= misdn_lib_send_event(bc, EVENT_PROCEEDING ); 04068 } 04069 04070 if (pbx_start_chan(ch)<0) { 04071 hangup_chan(ch); 04072 04073 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n"); 04074 chan=NULL; 04075 04076 if (bc->nt) { 04077 hanguptone_indicate(ch); 04078 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE ); 04079 } else 04080 misdn_lib_send_event(bc, EVENT_RELEASE); 04081 } 04082 } else { 04083 04084 if (bc->sending_complete) { 04085 ch->state=MISDN_EXTCANTMATCH; 04086 bc->out_cause=1; 04087 04088 if (bc->nt) { 04089 chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n"); 04090 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE); 04091 } else { 04092 chan_misdn_log(0,bc->port," --> sending_complete so we never match ..\n"); 04093 misdn_lib_send_event(bc, EVENT_RELEASE); 04094 } 04095 04096 } else { 04097 04098 int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE ); 04099 if (ret == -ENOCHAN) { 04100 ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n"); 04101 misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE); 04102 } 04103 /* send tone to phone :) */ 04104 04105 /** ADD IGNOREPAT **/ 04106 04107 int stop_tone, dad_len; 04108 misdn_cfg_get( 0, MISDN_GEN_STOP_TONE,