Sat Nov 25 00:45:33 2006

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

Generated on Sat Nov 25 00:45:33 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6