Wed Oct 28 15:47:51 2009

Asterisk developer's documentation


chan_misdn.c

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

Generated on Wed Oct 28 15:47:51 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6