Sun Aug 6 15:02:32 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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 ast_mutex_t release_lock_mutex;
00066 
00067 #define release_lock ast_mutex_lock(&release_lock_mutex)
00068 #define release_unlock ast_mutex_unlock(&release_lock_mutex)
00069 
00070 
00071 /* BEGIN: chan_misdn.h */
00072 
00073 enum misdn_chan_state {
00074    MISDN_NOTHING,    /*!< at beginning */
00075    MISDN_WAITING4DIGS, /*!<  when waiting for infos */
00076    MISDN_EXTCANTMATCH, /*!<  when asterisk couldnt match our ext */
00077    MISDN_DIALING, /*!<  when pbx_start */
00078    MISDN_PROGRESS, /*!<  we got a progress */
00079    MISDN_CALLING, /*!<  when misdn_call is called */
00080    MISDN_CALLING_ACKNOWLEDGE, /*!<  when we get SETUP_ACK */
00081    MISDN_ALERTING, /*!<  when Alerting */
00082    MISDN_BUSY, /*!<  when BUSY */
00083    MISDN_CONNECTED, /*!<  when connected */
00084    MISDN_BRIDGED, /*!<  when bridged */
00085    MISDN_CLEANING, /*!< when hangup from * but we were connected before */
00086    MISDN_HUNGUP_FROM_MISDN, /*!< when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
00087    MISDN_HUNGUP_FROM_AST, /*!< when DISCONNECT/RELEASE/REL_COMP came out of */
00088    /* misdn_hangup */
00089    MISDN_HOLDED, /*!< if this chan is holded */
00090    MISDN_HOLD_DISCONNECT /*!< if this chan is holded */
00091   
00092 };
00093 
00094 #define ORG_AST 1
00095 #define ORG_MISDN 2
00096 
00097 struct chan_list {
00098   
00099    ast_mutex_t lock;
00100 
00101    enum misdn_chan_state state;
00102    int holded; 
00103    int orginator;
00104 
00105    int norxtone;
00106    int notxtone; 
00107 
00108    int pipe[2];
00109    char ast_rd_buf[4096];
00110    struct ast_frame frame;
00111 
00112    int faxdetect;
00113    int faxhandled;
00114 
00115    int ast_dsp;
00116    
00117    struct ast_dsp *dsp;
00118    struct ast_trans_pvt *trans;
00119   
00120    struct ast_channel * ast;
00121   
00122    struct misdn_bchannel *bc;
00123    struct misdn_bchannel *holded_bc;
00124 
00125    unsigned int l3id;
00126    int addr;
00127    
00128    struct chan_list *peer;
00129    struct chan_list *next;
00130    struct chan_list *prev;
00131    struct chan_list *first;
00132 };
00133 
00134 struct robin_list {
00135    char *group;
00136    int port;
00137    int channel;
00138    struct robin_list *next;
00139    struct robin_list *prev;
00140 };
00141 static struct robin_list *robin = NULL;
00142 
00143 static inline void free_robin_list_r (struct robin_list *r)
00144 {
00145    if (r) {
00146       if (r->next) free_robin_list_r(r->next);
00147       if (r->group) free(r->group);
00148       free(r);
00149    }
00150 }
00151 
00152 static void free_robin_list ( void )
00153 {
00154    free_robin_list_r(robin);
00155    robin = NULL;
00156 }
00157 
00158 struct robin_list* get_robin_position (char *group) 
00159 {
00160    struct robin_list *iter = robin;
00161    for (; iter; iter = iter->next) {
00162       if (!strcasecmp(iter->group, group))
00163          return iter;
00164    }
00165    struct robin_list *new = (struct robin_list *)calloc(1, sizeof(struct robin_list));
00166    new->group = strndup(group, strlen(group));
00167    new->channel = 1;
00168    if (robin) {
00169       new->next = robin;
00170       robin->prev = new;
00171    }
00172    robin = new;
00173    return robin;
00174 }
00175 
00176 struct ast_channel *misdn_new(struct chan_list *cl, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c);
00177 void send_digit_to_chan(struct chan_list *cl, char digit );
00178 
00179 
00180 #define AST_CID_P(ast) ast->cid.cid_num
00181 #define AST_BRIDGED_P(ast) ast_bridged_channel(ast) 
00182 #define AST_LOAD_CFG ast_config_load
00183 #define AST_DESTROY_CFG ast_config_destroy
00184 
00185 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
00186 #define MISDN_ASTERISK_PVT(ast) 1
00187 #define MISDN_ASTERISK_TYPE(ast) ast->tech->type
00188 
00189 /* END: chan_misdn.h */
00190 
00191 #include <asterisk/strings.h>
00192 
00193 /* #define MISDN_DEBUG 1 */
00194 
00195 static  char *desc = "Channel driver for mISDN Support (Bri/Pri)";
00196 static  char *type = "mISDN";
00197 
00198 int tracing = 0 ;
00199 
00200 static int usecnt=0;
00201 
00202 char **misdn_key_vector=NULL;
00203 int misdn_key_vector_size=0;
00204 
00205 /* Only alaw and mulaw is allowed for now */
00206 static int prefformat =  AST_FORMAT_ALAW ; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
00207 
00208 static ast_mutex_t usecnt_lock; 
00209 
00210 int *misdn_debug;
00211 int *misdn_debug_only;
00212 int max_ports;
00213 
00214 struct chan_list dummy_cl;
00215 
00216 struct chan_list *cl_te=NULL;
00217 ast_mutex_t cl_te_lock;
00218 
00219 enum event_response_e
00220 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
00221 
00222 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc);
00223 
00224 void cl_queue_chan(struct chan_list **list, struct chan_list *chan);
00225 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan);
00226 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc);
00227 void chan_misdn_log(int level, int port, char *tmpl, ...);
00228 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...);
00229 
00230 static int start_bc_tones(struct chan_list *cl);
00231 static int stop_bc_tones(struct chan_list *cl);
00232 static void release_chan(struct misdn_bchannel *bc);
00233 
00234 static int misdn_set_opt_exec(struct ast_channel *chan, void *data);
00235 static int misdn_facility_exec(struct ast_channel *chan, void *data);
00236 
00237 /*************** Helpers *****************/
00238 
00239 static struct chan_list * get_chan_by_ast(struct ast_channel *ast)
00240 {
00241    struct chan_list *tmp;
00242   
00243    for (tmp=cl_te; tmp; tmp = tmp->next) {
00244       if ( tmp->ast == ast ) return tmp;
00245    }
00246   
00247    return NULL;
00248 }
00249 
00250 static struct chan_list * get_chan_by_ast_name(char *name)
00251 {
00252    struct chan_list *tmp;
00253   
00254    for (tmp=cl_te; tmp; tmp = tmp->next) {
00255       if ( tmp->ast  && strcmp(tmp->ast->name,name) == 0) return tmp;
00256    }
00257   
00258    return NULL;
00259 }
00260 
00261 static char* tone2str(struct misdn_bchannel *bc)
00262 {
00263    static struct {
00264       char name[16];
00265       enum tone_e tone;
00266    } *tone, tone_buf[] = {
00267       {"NOTONE",TONE_NONE},
00268       {"DIAL",TONE_DIAL},
00269       {"BUSY",TONE_BUSY},
00270       {"ALERT",TONE_ALERTING},
00271       {"",TONE_NONE}
00272    };
00273   
00274   
00275    for (tone=&tone_buf[0]; tone->name[0]; tone++) {
00276       if (tone->tone == bc->tone) return tone->name;
00277    }
00278    return NULL;
00279 }
00280 
00281 static char *bearer2str(int cap) {
00282    static char *bearers[]={
00283       "Speech",
00284       "Audio 3.1k",
00285       "Unres Digital",
00286       "Res Digital",
00287       "Unknown Bearer"
00288    };
00289    
00290    switch (cap) {
00291    case INFO_CAPABILITY_SPEECH:
00292       return bearers[0];
00293       break;
00294    case INFO_CAPABILITY_AUDIO_3_1K:
00295       return bearers[1];
00296       break;
00297    case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
00298       return bearers[2];
00299       break;
00300    case INFO_CAPABILITY_DIGITAL_RESTRICTED:
00301       return bearers[3];
00302       break;
00303    default:
00304       return bearers[4];
00305       break;
00306    }
00307 }
00308 
00309 static void print_bearer(struct misdn_bchannel *bc) 
00310 {
00311    
00312    chan_misdn_log(2, bc->port, " --> Bearer: %s\n",bearer2str(bc->capability));
00313    
00314    switch(bc->law) {
00315    case INFO_CODEC_ALAW:
00316       chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
00317       break;
00318    case INFO_CODEC_ULAW:
00319       chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
00320       break;
00321    }
00322 }
00323 /*************** Helpers END *************/
00324 
00325 void send_digit_to_chan(struct chan_list *cl, char digit )
00326 {
00327    static const char* dtmf_tones[] = {
00328       "!941+1336/100,!0/100", /* 0 */
00329       "!697+1209/100,!0/100", /* 1 */
00330       "!697+1336/100,!0/100", /* 2 */
00331       "!697+1477/100,!0/100", /* 3 */
00332       "!770+1209/100,!0/100", /* 4 */
00333       "!770+1336/100,!0/100", /* 5 */
00334       "!770+1477/100,!0/100", /* 6 */
00335       "!852+1209/100,!0/100", /* 7 */
00336       "!852+1336/100,!0/100", /* 8 */
00337       "!852+1477/100,!0/100", /* 9 */
00338       "!697+1633/100,!0/100", /* A */
00339       "!770+1633/100,!0/100", /* B */
00340       "!852+1633/100,!0/100", /* C */
00341       "!941+1633/100,!0/100", /* D */
00342       "!941+1209/100,!0/100", /* * */
00343       "!941+1477/100,!0/100" };  /* # */
00344    struct ast_channel *chan=cl->ast; 
00345   
00346    if (digit >= '0' && digit <='9')
00347       ast_playtones_start(chan,0,dtmf_tones[digit-'0'], 0);
00348    else if (digit >= 'A' && digit <= 'D')
00349       ast_playtones_start(chan,0,dtmf_tones[digit-'A'+10], 0);
00350    else if (digit == '*')
00351       ast_playtones_start(chan,0,dtmf_tones[14], 0);
00352    else if (digit == '#')
00353       ast_playtones_start(chan,0,dtmf_tones[15], 0);
00354    else {
00355       /* not handled */
00356       ast_log(LOG_DEBUG, "Unable to handle DTMF tone '%c' for '%s'\n", digit, chan->name);
00357     
00358     
00359    }
00360 }
00361 /*** CLI HANDLING ***/
00362 static int misdn_set_debug(int fd, int argc, char *argv[])
00363 {
00364    if (argc != 4 && argc != 5 && argc != 6 && argc != 7)
00365       return RESULT_SHOWUSAGE; 
00366 
00367    int level = atoi(argv[3]);
00368 
00369    switch (argc) {
00370       case 4:  
00371       case 5: {
00372                int only = 0;
00373                if (argc == 5) {
00374                   if (strncasecmp(argv[4], "only", strlen(argv[4])))
00375                      return RESULT_SHOWUSAGE;
00376                   else
00377                      only = 1;
00378                }
00379                int i;
00380                for (i=0; i<=max_ports; i++) {
00381                   misdn_debug[i] = level;
00382                   misdn_debug_only[i] = only;
00383                }
00384                ast_cli(fd, "changing debug level for all ports to %d%s\n",misdn_debug[0], only?" (only)":"");
00385             }
00386             break;
00387       case 6: 
00388       case 7: {
00389                if (strncasecmp(argv[4], "port", strlen(argv[4])))
00390                   return RESULT_SHOWUSAGE;
00391                int port = atoi(argv[5]);
00392                if (port <= 0 || port > max_ports) {
00393                   switch (max_ports) {
00394                      case 0:
00395                         ast_cli(fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
00396                         break;
00397                      case 1:
00398                         ast_cli(fd, "port number not valid! only port 1 is availble.\n");
00399                         break;
00400                      default:
00401                         ast_cli(fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
00402                      }
00403                      return 0;
00404                }
00405                if (argc == 7) {
00406                   if (strncasecmp(argv[6], "only", strlen(argv[6])))
00407                      return RESULT_SHOWUSAGE;
00408                   else
00409                      misdn_debug_only[port] = 1;
00410                } else
00411                   misdn_debug_only[port] = 0;
00412                misdn_debug[port] = level;
00413                ast_cli(fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port]?" (only)":"", port);
00414             }
00415    }
00416    return 0;
00417 }
00418 
00419 
00420 static int misdn_set_crypt_debug(int fd, int argc, char *argv[])
00421 {
00422    if (argc != 5 )return RESULT_SHOWUSAGE; 
00423 
00424    return 0;
00425 }
00426 
00427 
00428 static int misdn_restart_port (int fd, int argc, char *argv[])
00429 {
00430    int port;
00431   
00432    if (argc != 4)
00433       return RESULT_SHOWUSAGE;
00434   
00435    port = atoi(argv[3]);
00436 
00437    misdn_lib_port_restart(port);
00438 
00439    return 0;
00440 }
00441 
00442 static int misdn_port_up (int fd, int argc, char *argv[])
00443 {
00444    int port;
00445    
00446    if (argc != 4)
00447       return RESULT_SHOWUSAGE;
00448    
00449    port = atoi(argv[3]);
00450    
00451    misdn_lib_get_port_up(port);
00452   
00453    return 0;
00454 }
00455 
00456 
00457 static int misdn_show_config (int fd, int argc, char *argv[])
00458 {
00459    char buffer[BUFFERSIZE];
00460    enum misdn_cfg_elements elem;
00461    int linebreak;
00462 
00463    int onlyport = -1;
00464    if (argc >= 4) {
00465       if (!sscanf(argv[3], "%d", &onlyport) || onlyport < 0) {
00466          ast_cli(fd, "Unknown option: %s\n", argv[3]);
00467          return RESULT_SHOWUSAGE;
00468       }
00469    }
00470    
00471    if (argc == 3 || onlyport == 0) {
00472       ast_cli(fd,"Misdn General-Config: \n"); 
00473       ast_cli(fd," ->  VERSION: " CHAN_MISDN_VERSION "\n");
00474       
00475       for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
00476          misdn_cfg_get_config_string( 0, elem, buffer, BUFFERSIZE);
00477          ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00478       }
00479    }
00480 
00481    if (onlyport < 0) {
00482       int port = misdn_cfg_get_next_port(0);
00483       for (; port > 0; port = misdn_cfg_get_next_port(port)) {
00484          ast_cli(fd, "\n[PORT %d]\n", port);
00485          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00486             misdn_cfg_get_config_string( port, elem, buffer, BUFFERSIZE);
00487             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00488          }  
00489          ast_cli(fd, "\n");
00490       }
00491    }
00492    
00493    if (onlyport > 0) {
00494       if (misdn_cfg_is_port_valid(onlyport)) {
00495          ast_cli(fd, "[PORT %d]\n", onlyport);
00496          for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
00497             misdn_cfg_get_config_string( onlyport, elem, buffer, BUFFERSIZE);
00498             ast_cli(fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
00499          }  
00500          ast_cli(fd, "\n");
00501       } else {
00502          ast_cli(fd, "Port %d is not active!\n", onlyport);
00503       }
00504    }
00505    return 0;
00506 }
00507 
00508 
00509 
00510 struct state_struct {
00511    enum misdn_chan_state state;
00512    char txt[255] ;
00513 } ;
00514 
00515 struct state_struct state_array[] = {
00516    {MISDN_NOTHING,"NOTHING"}, /* at beginning */
00517    {MISDN_WAITING4DIGS,"WAITING4DIGS"}, /*  when waiting for infos */
00518    {MISDN_EXTCANTMATCH,"EXTCANTMATCH"}, /*  when asterisk couldnt match our ext */
00519    {MISDN_DIALING,"DIALING"}, /*  when pbx_start */
00520    {MISDN_PROGRESS,"PROGRESS"}, /*  when pbx_start */
00521    {MISDN_CALLING,"CALLING"}, /*  when misdn_call is called */
00522    {MISDN_ALERTING,"ALERTING"}, /*  when Alerting */
00523    {MISDN_BUSY,"BUSY"}, /*  when BUSY */
00524    {MISDN_CONNECTED,"CONNECTED"}, /*  when connected */
00525    {MISDN_BRIDGED,"BRIDGED"}, /*  when bridged */
00526    {MISDN_CLEANING,"CLEANING"}, /* when hangup from * but we were connected before */
00527    {MISDN_HUNGUP_FROM_MISDN,"HUNGUP_FROM_MISDN"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
00528    {MISDN_HOLDED,"HOLDED"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
00529    {MISDN_HOLD_DISCONNECT,"HOLD_DISCONNECT"}, /* when DISCONNECT/RELEASE/REL_COMP  cam from misdn */
00530    {MISDN_HUNGUP_FROM_AST,"HUNGUP_FROM_AST"} /* when DISCONNECT/RELEASE/REL_COMP came out of */
00531    /* misdn_hangup */
00532 };
00533 
00534 
00535 
00536 
00537 char *misdn_get_ch_state(struct chan_list *p) 
00538 {
00539    int i;
00540    if( !p) return NULL;
00541   
00542    for (i=0; i< sizeof(state_array)/sizeof(struct state_struct); i++) {
00543       if ( state_array[i].state == p->state) return state_array[i].txt; 
00544    }
00545   
00546    return NULL;
00547 }
00548 
00549 static int misdn_reload (int fd, int argc, char *argv[])
00550 {
00551    int i, cfg_debug;
00552    
00553    ast_cli(fd, "Reloading mISDN Config\n");
00554    chan_misdn_log(0, 0, "Dynamic Crypting Activation is not support during reload at the moment\n");
00555    
00556    free_robin_list();
00557 
00558    misdn_cfg_reload();
00559 
00560    {
00561       char tempbuf[BUFFERSIZE];
00562       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
00563       if (strlen(tempbuf))
00564          tracing = 1;
00565    }
00566 
00567    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(int));
00568    for (i = 0;  i <= max_ports; i++) {
00569       misdn_debug[i] = cfg_debug;
00570       misdn_debug_only[i] = 0;
00571    }
00572    
00573    return 0;
00574 }
00575 
00576 static void print_bc_info (int fd, struct chan_list* help, struct misdn_bchannel* bc)
00577 {
00578    struct ast_channel *ast=help->ast;
00579    ast_cli(fd,
00580       "* Pid:%d Prt:%d Ch:%d Mode:%s Org:%s dad:%s oad:%s ctx:%s state:%s\n",
00581       bc->pid, bc->port, bc->channel,
00582       bc->nt?"NT":"TE",
00583       help->orginator == ORG_AST?"*":"I",
00584       ast?ast->exten:NULL,
00585       ast?AST_CID_P(ast):NULL,
00586       ast?ast->context:NULL,
00587       misdn_get_ch_state(help)
00588       );
00589    if (misdn_debug[bc->port] > 0)
00590       ast_cli(fd,
00591          "  --> astname: %s\n"
00592          "  --> ch_l3id: %x\n"
00593          "  --> ch_addr: %x\n"
00594          "  --> bc_addr: %x\n"
00595          "  --> bc_l3id: %x\n"
00596          "  --> tone: %s\n"
00597          "  --> display: %s\n"
00598          "  --> activated: %d\n"
00599          "  --> capability: %s\n"
00600          "  --> echo_cancel: %d\n"
00601          "  --> notone : rx %d tx:%d\n"
00602          "  --> bc_hold: %d holded_bc :%d\n",
00603          help->ast->name,
00604          help->l3id,
00605          help->addr,
00606          bc->addr,
00607          bc?bc->l3_id:-1,
00608          tone2str(bc),
00609          bc->display,
00610          
00611          bc->active,
00612          bearer2str(bc->capability),
00613          bc->ec_enable,
00614          help->norxtone,help->notxtone,
00615          bc->holded, help->holded_bc?1:0
00616          );
00617   
00618 }
00619 
00620 
00621 static int misdn_show_cls (int fd, int argc, char *argv[])
00622 {
00623    struct chan_list *help=cl_te;
00624   
00625    ast_cli(fd,"Chan List: %p\n",cl_te); 
00626   
00627    for (;help; help=help->next) {
00628       struct misdn_bchannel *bc=help->bc;   
00629       struct ast_channel *ast=help->ast;
00630       if (misdn_debug[0] > 2) ast_cli(fd, "Bc:%p Ast:%p\n", bc, ast);
00631       if (bc) {
00632          print_bc_info(fd, help, bc);
00633       } else if ( (bc=help->holded_bc) ) {
00634          chan_misdn_log(0, 0, "ITS A HOLDED BC:\n");
00635          print_bc_info(fd, help,  bc);
00636       } else {
00637          ast_cli(fd,"* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, AST_CID_P(ast));
00638       }
00639    }
00640   
00641   
00642    return 0;
00643 }
00644 
00645 
00646 
00647 static int misdn_show_cl (int fd, int argc, char *argv[])
00648 {
00649    struct chan_list *help=cl_te;
00650 
00651    if (argc != 4)
00652       return RESULT_SHOWUSAGE;
00653   
00654    for (;help; help=help->next) {
00655       struct misdn_bchannel *bc=help->bc;   
00656       struct ast_channel *ast=help->ast;
00657     
00658       if (bc && ast) {
00659          if (!strcasecmp(ast->name,argv[3])) {
00660             print_bc_info(fd, help, bc);
00661             break; 
00662          }
00663       } 
00664    }
00665   
00666   
00667    return 0;
00668 }
00669 
00670 ast_mutex_t lock;
00671 int MAXTICS=8;
00672 
00673 static int misdn_set_tics (int fd, int argc, char *argv[])
00674 {
00675    if (argc != 4)
00676       return RESULT_SHOWUSAGE;
00677   
00678    MAXTICS=atoi(argv[3]);
00679   
00680    return 0;
00681 }
00682 
00683 
00684 
00685 static int misdn_show_stacks (int fd, int argc, char *argv[])
00686 {
00687    int port;
00688    
00689    ast_cli(fd, "BEGIN STACK_LIST:\n");
00690    for (port=misdn_cfg_get_next_port(0); port > 0;
00691         port=misdn_cfg_get_next_port(port)) {
00692       char buf[128];
00693       get_show_stack_details(port,buf);
00694       ast_cli(fd,"  %s  Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00695    }
00696       
00697 
00698    return 0;
00699 
00700 }
00701 
00702 static int misdn_show_port (int fd, int argc, char *argv[])
00703 {
00704    int port;
00705    
00706    if (argc != 4)
00707       return RESULT_SHOWUSAGE;
00708   
00709    port = atoi(argv[3]);
00710   
00711    ast_cli(fd, "BEGIN STACK_LIST:\n");
00712 
00713    char buf[128];
00714    get_show_stack_details(port,buf);
00715    ast_cli(fd,"  %s  Debug:%d%s\n",buf, misdn_debug[port], misdn_debug_only[port]?"(only)":"");
00716 
00717    
00718    return 0;
00719 }
00720 
00721 static int misdn_send_cd (int fd, int argc, char *argv[])
00722 {
00723    char *channame; 
00724    char *nr; 
00725   
00726    if (argc != 5)
00727       return RESULT_SHOWUSAGE;
00728   
00729    channame = argv[3];
00730    nr = argv[4];
00731    
00732    ast_cli(fd, "Sending Calldeflection (%s) to %s\n",nr, channame);
00733    
00734    {
00735       struct chan_list *tmp=get_chan_by_ast_name(channame);
00736       
00737       if (!tmp) {
00738          ast_cli(fd, "Sending CD with nr %s to %s failed Channel does not exist\n",nr, channame);
00739          return 0; 
00740       } else {
00741          
00742          misdn_lib_send_facility(tmp->bc, FACILITY_CALLDEFLECT, nr);
00743       }
00744    }
00745   
00746    return 0; 
00747 }
00748 
00749 
00750 
00751 static int misdn_send_digit (int fd, int argc, char *argv[])
00752 {
00753    char *channame; 
00754    char *msg; 
00755   
00756    if (argc != 5)
00757       return RESULT_SHOWUSAGE;
00758   
00759    channame = argv[3];
00760    msg = argv[4];
00761 
00762    ast_cli(fd, "Sending %s to %s\n",msg, channame);
00763   
00764    {
00765       struct chan_list *tmp=get_chan_by_ast_name(channame);
00766     
00767       if (!tmp) {
00768          ast_cli(fd, "Sending %s to %s failed Channel does not exist\n",msg, channame);
00769          return 0; 
00770       } else {
00771 #if 1
00772          int i;
00773          int msglen = strlen(msg);
00774          for (i=0; i<msglen; i++) {
00775             ast_cli(fd, "Sending: %c\n",msg[i]);
00776             send_digit_to_chan(tmp, msg[i]);
00777             /* res = ast_safe_sleep(tmp->ast, 250); */
00778             usleep(250000);
00779             /* res = ast_waitfor(tmp->ast,100); */
00780          }
00781 #else
00782          int res;
00783          res = ast_dtmf_stream(tmp->ast,NULL,msg,250);
00784 #endif
00785       }
00786    }
00787   
00788    return 0; 
00789 }
00790 
00791 static int misdn_toggle_echocancel (int fd, int argc, char *argv[])
00792 {
00793    char *channame; 
00794 
00795    if (argc != 4)
00796       return RESULT_SHOWUSAGE;
00797    
00798    channame = argv[3];
00799   
00800    ast_cli(fd, "Toggling EchoCancel on %s\n", channame);
00801   
00802    {
00803       struct chan_list *tmp=get_chan_by_ast_name(channame);
00804     
00805       if (!tmp) {
00806          ast_cli(fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
00807          return 0; 
00808       } else {
00809          tmp->bc->ec_enable=tmp->bc->ec_enable?0:1;
00810 
00811          if (tmp->bc->ec_enable) {
00812             manager_ec_enable(tmp->bc);
00813          } else {
00814             manager_ec_disable(tmp->bc);
00815          }
00816       }
00817    }
00818   
00819    return 0; 
00820 }
00821 
00822 
00823 
00824 static int misdn_send_display (int fd, int argc, char *argv[])
00825 {
00826    char *channame; 
00827    char *msg; 
00828   
00829    if (argc != 5)
00830       return RESULT_SHOWUSAGE;
00831   
00832    channame = argv[3];
00833    msg = argv[4];
00834 
00835    ast_cli(fd, "Sending %s to %s\n",msg, channame);
00836    {
00837       struct chan_list *tmp;
00838       tmp=get_chan_by_ast_name(channame);
00839     
00840       if (tmp && tmp->bc) {
00841          int l = sizeof(tmp->bc->display);
00842          strncpy(tmp->bc->display, msg, l);
00843          tmp->bc->display[l-1] = 0;
00844          misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
00845       } else {
00846          ast_cli(fd,"No such channel %s\n",channame);
00847          return RESULT_FAILURE;
00848       }
00849    }
00850 
00851    return RESULT_SUCCESS ;
00852 }
00853 
00854 
00855 
00856 
00857 static char *complete_ch_helper(char *line, char *word, int pos, int state, int rpos)
00858 {
00859    struct ast_channel *c;
00860    int which=0;
00861    char *ret;
00862    if (pos != rpos)
00863       return NULL;
00864    c = ast_channel_walk_locked(NULL);
00865    while(c) {
00866       if (!strncasecmp(word, c->name, strlen(word))) {
00867          if (++which > state)
00868             break;
00869       }
00870       ast_mutex_unlock(&c->lock);
00871       c = ast_channel_walk_locked(c);
00872    }
00873    if (c) {
00874       ret = strdup(c->name);
00875       ast_mutex_unlock(&c->lock);
00876    } else
00877       ret = NULL;
00878    return ret;
00879 }
00880 
00881 static char *complete_ch(char *line, char *word, int pos, int state)
00882 {
00883    return complete_ch_helper(line, word, pos, state, 3);
00884 }
00885 
00886 static char *complete_debug_port (char *line, char *word, int pos, int state)
00887 {
00888    if (state)
00889       return NULL;
00890 
00891    switch (pos) {
00892    case 4: if (*word == 'p')
00893             return strdup("port");
00894          else if (*word == 'o')
00895             return strdup("only");
00896          break;
00897    case 6: if (*word == 'o')
00898             return strdup("only");
00899          break;
00900    }
00901    return NULL;
00902 }
00903 
00904 static struct ast_cli_entry cli_send_cd =
00905 { {"misdn","send","calldeflect", NULL},
00906   misdn_send_cd,
00907   "Sends CallDeflection to mISDN Channel", 
00908   "Usage: misdn send calldeflect <channel> \"<nr>\" \n",
00909   complete_ch
00910 };
00911 
00912 
00913 static struct ast_cli_entry cli_send_digit =
00914 { {"misdn","send","digit", NULL},
00915   misdn_send_digit,
00916   "Sends DTMF Digit to mISDN Channel", 
00917   "Usage: misdn send digit <channel> \"<msg>\" \n"
00918   "       Send <digit> to <channel> as DTMF Tone\n"
00919   "       when channel is a mISDN channel\n",
00920   complete_ch
00921 };
00922 
00923 
00924 static struct ast_cli_entry cli_toggle_echocancel =
00925 { {"misdn","toggle","echocancel", NULL},
00926   misdn_toggle_echocancel,
00927   "Toggles EchoCancel on mISDN Channel", 
00928   "Usage: misdn toggle echocancel <channel>\n", 
00929   complete_ch
00930 };
00931 
00932 
00933 
00934 static struct ast_cli_entry cli_send_display =
00935 { {"misdn","send","display", NULL},
00936   misdn_send_display,
00937   "Sends Text to mISDN Channel", 
00938   "Usage: misdn send display <channel> \"<msg>\" \n"
00939   "       Send <msg> to <channel> as Display Message\n"
00940   "       when channel is a mISDN channel\n",
00941   complete_ch
00942 };
00943 
00944 
00945 static struct ast_cli_entry cli_show_config =
00946 { {"misdn","show","config", NULL},
00947   misdn_show_config,
00948   "Shows internal mISDN config, read from cfg-file", 
00949   "Usage: misdn show config [port | 0]\n       use 0 to only print the general config.\n"
00950 };
00951  
00952 
00953 static struct ast_cli_entry cli_reload =
00954 { {"misdn","reload", NULL},
00955   misdn_reload,
00956   "Reloads internal mISDN config, read from cfg-file", 
00957   "Usage: misdn reload\n"
00958 };
00959 
00960 static struct ast_cli_entry cli_set_tics =
00961 { {"misdn","set","tics", NULL},
00962   misdn_set_tics,
00963   "", 
00964   "\n"
00965 };
00966 
00967 
00968 static struct ast_cli_entry cli_show_cls =
00969 { {"misdn","show","channels", NULL},
00970   misdn_show_cls,
00971   "Shows internal mISDN chan_list", 
00972   "Usage: misdn show channels\n"
00973 };
00974 
00975 static struct ast_cli_entry cli_show_cl =
00976 { {"misdn","show","channel", NULL},
00977   misdn_show_cl,
00978   "Shows internal mISDN chan_list", 
00979   "Usage: misdn show channels\n",
00980   complete_ch
00981 };
00982 
00983 
00984 
00985 static struct ast_cli_entry cli_restart_port =
00986 { {"misdn","restart","port", NULL},
00987   misdn_restart_port,
00988   "Restarts the given port", 
00989   "Usage: misdn restart port\n"
00990 };
00991 
00992 
00993 static struct ast_cli_entry cli_port_up =
00994 { {"misdn","port","up", NULL},
00995   misdn_port_up,
00996   "Tries to establish L1 on the given port", 
00997   "Usage: misdn port up <port>\n"
00998 };
00999 
01000 
01001 static struct ast_cli_entry cli_show_stacks =
01002 { {"misdn","show","stacks", NULL},
01003   misdn_show_stacks,
01004   "Shows internal mISDN stack_list", 
01005   "Usage: misdn show stacks\n"
01006 };
01007 
01008 static struct ast_cli_entry cli_show_port =
01009 { {"misdn","show","port", NULL},
01010   misdn_show_port,
01011   "Shows detailed information for given port", 
01012   "Usage: misdn show port <port>\n"
01013 };
01014 
01015 
01016 
01017 static struct ast_cli_entry cli_set_debug =
01018 { {"misdn","set","debug", NULL},
01019   misdn_set_debug,
01020   "Sets Debuglevel of chan_misdn",
01021   "Usage: misdn set debug <level> [only] | [port <port> [only]]\n",
01022   complete_debug_port
01023 };
01024 
01025 static struct ast_cli_entry cli_set_crypt_debug =
01026 { {"misdn","set","crypt","debug", NULL},
01027   misdn_set_crypt_debug,
01028   "Sets CryptDebuglevel of chan_misdn, at the moment, level={1,2}", 
01029   "Usage: misdn set crypt debug <level>\n"
01030 };
01031 /*** CLI END ***/
01032 
01033 
01034 /*****************************/
01035 /*** AST Indications Start ***/
01036 /*****************************/
01037 
01038 static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
01039 {
01040    int port=0;
01041    int r;
01042    struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01043    struct misdn_bchannel *newbc;
01044    char *opts=NULL, *ext=NULL;
01045    char dest_cp[256];
01046    char *tokb;
01047    
01048    {
01049       strncpy(dest_cp,dest,sizeof(dest_cp)-1);
01050       dest_cp[sizeof(dest_cp)]=0;
01051       
01052       ext=strtok_r(dest_cp,"/",&tokb);
01053       
01054       if (ext) {
01055          ext=strtok_r(NULL,"/",&tokb);
01056          if (ext) {
01057             opts=strtok_r(NULL,"/",&tokb);
01058          } else {
01059             chan_misdn_log(-1,0,"misdn_call: No Extension given!\n");
01060             return -1;
01061          }
01062       }
01063       
01064       
01065    }
01066 
01067    if (!ast) {
01068       ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
01069       return -1;
01070    }
01071 
01072    if (((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) || !dest  ) {
01073       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01074       ast->hangupcause=41;
01075       ast_setstate(ast, AST_STATE_DOWN);
01076       return -1;
01077    }
01078 
01079 
01080    if (!ch) {
01081       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01082       ast->hangupcause=41;
01083       ast_setstate(ast, AST_STATE_DOWN);
01084       return -1;
01085    }
01086    
01087    newbc=ch->bc;
01088    
01089    if (!newbc) {
01090       ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast->name);
01091       ast->hangupcause=41;
01092       ast_setstate(ast, AST_STATE_DOWN);
01093       return -1;
01094    }
01095 
01096    port=newbc->port;
01097 
01098    ast_copy_string(newbc->dad, ext, sizeof(newbc->dad));
01099    ast_copy_string(ast->exten, ext, sizeof(ast->exten));
01100    
01101    chan_misdn_log(1, 0, "* CALL: %s\n",dest);
01102    
01103    chan_misdn_log(1, port, " --> * dad:%s tech:%s ctx:%s\n",ast->exten,ast->name, ast->context);
01104    
01105    {
01106       char context[BUFFERSIZE];
01107       
01108       misdn_cfg_get( port, MISDN_CFG_CONTEXT, context, sizeof(ast->context));
01109       {
01110          int l = sizeof(ast->context);
01111          strncpy(ast->context,context, l);
01112          ast->context[l-1] = 0;
01113       }
01114       chan_misdn_log(2, port, " --> * Setting Context to %s\n",context);
01115       misdn_cfg_get( port, MISDN_CFG_LANGUAGE, ast->language, BUFFERSIZE);
01116       
01117       misdn_cfg_get( port, MISDN_CFG_TXGAIN, &newbc->txgain, sizeof(int));
01118       misdn_cfg_get( port, MISDN_CFG_RXGAIN, &newbc->rxgain, sizeof(int));
01119       
01120       misdn_cfg_get( port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(newbc->te_choose_channel), sizeof(int));
01121       
01122 
01123       {
01124          char callerid[BUFFERSIZE];
01125          misdn_cfg_get( port, MISDN_CFG_CALLERID, callerid, BUFFERSIZE);
01126          if ( ! ast_strlen_zero(callerid) ) {
01127             chan_misdn_log(1, port, " --> * Setting Cid to %s\n", callerid);
01128             {
01129                int l = sizeof(newbc->oad);
01130                strncpy(newbc->oad,callerid, l);
01131                newbc->oad[l-1] = 0;
01132             }
01133          }
01134 
01135          
01136          misdn_cfg_get( port, MISDN_CFG_DIALPLAN, &newbc->dnumplan, sizeof(int));
01137          switch (newbc->dnumplan) {
01138          case NUMPLAN_INTERNATIONAL:
01139             chan_misdn_log(2, port, " --> TON: International\n");
01140             break;
01141          case NUMPLAN_NATIONAL:
01142             chan_misdn_log(2, port, " --> TON: National\n");
01143             break;
01144          case NUMPLAN_SUBSCRIBER:
01145             chan_misdn_log(2, port, " --> TON: Subscriber\n");
01146             break;
01147          case NUMPLAN_UNKNOWN:
01148             chan_misdn_log(2, port, " --> TON: Unknown\n");
01149             break;
01150             /* Maybe we should cut off the prefix if present ? */
01151          default:
01152                chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01153                break;
01154          }
01155 
01156 
01157          misdn_cfg_get( port, MISDN_CFG_LOCALDIALPLAN, &newbc->onumplan, sizeof(int));
01158          switch (newbc->onumplan) {
01159          case NUMPLAN_INTERNATIONAL:
01160             chan_misdn_log(2, port, " --> TON: International\n");
01161             break;
01162          case NUMPLAN_NATIONAL:
01163             chan_misdn_log(2, port, " --> TON: National\n");
01164             break;
01165          case NUMPLAN_SUBSCRIBER:
01166             chan_misdn_log(2, port, " --> TON: Subscriber\n");
01167             break;
01168          case NUMPLAN_UNKNOWN:
01169             chan_misdn_log(2, port, " --> TON: Unknown\n");
01170             break;
01171             /* Maybe we should cut off the prefix if present ? */
01172          default:
01173                chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
01174                break;
01175          }
01176       }
01177 
01178 
01179 
01180       
01181       {
01182          int eb3;
01183          
01184          misdn_cfg_get( port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
01185          newbc->early_bconnect=eb3;
01186          
01187       }
01188       
01189 
01190       
01191       /* Will be overridden by asterisk in head! */
01192       {
01193          int pres;
01194          
01195          misdn_cfg_get( port, MISDN_CFG_PRES, &pres, sizeof(int));
01196          newbc->pres=pres?0:1;
01197          
01198       }
01199       
01200       int def_callingpres;
01201       misdn_cfg_get( port, MISDN_CFG_USE_CALLINGPRES, &def_callingpres, sizeof(int));
01202       if ( def_callingpres) {
01203          
01204          switch (ast->cid.cid_pres & 0x60){
01205             
01206          case AST_PRES_RESTRICTED:
01207             chan_misdn_log(2, port, " --> PRES: Restricted (0x1)\n");
01208             newbc->pres=1;
01209             break;
01210             
01211             
01212          case AST_PRES_UNAVAILABLE:
01213             chan_misdn_log(2, port, " --> PRES: Unavailable (0x2)\n");
01214             newbc->pres=2;
01215             break;
01216             
01217          default:
01218             chan_misdn_log(2, port, " --> PRES: Allowed (0x0)\n");
01219             newbc->pres=0;
01220          }
01221          
01222          switch (ast->cid.cid_pres & 0x3){
01223             
01224          case AST_PRES_USER_NUMBER_UNSCREENED:
01225             chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01226             newbc->screen=0;
01227             break;
01228 
01229          case AST_PRES_USER_NUMBER_PASSED_SCREEN:
01230             chan_misdn_log(2, port, " --> SCREEN: Passed Screen (0x1)\n");
01231             newbc->screen=1;
01232             break;
01233          case AST_PRES_USER_NUMBER_FAILED_SCREEN:
01234             chan_misdn_log(2, port, " --> SCREEN: Failed Screen (0x2)\n");
01235             newbc->screen=2;
01236             break;
01237             
01238          case AST_PRES_NETWORK_NUMBER:
01239             chan_misdn_log(2, port, " --> SCREEN: Network Nr. (0x3)\n");
01240             newbc->screen=3;
01241             break;
01242             
01243          default:
01244             chan_misdn_log(2, port, " --> SCREEN: Unscreened (0x0)\n");
01245             newbc->screen=0;
01246          }
01247       }
01248 
01249       
01250       {
01251          int ec, ectr;
01252          
01253          misdn_cfg_get( port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
01254          
01255          misdn_cfg_get( port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
01256          if (ec == 1 ) {
01257             newbc->ec_enable=1;
01258          } else if ( ec > 1 ) {
01259             newbc->ec_enable=1;
01260             newbc->ec_deftaps=ec;
01261          }
01262 
01263 
01264          if (ectr>=0) {
01265             newbc->ec_training=ectr;
01266          }
01267          
01268       }
01269       
01270    } 
01271    
01272    chan_misdn_log(3, port, " --> * adding2newbc ext %s\n",ast->exten);
01273    if (ast->exten) {
01274       int l = sizeof(newbc->dad);
01275       strncpy(newbc->dad,ast->exten, l);
01276       newbc->dad[l-1] = 0;
01277    }
01278    newbc->rad[0]=0;
01279    chan_misdn_log(3, port, " --> * adding2newbc callerid %s\n",AST_CID_P(ast));
01280    if (ast_strlen_zero(newbc->oad) && AST_CID_P(ast) ) {
01281       if (AST_CID_P(ast)) {
01282          int l = sizeof(newbc->oad);
01283          strncpy(newbc->oad,AST_CID_P(ast), l);
01284          newbc->oad[l-1] = 0;
01285       }
01286    }
01287    
01288    {
01289       struct chan_list *ch=MISDN_ASTERISK_TECH_PVT(ast);
01290       if (!ch) { ast_verbose("No chan_list in misdn_call"); return -1;}
01291       ch->bc = newbc;
01292       ch->orginator=ORG_AST;
01293       ch->ast = ast;
01294       
01295       MISDN_ASTERISK_TECH_PVT(ast) = ch ;
01296       
01297       
01298       
01299       newbc->capability=ast->transfercapability;
01300       pbx_builtin_setvar_helper(ast,"TRANSFERCAPABILITY",ast_transfercapability2str(newbc->capability));
01301       if ( ast->transfercapability == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
01302          chan_misdn_log(2, port, " --> * Call with flag Digital\n");
01303       }
01304       
01305 
01306       /* Finally The Options Override Everything */
01307       if (opts)
01308          misdn_set_opt_exec(ast,opts);
01309       else
01310          chan_misdn_log(1,0,"NO OPTS GIVEN\n");
01311       
01312       
01313       cl_queue_chan(&cl_te, ch) ;
01314       ch->state=MISDN_CALLING;
01315 
01316       chan_misdn_trace_call(ast,1,"*->I: EVENT_CALL\n" );
01317       
01318       r=misdn_lib_send_event( newbc, EVENT_SETUP );
01319       
01320       /** we should have l3id after sending setup **/
01321       ch->l3id=newbc->l3_id;
01322    }
01323    
01324    if ( r == -ENOCHAN  ) {
01325       chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
01326       chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n",newbc?newbc->pid:-1);
01327       ast->hangupcause=34;
01328       ast_setstate(ast, AST_STATE_DOWN);
01329       return -1;
01330    }
01331    
01332    chan_misdn_log(1, port, " --> * SEND: State Dialing pid:%d\n",newbc?newbc->pid:1);
01333 
01334    ast_setstate(ast, AST_STATE_DIALING);
01335    
01336    ast->hangupcause=16;
01337    return 0; 
01338 }
01339 
01340 
01341 int misdn_answer(struct ast_channel *ast)
01342 {
01343    struct chan_list *p;
01344 
01345    
01346    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01347    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01348    
01349    chan_misdn_trace_call(ast,1,"*->I: EVENT_ANSWER\n");
01350    
01351    chan_misdn_log(1, p? (p->bc? p->bc->port : 0) : 0, "* ANSWER:\n");
01352    
01353    if (!p) {
01354       ast_log(LOG_WARNING, " --> Channel not connected ??\n");
01355       ast_queue_hangup(ast);
01356    }
01357 
01358    if (!p->bc) {
01359       chan_misdn_log(1, 0, " --> Got Answer, but theres no bc obj ??\n");
01360 
01361       ast_queue_hangup(ast);
01362    }
01363 
01364    {
01365       char *tmp_key = pbx_builtin_getvar_helper(p->ast, "CRYPT_KEY");
01366       
01367       if (tmp_key ) {
01368          chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
01369          {
01370             int l = sizeof(p->bc->crypt_key);
01371             strncpy(p->bc->crypt_key,tmp_key, l);
01372             p->bc->crypt_key[l-1] = 0;
01373          }
01374       } else {
01375          chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
01376       }
01377     
01378    }
01379 
01380    {
01381       char *async=pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
01382       if (async) {
01383          chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
01384          p->bc->async=1;
01385       }
01386    }
01387    
01388    p->state = MISDN_CONNECTED;
01389    misdn_lib_send_event( p->bc, EVENT_CONNECT);
01390    start_bc_tones(p);
01391    
01392    return 0;
01393 }
01394 
01395 int misdn_digit(struct ast_channel *ast, char digit )
01396 {
01397    struct chan_list *p;
01398    
01399    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01400    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01401    
01402 
01403    struct misdn_bchannel *bc=p->bc;
01404    chan_misdn_log(1, bc?bc->port:0, "* IND : Digit %c\n",digit);
01405    
01406    if (!bc) {
01407       ast_log(LOG_WARNING, " --> !! Got Digit Event withut having bchannel Object\n");
01408       return -1;
01409    }
01410    
01411    switch (p->state ) {
01412       case MISDN_CALLING:
01413       {
01414          
01415          char buf[8];
01416          buf[0]=digit;
01417          buf[1]=0;
01418          
01419          int l = sizeof(bc->infos_pending);
01420          strncat(bc->infos_pending,buf,l);
01421          bc->infos_pending[l-1] = 0;
01422       }
01423       break;
01424       case MISDN_CALLING_ACKNOWLEDGE:
01425       {
01426          bc->info_dad[0]=digit;
01427          bc->info_dad[1]=0;
01428          
01429          {
01430             int l = sizeof(bc->dad);
01431             strncat(bc->dad,bc->info_dad, l - strlen(bc->dad));
01432             bc->dad[l-1] = 0;
01433       }
01434          {
01435             int l = sizeof(p->ast->exten);
01436             strncpy(p->ast->exten, bc->dad, l);
01437             p->ast->exten[l-1] = 0;
01438          }
01439          
01440          misdn_lib_send_event( bc, EVENT_INFORMATION);
01441       }
01442       break;
01443       
01444       default:
01445          if ( bc->send_dtmf ) {
01446             send_digit_to_chan(p,digit);
01447          }
01448       break;
01449    }
01450    
01451    return 0;
01452 }
01453 
01454 
01455 int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
01456 {
01457    struct chan_list *p;
01458    
01459    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01460    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01461    
01462    chan_misdn_log(1, p->bc?p->bc->port:0, "* IND: Got Fixup State:%s Holded:%d L3id:%x\n", misdn_get_ch_state(p), p->holded, p->l3id);
01463    
01464    p->ast = ast ;
01465    p->state=MISDN_CONNECTED;
01466   
01467    return 0;
01468 }
01469 
01470 
01471 int misdn_transfer (struct ast_channel *ast, char *dest)
01472 {
01473    struct chan_list *p;
01474    
01475    if (!ast || ! MISDN_ASTERISK_PVT(ast)) return -1;
01476    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01477 
01478    chan_misdn_log(1, p->bc?p->bc->port:0, "* IND : Got Transfer %s\n",dest);
01479    return 0;
01480 }
01481 
01482 
01483 
01484 int misdn_indication(struct ast_channel *ast, int cond)
01485 {
01486    struct chan_list *p;
01487 
01488   
01489    if (!ast || ! MISDN_ASTERISK_PVT(ast)) {
01490       ast_log(LOG_WARNING, "Returnded -1 in misdn_indication\n");
01491       return -1;
01492    }
01493    p = MISDN_ASTERISK_TECH_PVT(ast) ;
01494    
01495    if (!p->bc ) {
01496       chan_misdn_log(1, 0, "* IND : Indication from %s\n",ast->exten);
01497       ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
01498       return -1;
01499    }
01500    
01501    chan_misdn_log(1, p->bc->port, "* IND : Indication from %s\n",ast->exten);
01502    
01503    switch (cond) {
01504    case AST_CONTROL_BUSY:
01505       chan_misdn_log(1, p->bc->port, "* IND :\tbusy\n");
01506       chan_misdn_log(1, p->bc->port, " --> * SEND: State Busy pid:%d\n",p->bc?p->bc->pid:-1);
01507       ast_setstate(ast,AST_STATE_BUSY);
01508       
01509       p->bc->out_cause=17;
01510       if (p->state != MISDN_CONNECTED) {
01511          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01512          manager_send_tone(p->bc, TONE_BUSY);
01513       } else {
01514          chan_misdn_log(0, p->bc->port, " --> !! Got Busy in Connected State !?! port:%d ast:%s\n",
01515                    p->bc->port, ast->name);
01516       }
01517       break;
01518    case AST_CONTROL_RING:
01519       chan_misdn_log(1, p->bc->port, " --> * IND :\tring pid:%d\n",p->bc?p->bc->pid:-1);
01520       break;
01521    case AST_CONTROL_RINGING:
01522       if ( p->state == MISDN_ALERTING) {
01523          chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d but I ws Ringing before, so ignoreing it\n",p->bc?p->bc->pid:-1);
01524          break;
01525       }
01526       p->state=MISDN_ALERTING;
01527       
01528       chan_misdn_log(1, p->bc->port, " --> * IND :\tringing pid:%d\n",p->bc?p->bc->pid:-1);
01529       
01530       misdn_lib_send_event( p->bc, EVENT_ALERTING);
01531       
01532       manager_send_tone(p->bc, TONE_ALERTING);
01533       chan_misdn_log(1, p->bc->port, " --> * SEND: State Ring pid:%d\n",p->bc?p->bc->pid:-1);
01534       ast_setstate(ast,AST_STATE_RINGING);
01535       break;
01536       
01537    case AST_CONTROL_ANSWER:
01538       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n",p->bc?p->bc->pid:-1);
01539       break;
01540    case AST_CONTROL_TAKEOFFHOOK:
01541       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n",p->bc?p->bc->pid:-1);
01542       break;
01543    case AST_CONTROL_OFFHOOK:
01544       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n",p->bc?p->bc->pid:-1);
01545       break; 
01546    case AST_CONTROL_FLASH:
01547       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n",p->bc?p->bc->pid:-1);
01548       break;
01549    case AST_CONTROL_PROGRESS:
01550       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n",p->bc?p->bc->pid:-1);
01551       break;
01552    case AST_CONTROL_CONGESTION:
01553       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n",p->bc?p->bc->pid:-1);
01554 
01555       p->bc->out_cause=42;
01556       if (p->state != MISDN_CONNECTED) {
01557          start_bc_tones(p);
01558          //misdn_lib_send_event( p->bc, EVENT_RELEASE_COMPLETE);
01559          misdn_lib_send_event( p->bc, EVENT_RELEASE);
01560       } else {
01561          misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
01562       }
01563       if (p->bc->nt) {
01564          manager_send_tone(p->bc, TONE_BUSY);
01565       }
01566       break;
01567    case -1 :
01568       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! pid:%d\n",p->bc?p->bc->pid:-1);
01569       break;
01570    case AST_CONTROL_HOLD:
01571       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01572       break;
01573    case AST_CONTROL_UNHOLD:
01574       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n",p->bc?p->bc->pid:-1);
01575       break;
01576    default:
01577       ast_log(LOG_WARNING, " --> * Unknown Indication:%d pid:%d\n",cond,p->bc?p->bc->pid:-1);
01578    }
01579   
01580    return 0;
01581 }
01582 
01583 int misdn_hangup(struct ast_channel *ast)
01584 {
01585    struct chan_list *p;
01586    struct misdn_bchannel *bc=NULL;
01587    
01588    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
01589    
01590    release_lock;
01591 
01592    chan_misdn_trace_call(ast,1,"*->I: EVENT_HANGUP cause=%d\n",ast->hangupcause);
01593    
01594    ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
01595    
01596    if (!p) {
01597       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
01598       release_unlock;
01599       return 0 ;
01600    }
01601    
01602    bc=p->bc;
01603 
01604    if (!bc) {
01605       release_unlock;
01606       ast_log(LOG_WARNING,"Hangup with private but no bc ?\n");
01607       return 0;
01608    }
01609 
01610    
01611    MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01612    p->ast=NULL;
01613 
01614    if (ast->_state == AST_STATE_RESERVED) {
01615       /* between request and call */
01616       MISDN_ASTERISK_TECH_PVT(ast)=NULL;
01617       release_unlock;
01618       
01619       cl_dequeue_chan(&cl_te, p);
01620       free(p);
01621 
01622       misdn_lib_release(bc);
01623       
01624       return 0;
01625    }
01626 
01627    stop_bc_tones(p);
01628    
01629    release_unlock;
01630    
01631    
01632    
01633    
01634    
01635    
01636    {
01637       char *varcause=NULL;
01638       bc->cause=ast->hangupcause?ast->hangupcause:16;
01639       
01640       if ( (varcause=pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
01641            (varcause=pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
01642          int tmpcause=atoi(varcause);
01643          bc->out_cause=tmpcause?tmpcause:16;
01644       }
01645     
01646       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));
01647       chan_misdn_log(2, bc->port, " --> l3id:%x\n",p->l3id);
01648       chan_misdn_log(1, bc->port, " --> cause:%d\n",bc->cause);
01649       chan_misdn_log(1, bc->port, " --> out_cause:%d\n",bc->out_cause);
01650       
01651       switch (p->state) {
01652       case MISDN_CALLING:
01653          p->state=MISDN_CLEANING;
01654          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
01655          break;
01656       case MISDN_HOLDED:
01657       case MISDN_DIALING:
01658          start_bc_tones(p);
01659          manager_send_tone(bc, TONE_BUSY);
01660          p->state=MISDN_CLEANING;
01661          
01662          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
01663       
01664          break;
01665       
01666       case MISDN_ALERTING:
01667          chan_misdn_log(2, bc->port, " --> * State Alerting\n");
01668 
01669          if (p->orginator != ORG_AST) 
01670             manager_send_tone(bc, TONE_BUSY);
01671       
01672          p->state=MISDN_CLEANING;
01673          misdn_lib_send_event( bc, EVENT_DISCONNECT);
01674          break;
01675       case MISDN_CONNECTED:
01676          /*  Alerting or Disconect */
01677          chan_misdn_log(2, bc->port, " --> * State Connected\n");
01678          start_bc_tones(p);
01679          manager_send_tone(bc, TONE_BUSY);
01680          misdn_lib_send_event( bc, EVENT_DISCONNECT);
01681       
01682          p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
01683          break;
01684 
01685       case MISDN_CLEANING:
01686          break;
01687       
01688       case MISDN_HOLD_DISCONNECT:
01689          /* need to send release here */
01690          chan_misdn_log(2, bc->port, " --> state HOLD_DISC\n");
01691          chan_misdn_log(1, bc->port, " --> cause %d\n",bc->cause);
01692          chan_misdn_log(1, bc->port, " --> out_cause %d\n",bc->out_cause);
01693          
01694          misdn_lib_send_event(bc,EVENT_RELEASE);
01695          break;
01696       default:
01697          /*  Alerting or Disconect */
01698          if (bc->nt)
01699             misdn_lib_send_event(bc, EVENT_RELEASE);
01700          else
01701             misdn_lib_send_event(bc, EVENT_DISCONNECT);
01702          p->state=MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
01703       }
01704     
01705    }
01706    
01707    chan_misdn_log(1, bc->port, "Channel: %s hanguped\n",ast->name);
01708    
01709    return 0;
01710 }
01711 
01712 struct ast_frame  *misdn_read(struct ast_channel *ast)
01713 {
01714    struct chan_list *tmp;
01715    
01716    char blah[255];
01717    int len =0 ;
01718    
01719    if (!ast) return NULL;
01720    if (! (tmp=MISDN_ASTERISK_TECH_PVT(ast)) ) return NULL;
01721    if (!tmp->bc) return NULL;
01722    
01723    
01724    read(tmp->pipe[0],blah,sizeof(blah));
01725    
01726    
01727    len = misdn_ibuf_usedcount(tmp->bc->astbuf);
01728 
01729    /*shrinken len if necessary, we transmit at maximum 4k*/
01730    len = len<=sizeof(tmp->ast_rd_buf)?len:sizeof(tmp->ast_rd_buf);
01731    
01732    misdn_ibuf_memcpy_r(tmp->ast_rd_buf, tmp->bc->astbuf,len);
01733    
01734    tmp->frame.frametype  = AST_FRAME_VOICE;
01735    tmp->frame.subclass = AST_FORMAT_ALAW;
01736    tmp->frame.datalen = len;
01737    tmp->frame.samples = len ;
01738    tmp->frame.mallocd =0 ;
01739    tmp->frame.offset= 0 ;
01740    tmp->frame.src = NULL;
01741    tmp->frame.data = tmp->ast_rd_buf ;
01742 
01743    chan_misdn_trace_call(tmp->ast,3,"*->I: EVENT_READ len=%d\n",len);
01744    return &tmp->frame;
01745 }
01746 
01747 int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
01748 {
01749    struct chan_list *p;
01750    int i  = 0;
01751    
01752    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
01753    
01754    if (!p->bc ) {
01755       ast_log(LOG_WARNING, "private but no bc\n");
01756       return -1;
01757    }
01758    
01759    if (p->bc->tone != TONE_NONE)
01760       manager_send_tone(p->bc,TONE_NONE);
01761    
01762    
01763    if (p->holded ) {
01764       chan_misdn_log(5, p->bc->port, "misdn_write: Returning because holded\n");
01765       return 0;
01766    }
01767    
01768    if (p->notxtone) {
01769       chan_misdn_log(5, p->bc->port, "misdn_write: Returning because notxone\n");
01770       return 0;
01771    }
01772    
01773    if ( !(frame->subclass & prefformat)) {
01774       chan_misdn_log(0, p->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
01775    }
01776    
01777    
01778 #if MISDN_DEBUG
01779    {
01780       int i, max=5>frame->samples?frame->samples:5;
01781       
01782       printf("write2mISDN %p %d bytes: ", p, frame->samples);
01783       
01784       for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame->data)[i]);
01785       printf ("\n");
01786    }
01787 #endif
01788    chan_misdn_trace_call(ast,3,"*->I: EVENT_WRITE len=%d\n",frame->samples);
01789    i= manager_tx2misdn_frm(p->bc, frame->data, frame->samples);
01790    
01791    return 0;
01792 }
01793 
01794 
01795 enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
01796                   struct ast_channel *c1, int flags,
01797                   struct ast_frame **fo,
01798                   struct ast_channel **rc,
01799                   int timeoutms)
01800 
01801 {
01802    struct chan_list *ch1,*ch2;
01803    struct ast_channel *carr[2], *who;
01804    int to=-1;
01805    struct ast_frame *f;
01806   
01807    ch1=get_chan_by_ast(c0);
01808    ch2=get_chan_by_ast(c1);
01809 
01810    carr[0]=c0;
01811    carr[1]=c1;
01812   
01813   
01814    if (ch1 && ch2 ) ;
01815    else
01816       return -1;
01817   
01818 
01819    int bridging;
01820    misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
01821    if (bridging) {
01822       int ecwb;
01823       misdn_cfg_get( ch1->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
01824       if ( !ecwb ) {
01825          chan_misdn_log(0, ch1->bc->port, "Disabling Echo Cancellor when Bridged\n");
01826          ch1->bc->ec_enable=0;
01827          manager_ec_disable(ch1->bc);
01828       }
01829       misdn_cfg_get( ch2->bc->port, MISDN_CFG_ECHOCANCELWHENBRIDGED, &ecwb, sizeof(int));
01830       if ( !ecwb ) {
01831          chan_misdn_log(0, ch2->bc->port, "Disabling Echo Cancellor when Bridged\n");
01832          ch2->bc->ec_enable=0;
01833          manager_ec_disable(ch2->bc);
01834       }
01835       
01836       /* trying to make a mISDN_dsp conference */
01837       chan_misdn_log(0, ch1->bc->port, "I SEND: Making conference with Number:%d\n", (ch1->bc->pid<<1) +1);
01838 
01839       misdn_lib_bridge(ch1->bc,ch2->bc);
01840    }
01841    
01842    chan_misdn_log(1, ch1->bc->port, "* Makeing Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
01843   
01844    while(1) {
01845       to=-1;
01846       who = ast_waitfor_n(carr, 2, &to);
01847 
01848       if (!who) {
01849          ast_log(LOG_DEBUG,"misdn_bridge: empty read\n");
01850          continue;
01851       }
01852       f = ast_read(who);
01853     
01854       if (!f || f->frametype == AST_FRAME_CONTROL) {
01855          /* got hangup .. */
01856          *fo=f;
01857          *rc=who;
01858       
01859          break;
01860       }
01861     
01862     
01863       if (who == c0) {
01864          ast_write(c1,f);
01865       }
01866       else {
01867          ast_write(c0,f);
01868       }
01869     
01870    }
01871   
01872    if (bridging) {
01873       misdn_lib_split_bridge(ch1->bc,ch2->bc);
01874    }
01875   
01876    return 0;
01877 }
01878 
01879 /** AST INDICATIONS END **/
01880 
01881 static int start_bc_tones(struct chan_list* cl)
01882 {
01883    manager_bchannel_activate(cl->bc);
01884    manager_send_tone(cl->bc ,TONE_NONE);
01885    cl->notxtone=0;
01886    cl->norxtone=0;
01887    return 0;
01888 }
01889 
01890 static int stop_bc_tones(struct chan_list *cl)
01891 {
01892    if (cl->bc) {
01893       manager_bchannel_deactivate(cl->bc);
01894    }
01895    cl->notxtone=1;
01896    cl->norxtone=1;
01897    
01898    return 0;
01899 }
01900 
01901 
01902 struct chan_list *init_chan_list(void)
01903 {
01904    struct chan_list *cl=malloc(sizeof(struct chan_list));
01905    
01906    if (!cl) {
01907       chan_misdn_log(0, 0, "misdn_request: malloc failed!");
01908       return NULL;
01909    }
01910    
01911    memset(cl,0,sizeof(struct chan_list));
01912    
01913    return cl;
01914    
01915 }
01916 
01917 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
01918 
01919 {
01920    struct ast_channel *tmp = NULL;
01921    char group[BUFFERSIZE]="";
01922    char buf[128];
01923    char buf2[128], *ext=NULL, *port_str;
01924    char *tokb=NULL, *p=NULL;
01925    int channel=0, port=0;
01926    struct misdn_bchannel *newbc = NULL;
01927    
01928    struct chan_list *cl=init_chan_list();
01929    
01930    sprintf(buf,"%s/%s",type,(char*)data);
01931    strncpy(buf2,data, 128);
01932    buf2[127] = 0;
01933    port_str=strtok_r(buf2,"/", &tokb);
01934 
01935    ext=strtok_r(NULL,"/", &tokb);
01936 
01937    /*
01938      if (!ext) {
01939      ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITH WRONG ARGS, check extension.conf\n",ext);
01940      
01941      return NULL;
01942      }
01943    */
01944    
01945    if (port_str) {
01946       if (port_str[0]=='g' && port_str[1]==':' ) {
01947          /* We make a group call lets checkout which ports are in my group */
01948          port_str += 2;
01949          strncpy(group, port_str, BUFFERSIZE);
01950          group[127] = 0;
01951          chan_misdn_log(2, 0, " --> Group Call group: %s\n",group);
01952       } 
01953       else if ((p = strchr(port_str, ':'))) {
01954          // we have a preselected channel
01955          *p = 0;
01956          channel = atoi(++p);
01957          port = atoi(port_str);
01958          chan_misdn_log(2, port, " --> Call on preselected Channel (%d) on Port %d\n", channel, port);
01959       }
01960       else {
01961          port = atoi(port_str);
01962       }
01963       
01964       
01965    } else {
01966       ast_log(LOG_WARNING, " --> ! IND : CALL dad:%s WITHOUT PORT/Group, check extension.conf\n",ext);
01967       return NULL;
01968    }
01969 
01970    if (!ast_strlen_zero(group)) {
01971    
01972       char cfg_group[BUFFERSIZE];
01973       struct robin_list *rr = NULL;
01974 
01975       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
01976          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...");
01977          rr = get_robin_position(group);
01978       }
01979       
01980       if (rr) {
01981          int robin_channel = rr->channel;
01982          int port_start;
01983          int next_chan = 1;
01984 
01985          do {
01986             port_start = 0;
01987             for (port = misdn_cfg_get_next_port_spin(rr->port); port > 0 && port != port_start;
01988                 port = misdn_cfg_get_next_port_spin(port)) {
01989 
01990                if (!port_start)
01991                   port_start = port;
01992 
01993                if (port >= port_start)
01994                   next_chan = 1;
01995                
01996                if (port < port_start && next_chan) {
01997                   if (++robin_channel >= MAX_BCHANS) {
01998                      robin_channel = 1;
01999                   }
02000                   next_chan = 0;
02001                }
02002 
02003                misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02004                
02005                if (!strcasecmp(cfg_group, group)) {
02006                   int l1, port_up;
02007                
02008                   misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
02009                   port_up = misdn_lib_port_up(port);
02010                   
02011                   if ((l1 && port_up) || !l1)   {
02012                      newbc = misdn_lib_get_free_bc(port, robin_channel);
02013                      if (newbc) {
02014                         chan_misdn_log(4, port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
02015                         if (port_up)
02016                            chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
02017                         rr->port = newbc->port;
02018                         rr->channel = newbc->channel;
02019                         break;
02020                      }
02021                   }
02022                }
02023             }
02024          } while (!newbc && robin_channel != rr->channel);
02025          
02026          if (!newbc)
02027             chan_misdn_log(4, port, " Failed! No free channel in group %d!", group);
02028       }
02029       
02030       else {      
02031          for (port=misdn_cfg_get_next_port(0); port > 0;
02032              port=misdn_cfg_get_next_port(port)) {
02033             
02034             misdn_cfg_get( port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
02035             
02036             if (!strcasecmp(cfg_group, group)) {
02037                int l1, port_up;
02038                
02039                misdn_cfg_get( 0, MISDN_GEN_L1_INFO_OK, &l1, sizeof(l1));
02040                port_up = misdn_lib_port_up(port);
02041 
02042                chan_misdn_log(4, port, "def_l1:%d, portup:%d\n", l1, port_up);
02043                
02044                if ((l1 && port_up) || !l1)   {
02045                   newbc = misdn_lib_get_free_bc(port, 0);
02046                   if (newbc)
02047                      break;
02048                }
02049             }
02050          }
02051       }
02052       
02053    } else {
02054       if (channel)
02055          chan_misdn_log(1, port," --> preselected_channel: %d\n",channel);
02056       newbc = misdn_lib_get_free_bc(port, channel);
02057    }
02058    
02059    if (!newbc) {
02060       chan_misdn_log(1, 0, " --> ! No free channel chan ext:%s even after Group Call\n",ext);
02061       chan_misdn_log(1, 0, " --> SEND: State Down\n");
02062       return NULL;
02063    }
02064    
02065    cl->bc=newbc;
02066    
02067    tmp = misdn_new(cl, AST_STATE_RESERVED, buf, "default", ext, ext, format, port, channel);
02068    
02069    return tmp;
02070 }
02071 
02072 
02073 struct ast_channel_tech misdn_tech = {
02074    .type="mISDN",
02075    .description="Channel driver for mISDN Support (Bri/Pri)",
02076    .capabilities= AST_FORMAT_ALAW ,
02077    .requester=misdn_request,
02078    .send_digit=misdn_digit,
02079    .call=misdn_call,
02080    .bridge=misdn_bridge, 
02081    .hangup=misdn_hangup,
02082    .answer=misdn_answer,
02083    .read=misdn_read,
02084    .write=misdn_write,
02085    .indicate=misdn_indication,
02086    .fixup=misdn_fixup,
02087    .properties=0
02088    /* .transfer=misdn_transfer */
02089 };
02090 
02091 struct ast_channel_tech misdn_tech_wo_bridge = {
02092    .type="mISDN",
02093    .description="Channel driver for mISDN Support (Bri/Pri)",
02094    .capabilities=AST_FORMAT_ALAW ,
02095    .requester=misdn_request,
02096    .send_digit=misdn_digit,
02097    .call=misdn_call,
02098    .hangup=misdn_hangup,
02099    .answer=misdn_answer,
02100    .read=misdn_read,
02101    .write=misdn_write,
02102    .indicate=misdn_indication,
02103    .fixup=misdn_fixup,
02104    .properties=0
02105    /* .transfer=misdn_transfer */
02106 };
02107 
02108 
02109 unsigned long glob_channel=0;
02110 
02111 struct ast_channel *misdn_new(struct chan_list *chlist, int state, char * name, char * context, char *exten, char *callerid, int format, int port, int c)
02112 {
02113    struct ast_channel *tmp;
02114    
02115    tmp = ast_channel_alloc(1);
02116    
02117    if (tmp) {
02118       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s ctx:%s\n",exten,callerid, context);
02119       
02120       
02121       if (c<=0) {
02122          c=glob_channel++;
02123          snprintf(tmp->name, sizeof(tmp->name), "%s/%d-u%d",
02124              type, port, c);
02125       } else {
02126          snprintf(tmp->name, sizeof(tmp->name), "%s/%d-%d",
02127              type, port, c);
02128       }
02129       
02130       tmp->type = type;
02131     
02132       tmp->nativeformats = prefformat;
02133       tmp->readformat = format;
02134       tmp->writeformat = format;
02135     
02136       tmp->tech_pvt = chlist;
02137 
02138       int bridging;
02139       misdn_cfg_get( 0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
02140       if (bridging)
02141          tmp->tech = &misdn_tech;
02142       else
02143          tmp->tech = &misdn_tech_wo_bridge;
02144     
02145     
02146       tmp->writeformat = format;
02147       tmp->readformat = format;
02148       tmp->priority=1;
02149     
02150       
02151       if (context) {
02152          ast_copy_string(tmp->context, context, sizeof(tmp->context));
02153       }  else {
02154          chan_misdn_log(1,0,"misdn_new: no context given.\n");
02155       }
02156       
02157       if (exten) {
02158          ast_copy_string(tmp->exten, exten,  sizeof(tmp->exten));
02159       } else {
02160          chan_misdn_log(1,0,"misdn_new: no exten given.\n");
02161       }
02162       
02163       if (callerid) {
02164          char *cid_name, *cid_num;
02165       
02166          ast_callerid_parse(callerid, &cid_name, &cid_num);
02167          ast_set_callerid(tmp, cid_num, cid_name, cid_num);
02168       }
02169 
02170       {
02171          if (pipe(chlist->pipe)<0)
02172             perror("Pipe failed\n");
02173          
02174          tmp->fds[0]=chlist->pipe[0];
02175          
02176       }
02177       
02178       if (chlist->bc) {
02179          int port=chlist->bc->port;
02180          misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
02181          
02182          {
02183             char buf[256];
02184             ast_group_t pg,cg;
02185             
02186             misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02187             misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02188             
02189             chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
02190             tmp->pickupgroup=pg;
02191             tmp->callgroup=cg;
02192          }
02193          misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
02194          misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
02195          chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
02196          
02197       } else {
02198          chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
02199       }
02200       
02201       ast_setstate(tmp, state);
02202       if (state == AST_STATE_RING)
02203          tmp->rings = 1;
02204       else
02205          tmp->rings = 0;
02206    } else {
02207       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02208       chan_misdn_log(0,0,"Unable to allocate channel structure\n");
02209    }
02210    
02211    return tmp;
02212 }
02213 
02214 
02215 
02216 int misdn_tx2ast_frm(struct chan_list * tmp, char * buf,  int len )
02217 {
02218    struct ast_frame frame;
02219    
02220    /* If in hold state we drop frame .. */
02221    if (tmp->holded ) return 0;
02222 
02223    switch(tmp->state) {
02224    case MISDN_CLEANING:
02225    case MISDN_EXTCANTMATCH:
02226    case MISDN_WAITING4DIGS:
02227       return 0;
02228    default:
02229       break;
02230    }
02231    
02232    if (tmp->norxtone) {
02233       chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
02234       return 0;
02235    }
02236    
02237    frame.frametype  = AST_FRAME_VOICE;
02238    frame.subclass = AST_FORMAT_ALAW;
02239    frame.datalen = len;
02240    frame.samples = len ;
02241    frame.mallocd =0 ;
02242    frame.offset= 0 ;
02243    frame.src = NULL;
02244    frame.data = buf ;
02245    
02246    if (tmp->faxdetect || tmp->ast_dsp ) {
02247       struct ast_frame *f,*f2;
02248       if (tmp->trans)
02249          f2=ast_translate(tmp->trans, &frame,0);
02250       else {
02251          chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02252          return 0;
02253       }
02254       
02255       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02256       if (f && (f->frametype == AST_FRAME_DTMF)) {
02257          ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
02258          if (f->subclass == 'f' && tmp->faxdetect) {
02259             /* Fax tone -- Handle and return NULL */
02260             struct ast_channel *ast = tmp->ast;
02261             if (!tmp->faxhandled) {
02262                tmp->faxhandled++;
02263                if (strcmp(ast->exten, "fax")) {
02264                   if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
02265                      if (option_verbose > 2)
02266                         ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
02267                      /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02268                      pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02269                      if (ast_async_goto(ast, ast->context, "fax", 1))
02270                         ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
02271                   } else
02272                      ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
02273                } else
02274                   ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02275             } else
02276                ast_log(LOG_DEBUG, "Fax already handled\n");
02277             frame.frametype = AST_FRAME_NULL;
02278             frame.subclass = 0;
02279             f = &frame;
02280          }  else if ( tmp->ast_dsp) {
02281             struct ast_frame fr;
02282             memset(&fr, 0 , sizeof(fr));
02283             fr.frametype = AST_FRAME_DTMF;
02284             fr.subclass = f->subclass ;
02285             fr.src=NULL;
02286             fr.data = NULL ;
02287             fr.datalen = 0;
02288             fr.samples = 0 ;
02289             fr.mallocd =0 ;
02290             fr.offset= 0 ;
02291             
02292             chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
02293             ast_queue_frame(tmp->ast, &fr);
02294             
02295             frame.frametype = AST_FRAME_NULL;
02296             frame.subclass = 0;
02297             f = &frame;
02298          }
02299       }
02300    }
02301    
02302    if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
02303 #if MISDN_DEBUG
02304       int i, max=5>len?len:5;
02305     
02306       printf("write2* %p %d bytes: ",tmp, len);
02307     
02308       for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
02309       printf ("\n");
02310 #endif
02311       chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
02312       ast_queue_frame(tmp->ast,&frame);
02313       
02314    }  else {
02315       ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
02316    }
02317    
02318    return 0;
02319 }
02320 
02321 /** Channel Queue ***/
02322 
02323 struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
02324 {
02325    struct chan_list *help=list;
02326    for (;help; help=help->next) {
02327       if (help->l3id == l3id ) return help;
02328    }
02329   
02330    chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
02331   
02332    return NULL;
02333 }
02334 
02335 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
02336 {
02337    struct chan_list *help=list;
02338    for (;help; help=help->next) {
02339       if (help->bc == bc) return help;
02340    }
02341   
02342    chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02343   
02344    return NULL;
02345 }
02346 
02347 
02348 struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
02349 {
02350    struct chan_list *help=list;
02351    
02352    chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
02353    for (;help; help=help->next) {
02354       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
02355       if (help->bc->port == bc->port
02356           && help->bc->holded ) return help;
02357    }
02358    
02359    chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02360   
02361    return NULL;
02362 }
02363 
02364 void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
02365 {
02366    chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
02367   
02368    ast_mutex_lock(&cl_te_lock);
02369    if (!*list) {
02370       *list = chan;
02371    } else {
02372       struct chan_list *help=*list;
02373       for (;help->next; help=help->next); 
02374       help->next=chan;
02375    }
02376    chan->next=NULL;
02377    ast_mutex_unlock(&cl_te_lock);
02378 }
02379 
02380 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
02381 {
02382    if (chan->dsp) 
02383       ast_dsp_free(chan->dsp);
02384    if (chan->trans)
02385       ast_translator_free_path(chan->trans);
02386    
02387 
02388    ast_mutex_lock(&cl_te_lock);
02389    if (!*list) {
02390       ast_mutex_unlock(&cl_te_lock);
02391       return;
02392    }
02393   
02394    if (*list == chan) {
02395       *list=(*list)->next;
02396       ast_mutex_unlock(&cl_te_lock);
02397       return ;
02398    }
02399   
02400    {
02401       struct chan_list *help=*list;
02402       for (;help->next; help=help->next) {
02403          if (help->next == chan) {
02404             help->next=help->next->next;
02405             ast_mutex_unlock(&cl_te_lock);
02406             return;
02407          }
02408       }
02409    }
02410    
02411    ast_mutex_unlock(&cl_te_lock);
02412 }
02413 
02414 /** Channel Queue End **/
02415 
02416 
02417 
02418 /** Isdn asks us to release channel, pendant to misdn_hangup **/
02419 static void release_chan(struct misdn_bchannel *bc) {
02420    struct ast_channel *ast=NULL;
02421    
02422    {
02423       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02424       if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
02425       
02426       release_lock;
02427       if (ch->ast) {
02428          ast=ch->ast;
02429       } 
02430       release_unlock;
02431       
02432       chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
02433       if (ch) {
02434          if (ast)
02435             chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
02436          
02437          close(ch->pipe[0]);
02438          close(ch->pipe[1]);
02439          
02440          if (ast && MISDN_ASTERISK_PVT(ast)) {
02441             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));
02442             chan_misdn_log(3, bc->port, " --> * State Down\n");
02443             /* copy cause */
02444             send_cause2ast(ast,bc);
02445             
02446             MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02447             
02448       
02449             if (ast->_state != AST_STATE_RESERVED) {
02450                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
02451                ast_setstate(ast, AST_STATE_DOWN);
02452             }
02453             
02454             switch(ch->state) {
02455             case MISDN_EXTCANTMATCH:
02456             case MISDN_WAITING4DIGS:
02457             {
02458                chan_misdn_log(3,  bc->port, " --> * State Wait4dig | ExtCantMatch\n");
02459                ast_hangup(ast);
02460             }
02461             break;
02462             
02463             case MISDN_DIALING:
02464             case MISDN_CALLING_ACKNOWLEDGE:
02465             case MISDN_PROGRESS:
02466                chan_misdn_log(2,  bc->port, "* --> In State Dialin\n");
02467                chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02468                
02469 
02470                ast_queue_hangup(ast);
02471                break;
02472             case MISDN_CALLING:
02473                
02474                chan_misdn_log(2,  bc->port, "* --> In State Callin\n");
02475                
02476                if (!bc->nt) {
02477                   chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02478                   ast_queue_hangup(ast);
02479                } else {
02480                   chan_misdn_log(2,  bc->port, "* --> Hangup\n");
02481                   ast_queue_hangup(ast);
02482                   //ast_hangup(ast);
02483                }
02484                break;
02485                
02486             case MISDN_CLEANING:
02487                /* this state comes out of ast so we mustnt call a ast function ! */
02488                chan_misdn_log(2,  bc->port, "* --> In StateCleaning\n");
02489                break;
02490             case MISDN_HOLD_DISCONNECT:
02491                chan_misdn_log(2,  bc->port, "* --> In HOLD_DISC\n");
02492                break;
02493             default:
02494                chan_misdn_log(2,  bc->port, "* --> In State Default\n");
02495                chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02496    
02497                
02498                if (ast && MISDN_ASTERISK_PVT(ast)) {
02499                   ast_queue_hangup(ast);
02500                } else {
02501                   chan_misdn_log (0,  bc->port, "!! Not really queued!\n");
02502                }
02503             }
02504          }
02505          cl_dequeue_chan(&cl_te, ch);
02506          
02507          free(ch);
02508       } else {
02509          /* chan is already cleaned, so exiting  */
02510       }
02511    }
02512 }
02513 /*** release end **/
02514 
02515 void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
02516 {
02517    chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
02518    
02519    tmp_ch->state=MISDN_HOLD_DISCONNECT;
02520   
02521    ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
02522 
02523    holded_chan->state=MISDN_CONNECTED;
02524    holded_chan->holded=0;
02525    misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
02526    
02527    ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
02528 }
02529 
02530 
02531 void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
02532 {
02533    char predial[256]="";
02534    char *p = predial;
02535   
02536    struct ast_frame fr;
02537   
02538    strncpy(predial, ast->exten, sizeof(predial) -1 );
02539   
02540    ch->state=MISDN_DIALING;
02541    
02542    if (bc->nt) {
02543       int ret; 
02544       ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02545    } else {
02546       int ret;
02547       if ( misdn_lib_is_ptp(bc->port)) {
02548          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02549       } else {
02550          ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
02551       }
02552    }
02553 
02554    manager_send_tone(bc,TONE_DIAL);  
02555   
02556    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));
02557   
02558    strncpy(ast->exten,"s", 2);
02559   
02560    if (ast_pbx_start(ast)<0) {
02561       ast=NULL;
02562       manager_send_tone(bc,TONE_BUSY);
02563       if (bc->nt)
02564          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02565       else
02566          misdn_lib_send_event(bc, EVENT_DISCONNECT );
02567    }
02568   
02569   
02570    while (!ast_strlen_zero(p) ) {
02571       fr.frametype = AST_FRAME_DTMF;
02572       fr.subclass = *p ;
02573       fr.src=NULL;
02574       fr.data = NULL ;
02575       fr.datalen = 0;
02576       fr.samples = 0 ;
02577       fr.mallocd =0 ;
02578       fr.offset= 0 ;
02579 
02580       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02581          ast_queue_frame(ch->ast, &fr);
02582       }
02583       p++;
02584    }
02585 }
02586 
02587 
02588 
02589 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
02590    
02591    ast->hangupcause=bc->cause;
02592    
02593    switch ( bc->cause) {
02594       
02595    case 1: /** Congestion Cases **/
02596    case 2:
02597    case 3:
02598    case 4:
02599    case 22:
02600    case 27:
02601       chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
02602       
02603       ast_queue_control(ast, AST_CONTROL_CONGESTION);
02604       break;
02605       
02606    case 21:
02607    case 17: /* user busy */
02608       chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
02609       
02610       ast_queue_control(ast, AST_CONTROL_BUSY);
02611       
02612       break;
02613    }
02614 }
02615 
02616 /************************************************************/
02617 /*  Receive Events from isdn_lib  here                     */
02618 /************************************************************/
02619 enum event_response_e
02620 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
02621 {
02622    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02623    
02624    if (!ch)
02625       ch=find_chan_by_l3id(cl_te, bc->l3_id);
02626    
02627    if (event != EVENT_BCHAN_DATA) { /*  Debug Only Non-Bchan */
02628       chan_misdn_log(1, bc->port, "I IND :%s oad:%s dad:%s port:%d\n", manager_isdn_get_info(event), bc->oad, bc->dad, bc->port);
02629       misdn_lib_log_ies(bc);
02630    }
02631    
02632    if (event != EVENT_SETUP) {
02633       if (!ch) {
02634          if (event != EVENT_CLEANUP )
02635             ast_log(LOG_WARNING, "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);
02636          return -1;
02637       }
02638    }
02639    
02640    if (ch ) {
02641       switch (event) {
02642       case EVENT_RELEASE:
02643       case EVENT_RELEASE_COMPLETE:
02644       case EVENT_CLEANUP:
02645          break;
02646       default:
02647          if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02648             if (event!=EVENT_BCHAN_DATA)
02649                ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
02650             return -1;
02651          }
02652       }
02653    }
02654    
02655    
02656    switch (event) {
02657    case EVENT_NEW_L3ID:
02658       ch->l3id=bc->l3_id;
02659       break;
02660 
02661    case EVENT_NEW_BC:
02662       if (bc)
02663          ch->bc=bc;
02664       break;
02665       
02666    case EVENT_DTMF_TONE:
02667    {
02668       /*  sending INFOS as DTMF-Frames :) */
02669       struct ast_frame fr;
02670       memset(&fr, 0 , sizeof(fr));
02671       fr.frametype = AST_FRAME_DTMF;
02672       fr.subclass = bc->dtmf ;
02673       fr.src=NULL;
02674       fr.data = NULL ;
02675       fr.datalen = 0;
02676       fr.samples = 0 ;
02677       fr.mallocd =0 ;
02678       fr.offset= 0 ;
02679       
02680       chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
02681       
02682       ast_queue_frame(ch->ast, &fr);
02683    }
02684    break;
02685    case EVENT_STATUS:
02686       break;
02687     
02688    case EVENT_INFORMATION:
02689    {
02690       int stop_tone;
02691       misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
02692       if ( stop_tone && bc->tone != TONE_NONE) {
02693          manager_send_tone(bc,TONE_NONE);
02694       }
02695       
02696       if (ch->state == MISDN_WAITING4DIGS ) {
02697          /*  Ok, incomplete Setup, waiting till extension exists */
02698          {
02699             int l = sizeof(bc->dad);
02700             strncat(bc->dad,bc->info_dad, l);
02701             bc->dad[l-1] = 0;
02702          }
02703          
02704          
02705          {
02706             int l = sizeof(ch->ast->exten);
02707             strncpy(ch->ast->exten, bc->dad, l);
02708             ch->ast->exten[l-1] = 0;
02709          }
02710 /*       chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
02711          
02712          char bc_context[BUFFERSIZE];
02713          misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02714          if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02715             chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
02716             manager_send_tone(bc,TONE_BUSY);
02717             ch->state=MISDN_EXTCANTMATCH;
02718             bc->out_cause=1;
02719             if (bc->nt)
02720                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02721             else
02722                misdn_lib_send_event(bc, EVENT_DISCONNECT );
02723             break;
02724          }
02725          if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02726             ch->state=MISDN_DIALING;
02727      
02728             manager_send_tone(bc,TONE_NONE);
02729 /*          chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
02730             if (ast_pbx_start(ch->ast)<0) {
02731                chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
02732                manager_send_tone(bc,TONE_BUSY);
02733                if (bc->nt)
02734                   misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02735                else
02736                   misdn_lib_send_event(bc, EVENT_DISCONNECT );
02737             }
02738          }
02739    
02740       } else {
02741          /*  sending INFOS as DTMF-Frames :) */
02742          struct ast_frame fr;
02743          fr.frametype = AST_FRAME_DTMF;
02744          fr.subclass = bc->info_dad[0] ;
02745          fr.src=NULL;
02746          fr.data = NULL ;
02747          fr.datalen = 0;
02748          fr.samples = 0 ;
02749          fr.mallocd =0 ;
02750          fr.offset= 0 ;
02751 
02752          
02753          int digits;
02754          misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
02755          if (ch->state != MISDN_CONNECTED ) {
02756             if (digits) {
02757                int l = sizeof(bc->dad);
02758                strncat(bc->dad,bc->info_dad, l);
02759                bc->dad[l-1] = 0;
02760                l = sizeof(ch->ast->exten);
02761                strncpy(ch->ast->exten, bc->dad, l);
02762                ch->ast->exten[l-1] = 0;
02763 
02764                ast_cdr_update(ch->ast);
02765             }
02766             
02767             ast_queue_frame(ch->ast, &fr);
02768          }
02769          
02770       }
02771    }
02772    break;
02773    case EVENT_SETUP:
02774    {
02775       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02776       if (ch && ch->state != MISDN_NOTHING ) {
02777          chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
02778          return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
02779       }
02780    }
02781    
02782    int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
02783    if (!bc->nt && ! msn_valid) {
02784       chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
02785       return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
02786    }
02787    
02788    print_bearer(bc);
02789     
02790    {
02791       struct chan_list *ch=init_chan_list();
02792       struct ast_channel *chan;
02793       char name[128];
02794       if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
02795       
02796       ch->bc = bc;
02797       ch->l3id=bc->l3_id;
02798       ch->addr=bc->addr;
02799       ch->orginator = ORG_MISDN;
02800 
02801       
02802       {
02803          char prefix[BUFFERSIZE]="";
02804          switch( bc->onumplan ) {
02805          case NUMPLAN_INTERNATIONAL:
02806             misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02807             break;
02808      
02809          case NUMPLAN_NATIONAL:
02810             misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02811             break;
02812      
02813      
02814          case NUMPLAN_SUBSCRIBER:
02815             /* dunno what to do here ? */
02816             break;
02817 
02818          case NUMPLAN_UNKNOWN:
02819             break;
02820          default:
02821             break;
02822          }
02823 
02824          {
02825             int l = strlen(prefix) + strlen(bc->oad);
02826             char tmp[l+1];
02827             strcpy(tmp,prefix);
02828             strcat(tmp,bc->oad);
02829             strcpy(bc->oad,tmp);
02830          }
02831          
02832          if (!ast_strlen_zero(bc->oad))
02833             sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
02834          else
02835             sprintf(name,"mISDN/%d",bc->port);
02836 
02837 
02838          if (!ast_strlen_zero(bc->dad)) {
02839             strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
02840             bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
02841          }
02842          
02843          if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02844             strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
02845             bc->dad[sizeof(bc->dad)-1] = 0;
02846          }
02847          prefix[0] = 0;
02848          
02849          switch( bc->dnumplan ) {
02850          case NUMPLAN_INTERNATIONAL:
02851             misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02852             break;
02853             
02854          case NUMPLAN_NATIONAL:
02855             misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02856             break;
02857             
02858             
02859          case NUMPLAN_SUBSCRIBER:
02860             /* dunno what to do here ? */
02861             break;
02862             
02863          case NUMPLAN_UNKNOWN:
02864             break;
02865          default:
02866             break;
02867          }
02868       
02869          {
02870             int l = strlen(prefix) + strlen(bc->dad);
02871             char tmp[l+1];
02872             strcpy(tmp,prefix);
02873             strcat(tmp,bc->dad);
02874             strcpy(bc->dad,tmp);
02875          }
02876          
02877          char bc_context[BUFFERSIZE];
02878          misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02879          chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
02880          
02881          if (!chan) {
02882             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02883             return 0;
02884          }
02885          
02886          ch->ast = chan;
02887          pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
02888          
02889       }
02890 
02891       
02892 
02893       chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
02894       
02895       if ( bc->pres ) {
02896          chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
02897       }  else {
02898          chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
02899       }
02900       
02901       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
02902       chan->transfercapability=bc->capability;
02903       
02904       switch (bc->capability) {
02905       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02906          pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
02907          break;
02908       default:
02909          pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
02910       }
02911 
02912       /** queue new chan **/
02913       cl_queue_chan(&cl_te, ch) ;
02914 
02915       
02916       /*
02917         added support for s extension hope it will help those poor cretains
02918         which haven't overlap dial.
02919       */
02920       {
02921          
02922          misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));        
02923          
02924       }
02925 
02926       {
02927          int eb3;
02928          
02929          misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
02930          bc->early_bconnect=eb3;
02931          
02932       }
02933 
02934       {
02935          int ec, ectr;
02936          
02937          misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
02938          
02939          misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
02940          if (ec == 1 ) {
02941             bc->ec_enable=1;
02942          } else if ( ec > 1 ) {
02943             bc->ec_enable=1;
02944             bc->ec_deftaps=ec;
02945          }
02946          
02947          if ( ectr>=0 ) {
02948             bc->ec_training=ectr;
02949          }
02950       }
02951       
02952 
02953       if (bc->urate>0) {
02954          char buf[16];
02955          snprintf(buf,16,"%d",bc->urate);
02956          pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
02957       }
02958 
02959 
02960 
02961       /**
02962          from here on  we start the PBX, so no configuration should
02963          be considered anymore
02964       **/
02965       
02966       int ai;
02967       misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
02968       if ( ai ) {
02969          do_immediate_setup(bc, ch , chan);
02970          break;
02971       }
02972       
02973          
02974       int immediate;
02975       misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
02976       
02977       if (ast_strlen_zero(bc->orig_dad) && immediate ) {
02978          do_immediate_setup(bc, ch , chan);
02979          break;
02980       }
02981       
02982       /* Check for Pickup Request first */
02983       if (!strcmp(chan->exten, ast_pickup_ext())) {
02984          int ret;/** Sending SETUP_ACK**/
02985          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02986    
02987          if (ast_pickup_call(chan)) {
02988             ast_hangup(chan);
02989          } else {
02990             ch->state = MISDN_CALLING_ACKNOWLEDGE;
02991      
02992             ch->ast=NULL;
02993      
02994             ast_setstate(chan, AST_STATE_DOWN);
02995             ast_hangup(chan); 
02996      
02997             break;
02998          }
02999       }
03000       
03001       /** Now after we've finished configuring our channel object
03002           we'll jump into the dialplan **/
03003       
03004       char bc_context[BUFFERSIZE];
03005       misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
03006       if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03007          chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
03008          manager_send_tone(bc,TONE_BUSY);
03009          ch->state=MISDN_EXTCANTMATCH;
03010          bc->out_cause=1;
03011          if (bc->nt)
03012             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03013          else
03014             misdn_lib_send_event(bc, EVENT_DISCONNECT );
03015          break;
03016       }
03017       
03018       if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03019          ch->state=MISDN_DIALING;
03020    
03021          if (bc->nt) {
03022             int ret; 
03023             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03024          } else {
03025             int ret;
03026             ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
03027          }
03028    
03029          if (ast_pbx_start(chan)<0) {
03030             chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03031             chan=NULL;
03032             manager_send_tone(bc,TONE_BUSY);
03033             if (bc->nt)
03034                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03035             else
03036                misdn_lib_send_event(bc, EVENT_DISCONNECT );
03037          }
03038       } else {
03039          int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03040          if (ret == -ENOCHAN) {
03041             ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
03042             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03043          }
03044          /*  send tone to phone :) */
03045          
03046          int stop_tone;
03047          misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03048          if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) 
03049             manager_send_tone(bc,TONE_NONE);
03050          else
03051             manager_send_tone(bc,TONE_DIAL);
03052    
03053          ch->state=MISDN_WAITING4DIGS;
03054       }
03055       
03056    }
03057    break;
03058    case EVENT_SETUP_ACKNOWLEDGE:
03059    {
03060       ch->state = MISDN_CALLING_ACKNOWLEDGE;
03061       if (!ast_strlen_zero(bc->infos_pending)) {
03062          /* TX Pending Infos */
03063          
03064          {
03065             int l = sizeof(bc->dad);
03066             strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
03067             bc->dad[l-1] = 0;
03068          }  
03069          {
03070             int l = sizeof(ch->ast->exten);
03071             strncpy(ch->ast->exten, bc->dad, l);
03072             ch->ast->exten[l-1] = 0;
03073          }
03074          {
03075             int l = sizeof(bc->info_dad);
03076             strncpy(bc->info_dad, bc->infos_pending, l);
03077             bc->info_dad[l-1] = 0;
03078          }
03079          strncpy(bc->infos_pending,"", 1);
03080 
03081          misdn_lib_send_event(bc, EVENT_INFORMATION);
03082       }
03083    }
03084    break;
03085    case EVENT_PROCEEDING:
03086    {
03087       
03088       if ( misdn_cap_is_speech(bc->capability) &&
03089            misdn_inband_avail(bc) ) {
03090          start_bc_tones(ch);
03091       }
03092    }
03093    break;
03094    case EVENT_PROGRESS:
03095       if (!bc->nt ) {
03096          if ( misdn_cap_is_speech(bc->capability) &&
03097               misdn_inband_avail(bc)
03098             ) {
03099             start_bc_tones(ch);
03100          }
03101          
03102          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
03103          
03104          ch->state=MISDN_PROGRESS;
03105       }
03106       break;
03107       
03108       
03109    case EVENT_ALERTING:
03110    {
03111       ch->state = MISDN_ALERTING;
03112       
03113       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
03114       ast_setstate(ch->ast, AST_STATE_RINGING);
03115       
03116       cb_log(1,bc->port,"Set State Ringing\n");
03117       
03118       if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
03119           start_bc_tones(ch);
03120        }
03121    }
03122    break;
03123    case EVENT_CONNECT:
03124       misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
03125    case EVENT_CONNECT_ACKNOWLEDGE:
03126    {
03127       bc->state=STATE_CONNECTED;
03128       
03129       ch->l3id=bc->l3_id;
03130       ch->addr=bc->addr;
03131       
03132       start_bc_tones(ch);
03133       
03134       chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
03135       
03136       ch->state = MISDN_CONNECTED;
03137       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
03138    }
03139    break;
03140    case EVENT_DISCONNECT:
03141    {
03142       
03143       struct chan_list *holded_ch=find_holded(cl_te, bc);
03144       
03145       
03146       send_cause2ast(ch->ast,bc);
03147 
03148       if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
03149          /* If there's inband information available (e.g. a
03150             recorded message saying what was wrong with the
03151             dialled number, or perhaps even giving an
03152             alternative number, then play it instead of
03153             immediately releasing the call */
03154          start_bc_tones(ch);
03155          break;
03156       }
03157       
03158       /*Check for holded channel, to implement transfer*/
03159       if (holded_ch ) {
03160          if  (ch->state == MISDN_CONNECTED ) {
03161             misdn_transfer_bc(ch, holded_ch) ;
03162             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03163             break;
03164          }
03165       }
03166       
03167       stop_bc_tones(ch);
03168       bc->out_cause=16;
03169       misdn_lib_send_event(bc,EVENT_RELEASE);
03170       
03171    }
03172    break;
03173    
03174    case EVENT_RELEASE:
03175       {
03176          
03177          switch ( bc->cause) {
03178             
03179          case -1:
03180             /*
03181               OK, it really sucks, this is a RELEASE from NT-Stack So we take
03182               it and return easylie, It seems that we've send a DISCONNECT
03183               before, so we should RELEASE_COMPLETE after that Disconnect
03184               (looks like ALERTING State at misdn_hangup !!
03185             */
03186             return RESPONSE_OK;
03187             break;
03188          }
03189          
03190          
03191          bc->out_cause=16;
03192          
03193          stop_bc_tones(ch);
03194          release_chan(bc);
03195       }
03196       break;
03197    case EVENT_RELEASE_COMPLETE:
03198    {
03199       stop_bc_tones(ch);
03200       release_chan(bc);
03201    }
03202    break;
03203    
03204    case EVENT_BCHAN_DATA:
03205    {
03206       chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
03207       
03208       if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
03209          misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
03210       } else {
03211          int len=bc->bframe_len;
03212          int free=misdn_ibuf_freecount(bc->astbuf);
03213          
03214          
03215          if (bc->bframe_len > free) {
03216             ast_log(LOG_DEBUG, "sbuf overflow!\n");
03217             len=misdn_ibuf_freecount(bc->astbuf);
03218 
03219             if (len == 0) {
03220                ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
03221             }
03222          }
03223          
03224          misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
03225          
03226          {
03227             char blah[1]="\0";
03228 #ifdef FLATTEN_JITTER
03229             {
03230                struct timeval tv;
03231                gettimeofday(&tv,NULL);
03232                
03233                if (tv.tv_usec % 10000 > 0 ) {
03234                   write(ch->pipe[1], blah,sizeof(blah));
03235                   bc->time_usec=tv.tv_usec;
03236                }
03237             }
03238 #else
03239             write(ch->pipe[1], blah,sizeof(blah));
03240 #endif
03241             
03242             
03243          }
03244       }
03245       
03246    }
03247    break;
03248    case EVENT_TIMEOUT:
03249       break; /* Ignore now .. */
03250       {
03251          switch (ch->state) {
03252          case MISDN_CALLING:
03253             chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
03254                break;
03255          case MISDN_DIALING:
03256          case MISDN_PROGRESS:
03257             break;
03258          default:
03259             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03260          }
03261       }
03262       break;
03263    case EVENT_CLEANUP:
03264    {
03265       stop_bc_tones(ch);
03266       release_chan(bc);
03267    }
03268    break;
03269     
03270    /***************************/
03271    /** Suplementary Services **/
03272    /***************************/
03273    case EVENT_RETRIEVE:
03274    {
03275       struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
03276       ch->state = MISDN_CONNECTED;
03277       
03278       if (hold_ast) {
03279          ast_moh_stop(hold_ast);
03280       }
03281       
03282       if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
03283          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
03284       
03285       
03286    }
03287    break;
03288     
03289    case EVENT_HOLD:
03290    {
03291       int hold_allowed;
03292       misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
03293       
03294       if (!hold_allowed) {
03295          chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
03296          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03297          break;
03298       }
03299 
03300       {
03301          struct chan_list *holded_ch=find_holded(cl_te, bc);
03302          if (holded_ch) {
03303             misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03304             chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
03305             break;
03306          }
03307       }
03308       
03309       if (AST_BRIDGED_P(ch->ast)){
03310          ch->state = MISDN_HOLDED;
03311          ch->l3id = bc->l3_id;
03312          
03313          ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
03314          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
03315       } else {
03316          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03317          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
03318       }
03319    } 
03320    break;
03321    default:
03322       ast_log(LOG_WARNING, "Got Unknown Event\n");
03323       break;
03324    }
03325    
03326    return RESPONSE_OK;
03327 }
03328 
03329 /** TE STUFF END **/
03330 
03331 /******************************************
03332  *
03333  *   Asterisk Channel Endpoint END
03334  *
03335  *
03336  *******************************************/
03337 
03338 
03339 int clearl3_true ( void ) {
03340    int default_clearl3;
03341    misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
03342    return default_clearl3;
03343 }
03344 
03345 int g_config_initialized=0;
03346 
03347 int load_module(void)
03348 {
03349    int i;
03350    
03351    char ports[256]="";
03352    
03353    max_ports=misdn_lib_maxports_get();
03354    
03355    if (max_ports<=0) {
03356       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
03357       return -1;
03358    }
03359    
03360    
03361    misdn_cfg_init(max_ports);
03362    g_config_initialized=1;
03363    
03364    misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
03365    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
03366    for (i = 1; i <= max_ports; i++)
03367       misdn_debug[i] = misdn_debug[0];
03368    misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
03369 
03370    
03371    {
03372       char tempbuf[BUFFERSIZE];
03373       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
03374       if (strlen(tempbuf))
03375          tracing = 1;
03376    }
03377 
03378    ast_mutex_init(&cl_te_lock);
03379    ast_mutex_init(&release_lock_mutex);
03380 
03381    misdn_cfg_get_ports_string(ports);
03382    if (strlen(ports))
03383       chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
03384    
03385    {
03386       struct misdn_lib_iface iface = {
03387          .cb_event = cb_events,
03388          .cb_log = chan_misdn_log,
03389          .cb_clearl3_true = clearl3_true
03390       };
03391       if (misdn_lib_init(ports, &iface, NULL))
03392          chan_misdn_log(0, 0, "No te ports initialized\n");
03393    }
03394 
03395 
03396    {
03397       if (ast_channel_register(&misdn_tech)) {
03398          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
03399          unload_module();
03400          return -1;
03401       }
03402    }
03403   
03404    ast_cli_register(&cli_send_display);
03405    ast_cli_register(&cli_send_cd);
03406    ast_cli_register(&cli_send_digit);
03407    ast_cli_register(&cli_toggle_echocancel);
03408    ast_cli_register(&cli_set_tics);
03409 
03410    ast_cli_register(&cli_show_cls);
03411    ast_cli_register(&cli_show_cl);
03412    ast_cli_register(&cli_show_config);
03413    ast_cli_register(&cli_show_port);
03414    ast_cli_register(&cli_show_stacks);
03415 
03416    ast_cli_register(&cli_restart_port);
03417    ast_cli_register(&cli_port_up);
03418    ast_cli_register(&cli_set_debug);
03419    ast_cli_register(&cli_set_crypt_debug);
03420    ast_cli_register(&cli_reload);
03421 
03422   
03423    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
03424              "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
03425              "Sets mISDN opts. and optargs\n"
03426              "\n"
03427       );
03428 
03429    
03430    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
03431              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
03432              "Sends the Facility Message FACILITY_TYPE with \n"
03433              "the given Arguments to the current ISDN Channel\n"
03434              "Supported Facilities are:\n"
03435              "\n"
03436              "type=calldeflect args=Nr where to deflect\n"
03437              "\n"
03438       );
03439   
03440    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
03441 
03442    return 0;
03443 }
03444 
03445 
03446 
03447 int unload_module(void)
03448 {
03449    /* First, take us out of the channel loop */
03450    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
03451    
03452    if (!g_config_initialized) return 0;
03453    
03454    ast_cli_unregister(&cli_send_display);
03455    
03456    ast_cli_unregister(&cli_send_cd);
03457    
03458    ast_cli_unregister(&cli_send_digit);
03459    ast_cli_unregister(&cli_toggle_echocancel);
03460    ast_cli_unregister(&cli_set_tics);
03461   
03462    ast_cli_unregister(&cli_show_cls);
03463    ast_cli_unregister(&cli_show_cl);
03464    ast_cli_unregister(&cli_show_config);
03465    ast_cli_unregister(&cli_show_port);
03466    ast_cli_unregister(&cli_show_stacks);
03467    ast_cli_unregister(&cli_restart_port);
03468    ast_cli_unregister(&cli_port_up);
03469    ast_cli_unregister(&cli_set_debug);
03470    ast_cli_unregister(&cli_set_crypt_debug);
03471    ast_cli_unregister(&cli_reload);
03472    /* ast_unregister_application("misdn_crypt"); */
03473    ast_unregister_application("misdn_set_opt");
03474    ast_unregister_application("misdn_facility");
03475   
03476    ast_channel_unregister(&misdn_tech);
03477 
03478    free_robin_list();
03479    misdn_cfg_destroy();
03480    misdn_lib_destroy();
03481   
03482    if (misdn_debug)
03483       free(misdn_debug);
03484    if (misdn_debug_only)
03485       free(misdn_debug_only);
03486    
03487    return 0;
03488 }
03489 
03490 int usecount(void)
03491 {
03492    int res;
03493    ast_mutex_lock(&usecnt_lock);
03494    res = usecnt;
03495    ast_mutex_unlock(&usecnt_lock);
03496    return res;
03497 }
03498 
03499 char *description(void)
03500 {
03501    return desc;
03502 }
03503 
03504 char *key(void)
03505 {
03506    return ASTERISK_GPL_KEY;
03507 }
03508 
03509 void chan_misdn_log(int level, int port, char *tmpl, ...)
03510 {
03511    if (! ((0 <= port) && (port <= max_ports))) {
03512       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
03513       return;
03514    }
03515       
03516    va_list ap;
03517    char buf[1024];
03518   
03519    va_start(ap, tmpl);
03520    vsnprintf( buf, 1023, tmpl, ap );
03521    va_end(ap);
03522    
03523    if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
03524       ast_console_puts(buf);
03525    }
03526    
03527    if (level <= misdn_debug[0] && tracing) {
03528       time_t tm = time(NULL);
03529       char *tmp=ctime(&tm),*p;
03530       char file[BUFFERSIZE];
03531       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
03532       FILE *fp= fopen(file, "a+");
03533 
03534       p=strchr(tmp,'\n');
03535       if (p) *p=':';
03536     
03537       if (!fp) {
03538          ast_console_puts("Error opening Tracefile: ");
03539          ast_console_puts(strerror(errno));
03540          ast_console_puts("\n");
03541          return ;
03542       }
03543       
03544       fputs(tmp,fp);
03545       fputs(" ", fp);
03546       fputs(buf, fp);
03547 
03548       fclose(fp);
03549    }
03550 }
03551 
03552 
03553 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
03554 {
03555    va_list ap;
03556    char buf[1024];
03557    char name[1024];
03558 
03559    int trace;
03560    misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
03561    if (!trace) return ;
03562    
03563    if (misdn_debug[0] < debug) return ; 
03564    
03565    char tracedir[BUFFERSIZE];
03566    misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
03567    sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
03568    
03569    va_start(ap, tmpl);
03570    
03571    vsprintf( buf, tmpl, ap );
03572    
03573    va_end(ap);
03574    
03575    time_t tm = time(NULL);
03576    char *tmp=ctime(&tm),*p;
03577    FILE *fp= fopen(name, "a");
03578    int fd;
03579    
03580    if (!fp) {
03581       ast_console_puts("Error opening Tracefile");
03582       ast_console_puts(strerror(errno));
03583       ast_console_puts("\n");
03584       return ;
03585    }
03586    
03587    fd=fileno(fp) ;
03588    
03589    flock(fd, LOCK_EX);
03590    
03591    p=strchr(tmp,'\n');
03592    if (p) *p=':';
03593    
03594    
03595    
03596    fputs(tmp,fp);
03597    fputs(" ", fp);
03598    fputs(buf, fp);
03599 
03600    flock(fd, LOCK_UN);
03601    
03602    fclose(fp);
03603    
03604 }
03605 
03606 
03607 /*** SOME APPS ;)***/
03608 
03609 static int misdn_facility_exec(struct ast_channel *chan, void *data)
03610 {
03611    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03612    char *tok, *tokb;
03613    
03614 
03615    if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03616       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
03617       return -1;
03618    }
03619    
03620    if (ast_strlen_zero((char *)data)) {
03621       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03622       return -1;
03623    }
03624    
03625    tok=strtok_r((char*)data,"|", &tokb) ;
03626    
03627    if (!tok) {
03628       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03629       return -1;
03630    }
03631    
03632    if (!strcasecmp(tok,"calldeflect")) {
03633       tok=strtok_r(NULL,"|", &tokb) ;
03634       
03635       if (!tok) {
03636          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
03637       }
03638       
03639       misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
03640       
03641    } else {
03642       ast_log(LOG_WARNING, "Unknown Facility: %s\n",tok);
03643    }
03644    
03645    return 0;
03646    
03647 }
03648 
03649 
03650 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
03651 {
03652    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03653    char *tok,*tokb;
03654    int  keyidx=0;
03655    int rxgain=0;
03656    int txgain=0;
03657 
03658    if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03659       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
03660       return -1;
03661    }
03662    
03663    if (ast_strlen_zero((char *)data)) {
03664       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
03665       return -1;
03666    }
03667 
03668    for (tok=strtok_r((char*)data, ":",&tokb);
03669         tok;
03670         tok=strtok_r(NULL,":",&tokb) ) {
03671       int neglect=0;
03672       
03673       if (tok[0] == '!' ) {
03674          neglect=1;
03675          tok++;
03676       }
03677       
03678       switch(tok[0]) {
03679          
03680       case 'd' :
03681          strncpy(ch->bc->display,++tok,84);
03682          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
03683          break;
03684          
03685       case 'n':
03686          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
03687          ch->bc->nodsp=1;
03688          break;
03689 
03690       case 'j':
03691          chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
03692          ch->bc->nojitter=1;
03693          break;
03694       
03695       case 'v':
03696          tok++;
03697 
03698          switch ( tok[0] ) {
03699          case 'r' :
03700             rxgain=atoi(++tok);
03701             if (rxgain<-8) rxgain=-8;
03702             if (rxgain>8) rxgain=8;
03703             ch->bc->rxgain=rxgain;
03704             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
03705             break;
03706          case 't':
03707             txgain=atoi(++tok);
03708             if (txgain<-8) txgain=-8;
03709             if (txgain>8) txgain=8;
03710             ch->bc->txgain=txgain;
03711             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
03712             break;
03713          }
03714          break;
03715       
03716       case 'c':
03717          keyidx=atoi(++tok);
03718       
03719          if (keyidx > misdn_key_vector_size  || keyidx < 0 ) {
03720             ast_log(LOG_WARNING, "You entered the keyidx: %d but we have only %d keys\n",keyidx, misdn_key_vector_size );
03721             continue; 
03722          }
03723       
03724          {
03725             int l = sizeof(ch->bc->crypt_key);
03726             strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
03727             ch->bc->crypt_key[l-1] = 0;
03728          }
03729          chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
03730          break;
03731 
03732       case 'e':
03733          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
03734          
03735          if (neglect) {
03736             ch->bc->ec_enable=0;
03737          } else {
03738             ch->bc->ec_enable=1;
03739             ch->bc->orig=ch->orginator;
03740             tok++;
03741             if (tok) {
03742                ch->bc->ec_deftaps=atoi(tok);
03743             }
03744          }
03745          
03746          break;
03747       
03748       case 'h':
03749          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
03750          if (strlen(tok) > 1 && tok[1]=='1') {
03751             chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
03752             ch->bc->async=1;
03753             ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03754             /*ch->bc->state=STATE_CONNECTED;
03755               misdn_lib_setup_bc(ch->bc);*/
03756          } else {
03757             ch->bc->async=0;
03758             ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03759             /*ch->bc->state=STATE_CONNECTED;
03760               misdn_lib_setup_bc(ch->bc);*/
03761          }
03762          break;
03763             
03764       case 's':
03765          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
03766          ch->bc->send_dtmf=1;
03767          break;
03768          
03769       case 'f':
03770          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
03771          ch->faxdetect=1;
03772          break;
03773 
03774       case 'a':
03775          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
03776          ch->ast_dsp=1;
03777          break;
03778 
03779       case 'p':
03780          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
03781          /* CRICH: callingpres!!! */
03782          if (strstr(tok,"allowed") ) {
03783             ch->bc->pres=0;
03784          } else if (strstr(tok,"not_screened")) {
03785             ch->bc->pres=1;
03786          }
03787          
03788          
03789          break;
03790       
03791       
03792       default:
03793          break;
03794       }
03795    }
03796    
03797    if (ch->faxdetect || ch->ast_dsp) {
03798       
03799       if (!ch->dsp) ch->dsp = ast_dsp_new();
03800       if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
03801       if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
03802    }
03803 
03804    if (ch->ast_dsp) {
03805       chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
03806       ch->bc->nodsp=1;
03807       ch->bc->nojitter=1;
03808    }
03809    
03810    return 0;
03811 }
03812 
03813 

Generated on Sun Aug 6 15:02:32 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2