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

Generated on Sat Sep 16 07:28:07 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7