Wed Aug 18 22:33:47 2010

Asterisk developer's documentation


chan_misdn.c

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

Generated on Wed Aug 18 22:33:47 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7