Fri Apr 24 16:25:54 2009

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

Generated on Fri Apr 24 16:25:54 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7