Mon Mar 20 08:20:09 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          if (cid_name)
02168             tmp->cid.cid_name=strdup(cid_name);
02169          if (cid_num)
02170             tmp->cid.cid_num=strdup(cid_num);
02171       }
02172 
02173       {
02174          if (pipe(chlist->pipe)<0)
02175             perror("Pipe failed\n");
02176          
02177          tmp->fds[0]=chlist->pipe[0];
02178          
02179       }
02180       
02181       if (chlist->bc) {
02182          int port=chlist->bc->port;
02183          misdn_cfg_get( port, MISDN_CFG_LANGUAGE, tmp->language, sizeof(tmp->language));
02184          
02185          {
02186             char buf[256];
02187             ast_group_t pg,cg;
02188             
02189             misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
02190             misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
02191             
02192             chan_misdn_log(2, port, " --> * CallGrp:%s PickupGrp:%s\n",ast_print_group(buf,sizeof(buf),cg),ast_print_group(buf,sizeof(buf),pg));
02193             tmp->pickupgroup=pg;
02194             tmp->callgroup=cg;
02195          }
02196          misdn_cfg_get(port, MISDN_CFG_TXGAIN, &chlist->bc->txgain, sizeof(int));
02197          misdn_cfg_get(port, MISDN_CFG_RXGAIN, &chlist->bc->rxgain, sizeof(int));
02198          chan_misdn_log(2, port, " --> rxgain:%d txgain:%d\n",chlist->bc->rxgain,chlist->bc->txgain);
02199          
02200       } else {
02201          chan_misdn_log(3, 0, " --> Not Setting Pickupgroup, we have no bc yet\n");
02202       }
02203       
02204       ast_setstate(tmp, state);
02205       if (state == AST_STATE_RING)
02206          tmp->rings = 1;
02207       else
02208          tmp->rings = 0;
02209    } else {
02210       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02211       chan_misdn_log(0,0,"Unable to allocate channel structure\n");
02212    }
02213    
02214    return tmp;
02215 }
02216 
02217 
02218 
02219 int misdn_tx2ast_frm(struct chan_list * tmp, char * buf,  int len )
02220 {
02221    struct ast_frame frame;
02222    
02223    /* If in hold state we drop frame .. */
02224    if (tmp->holded ) return 0;
02225 
02226    switch(tmp->state) {
02227    case MISDN_CLEANING:
02228    case MISDN_EXTCANTMATCH:
02229    case MISDN_WAITING4DIGS:
02230       return 0;
02231    default:
02232       break;
02233    }
02234    
02235    if (tmp->norxtone) {
02236       chan_misdn_log(3, tmp->bc->port, "misdn_tx2ast_frm: Returning because norxtone\n");
02237       return 0;
02238    }
02239    
02240    frame.frametype  = AST_FRAME_VOICE;
02241    frame.subclass = AST_FORMAT_ALAW;
02242    frame.datalen = len;
02243    frame.samples = len ;
02244    frame.mallocd =0 ;
02245    frame.offset= 0 ;
02246    frame.src = NULL;
02247    frame.data = buf ;
02248    
02249    if (tmp->faxdetect || tmp->ast_dsp ) {
02250       struct ast_frame *f,*f2;
02251       if (tmp->trans)
02252          f2=ast_translate(tmp->trans, &frame,0);
02253       else {
02254          chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02255          return 0;
02256       }
02257       
02258       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02259       if (f && (f->frametype == AST_FRAME_DTMF)) {
02260          ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c", f->subclass);
02261          if (f->subclass == 'f' && tmp->faxdetect) {
02262             /* Fax tone -- Handle and return NULL */
02263             struct ast_channel *ast = tmp->ast;
02264             if (!tmp->faxhandled) {
02265                tmp->faxhandled++;
02266                if (strcmp(ast->exten, "fax")) {
02267                   if (ast_exists_extension(ast, ast_strlen_zero(ast->macrocontext)? ast->context : ast->macrocontext, "fax", 1, AST_CID_P(ast))) {
02268                      if (option_verbose > 2)
02269                         ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
02270                      /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02271                      pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02272                      if (ast_async_goto(ast, ast->context, "fax", 1))
02273                         ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, ast->context);
02274                   } else
02275                      ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n",ast->context, ast->exten);
02276                } else
02277                   ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02278             } else
02279                ast_log(LOG_DEBUG, "Fax already handled\n");
02280             frame.frametype = AST_FRAME_NULL;
02281             frame.subclass = 0;
02282             f = &frame;
02283          }  else if ( tmp->ast_dsp) {
02284             struct ast_frame fr;
02285             memset(&fr, 0 , sizeof(fr));
02286             fr.frametype = AST_FRAME_DTMF;
02287             fr.subclass = f->subclass ;
02288             fr.src=NULL;
02289             fr.data = NULL ;
02290             fr.datalen = 0;
02291             fr.samples = 0 ;
02292             fr.mallocd =0 ;
02293             fr.offset= 0 ;
02294             
02295             chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n",f->subclass);
02296             ast_queue_frame(tmp->ast, &fr);
02297             
02298             frame.frametype = AST_FRAME_NULL;
02299             frame.subclass = 0;
02300             f = &frame;
02301          }
02302       }
02303    }
02304    
02305    if (tmp && tmp->ast && MISDN_ASTERISK_PVT (tmp->ast) && MISDN_ASTERISK_TECH_PVT(tmp->ast) ) {
02306 #if MISDN_DEBUG
02307       int i, max=5>len?len:5;
02308     
02309       printf("write2* %p %d bytes: ",tmp, len);
02310     
02311       for (i=0; i<  max ; i++) printf("%2.2x ",((char*) frame.data)[i]);
02312       printf ("\n");
02313 #endif
02314       chan_misdn_log(9, tmp->bc->port, "Queueing %d bytes 2 Asterisk\n",len);
02315       ast_queue_frame(tmp->ast,&frame);
02316       
02317    }  else {
02318       ast_log (LOG_WARNING, "No ast || ast->pvt || ch\n");
02319    }
02320    
02321    return 0;
02322 }
02323 
02324 /** Channel Queue ***/
02325 
02326 struct chan_list *find_chan_by_l3id(struct chan_list *list, unsigned long l3id)
02327 {
02328    struct chan_list *help=list;
02329    for (;help; help=help->next) {
02330       if (help->l3id == l3id ) return help;
02331    }
02332   
02333    chan_misdn_log(4, list? (list->bc? list->bc->port : 0) : 0, "$$$ find_chan: No channel found with l3id:%x\n",l3id);
02334   
02335    return NULL;
02336 }
02337 
02338 struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
02339 {
02340    struct chan_list *help=list;
02341    for (;help; help=help->next) {
02342       if (help->bc == bc) return help;
02343    }
02344   
02345    chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02346   
02347    return NULL;
02348 }
02349 
02350 
02351 struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
02352 {
02353    struct chan_list *help=list;
02354    
02355    chan_misdn_log(4, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n",bc->channel, bc->oad,bc->dad);
02356    for (;help; help=help->next) {
02357       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n",help->bc->holded, help->bc->channel);
02358       if (help->bc->port == bc->port
02359           && help->bc->holded ) return help;
02360    }
02361    
02362    chan_misdn_log(4, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n",bc->oad,bc->dad);
02363   
02364    return NULL;
02365 }
02366 
02367 void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
02368 {
02369    chan_misdn_log(4, chan->bc? chan->bc->port : 0, "* Queuing chan %p\n",chan);
02370   
02371    ast_mutex_lock(&cl_te_lock);
02372    if (!*list) {
02373       *list = chan;
02374    } else {
02375       struct chan_list *help=*list;
02376       for (;help->next; help=help->next); 
02377       help->next=chan;
02378    }
02379    chan->next=NULL;
02380    ast_mutex_unlock(&cl_te_lock);
02381 }
02382 
02383 void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
02384 {
02385    if (chan->dsp) 
02386       ast_dsp_free(chan->dsp);
02387    if (chan->trans)
02388       ast_translator_free_path(chan->trans);
02389    
02390 
02391    ast_mutex_lock(&cl_te_lock);
02392    if (!*list) {
02393       ast_mutex_unlock(&cl_te_lock);
02394       return;
02395    }
02396   
02397    if (*list == chan) {
02398       *list=(*list)->next;
02399       ast_mutex_unlock(&cl_te_lock);
02400       return ;
02401    }
02402   
02403    {
02404       struct chan_list *help=*list;
02405       for (;help->next; help=help->next) {
02406          if (help->next == chan) {
02407             help->next=help->next->next;
02408             ast_mutex_unlock(&cl_te_lock);
02409             return;
02410          }
02411       }
02412    }
02413    
02414    ast_mutex_unlock(&cl_te_lock);
02415 }
02416 
02417 /** Channel Queue End **/
02418 
02419 
02420 
02421 /** Isdn asks us to release channel, pendant to misdn_hangup **/
02422 static void release_chan(struct misdn_bchannel *bc) {
02423    struct ast_channel *ast=NULL;
02424    
02425    {
02426       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02427       if (!ch) ch=find_chan_by_l3id (cl_te, bc->l3_id);
02428       
02429       release_lock;
02430       if (ch->ast) {
02431          ast=ch->ast;
02432       } 
02433       release_unlock;
02434       
02435       chan_misdn_log(1, bc->port, "Trying to Release bc with l3id: %x\n",bc->l3_id);
02436       if (ch) {
02437          if (ast)
02438             chan_misdn_trace_call(ast,1,"I->*: EVENT_RELEASE\n");
02439          
02440          close(ch->pipe[0]);
02441          close(ch->pipe[1]);
02442          
02443          if (ast && MISDN_ASTERISK_PVT(ast)) {
02444             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));
02445             chan_misdn_log(3, bc->port, " --> * State Down\n");
02446             /* copy cause */
02447             send_cause2ast(ast,bc);
02448             
02449             MISDN_ASTERISK_TECH_PVT(ast)=NULL;
02450             
02451       
02452             if (ast->_state != AST_STATE_RESERVED) {
02453                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
02454                ast_setstate(ast, AST_STATE_DOWN);
02455             }
02456             
02457             switch(ch->state) {
02458             case MISDN_EXTCANTMATCH:
02459             case MISDN_WAITING4DIGS:
02460             {
02461                chan_misdn_log(3,  bc->port, " --> * State Wait4dig | ExtCantMatch\n");
02462                ast_hangup(ast);
02463             }
02464             break;
02465             
02466             case MISDN_DIALING:
02467             case MISDN_CALLING_ACKNOWLEDGE:
02468             case MISDN_PROGRESS:
02469                chan_misdn_log(2,  bc->port, "* --> In State Dialin\n");
02470                chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02471                
02472 
02473                ast_queue_hangup(ast);
02474                break;
02475             case MISDN_CALLING:
02476                
02477                chan_misdn_log(2,  bc->port, "* --> In State Callin\n");
02478                
02479                if (!bc->nt) {
02480                   chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02481                   ast_queue_hangup(ast);
02482                } else {
02483                   chan_misdn_log(2,  bc->port, "* --> Hangup\n");
02484                   ast_queue_hangup(ast);
02485                   //ast_hangup(ast);
02486                }
02487                break;
02488                
02489             case MISDN_CLEANING:
02490                /* this state comes out of ast so we mustnt call a ast function ! */
02491                chan_misdn_log(2,  bc->port, "* --> In StateCleaning\n");
02492                break;
02493             case MISDN_HOLD_DISCONNECT:
02494                chan_misdn_log(2,  bc->port, "* --> In HOLD_DISC\n");
02495                break;
02496             default:
02497                chan_misdn_log(2,  bc->port, "* --> In State Default\n");
02498                chan_misdn_log(2,  bc->port, "* --> Queue Hangup\n");
02499    
02500                
02501                if (ast && MISDN_ASTERISK_PVT(ast)) {
02502                   ast_queue_hangup(ast);
02503                } else {
02504                   chan_misdn_log (0,  bc->port, "!! Not really queued!\n");
02505                }
02506             }
02507          }
02508          cl_dequeue_chan(&cl_te, ch);
02509          
02510          free(ch);
02511       } else {
02512          /* chan is already cleaned, so exiting  */
02513       }
02514    }
02515 }
02516 /*** release end **/
02517 
02518 void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
02519 {
02520    chan_misdn_log(4,0,"TRANSFERING %s to %s\n",holded_chan->ast->name, tmp_ch->ast->name);
02521    
02522    tmp_ch->state=MISDN_HOLD_DISCONNECT;
02523   
02524    ast_moh_stop(AST_BRIDGED_P(holded_chan->ast));
02525 
02526    holded_chan->state=MISDN_CONNECTED;
02527    holded_chan->holded=0;
02528    misdn_lib_transfer(holded_chan->bc?holded_chan->bc:holded_chan->holded_bc);
02529    
02530    ast_channel_masquerade(holded_chan->ast, AST_BRIDGED_P(tmp_ch->ast));
02531 }
02532 
02533 
02534 void do_immediate_setup(struct misdn_bchannel *bc,struct chan_list *ch , struct ast_channel *ast)
02535 {
02536    char predial[256]="";
02537    char *p = predial;
02538   
02539    struct ast_frame fr;
02540   
02541    strncpy(predial, ast->exten, sizeof(predial) -1 );
02542   
02543    ch->state=MISDN_DIALING;
02544    
02545    if (bc->nt) {
02546       int ret; 
02547       ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02548    } else {
02549       int ret;
02550       if ( misdn_lib_is_ptp(bc->port)) {
02551          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02552       } else {
02553          ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
02554       }
02555    }
02556 
02557    manager_send_tone(bc,TONE_DIAL);  
02558   
02559    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));
02560   
02561    strncpy(ast->exten,"s", 2);
02562   
02563    if (ast_pbx_start(ast)<0) {
02564       ast=NULL;
02565       manager_send_tone(bc,TONE_BUSY);
02566       if (bc->nt)
02567          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02568       else
02569          misdn_lib_send_event(bc, EVENT_DISCONNECT );
02570    }
02571   
02572   
02573    while (!ast_strlen_zero(p) ) {
02574       fr.frametype = AST_FRAME_DTMF;
02575       fr.subclass = *p ;
02576       fr.src=NULL;
02577       fr.data = NULL ;
02578       fr.datalen = 0;
02579       fr.samples = 0 ;
02580       fr.mallocd =0 ;
02581       fr.offset= 0 ;
02582 
02583       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02584          ast_queue_frame(ch->ast, &fr);
02585       }
02586       p++;
02587    }
02588 }
02589 
02590 
02591 
02592 void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel*bc) {
02593    
02594    ast->hangupcause=bc->cause;
02595    
02596    switch ( bc->cause) {
02597       
02598    case 1: /** Congestion Cases **/
02599    case 2:
02600    case 3:
02601    case 4:
02602    case 22:
02603    case 27:
02604       chan_misdn_log(1, bc?bc->port:0, " --> * SEND: Queue Congestion pid:%d\n", bc?bc->pid:-1);
02605       
02606       ast_queue_control(ast, AST_CONTROL_CONGESTION);
02607       break;
02608       
02609    case 21:
02610    case 17: /* user busy */
02611       chan_misdn_log(1,  bc?bc->port:0, " --> * SEND: Queue Busy pid:%d\n", bc?bc->pid:-1);
02612       
02613       ast_queue_control(ast, AST_CONTROL_BUSY);
02614       
02615       break;
02616    }
02617 }
02618 
02619 /************************************************************/
02620 /*  Receive Events from isdn_lib  here                     */
02621 /************************************************************/
02622 enum event_response_e
02623 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
02624 {
02625    struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02626    
02627    if (!ch)
02628       ch=find_chan_by_l3id(cl_te, bc->l3_id);
02629    
02630    if (event != EVENT_BCHAN_DATA) { /*  Debug Only Non-Bchan */
02631       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);
02632       misdn_lib_log_ies(bc);
02633    }
02634    
02635    if (event != EVENT_SETUP) {
02636       if (!ch) {
02637          if (event != EVENT_CLEANUP )
02638             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);
02639          return -1;
02640       }
02641    }
02642    
02643    if (ch ) {
02644       switch (event) {
02645       case EVENT_RELEASE:
02646       case EVENT_RELEASE_COMPLETE:
02647       case EVENT_CLEANUP:
02648          break;
02649       default:
02650          if ( !ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
02651             if (event!=EVENT_BCHAN_DATA)
02652                ast_log(LOG_WARNING, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
02653             return -1;
02654          }
02655       }
02656    }
02657    
02658    
02659    switch (event) {
02660    case EVENT_NEW_L3ID:
02661       ch->l3id=bc->l3_id;
02662       break;
02663 
02664    case EVENT_NEW_BC:
02665       if (bc)
02666          ch->bc=bc;
02667       break;
02668       
02669    case EVENT_DTMF_TONE:
02670    {
02671       /*  sending INFOS as DTMF-Frames :) */
02672       struct ast_frame fr;
02673       memset(&fr, 0 , sizeof(fr));
02674       fr.frametype = AST_FRAME_DTMF;
02675       fr.subclass = bc->dtmf ;
02676       fr.src=NULL;
02677       fr.data = NULL ;
02678       fr.datalen = 0;
02679       fr.samples = 0 ;
02680       fr.mallocd =0 ;
02681       fr.offset= 0 ;
02682       
02683       chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
02684       
02685       ast_queue_frame(ch->ast, &fr);
02686    }
02687    break;
02688    case EVENT_STATUS:
02689       break;
02690     
02691    case EVENT_INFORMATION:
02692    {
02693       int stop_tone;
02694       misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
02695       if ( stop_tone && bc->tone != TONE_NONE) {
02696          manager_send_tone(bc,TONE_NONE);
02697       }
02698       
02699       if (ch->state == MISDN_WAITING4DIGS ) {
02700          /*  Ok, incomplete Setup, waiting till extension exists */
02701          {
02702             int l = sizeof(bc->dad);
02703             strncat(bc->dad,bc->info_dad, l);
02704             bc->dad[l-1] = 0;
02705          }
02706          
02707          
02708          {
02709             int l = sizeof(ch->ast->exten);
02710             strncpy(ch->ast->exten, bc->dad, l);
02711             ch->ast->exten[l-1] = 0;
02712          }
02713 /*       chan_misdn_log(5, bc->port, "Can Match Extension: dad:%s oad:%s\n",bc->dad,bc->oad);*/
02714          
02715          char bc_context[BUFFERSIZE];
02716          misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02717          if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02718             chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
02719             manager_send_tone(bc,TONE_BUSY);
02720             ch->state=MISDN_EXTCANTMATCH;
02721             bc->out_cause=1;
02722             if (bc->nt)
02723                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02724             else
02725                misdn_lib_send_event(bc, EVENT_DISCONNECT );
02726             break;
02727          }
02728          if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
02729             ch->state=MISDN_DIALING;
02730      
02731             manager_send_tone(bc,TONE_NONE);
02732 /*          chan_misdn_log(1, bc->port, " --> * Starting Ast ctx:%s\n", ch->ast->context);*/
02733             if (ast_pbx_start(ch->ast)<0) {
02734                chan_misdn_log(0, bc->port, "ast_pbx_start returned < 0 in INFO\n");
02735                manager_send_tone(bc,TONE_BUSY);
02736                if (bc->nt)
02737                   misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02738                else
02739                   misdn_lib_send_event(bc, EVENT_DISCONNECT );
02740             }
02741          }
02742    
02743       } else {
02744          /*  sending INFOS as DTMF-Frames :) */
02745          struct ast_frame fr;
02746          fr.frametype = AST_FRAME_DTMF;
02747          fr.subclass = bc->info_dad[0] ;
02748          fr.src=NULL;
02749          fr.data = NULL ;
02750          fr.datalen = 0;
02751          fr.samples = 0 ;
02752          fr.mallocd =0 ;
02753          fr.offset= 0 ;
02754 
02755          
02756          int digits;
02757          misdn_cfg_get( 0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
02758          if (ch->state != MISDN_CONNECTED ) {
02759             if (digits) {
02760                int l = sizeof(bc->dad);
02761                strncat(bc->dad,bc->info_dad, l);
02762                bc->dad[l-1] = 0;
02763                l = sizeof(ch->ast->exten);
02764                strncpy(ch->ast->exten, bc->dad, l);
02765                ch->ast->exten[l-1] = 0;
02766 
02767                ast_cdr_update(ch->ast);
02768             }
02769             
02770             ast_queue_frame(ch->ast, &fr);
02771          }
02772          
02773       }
02774    }
02775    break;
02776    case EVENT_SETUP:
02777    {
02778       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
02779       if (ch && ch->state != MISDN_NOTHING ) {
02780          chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
02781          return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
02782       }
02783    }
02784    
02785    int msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
02786    if (!bc->nt && ! msn_valid) {
02787       chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
02788       return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
02789    }
02790    
02791    print_bearer(bc);
02792     
02793    {
02794       struct chan_list *ch=init_chan_list();
02795       struct ast_channel *chan;
02796       char name[128];
02797       if (!ch) { chan_misdn_log(0, bc->port, "cb_events: malloc for chan_list failed!\n"); return 0;}
02798       
02799       ch->bc = bc;
02800       ch->l3id=bc->l3_id;
02801       ch->addr=bc->addr;
02802       ch->orginator = ORG_MISDN;
02803 
02804       
02805       {
02806          char prefix[BUFFERSIZE]="";
02807          switch( bc->onumplan ) {
02808          case NUMPLAN_INTERNATIONAL:
02809             misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02810             break;
02811      
02812          case NUMPLAN_NATIONAL:
02813             misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02814             break;
02815      
02816      
02817          case NUMPLAN_SUBSCRIBER:
02818             /* dunno what to do here ? */
02819             break;
02820 
02821          case NUMPLAN_UNKNOWN:
02822             break;
02823          default:
02824             break;
02825          }
02826 
02827          {
02828             int l = strlen(prefix) + strlen(bc->oad);
02829             char tmp[l+1];
02830             strcpy(tmp,prefix);
02831             strcat(tmp,bc->oad);
02832             strcpy(bc->oad,tmp);
02833          }
02834          
02835          if (!ast_strlen_zero(bc->oad))
02836             sprintf(name,"mISDN/%d/%s",bc->port,bc->oad);
02837          else
02838             sprintf(name,"mISDN/%d",bc->port);
02839 
02840 
02841          if (!ast_strlen_zero(bc->dad)) {
02842             strncpy(bc->orig_dad,bc->dad, sizeof(bc->orig_dad));
02843             bc->orig_dad[sizeof(bc->orig_dad)-1] = 0;
02844          }
02845          
02846          if ( ast_strlen_zero(bc->dad) && !ast_strlen_zero(bc->keypad)) {
02847             strncpy(bc->dad,bc->keypad, sizeof(bc->dad));
02848             bc->dad[sizeof(bc->dad)-1] = 0;
02849          }
02850          prefix[0] = 0;
02851          
02852          switch( bc->dnumplan ) {
02853          case NUMPLAN_INTERNATIONAL:
02854             misdn_cfg_get( bc->port, MISDN_CFG_INTERNATPREFIX, prefix, BUFFERSIZE);
02855             break;
02856             
02857          case NUMPLAN_NATIONAL:
02858             misdn_cfg_get( bc->port, MISDN_CFG_NATPREFIX, prefix, BUFFERSIZE);
02859             break;
02860             
02861             
02862          case NUMPLAN_SUBSCRIBER:
02863             /* dunno what to do here ? */
02864             break;
02865             
02866          case NUMPLAN_UNKNOWN:
02867             break;
02868          default:
02869             break;
02870          }
02871       
02872          {
02873             int l = strlen(prefix) + strlen(bc->dad);
02874             char tmp[l+1];
02875             strcpy(tmp,prefix);
02876             strcat(tmp,bc->dad);
02877             strcpy(bc->dad,tmp);
02878          }
02879          
02880          char bc_context[BUFFERSIZE];
02881          misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
02882          chan=misdn_new(ch, AST_STATE_RING,name ,bc_context, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
02883          
02884          if (!chan) {
02885             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
02886             return 0;
02887          }
02888          
02889          ch->ast = chan;
02890          pbx_builtin_setvar_helper(ch->ast,"REDIRECTING_NUMBER",bc->rad);
02891          
02892       }
02893 
02894       
02895 
02896       chan_misdn_trace_call(chan,1,"I->*: EVENT_SETUP\n");
02897       
02898       if ( bc->pres ) {
02899          chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
02900       }  else {
02901          chan->cid.cid_pres=AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
02902       }
02903       
02904       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
02905       chan->transfercapability=bc->capability;
02906       
02907       switch (bc->capability) {
02908       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
02909          pbx_builtin_setvar_helper(chan,"CALLTYPE","DIGITAL");
02910          break;
02911       default:
02912          pbx_builtin_setvar_helper(chan,"CALLTYPE","SPEECH");
02913       }
02914 
02915       /** queue new chan **/
02916       cl_queue_chan(&cl_te, ch) ;
02917 
02918       
02919       /*
02920         added support for s extension hope it will help those poor cretains
02921         which haven't overlap dial.
02922       */
02923       {
02924          
02925          misdn_cfg_get( bc->port, MISDN_CFG_LANGUAGE, chan->language, sizeof(chan->language));        
02926          
02927       }
02928 
02929       {
02930          int eb3;
02931          
02932          misdn_cfg_get( bc->port, MISDN_CFG_EARLY_BCONNECT, &eb3, sizeof(int));
02933          bc->early_bconnect=eb3;
02934          
02935       }
02936 
02937       {
02938          int ec, ectr;
02939          
02940          misdn_cfg_get( bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(int));
02941          
02942          misdn_cfg_get( bc->port, MISDN_CFG_ECHOTRAINING, &ectr, sizeof(int));
02943          if (ec == 1 ) {
02944             bc->ec_enable=1;
02945          } else if ( ec > 1 ) {
02946             bc->ec_enable=1;
02947             bc->ec_deftaps=ec;
02948          }
02949          
02950          if ( ectr>=0 ) {
02951             bc->ec_training=ectr;
02952          }
02953       }
02954       
02955 
02956       if (bc->urate>0) {
02957          char buf[16];
02958          snprintf(buf,16,"%d",bc->urate);
02959          pbx_builtin_setvar_helper(chan,"MISDN_URATE",buf);
02960       }
02961 
02962 
02963 
02964       /**
02965          from here on  we start the PBX, so no configuration should
02966          be considered anymore
02967       **/
02968       
02969       int ai;
02970       misdn_cfg_get( bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
02971       if ( ai ) {
02972          do_immediate_setup(bc, ch , chan);
02973          break;
02974       }
02975       
02976          
02977       int immediate;
02978       misdn_cfg_get( bc->port, MISDN_CFG_IMMEDIATE, &immediate, sizeof(int));
02979       
02980       if (ast_strlen_zero(bc->orig_dad) && immediate ) {
02981          do_immediate_setup(bc, ch , chan);
02982          break;
02983       }
02984       
02985       /* Check for Pickup Request first */
02986       if (!strcmp(chan->exten, ast_pickup_ext())) {
02987          int ret;/** Sending SETUP_ACK**/
02988          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
02989    
02990          if (ast_pickup_call(chan)) {
02991             ast_hangup(chan);
02992          } else {
02993             ch->state = MISDN_CALLING_ACKNOWLEDGE;
02994      
02995             ch->ast=NULL;
02996      
02997             ast_setstate(chan, AST_STATE_DOWN);
02998             ast_hangup(chan); 
02999      
03000             break;
03001          }
03002       }
03003       
03004       /** Now after we've finished configuring our channel object
03005           we'll jump into the dialplan **/
03006       
03007       char bc_context[BUFFERSIZE];
03008       misdn_cfg_get( bc->port, MISDN_CFG_CONTEXT, bc_context, BUFFERSIZE);
03009       if(!ast_canmatch_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03010          chan_misdn_log(0, bc->port, "Extension can never match, so disconnecting\n");
03011          manager_send_tone(bc,TONE_BUSY);
03012          ch->state=MISDN_EXTCANTMATCH;
03013          bc->out_cause=1;
03014          if (bc->nt)
03015             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03016          else
03017             misdn_lib_send_event(bc, EVENT_DISCONNECT );
03018          break;
03019       }
03020       
03021       if (ast_exists_extension(ch->ast, bc_context, bc->dad, 1, bc->oad)) {
03022          ch->state=MISDN_DIALING;
03023    
03024          if (bc->nt) {
03025             int ret; 
03026             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03027          } else {
03028             int ret;
03029             ret= misdn_lib_send_event(bc, EVENT_PROCEEDING );
03030          }
03031    
03032          if (ast_pbx_start(chan)<0) {
03033             chan_misdn_log(0, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03034             chan=NULL;
03035             manager_send_tone(bc,TONE_BUSY);
03036             if (bc->nt)
03037                misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03038             else
03039                misdn_lib_send_event(bc, EVENT_DISCONNECT );
03040          }
03041       } else {
03042          int ret= misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03043          if (ret == -ENOCHAN) {
03044             ast_log(LOG_WARNING,"Channel was catched, before we could Acknowledge\n");
03045             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03046          }
03047          /*  send tone to phone :) */
03048          
03049          int stop_tone;
03050          misdn_cfg_get( 0, MISDN_GEN_STOP_TONE, &stop_tone, sizeof(int));
03051          if ( (!ast_strlen_zero(bc->dad)) && stop_tone ) 
03052             manager_send_tone(bc,TONE_NONE);
03053          else
03054             manager_send_tone(bc,TONE_DIAL);
03055    
03056          ch->state=MISDN_WAITING4DIGS;
03057       }
03058       
03059    }
03060    break;
03061    case EVENT_SETUP_ACKNOWLEDGE:
03062    {
03063       ch->state = MISDN_CALLING_ACKNOWLEDGE;
03064       if (!ast_strlen_zero(bc->infos_pending)) {
03065          /* TX Pending Infos */
03066          
03067          {
03068             int l = sizeof(bc->dad);
03069             strncat(bc->dad,bc->infos_pending, l - strlen(bc->dad));
03070             bc->dad[l-1] = 0;
03071          }  
03072          {
03073             int l = sizeof(ch->ast->exten);
03074             strncpy(ch->ast->exten, bc->dad, l);
03075             ch->ast->exten[l-1] = 0;
03076          }
03077          {
03078             int l = sizeof(bc->info_dad);
03079             strncpy(bc->info_dad, bc->infos_pending, l);
03080             bc->info_dad[l-1] = 0;
03081          }
03082          strncpy(bc->infos_pending,"", 1);
03083 
03084          misdn_lib_send_event(bc, EVENT_INFORMATION);
03085       }
03086    }
03087    break;
03088    case EVENT_PROCEEDING:
03089    {
03090       
03091       if ( misdn_cap_is_speech(bc->capability) &&
03092            misdn_inband_avail(bc) ) {
03093          start_bc_tones(ch);
03094       }
03095    }
03096    break;
03097    case EVENT_PROGRESS:
03098       if (!bc->nt ) {
03099          if ( misdn_cap_is_speech(bc->capability) &&
03100               misdn_inband_avail(bc)
03101             ) {
03102             start_bc_tones(ch);
03103          }
03104          
03105          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
03106          
03107          ch->state=MISDN_PROGRESS;
03108       }
03109       break;
03110       
03111       
03112    case EVENT_ALERTING:
03113    {
03114       ch->state = MISDN_ALERTING;
03115       
03116       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
03117       ast_setstate(ch->ast, AST_STATE_RINGING);
03118       
03119       cb_log(1,bc->port,"Set State Ringing\n");
03120       
03121       if ( misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
03122           start_bc_tones(ch);
03123        }
03124    }
03125    break;
03126    case EVENT_CONNECT:
03127       misdn_lib_send_event(bc,EVENT_CONNECT_ACKNOWLEDGE);
03128    case EVENT_CONNECT_ACKNOWLEDGE:
03129    {
03130       bc->state=STATE_CONNECTED;
03131       
03132       ch->l3id=bc->l3_id;
03133       ch->addr=bc->addr;
03134       
03135       start_bc_tones(ch);
03136       
03137       chan_misdn_trace_call(ch->ast,1,"I->*: EVENT_CONNECT\n");
03138       
03139       ch->state = MISDN_CONNECTED;
03140       ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
03141    }
03142    break;
03143    case EVENT_DISCONNECT:
03144    {
03145       
03146       struct chan_list *holded_ch=find_holded(cl_te, bc);
03147       
03148       
03149       send_cause2ast(ch->ast,bc);
03150 
03151       if (misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
03152          /* If there's inband information available (e.g. a
03153             recorded message saying what was wrong with the
03154             dialled number, or perhaps even giving an
03155             alternative number, then play it instead of
03156             immediately releasing the call */
03157          start_bc_tones(ch);
03158          break;
03159       }
03160       
03161       /*Check for holded channel, to implement transfer*/
03162       if (holded_ch ) {
03163          if  (ch->state == MISDN_CONNECTED ) {
03164             misdn_transfer_bc(ch, holded_ch) ;
03165             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03166             break;
03167          }
03168       }
03169       
03170       stop_bc_tones(ch);
03171       bc->out_cause=16;
03172       misdn_lib_send_event(bc,EVENT_RELEASE);
03173       
03174    }
03175    break;
03176    
03177    case EVENT_RELEASE:
03178       {
03179          
03180          switch ( bc->cause) {
03181             
03182          case -1:
03183             /*
03184               OK, it really sucks, this is a RELEASE from NT-Stack So we take
03185               it and return easylie, It seems that we've send a DISCONNECT
03186               before, so we should RELEASE_COMPLETE after that Disconnect
03187               (looks like ALERTING State at misdn_hangup !!
03188             */
03189             return RESPONSE_OK;
03190             break;
03191          }
03192          
03193          
03194          bc->out_cause=16;
03195          
03196          stop_bc_tones(ch);
03197          release_chan(bc);
03198       }
03199       break;
03200    case EVENT_RELEASE_COMPLETE:
03201    {
03202       stop_bc_tones(ch);
03203       release_chan(bc);
03204    }
03205    break;
03206    
03207    case EVENT_BCHAN_DATA:
03208    {
03209       chan_misdn_trace_call(ch->ast,3,"I->*: EVENT_B_DATA len=%d\n",bc->bframe_len);
03210       
03211       if ( !misdn_cap_is_speech(ch->bc->capability) || bc->nojitter) {
03212          misdn_tx2ast_frm(ch, bc->bframe, bc->bframe_len );
03213       } else {
03214          int len=bc->bframe_len;
03215          int free=misdn_ibuf_freecount(bc->astbuf);
03216          
03217          
03218          if (bc->bframe_len > free) {
03219             ast_log(LOG_DEBUG, "sbuf overflow!\n");
03220             len=misdn_ibuf_freecount(bc->astbuf);
03221 
03222             if (len == 0) {
03223                ast_log(LOG_WARNING, "BCHAN_DATA: write buffer overflow port:%d channel:%d!\n",bc->port,bc->channel);
03224             }
03225          }
03226          
03227          misdn_ibuf_memcpy_w(bc->astbuf, bc->bframe, len);
03228          
03229          {
03230             char blah[1]="\0";
03231 #ifdef FLATTEN_JITTER
03232             {
03233                struct timeval tv;
03234                gettimeofday(&tv,NULL);
03235                
03236                if (tv.tv_usec % 10000 > 0 ) {
03237                   write(ch->pipe[1], blah,sizeof(blah));
03238                   bc->time_usec=tv.tv_usec;
03239                }
03240             }
03241 #else
03242             write(ch->pipe[1], blah,sizeof(blah));
03243 #endif
03244             
03245             
03246          }
03247       }
03248       
03249    }
03250    break;
03251    case EVENT_TIMEOUT:
03252       break; /* Ignore now .. */
03253       {
03254          switch (ch->state) {
03255          case MISDN_CALLING:
03256             chan_misdn_log(0, bc?bc->port:0, "GOT TIMOUT AT CALING pid:%d\n", bc?bc->pid:-1);
03257                break;
03258          case MISDN_DIALING:
03259          case MISDN_PROGRESS:
03260             break;
03261          default:
03262             misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
03263          }
03264       }
03265       break;
03266    case EVENT_CLEANUP:
03267    {
03268       stop_bc_tones(ch);
03269       release_chan(bc);
03270    }
03271    break;
03272     
03273    /***************************/
03274    /** Suplementary Services **/
03275    /***************************/
03276    case EVENT_RETRIEVE:
03277    {
03278       struct ast_channel *hold_ast=AST_BRIDGED_P(ch->ast);
03279       ch->state = MISDN_CONNECTED;
03280       
03281       if (hold_ast) {
03282          ast_moh_stop(hold_ast);
03283       }
03284       
03285       if ( misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0)
03286          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
03287       
03288       
03289    }
03290    break;
03291     
03292    case EVENT_HOLD:
03293    {
03294       int hold_allowed;
03295       misdn_cfg_get( bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
03296       
03297       if (!hold_allowed) {
03298          chan_misdn_log(0, bc->port, "Hold not allowed on port:%d\n", bc->port);
03299          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03300          break;
03301       }
03302 
03303       {
03304          struct chan_list *holded_ch=find_holded(cl_te, bc);
03305          if (holded_ch) {
03306             misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03307             chan_misdn_log(0, bc->port, "We can't use RETRIEVE at the moment due to mISDN bug!\n");
03308             break;
03309          }
03310       }
03311       
03312       if (AST_BRIDGED_P(ch->ast)){
03313          ch->state = MISDN_HOLDED;
03314          ch->l3id = bc->l3_id;
03315          
03316          ast_moh_start(AST_BRIDGED_P(ch->ast), NULL);
03317          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
03318       } else {
03319          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
03320          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
03321       }
03322    } 
03323    break;
03324    default:
03325       ast_log(LOG_WARNING, "Got Unknown Event\n");
03326       break;
03327    }
03328    
03329    return RESPONSE_OK;
03330 }
03331 
03332 /** TE STUFF END **/
03333 
03334 /******************************************
03335  *
03336  *   Asterisk Channel Endpoint END
03337  *
03338  *
03339  *******************************************/
03340 
03341 
03342 int clearl3_true ( void ) {
03343    int default_clearl3;
03344    misdn_cfg_get( 0, MISDN_GEN_CLEAR_L3, &default_clearl3, sizeof(int));
03345    return default_clearl3;
03346 }
03347 
03348 int g_config_initialized=0;
03349 
03350 int load_module(void)
03351 {
03352    int i;
03353    
03354    char ports[256]="";
03355    
03356    max_ports=misdn_lib_maxports_get();
03357    
03358    if (max_ports<=0) {
03359       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
03360       return -1;
03361    }
03362    
03363    
03364    misdn_cfg_init(max_ports);
03365    g_config_initialized=1;
03366    
03367    misdn_debug = (int *)malloc(sizeof(int) * (max_ports+1));
03368    misdn_cfg_get( 0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
03369    for (i = 1; i <= max_ports; i++)
03370       misdn_debug[i] = misdn_debug[0];
03371    misdn_debug_only = (int *)calloc(max_ports + 1, sizeof(int));
03372 
03373    
03374    {
03375       char tempbuf[BUFFERSIZE];
03376       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
03377       if (strlen(tempbuf))
03378          tracing = 1;
03379    }
03380 
03381    ast_mutex_init(&cl_te_lock);
03382    ast_mutex_init(&release_lock_mutex);
03383 
03384    misdn_cfg_get_ports_string(ports);
03385    if (strlen(ports))
03386       chan_misdn_log(0, 0, "Got: %s from get_ports\n",ports);
03387    
03388    {
03389       struct misdn_lib_iface iface = {
03390          .cb_event = cb_events,
03391          .cb_log = chan_misdn_log,
03392          .cb_clearl3_true = clearl3_true
03393       };
03394       if (misdn_lib_init(ports, &iface, NULL))
03395          chan_misdn_log(0, 0, "No te ports initialized\n");
03396    }
03397 
03398 
03399    {
03400       if (ast_channel_register(&misdn_tech)) {
03401          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
03402          unload_module();
03403          return -1;
03404       }
03405    }
03406   
03407    ast_cli_register(&cli_send_display);
03408    ast_cli_register(&cli_send_cd);
03409    ast_cli_register(&cli_send_digit);
03410    ast_cli_register(&cli_toggle_echocancel);
03411    ast_cli_register(&cli_set_tics);
03412 
03413    ast_cli_register(&cli_show_cls);
03414    ast_cli_register(&cli_show_cl);
03415    ast_cli_register(&cli_show_config);
03416    ast_cli_register(&cli_show_port);
03417    ast_cli_register(&cli_show_stacks);
03418 
03419    ast_cli_register(&cli_restart_port);
03420    ast_cli_register(&cli_port_up);
03421    ast_cli_register(&cli_set_debug);
03422    ast_cli_register(&cli_set_crypt_debug);
03423    ast_cli_register(&cli_reload);
03424 
03425   
03426    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_flags",
03427              "misdn_set_opt(:<opt><optarg>:<opt><optarg>..):\n"
03428              "Sets mISDN opts. and optargs\n"
03429              "\n"
03430       );
03431 
03432    
03433    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
03434              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
03435              "Sends the Facility Message FACILITY_TYPE with \n"
03436              "the given Arguments to the current ISDN Channel\n"
03437              "Supported Facilities are:\n"
03438              "\n"
03439              "type=calldeflect args=Nr where to deflect\n"
03440              "\n"
03441       );
03442   
03443    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registred -- (BE AWARE THIS DRIVER IS EXPERIMENTAL!)\n");
03444 
03445    return 0;
03446 }
03447 
03448 
03449 
03450 int unload_module(void)
03451 {
03452    /* First, take us out of the channel loop */
03453    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
03454    
03455    if (!g_config_initialized) return 0;
03456    
03457    ast_cli_unregister(&cli_send_display);
03458    
03459    ast_cli_unregister(&cli_send_cd);
03460    
03461    ast_cli_unregister(&cli_send_digit);
03462    ast_cli_unregister(&cli_toggle_echocancel);
03463    ast_cli_unregister(&cli_set_tics);
03464   
03465    ast_cli_unregister(&cli_show_cls);
03466    ast_cli_unregister(&cli_show_cl);
03467    ast_cli_unregister(&cli_show_config);
03468    ast_cli_unregister(&cli_show_port);
03469    ast_cli_unregister(&cli_show_stacks);
03470    ast_cli_unregister(&cli_restart_port);
03471    ast_cli_unregister(&cli_port_up);
03472    ast_cli_unregister(&cli_set_debug);
03473    ast_cli_unregister(&cli_set_crypt_debug);
03474    ast_cli_unregister(&cli_reload);
03475    /* ast_unregister_application("misdn_crypt"); */
03476    ast_unregister_application("misdn_set_opt");
03477    ast_unregister_application("misdn_facility");
03478   
03479    ast_channel_unregister(&misdn_tech);
03480 
03481    free_robin_list();
03482    misdn_cfg_destroy();
03483    misdn_lib_destroy();
03484   
03485    if (misdn_debug)
03486       free(misdn_debug);
03487    if (misdn_debug_only)
03488       free(misdn_debug_only);
03489    
03490    return 0;
03491 }
03492 
03493 int usecount(void)
03494 {
03495    int res;
03496    ast_mutex_lock(&usecnt_lock);
03497    res = usecnt;
03498    ast_mutex_unlock(&usecnt_lock);
03499    return res;
03500 }
03501 
03502 char *description(void)
03503 {
03504    return desc;
03505 }
03506 
03507 char *key(void)
03508 {
03509    return ASTERISK_GPL_KEY;
03510 }
03511 
03512 void chan_misdn_log(int level, int port, char *tmpl, ...)
03513 {
03514    if (! ((0 <= port) && (port <= max_ports))) {
03515       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
03516       return;
03517    }
03518       
03519    va_list ap;
03520    char buf[1024];
03521   
03522    va_start(ap, tmpl);
03523    vsnprintf( buf, 1023, tmpl, ap );
03524    va_end(ap);
03525    
03526    if (misdn_debug_only[port] ? (level==1 && misdn_debug[port]) || (level==misdn_debug[port]) : level <= misdn_debug[port]) {
03527       ast_console_puts(buf);
03528    }
03529    
03530    if (level <= misdn_debug[0] && tracing) {
03531       time_t tm = time(NULL);
03532       char *tmp=ctime(&tm),*p;
03533       char file[BUFFERSIZE];
03534       misdn_cfg_get( 0, MISDN_GEN_TRACEFILE, file, BUFFERSIZE);
03535       FILE *fp= fopen(file, "a+");
03536 
03537       p=strchr(tmp,'\n');
03538       if (p) *p=':';
03539     
03540       if (!fp) {
03541          ast_console_puts("Error opening Tracefile: ");
03542          ast_console_puts(strerror(errno));
03543          ast_console_puts("\n");
03544          return ;
03545       }
03546       
03547       fputs(tmp,fp);
03548       fputs(" ", fp);
03549       fputs(buf, fp);
03550 
03551       fclose(fp);
03552    }
03553 }
03554 
03555 
03556 void chan_misdn_trace_call(struct ast_channel *chan, int debug, char *tmpl, ...)
03557 {
03558    va_list ap;
03559    char buf[1024];
03560    char name[1024];
03561 
03562    int trace;
03563    misdn_cfg_get( 0, MISDN_GEN_TRACE_CALLS, &trace, sizeof(int));
03564    if (!trace) return ;
03565    
03566    if (misdn_debug[0] < debug) return ; 
03567    
03568    char tracedir[BUFFERSIZE];
03569    misdn_cfg_get( 0, MISDN_GEN_TRACE_DIR, tracedir, BUFFERSIZE);
03570    sprintf(name,"%s/%s.%s",tracedir, chan->uniqueid, chan->cid.cid_num );
03571    
03572    va_start(ap, tmpl);
03573    
03574    vsprintf( buf, tmpl, ap );
03575    
03576    va_end(ap);
03577    
03578    time_t tm = time(NULL);
03579    char *tmp=ctime(&tm),*p;
03580    FILE *fp= fopen(name, "a");
03581    int fd;
03582    
03583    if (!fp) {
03584       ast_console_puts("Error opening Tracefile");
03585       ast_console_puts(strerror(errno));
03586       ast_console_puts("\n");
03587       return ;
03588    }
03589    
03590    fd=fileno(fp) ;
03591    
03592    flock(fd, LOCK_EX);
03593    
03594    p=strchr(tmp,'\n');
03595    if (p) *p=':';
03596    
03597    
03598    
03599    fputs(tmp,fp);
03600    fputs(" ", fp);
03601    fputs(buf, fp);
03602 
03603    flock(fd, LOCK_UN);
03604    
03605    fclose(fp);
03606    
03607 }
03608 
03609 
03610 /*** SOME APPS ;)***/
03611 
03612 static int misdn_facility_exec(struct ast_channel *chan, void *data)
03613 {
03614    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03615    char *tok, *tokb;
03616    
03617 
03618    if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03619       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
03620       return -1;
03621    }
03622    
03623    if (ast_strlen_zero((char *)data)) {
03624       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03625       return -1;
03626    }
03627    
03628    tok=strtok_r((char*)data,"|", &tokb) ;
03629    
03630    if (!tok) {
03631       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
03632       return -1;
03633    }
03634    
03635    if (!strcasecmp(tok,"calldeflect")) {
03636       tok=strtok_r(NULL,"|", &tokb) ;
03637       
03638       if (!tok) {
03639          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
03640       }
03641       
03642       misdn_lib_send_facility(ch->bc, FACILITY_CALLDEFLECT, tok);
03643       
03644    } else {
03645       ast_log(LOG_WARNING, "Unknown Facility: %s\n",tok);
03646    }
03647    
03648    return 0;
03649    
03650 }
03651 
03652 
03653 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
03654 {
03655    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
03656    char *tok,*tokb;
03657    int  keyidx=0;
03658    int rxgain=0;
03659    int txgain=0;
03660 
03661    if (strcasecmp(MISDN_ASTERISK_TYPE(chan),"mISDN")) {
03662       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
03663       return -1;
03664    }
03665    
03666    if (ast_strlen_zero((char *)data)) {
03667       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
03668       return -1;
03669    }
03670 
03671    for (tok=strtok_r((char*)data, ":",&tokb);
03672         tok;
03673         tok=strtok_r(NULL,":",&tokb) ) {
03674       int neglect=0;
03675       
03676       if (tok[0] == '!' ) {
03677          neglect=1;
03678          tok++;
03679       }
03680       
03681       switch(tok[0]) {
03682          
03683       case 'd' :
03684          strncpy(ch->bc->display,++tok,84);
03685          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n",ch->bc->display);
03686          break;
03687          
03688       case 'n':
03689          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
03690          ch->bc->nodsp=1;
03691          break;
03692 
03693       case 'j':
03694          chan_misdn_log(1, ch->bc->port, "SETOPT: No jitter\n");
03695          ch->bc->nojitter=1;
03696          break;
03697       
03698       case 'v':
03699          tok++;
03700 
03701          switch ( tok[0] ) {
03702          case 'r' :
03703             rxgain=atoi(++tok);
03704             if (rxgain<-8) rxgain=-8;
03705             if (rxgain>8) rxgain=8;
03706             ch->bc->rxgain=rxgain;
03707             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",rxgain);
03708             break;
03709          case 't':
03710             txgain=atoi(++tok);
03711             if (txgain<-8) txgain=-8;
03712             if (txgain>8) txgain=8;
03713             ch->bc->txgain=txgain;
03714             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n",txgain);
03715             break;
03716          }
03717          break;
03718       
03719       case 'c':
03720          keyidx=atoi(++tok);
03721       
03722          if (keyidx > misdn_key_vector_size  || keyidx < 0 ) {
03723             ast_log(LOG_WARNING, "You entered the keyidx: %d but we have only %d keys\n",keyidx, misdn_key_vector_size );
03724             continue; 
03725          }
03726       
03727          {
03728             int l = sizeof(ch->bc->crypt_key);
03729             strncpy(ch->bc->crypt_key, misdn_key_vector[keyidx], l);
03730             ch->bc->crypt_key[l-1] = 0;
03731          }
03732          chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n",misdn_key_vector[keyidx]);
03733          break;
03734 
03735       case 'e':
03736          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
03737          
03738          if (neglect) {
03739             ch->bc->ec_enable=0;
03740          } else {
03741             ch->bc->ec_enable=1;
03742             ch->bc->orig=ch->orginator;
03743             tok++;
03744             if (tok) {
03745                ch->bc->ec_deftaps=atoi(tok);
03746             }
03747          }
03748          
03749          break;
03750       
03751       case 'h':
03752          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
03753          if (strlen(tok) > 1 && tok[1]=='1') {
03754             chan_misdn_log(1, ch->bc->port, "SETOPT: Digital TRANS_DIGITAL\n");
03755             ch->bc->async=1;
03756             ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03757             /*ch->bc->state=STATE_CONNECTED;
03758               misdn_lib_setup_bc(ch->bc);*/
03759          } else {
03760             ch->bc->async=0;
03761             ch->bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
03762             /*ch->bc->state=STATE_CONNECTED;
03763               misdn_lib_setup_bc(ch->bc);*/
03764          }
03765          break;
03766             
03767       case 's':
03768          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
03769          ch->bc->send_dtmf=1;
03770          break;
03771          
03772       case 'f':
03773          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
03774          ch->faxdetect=1;
03775          break;
03776 
03777       case 'a':
03778          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
03779          ch->ast_dsp=1;
03780          break;
03781 
03782       case 'p':
03783          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n",&tok[1]);
03784          /* CRICH: callingpres!!! */
03785          if (strstr(tok,"allowed") ) {
03786             ch->bc->pres=0;
03787          } else if (strstr(tok,"not_screened")) {
03788             ch->bc->pres=1;
03789          }
03790          
03791          
03792          break;
03793       
03794       
03795       default:
03796          break;
03797       }
03798    }
03799    
03800    if (ch->faxdetect || ch->ast_dsp) {
03801       
03802       if (!ch->dsp) ch->dsp = ast_dsp_new();
03803       if (ch->dsp) ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
03804       if (!ch->trans) ch->trans=ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
03805    }
03806 
03807    if (ch->ast_dsp) {
03808       chan_misdn_log(1,ch->bc->port,"SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
03809       ch->bc->nodsp=1;
03810       ch->bc->nojitter=1;
03811    }
03812    
03813    return 0;
03814 }
03815 
03816 

Generated on Mon Mar 20 08:20:09 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1