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

Generated on Fri Feb 19 17:12:39 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7