Thu Oct 8 00:58:58 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: 211596 $")
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], "%30d", &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       }
02436       return -1;
02437    case AST_CONTROL_RING:
02438       chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc ? p->bc->pid : -1);
02439       return -1;
02440    case AST_CONTROL_RINGING:
02441       chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02442       switch (p->state) {
02443       case MISDN_ALERTING:
02444          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);
02445          break;
02446       case MISDN_CONNECTED:
02447          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);
02448          return -1;
02449       default:
02450          p->state = MISDN_ALERTING;
02451          chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc ? p->bc->pid : -1);
02452          misdn_lib_send_event( p->bc, EVENT_ALERTING);
02453 
02454          if (p->other_ch && p->other_ch->bc) {
02455             if (misdn_inband_avail(p->other_ch->bc)) {
02456                chan_misdn_log(2, p->bc->port, " --> other End is mISDN and has inband info available\n");
02457                break;
02458             }
02459 
02460             if (!p->other_ch->bc->nt) {
02461                chan_misdn_log(2, p->bc->port, " --> other End is mISDN TE so it has inband info for sure (?)\n");
02462                break;
02463             }
02464          }
02465 
02466          chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc ? p->bc->pid : -1);
02467          ast_setstate(ast, AST_STATE_RING);
02468 
02469          if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio)
02470             chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
02471          else 
02472             return -1;
02473       }
02474       break;
02475    case AST_CONTROL_ANSWER:
02476       chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc ? p->bc->pid : -1);
02477       start_bc_tones(p);
02478       break;
02479    case AST_CONTROL_TAKEOFFHOOK:
02480       chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02481       return -1;
02482    case AST_CONTROL_OFFHOOK:
02483       chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc ? p->bc->pid : -1);
02484       return -1;
02485    case AST_CONTROL_FLASH:
02486       chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc ? p->bc->pid : -1);
02487       break;
02488    case AST_CONTROL_PROGRESS:
02489       chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc ? p->bc->pid : -1);
02490       misdn_lib_send_event( p->bc, EVENT_PROGRESS);
02491       break;
02492    case AST_CONTROL_PROCEEDING:
02493       chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc ? p->bc->pid : -1);
02494       misdn_lib_send_event( p->bc, EVENT_PROCEEDING);
02495       break;
02496    case AST_CONTROL_CONGESTION:
02497       chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc ? p->bc->pid : -1);
02498 
02499       p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
02500       start_bc_tones(p);
02501       misdn_lib_send_event( p->bc, EVENT_DISCONNECT);
02502 
02503       if (p->bc->nt) {
02504          hanguptone_indicate(p);
02505       }
02506       break;
02507    case -1 :
02508       chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc ? p->bc->pid : -1);
02509 
02510       stop_indicate(p);
02511 
02512       if (p->state == MISDN_CONNECTED) 
02513          start_bc_tones(p);
02514       break;
02515    case AST_CONTROL_HOLD:
02516       ast_moh_start(ast, data, p->mohinterpret); 
02517       chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02518       break;
02519    case AST_CONTROL_UNHOLD:
02520       ast_moh_stop(ast);
02521       chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc ? p->bc->pid : -1);
02522       break;
02523    default:
02524       chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc ? p->bc->pid : -1);
02525    }
02526   
02527    return 0;
02528 }
02529 
02530 static int misdn_hangup(struct ast_channel *ast)
02531 {
02532    struct chan_list *p;
02533    struct misdn_bchannel *bc = NULL;
02534    const char *varcause = NULL;
02535 
02536    ast_log(LOG_DEBUG, "misdn_hangup(%s)\n", ast->name);
02537 
02538    if (!ast || ! (p=MISDN_ASTERISK_TECH_PVT(ast) ) ) return -1;
02539 
02540    if (!p) {
02541       chan_misdn_log(3, 0, "misdn_hangup called, without chan_list obj.\n");
02542       return 0 ;
02543    }
02544 
02545    bc = p->bc;
02546 
02547    if (bc) {
02548       const char *tmp=pbx_builtin_getvar_helper(ast,"MISDN_USERUSER");
02549       if (tmp) {
02550          ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
02551          strcpy(bc->uu, tmp);
02552          bc->uulen=strlen(bc->uu);
02553       }
02554    }
02555 
02556    MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02557    p->ast = NULL;
02558 
02559    if (ast->_state == AST_STATE_RESERVED || 
02560       p->state == MISDN_NOTHING || 
02561       p->state == MISDN_HOLDED || 
02562       p->state == MISDN_HOLD_DISCONNECT ) {
02563 
02564       CLEAN_CH:
02565       /* between request and call */
02566       ast_log(LOG_DEBUG, "State Reserved (or nothing) => chanIsAvail\n");
02567       MISDN_ASTERISK_TECH_PVT(ast) = NULL;
02568    
02569       ast_mutex_lock(&release_lock);
02570       cl_dequeue_chan(&cl_te, p);
02571       close(p->pipe[0]);
02572       close(p->pipe[1]);
02573       free(p);
02574       ast_mutex_unlock(&release_lock);
02575       
02576       if (bc)
02577          misdn_lib_release(bc);
02578       
02579       return 0;
02580    }
02581 
02582    if (!bc) {
02583       ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n", misdn_get_ch_state(p), p->l3id);
02584       goto CLEAN_CH;
02585    }
02586 
02587 
02588    p->need_hangup = 0;
02589    p->need_queue_hangup = 0;
02590    p->need_busy = 0;
02591 
02592 
02593    if (!p->bc->nt) 
02594       stop_bc_tones(p);
02595 
02596    bc->out_cause = ast->hangupcause ? ast->hangupcause : AST_CAUSE_NORMAL_CLEARING;
02597 
02598    if ((varcause = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE")) ||
02599       (varcause = pbx_builtin_getvar_helper(ast, "PRI_CAUSE"))) {
02600       int tmpcause = atoi(varcause);
02601       bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
02602    }
02603 
02604    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));
02605    chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
02606    chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
02607    chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
02608    chan_misdn_log(2, bc->port, " --> state:%s\n", misdn_get_ch_state(p));
02609 
02610    switch (p->state) {
02611    case MISDN_INCOMING_SETUP:
02612       /* This is the only place in misdn_hangup, where we 
02613        * can call release_chan, else it might create lot's of trouble
02614        * */
02615       ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
02616       release_chan(bc);
02617 
02618       p->state = MISDN_CLEANING;
02619       if (bc->need_release_complete)
02620          misdn_lib_send_event( bc, EVENT_RELEASE_COMPLETE);
02621       break;
02622    case MISDN_HOLDED:
02623    case MISDN_DIALING:
02624       start_bc_tones(p);
02625       hanguptone_indicate(p);
02626 
02627       if (bc->need_disconnect)
02628          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02629       break;
02630    case MISDN_CALLING_ACKNOWLEDGE:
02631       start_bc_tones(p);
02632       hanguptone_indicate(p);
02633 
02634       if (bc->need_disconnect)
02635          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02636       break;
02637 
02638    case MISDN_CALLING:
02639    case MISDN_ALERTING:
02640    case MISDN_PROGRESS:
02641    case MISDN_PROCEEDING:
02642       if (p->originator != ORG_AST) 
02643          hanguptone_indicate(p);
02644 
02645       /*p->state=MISDN_CLEANING;*/
02646       if (bc->need_disconnect)
02647          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02648       break;
02649    case MISDN_CONNECTED:
02650    case MISDN_PRECONNECTED:
02651       /*  Alerting or Disconnect */
02652       if (p->bc->nt) {
02653          start_bc_tones(p);
02654          hanguptone_indicate(p);
02655          p->bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
02656       }
02657       if (bc->need_disconnect)
02658          misdn_lib_send_event( bc, EVENT_DISCONNECT);
02659 
02660       /*p->state=MISDN_CLEANING;*/
02661       break;
02662    case MISDN_DISCONNECTED:
02663       if (bc->need_release)
02664          misdn_lib_send_event( bc, EVENT_RELEASE);
02665       p->state = MISDN_CLEANING; /* MISDN_HUNGUP_FROM_AST; */
02666       break;
02667 
02668    case MISDN_RELEASED:
02669    case MISDN_CLEANING:
02670       p->state = MISDN_CLEANING;
02671       break;
02672 
02673    case MISDN_BUSY:
02674       break;
02675 
02676    case MISDN_HOLD_DISCONNECT:
02677       /* need to send release here */
02678       chan_misdn_log(1, bc->port, " --> cause %d\n", bc->cause);
02679       chan_misdn_log(1, bc->port, " --> out_cause %d\n", bc->out_cause);
02680 
02681       bc->out_cause = -1;
02682       if (bc->need_release)
02683          misdn_lib_send_event(bc, EVENT_RELEASE);
02684       p->state = MISDN_CLEANING;
02685       break;
02686    default:
02687       if (bc->nt) {
02688          bc->out_cause = -1;
02689          if (bc->need_release)
02690             misdn_lib_send_event(bc, EVENT_RELEASE);
02691          p->state = MISDN_CLEANING; 
02692       } else {
02693          if (bc->need_disconnect)
02694             misdn_lib_send_event(bc, EVENT_DISCONNECT);
02695       }
02696    }
02697 
02698    p->state = MISDN_CLEANING;
02699 
02700    chan_misdn_log(3, bc->port, " --> Channel: %s hanguped new state:%s\n", ast->name, misdn_get_ch_state(p));
02701 
02702    return 0;
02703 }
02704 
02705 
02706 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
02707 {
02708    struct ast_frame *f,*f2;
02709  
02710    if (tmp->trans) {
02711       f2 = ast_translate(tmp->trans, frame, 0);
02712       f = ast_dsp_process(tmp->ast, tmp->dsp, f2);
02713    } else {
02714       chan_misdn_log(0, tmp->bc->port, "No T-Path found\n");
02715       return NULL;
02716    }
02717 
02718    if (!f || (f->frametype != AST_FRAME_DTMF))
02719       return frame;
02720  
02721    ast_log(LOG_DEBUG, "Detected inband DTMF digit: %c\n", f->subclass);
02722  
02723    if (tmp->faxdetect && (f->subclass == 'f')) {
02724       /* Fax tone -- Handle and return NULL */
02725       if (!tmp->faxhandled) {
02726          struct ast_channel *ast = tmp->ast;
02727          tmp->faxhandled++;
02728          chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast->name);
02729          tmp->bc->rxgain = 0;
02730          isdn_lib_update_rxgain(tmp->bc);
02731          tmp->bc->txgain = 0;
02732          isdn_lib_update_txgain(tmp->bc);
02733 #ifdef MISDN_1_2
02734          *tmp->bc->pipeline = 0;
02735 #else
02736          tmp->bc->ec_enable = 0;
02737 #endif
02738          isdn_lib_update_ec(tmp->bc);
02739          isdn_lib_stop_dtmf(tmp->bc);
02740          switch (tmp->faxdetect) {
02741          case 1:
02742             if (strcmp(ast->exten, "fax")) {
02743                char *context;
02744                char context_tmp[BUFFERSIZE];
02745                misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
02746                context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
02747                if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
02748                   if (option_verbose > 2)
02749                      ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
02750                   /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
02751                   pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
02752                   if (ast_async_goto(ast, context, "fax", 1))
02753                      ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, context);
02754                } else
02755                   ast_log(LOG_NOTICE, "Fax detected, but no fax extension ctx:%s exten:%s\n", context, ast->exten);
02756             } else {
02757                ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
02758             }
02759             break;
02760          case 2:
02761             ast_verbose(VERBOSE_PREFIX_3 "Not redirecting %s to fax extension, nojump is set.\n", ast->name);
02762             break;
02763          }
02764       } else {
02765          ast_log(LOG_DEBUG, "Fax already handled\n");
02766       }
02767    }
02768    
02769    if (tmp->ast_dsp && (f->subclass != 'f')) {
02770       chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass);
02771    }
02772 
02773    return f;
02774 }
02775 
02776 
02777 static struct ast_frame *misdn_read(struct ast_channel *ast)
02778 {
02779    struct chan_list *tmp;
02780    fd_set rrfs;
02781    struct timeval tv;
02782    int len, t;
02783 
02784    if (!ast) {
02785       chan_misdn_log(1, 0, "misdn_read called without ast\n");
02786       return NULL;
02787    }
02788    if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
02789       chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
02790       return NULL;
02791    }
02792 
02793    if (!tmp->bc && !(tmp->state == MISDN_HOLDED)) {
02794       chan_misdn_log(1, 0, "misdn_read called without bc\n");
02795       return NULL;
02796    }
02797 
02798    tv.tv_sec=0;
02799    tv.tv_usec=20000;
02800 
02801    FD_ZERO(&rrfs);
02802    FD_SET(tmp->pipe[0],&rrfs);
02803 
02804    t=select(FD_SETSIZE,&rrfs,NULL, NULL,&tv);
02805 
02806    if (!t) {
02807       chan_misdn_log(3, tmp->bc->port, "read Select Timed out\n");
02808       len=160;
02809    }
02810 
02811    if (t<0) {
02812       chan_misdn_log(-1, tmp->bc->port, "Select Error (err=%s)\n",strerror(errno));
02813       return NULL;
02814    }
02815 
02816    if (FD_ISSET(tmp->pipe[0],&rrfs)) {
02817       len=read(tmp->pipe[0],tmp->ast_rd_buf,sizeof(tmp->ast_rd_buf));
02818 
02819       if (len<=0) {
02820          /* we hangup here, since our pipe is closed */
02821          chan_misdn_log(2,tmp->bc->port,"misdn_read: Pipe closed, hanging up\n");
02822          return NULL;
02823       }
02824 
02825    } else {
02826       return NULL;
02827    }
02828 
02829    tmp->frame.frametype = AST_FRAME_VOICE;
02830    tmp->frame.subclass = AST_FORMAT_ALAW;
02831    tmp->frame.datalen = len;
02832    tmp->frame.samples = len;
02833    tmp->frame.mallocd = 0;
02834    tmp->frame.offset = 0;
02835    tmp->frame.delivery = ast_tv(0,0);
02836    tmp->frame.src = NULL;
02837    tmp->frame.data = tmp->ast_rd_buf;
02838 
02839    if (tmp->faxdetect && !tmp->faxhandled) {
02840       if (tmp->faxdetect_timeout) {
02841          if (ast_tvzero(tmp->faxdetect_tv)) {
02842             tmp->faxdetect_tv = ast_tvnow();
02843             chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
02844             return process_ast_dsp(tmp, &tmp->frame);
02845          } else {
02846             struct timeval tv_now = ast_tvnow();
02847             int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
02848             if (diff <= (tmp->faxdetect_timeout * 1000)) {
02849                chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
02850                return process_ast_dsp(tmp, &tmp->frame);
02851             } else {
02852                chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
02853                tmp->faxdetect = 0;
02854                return &tmp->frame;
02855             }
02856          }
02857       } else {
02858          chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
02859          return process_ast_dsp(tmp, &tmp->frame);
02860       }
02861    } else {
02862       if (tmp->ast_dsp)
02863          return process_ast_dsp(tmp, &tmp->frame);
02864       else
02865          return &tmp->frame;
02866    }
02867 }
02868 
02869 
02870 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
02871 {
02872    struct chan_list *ch;
02873    int i  = 0;
02874    
02875    if (!ast || ! (ch = MISDN_ASTERISK_TECH_PVT(ast)) ) return -1;
02876 
02877    if (ch->state == MISDN_HOLDED) {
02878       chan_misdn_log(7, 0, "misdn_write: Returning because holded\n");
02879       return 0;
02880    }
02881    
02882    if (!ch->bc ) {
02883       ast_log(LOG_WARNING, "private but no bc\n");
02884       return -1;
02885    }
02886    
02887    if (ch->notxtone) {
02888       chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
02889       return 0;
02890    }
02891 
02892 
02893    if (!frame->subclass) {
02894       chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
02895       return 0;
02896    }
02897    
02898    if (!(frame->subclass & prefformat)) {
02899       
02900       chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%d\n", frame->subclass);
02901       return 0;
02902    }
02903    
02904 
02905    if (!frame->samples ) {
02906       chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
02907       
02908       if (!strcmp(frame->src,"ast_prod")) {
02909          chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
02910 
02911          if (ch->ts) {
02912             chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
02913             misdn_lib_tone_generator_start(ch->bc);
02914          }
02915          return 0;
02916       }
02917 
02918       return -1;
02919    }
02920 
02921    if ( ! ch->bc->addr ) {
02922       chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
02923       return 0;
02924    }
02925    
02926 #ifdef MISDN_DEBUG
02927    {
02928       int i, max = 5 > frame->samples ? frame->samples : 5;
02929 
02930       printf("write2mISDN %p %d bytes: ", p, frame->samples);
02931 
02932       for (i = 0; i < max; i++)
02933          printf("%2.2x ", ((char*) frame->data)[i]);
02934       printf ("\n");
02935    }
02936 #endif
02937 
02938    switch (ch->bc->bc_state) {
02939    case BCHAN_ACTIVATED:
02940    case BCHAN_BRIDGED:
02941       break;
02942    default:
02943       if (!ch->dropped_frame_cnt)
02944          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);
02945       
02946       ch->dropped_frame_cnt++;
02947       if (ch->dropped_frame_cnt > 100) {
02948          ch->dropped_frame_cnt = 0;
02949          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);
02950       }
02951 
02952       return 0;
02953    }
02954 
02955    chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
02956    if ( !ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability) ) {
02957       /* Buffered Transmit (triggered by read from isdn side)*/
02958       if (misdn_jb_fill(ch->jb, frame->data, frame->samples) < 0) {
02959          if (ch->bc->active)
02960             cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
02961       }
02962       
02963    } else {
02964       /*transmit without jitterbuffer*/
02965       i = misdn_lib_tx2misdn_frm(ch->bc, frame->data, frame->samples);
02966    }
02967 
02968    return 0;
02969 }
02970 
02971 
02972 
02973 
02974 static enum ast_bridge_result  misdn_bridge (struct ast_channel *c0,
02975                   struct ast_channel *c1, int flags,
02976                   struct ast_frame **fo,
02977                   struct ast_channel **rc,
02978                   int timeoutms)
02979 
02980 {
02981    struct chan_list *ch1, *ch2;
02982    struct ast_channel *carr[2], *who;
02983    int to = -1;
02984    struct ast_frame *f;
02985    int p1_b, p2_b;
02986    int bridging;
02987   
02988    ch1 = get_chan_by_ast(c0);
02989    ch2 = get_chan_by_ast(c1);
02990 
02991    carr[0] = c0;
02992    carr[1] = c1;
02993   
02994    if (!(ch1 && ch2))
02995       return -1;
02996 
02997    misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(int));
02998    misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(int));
02999 
03000    if (! p1_b || ! p2_b) {
03001       ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
03002       return AST_BRIDGE_FAILED;
03003    }
03004 
03005    misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03006    if (bridging) {
03007       /* trying to make a mISDN_dsp conference */
03008       chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
03009       misdn_lib_bridge(ch1->bc, ch2->bc);
03010    }
03011 
03012    if (option_verbose > 2) 
03013       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03014 
03015    chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between %s and %s\n", ch1->bc->oad, ch2->bc->oad);
03016  
03017    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_0) )
03018       ch1->ignore_dtmf = 1;
03019 
03020    if (! (flags & AST_BRIDGE_DTMF_CHANNEL_1) )
03021       ch2->ignore_dtmf = 1;
03022 
03023    for (;/*ever*/;) {
03024       to = -1;
03025       who = ast_waitfor_n(carr, 2, &to);
03026 
03027       if (!who) {
03028          ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
03029          break;
03030       }
03031       f = ast_read(who);
03032 
03033       if (!f || f->frametype == AST_FRAME_CONTROL) {
03034          /* got hangup .. */
03035 
03036          if (!f) 
03037             chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
03038          else
03039             chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass);
03040 
03041          *fo = f;
03042          *rc = who;
03043          break;
03044       }
03045       
03046       if ( f->frametype == AST_FRAME_DTMF ) {
03047          chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass, who->exten);
03048 
03049          *fo = f;
03050          *rc = who;
03051          break;
03052       }
03053    
03054 #if 0
03055       if (f->frametype == AST_FRAME_VOICE) {
03056          chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
03057    
03058          continue;
03059       }
03060 #endif
03061 
03062       if (who == c0) {
03063          ast_write(c1, f);
03064       }
03065       else {
03066          ast_write(c0, f);
03067       }
03068    }
03069 
03070    chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
03071 
03072    misdn_lib_split_bridge(ch1->bc, ch2->bc);
03073 
03074    return AST_BRIDGE_COMPLETE;
03075 }
03076 
03077 /** AST INDICATIONS END **/
03078 
03079 static int dialtone_indicate(struct chan_list *cl)
03080 {
03081    const struct tone_zone_sound *ts = NULL;
03082    struct ast_channel *ast = cl->ast;
03083    int nd = 0;
03084 
03085    if (!ast) {
03086       chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
03087       return -1;
03088    }
03089 
03090    misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
03091 
03092    if (nd) {
03093       chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
03094       return 0;
03095    }
03096    
03097    chan_misdn_log(3, cl->bc->port, " --> Dial\n");
03098    ts = ast_get_indication_tone(ast->zone, "dial");
03099    cl->ts = ts;   
03100    
03101    if (ts) {
03102       cl->notxtone = 0;
03103       cl->norxtone = 0;
03104       /* This prods us in misdn_write */
03105       ast_playtones_start(ast, 0, ts->data, 0);
03106    }
03107 
03108    return 0;
03109 }
03110 
03111 static int hanguptone_indicate(struct chan_list *cl)
03112 {
03113    misdn_lib_send_tone(cl->bc, TONE_HANGUP);
03114    return 0;
03115 }
03116 
03117 static int stop_indicate(struct chan_list *cl)
03118 {
03119    struct ast_channel *ast = cl->ast;
03120 
03121    if (!ast) {
03122       chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
03123       return -1;
03124    }
03125 
03126    chan_misdn_log(3, cl->bc->port, " --> None\n");
03127    misdn_lib_tone_generator_stop(cl->bc);
03128    ast_playtones_stop(ast);
03129 
03130    cl->ts = NULL;
03131    /*ast_deactivate_generator(ast);*/
03132 
03133    return 0;
03134 }
03135 
03136 
03137 static int start_bc_tones(struct chan_list* cl)
03138 {
03139    misdn_lib_tone_generator_stop(cl->bc);
03140    cl->notxtone = 0;
03141    cl->norxtone = 0;
03142    return 0;
03143 }
03144 
03145 static int stop_bc_tones(struct chan_list *cl)
03146 {
03147    if (!cl) return -1;
03148 
03149    cl->notxtone = 1;
03150    cl->norxtone = 1;
03151    
03152    return 0;
03153 }
03154 
03155 
03156 static struct chan_list *init_chan_list(int orig)
03157 {
03158    struct chan_list *cl;
03159 
03160    cl = calloc(1, sizeof(struct chan_list));
03161    if (!cl) {
03162       chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
03163       return NULL;
03164    }
03165    
03166    cl->originator = orig;
03167    cl->need_queue_hangup = 1;
03168    cl->need_hangup = 1;
03169    cl->need_busy = 1;
03170    cl->overlap_dial_task = -1;
03171 
03172    return cl;
03173 }
03174 
03175 static struct ast_channel *misdn_request(const char *type, int format, void *data, int *cause)
03176 {
03177    struct ast_channel *tmp = NULL;
03178    char group[BUFFERSIZE + 1] = "";
03179    char dial_str[128];
03180    char *buf2 = ast_strdupa(data);
03181    char *ext;
03182    char *port_str;
03183    char *p = NULL;
03184    int channel = 0;
03185    int port = 0;
03186    struct misdn_bchannel *newbc = NULL;
03187    int dec = 0;
03188 
03189    struct chan_list *cl = init_chan_list(ORG_AST);
03190 
03191    snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, (char *) data);
03192 
03193    /*
03194     * data is ---v
03195     * Dial(mISDN/g:group_name[/extension[/options]])
03196     * Dial(mISDN/port[:preselected_channel][/extension[/options]])
03197     *
03198     * The dial extension could be empty if you are using MISDN_KEYPAD
03199     * to control ISDN provider features.
03200     */
03201    port_str = strsep(&buf2, "/");
03202    if (!ast_strlen_zero(port_str)) {
03203       if (port_str[0] == 'g' && port_str[1] == ':' ) {
03204          /* We make a group call lets checkout which ports are in my group */
03205          port_str += 2;
03206          ast_copy_string(group, port_str, sizeof(group));
03207          chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
03208       } else if ((p = strchr(port_str, ':'))) {
03209          /* we have a preselected channel */
03210          *p = 0;
03211          channel = atoi(++p);
03212          port = atoi(port_str);
03213          chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
03214       } else {
03215          port = atoi(port_str);
03216       }
03217    } else {
03218       ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
03219       return NULL;
03220    }
03221 
03222    ext = strsep(&buf2, "/");
03223    if (!ext) {
03224       ext = "";
03225    }
03226 
03227    if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
03228       chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
03229       dec = 1;
03230    }
03231 
03232    if (!ast_strlen_zero(group)) {
03233       char cfg_group[BUFFERSIZE + 1];
03234       struct robin_list *rr = NULL;
03235 
03236       /* Group dial */
03237 
03238       if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
03239          chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
03240          rr = get_robin_position(group);
03241       }
03242 
03243       if (rr) {
03244          int port_start = 0;
03245          int port_bak = rr->port;
03246          int chan_bak = rr->channel;
03247 
03248          if (!rr->port)
03249             rr->port = misdn_cfg_get_next_port_spin(rr->port);
03250          
03251          for (; rr->port > 0; rr->port = misdn_cfg_get_next_port_spin(rr->port)) {
03252             int port_up;
03253             int check;
03254             int max_chan;
03255             int last_chance = 0;
03256 
03257             misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03258             if (strcasecmp(cfg_group, group))
03259                continue;
03260 
03261             misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03262             port_up = misdn_lib_port_up(rr->port, check);
03263 
03264             if (check && !port_up) 
03265                chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
03266 
03267             if (check && port_up < 0)
03268                ast_log(LOG_WARNING,"This port (%d) is blocked\n", rr->port);
03269 
03270             if ((port_start == rr->port) && (port_up <= 0))
03271                break;
03272 
03273             if (!port_start)
03274                port_start = rr->port;
03275 
03276             if (port_up <= 0)
03277                continue;
03278 
03279             max_chan = misdn_lib_get_maxchans(rr->port);
03280 
03281             for (++rr->channel; !last_chance && rr->channel <= max_chan; ++rr->channel) {
03282                if (rr->port == port_bak && rr->channel == chan_bak)
03283                   last_chance = 1;
03284 
03285                chan_misdn_log(1, 0, "trying port:%d channel:%d\n", rr->port, rr->channel);
03286                newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0);
03287                if (newbc) {
03288                   chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
03289                   if (port_up)
03290                      chan_misdn_log(4, rr->port, "portup:%d\n",  port_up);
03291                   port = rr->port;
03292                   break;
03293                }
03294             }
03295 
03296             if (newbc || last_chance)
03297                break;
03298 
03299             rr->channel = 0;
03300          }
03301          if (!newbc) {
03302             rr->port = port_bak;
03303             rr->channel = chan_bak;
03304          }
03305       } else {    
03306          for (port = misdn_cfg_get_next_port(0); port > 0;
03307              port = misdn_cfg_get_next_port(port)) {
03308 
03309             misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
03310 
03311             chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
03312             if (!strcasecmp(cfg_group, group)) {
03313                int port_up;
03314                int check;
03315                misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(int));
03316                port_up = misdn_lib_port_up(port, check);
03317 
03318                chan_misdn_log(4, port, "portup:%d\n", port_up);
03319 
03320                if (port_up > 0) {
03321                   newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
03322                   if (newbc)
03323                      break;
03324                }
03325             }
03326          }
03327       }
03328       
03329       /* Group dial failed ?*/
03330       if (!newbc) {
03331          ast_log(LOG_WARNING, 
03332                "Could not Dial out on group '%s'.\n"
03333                "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
03334                "\tOr there was no free channel on none of the ports\n\n"
03335                , group);
03336          return NULL;
03337       }
03338    } else {
03339       /* 'Normal' Port dial * Port dial */
03340       if (channel)
03341          chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
03342       newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
03343 
03344       if (!newbc) {
03345          ast_log(LOG_WARNING, "Could not create channel on port:%d with extensions:%s\n", port, ext);
03346          return NULL;
03347       }
03348    }
03349    
03350 
03351    /* create ast_channel and link all the objects together */
03352    cl->bc = newbc;
03353    
03354    tmp = misdn_new(cl, AST_STATE_RESERVED, ext, NULL, format, port, channel);
03355    if (!tmp) {
03356       ast_log(LOG_ERROR,"Could not create Asterisk object\n");
03357       return NULL;
03358    }
03359 
03360    cl->ast=tmp;
03361    
03362    /* register chan in local list */
03363    cl_queue_chan(&cl_te, cl) ;
03364    
03365    /* fill in the config into the objects */
03366    read_config(cl, ORG_AST);
03367 
03368    /* important */
03369    cl->need_hangup = 0;
03370    
03371    return tmp;
03372 }
03373 
03374 
03375 static int misdn_send_text(struct ast_channel *chan, const char *text)
03376 {
03377    struct chan_list *tmp = chan->tech_pvt;
03378    
03379    if (tmp && tmp->bc) {
03380       ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
03381       misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
03382    } else {
03383       ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
03384       return -1;
03385    }
03386    
03387    return 0;
03388 }
03389 
03390 static struct ast_channel_tech misdn_tech = {
03391    .type = "mISDN",
03392    .description = "Channel driver for mISDN Support (Bri/Pri)",
03393    .capabilities = AST_FORMAT_ALAW ,
03394    .requester = misdn_request,
03395    .send_digit_begin = misdn_digit_begin,
03396    .send_digit_end = misdn_digit_end,
03397    .call = misdn_call,
03398    .bridge = misdn_bridge, 
03399    .hangup = misdn_hangup,
03400    .answer = misdn_answer,
03401    .read = misdn_read,
03402    .write = misdn_write,
03403    .indicate = misdn_indication,
03404    .fixup = misdn_fixup,
03405    .send_text = misdn_send_text,
03406    .properties = 0
03407 };
03408 
03409 static struct ast_channel_tech misdn_tech_wo_bridge = {
03410    .type = "mISDN",
03411    .description = "Channel driver for mISDN Support (Bri/Pri)",
03412    .capabilities = AST_FORMAT_ALAW ,
03413    .requester = misdn_request,
03414    .send_digit_begin = misdn_digit_begin,
03415    .send_digit_end = misdn_digit_end,
03416    .call = misdn_call,
03417    .hangup = misdn_hangup,
03418    .answer = misdn_answer,
03419    .read = misdn_read,
03420    .write = misdn_write,
03421    .indicate = misdn_indication,
03422    .fixup = misdn_fixup,
03423    .send_text = misdn_send_text,
03424    .properties = 0
03425 };
03426 
03427 
03428 static int glob_channel = 0;
03429 
03430 static void update_name(struct ast_channel *tmp, int port, int c) 
03431 {
03432    int chan_offset = 0;
03433    int tmp_port = misdn_cfg_get_next_port(0);
03434    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03435       if (tmp_port == port)
03436          break;
03437       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2; 
03438    }
03439    if (c < 0)
03440       c = 0;
03441 
03442    ast_string_field_build(tmp, name, "%s/%d-u%d",
03443       misdn_type, chan_offset + c, glob_channel++);
03444 
03445    chan_misdn_log(3, port, " --> updating channel name to [%s]\n", tmp->name);
03446 }
03447 
03448 static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char *exten, char *callerid, int format, int port, int c)
03449 {
03450    struct ast_channel *tmp;
03451    char *cid_name = 0, *cid_num = 0;
03452    int chan_offset = 0;
03453    int tmp_port = misdn_cfg_get_next_port(0);
03454    int bridging;
03455 
03456    for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
03457       if (tmp_port == port)
03458          break;
03459       chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
03460    }
03461    if (c < 0)
03462       c = 0;
03463 
03464    if (callerid) {
03465       ast_callerid_parse(callerid, &cid_name, &cid_num);
03466    }
03467 
03468    tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", 0, "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
03469    if (tmp) {
03470       chan_misdn_log(2, 0, " --> * NEW CHANNEL dad:%s oad:%s\n", exten, callerid);
03471 
03472       tmp->nativeformats = prefformat;
03473 
03474       tmp->readformat = format;
03475       tmp->rawreadformat = format;
03476       tmp->writeformat = format;
03477       tmp->rawwriteformat = format;
03478     
03479       tmp->tech_pvt = chlist;
03480 
03481       misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(int));
03482 
03483       if (bridging)
03484          tmp->tech = &misdn_tech;
03485       else
03486          tmp->tech = &misdn_tech_wo_bridge;
03487 
03488       tmp->writeformat = format;
03489       tmp->readformat = format;
03490       tmp->priority=1;
03491 
03492       if (exten) 
03493          ast_copy_string(tmp->exten, exten, sizeof(tmp->exten));
03494       else
03495          chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
03496 
03497       if (callerid)
03498          /* Don't use ast_set_callerid() here because it will
03499           * generate a needless NewCallerID event */
03500          tmp->cid.cid_ani = ast_strdup(cid_num);
03501 
03502       if (pipe(chlist->pipe) < 0)
03503          perror("Pipe failed\n");
03504       tmp->fds[0] = chlist->pipe[0];
03505 
03506       if (state == AST_STATE_RING)
03507          tmp->rings = 1;
03508       else
03509          tmp->rings = 0;
03510 
03511            ast_jb_configure(tmp, misdn_get_global_jbconf());      
03512    } else {
03513       chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
03514    }
03515    
03516    return tmp;
03517 }
03518 
03519 static struct chan_list *find_chan_by_bc(struct chan_list *list, struct misdn_bchannel *bc)
03520 {
03521    struct chan_list *help = list;
03522    for (; help; help = help->next) {
03523       if (help->bc == bc) return help;
03524    }
03525 
03526    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03527 
03528    return NULL;
03529 }
03530 
03531 static struct chan_list *find_chan_by_pid(struct chan_list *list, int pid)
03532 {
03533    struct chan_list *help = list;
03534    for (; help; help = help->next) {
03535       if ( help->bc && (help->bc->pid == pid) ) return help;
03536    }
03537 
03538    chan_misdn_log(6, 0, "$$$ find_chan: No channel found for pid:%d\n", pid);
03539 
03540    return NULL;
03541 }
03542 
03543 static struct chan_list *find_holded(struct chan_list *list, struct misdn_bchannel *bc)
03544 {
03545    struct chan_list *help = list;
03546 
03547    if (bc->pri) return NULL;
03548 
03549    chan_misdn_log(6, bc->port, "$$$ find_holded: channel:%d oad:%s dad:%s\n", bc->channel, bc->oad, bc->dad);
03550    for (;help; help = help->next) {
03551       chan_misdn_log(4, bc->port, "$$$ find_holded: --> holded:%d channel:%d\n", help->state == MISDN_HOLDED, help->hold_info.channel);
03552       if ((help->state == MISDN_HOLDED) && 
03553          (help->hold_info.port == bc->port))
03554          return help;
03555    }
03556    chan_misdn_log(6, bc->port, "$$$ find_chan: No channel found for oad:%s dad:%s\n", bc->oad, bc->dad);
03557 
03558    return NULL;
03559 }
03560 
03561 
03562 static struct chan_list *find_holded_l3(struct chan_list *list, unsigned long l3_id, int w) 
03563 {
03564    struct chan_list *help = list;
03565 
03566    for (; help; help = help->next) {
03567       if ( (help->state == MISDN_HOLDED) &&
03568           (help->l3id == l3_id)   
03569          ) 
03570          return help;
03571    }
03572 
03573    return NULL;
03574 }
03575 
03576 static void cl_queue_chan(struct chan_list **list, struct chan_list *chan)
03577 {
03578    chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
03579   
03580    ast_mutex_lock(&cl_te_lock);
03581    if (!*list) {
03582       *list = chan;
03583    } else {
03584       struct chan_list *help = *list;
03585       for (; help->next; help = help->next); 
03586       help->next = chan;
03587    }
03588    chan->next = NULL;
03589    ast_mutex_unlock(&cl_te_lock);
03590 }
03591 
03592 static void cl_dequeue_chan(struct chan_list **list, struct chan_list *chan) 
03593 {
03594    struct chan_list *help;
03595 
03596    if (chan->dsp) 
03597       ast_dsp_free(chan->dsp);
03598    if (chan->trans)
03599       ast_translator_free_path(chan->trans);
03600 
03601    ast_mutex_lock(&cl_te_lock);
03602    if (!*list) {
03603       ast_mutex_unlock(&cl_te_lock);
03604       return;
03605    }
03606   
03607    if (*list == chan) {
03608       *list = (*list)->next;
03609       ast_mutex_unlock(&cl_te_lock);
03610       return;
03611    }
03612   
03613    for (help = *list; help->next; help = help->next) {
03614       if (help->next == chan) {
03615          help->next = help->next->next;
03616          ast_mutex_unlock(&cl_te_lock);
03617          return;
03618       }
03619    }
03620    
03621    ast_mutex_unlock(&cl_te_lock);
03622 }
03623 
03624 /** Channel Queue End **/
03625 
03626 
03627 static int pbx_start_chan(struct chan_list *ch)
03628 {
03629    int ret = ast_pbx_start(ch->ast);   
03630 
03631    if (ret >= 0) 
03632       ch->need_hangup = 0;
03633    else
03634       ch->need_hangup = 1;
03635 
03636    return ret;
03637 }
03638 
03639 static void hangup_chan(struct chan_list *ch)
03640 {
03641    int port = ch ? (ch->bc ? ch->bc->port : 0) : 0;
03642    if (!ch) {
03643       cb_log(1, 0, "Cannot hangup chan, no ch\n");
03644       return;
03645    }
03646 
03647    cb_log(5, port, "hangup_chan called\n");
03648 
03649    if (ch->need_hangup) {
03650       cb_log(2, port, " --> hangup\n");
03651       send_cause2ast(ch->ast, ch->bc, ch);
03652       ch->need_hangup = 0;
03653       ch->need_queue_hangup = 0;
03654       if (ch->ast)
03655          ast_hangup(ch->ast);
03656       return;
03657    }
03658 
03659    if (!ch->need_queue_hangup) {
03660       cb_log(2, port, " --> No need to queue hangup\n");
03661    }
03662 
03663    ch->need_queue_hangup = 0;
03664    if (ch->ast) {
03665       send_cause2ast(ch->ast, ch->bc, ch);
03666 
03667       if (ch->ast)
03668          ast_queue_hangup(ch->ast);
03669       cb_log(2, port, " --> queue_hangup\n");
03670    } else {
03671       cb_log(1, port, "Cannot hangup chan, no ast\n");
03672    }
03673 }
03674 
03675 /** Isdn asks us to release channel, pendant to misdn_hangup **/
03676 static void release_chan(struct misdn_bchannel *bc) {
03677    struct ast_channel *ast = NULL;
03678 
03679    ast_mutex_lock(&release_lock);
03680    {
03681       struct chan_list *ch=find_chan_by_bc(cl_te, bc);
03682       if (!ch)  {
03683          chan_misdn_log(1, bc->port, "release_chan: Ch not found!\n");
03684          ast_mutex_unlock(&release_lock);
03685          return;
03686       }
03687 
03688       if (ch->ast) {
03689          ast = ch->ast;
03690       } 
03691 
03692       chan_misdn_log(5, bc->port, "release_chan: bc with l3id: %x\n", bc->l3_id);
03693 
03694       /*releasing jitterbuffer*/
03695       if (ch->jb ) {
03696          misdn_jb_destroy(ch->jb);
03697          ch->jb = NULL;
03698       } else {
03699          if (!bc->nojitter)
03700             chan_misdn_log(5, bc->port, "Jitterbuffer already destroyed.\n");
03701       }
03702 
03703       if (ch->overlap_dial) {
03704          if (ch->overlap_dial_task != -1) {
03705             misdn_tasks_remove(ch->overlap_dial_task);
03706             ch->overlap_dial_task = -1;
03707          }
03708          ast_mutex_destroy(&ch->overlap_tv_lock);
03709       }
03710 
03711       if (ch->originator == ORG_AST) {
03712          misdn_out_calls[bc->port]--;
03713       } else {
03714          misdn_in_calls[bc->port]--;
03715       }
03716 
03717       if (ch) {
03718          close(ch->pipe[0]);
03719          close(ch->pipe[1]);
03720 
03721          if (ast && MISDN_ASTERISK_TECH_PVT(ast)) {
03722             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));
03723             chan_misdn_log(3, bc->port, " --> * State Down\n");
03724             MISDN_ASTERISK_TECH_PVT(ast) = NULL;
03725 
03726             if (ast->_state != AST_STATE_RESERVED) {
03727                chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
03728                ast_setstate(ast, AST_STATE_DOWN);
03729             }
03730          }
03731 
03732          ch->state = MISDN_CLEANING;
03733          cl_dequeue_chan(&cl_te, ch);
03734 
03735          free(ch);
03736       } else {
03737          /* chan is already cleaned, so exiting  */
03738       }
03739    }
03740    ast_mutex_unlock(&release_lock);
03741 /*** release end **/
03742 }
03743 
03744 static void misdn_transfer_bc(struct chan_list *tmp_ch, struct chan_list *holded_chan)
03745 {
03746    chan_misdn_log(4, 0, "TRANSFERRING %s to %s\n", holded_chan->ast->name, tmp_ch->ast->name);
03747 
03748    tmp_ch->state = MISDN_HOLD_DISCONNECT;
03749 
03750    ast_moh_stop(ast_bridged_channel(holded_chan->ast));
03751 
03752    holded_chan->state=MISDN_CONNECTED;
03753    /* misdn_lib_transfer(holded_chan->bc); */
03754    ast_channel_masquerade(holded_chan->ast, ast_bridged_channel(tmp_ch->ast));
03755 }
03756 
03757 
03758 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
03759 {
03760    char predial[256]="";
03761    char *p = predial;
03762   
03763    struct ast_frame fr;
03764 
03765    strncpy(predial, ast->exten, sizeof(predial) -1 );
03766 
03767    ch->state = MISDN_DIALING;
03768 
03769    if (!ch->noautorespond_on_setup) {
03770       if (bc->nt) {
03771          int ret; 
03772          ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03773       } else {
03774          int ret;
03775          if ( misdn_lib_is_ptp(bc->port)) {
03776             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03777          } else {
03778             ret = misdn_lib_send_event(bc, EVENT_PROCEEDING );
03779          }
03780       }
03781    } else {
03782       ch->state = MISDN_INCOMING_SETUP;
03783    }
03784 
03785    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);
03786   
03787    strcpy(ast->exten, "s");
03788  
03789    if (!ast_canmatch_extension(ast, ast->context, ast->exten, 1, bc->oad) || pbx_start_chan(ch) < 0) {
03790       ast = NULL;
03791       bc->out_cause = AST_CAUSE_UNALLOCATED;
03792       hangup_chan(ch);
03793       hanguptone_indicate(ch);
03794 
03795       if (bc->nt)
03796          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
03797       else
03798          misdn_lib_send_event(bc, EVENT_DISCONNECT );
03799    }
03800   
03801   
03802    while (!ast_strlen_zero(p) ) {
03803       fr.frametype = AST_FRAME_DTMF;
03804       fr.subclass = *p;
03805       fr.src = NULL;
03806       fr.data = NULL;
03807       fr.datalen = 0;
03808       fr.samples = 0;
03809       fr.mallocd = 0;
03810       fr.offset = 0;
03811       fr.delivery = ast_tv(0,0);
03812 
03813       if (ch->ast && MISDN_ASTERISK_PVT(ch->ast) && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
03814          ast_queue_frame(ch->ast, &fr);
03815       }
03816       p++;
03817    }
03818 }
03819 
03820 
03821 
03822 static void send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch) {
03823    if (!ast) {
03824       chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
03825       return;
03826    }
03827    if (!bc) {
03828       chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
03829       return;
03830    }
03831    if (!ch) {
03832       chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
03833       return;
03834    }
03835 
03836    ast->hangupcause = bc->cause;
03837 
03838    switch (bc->cause) {
03839 
03840    case AST_CAUSE_UNALLOCATED:
03841    case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
03842    case AST_CAUSE_NO_ROUTE_DESTINATION:
03843    case 4:  /* Send special information tone */
03844    case AST_CAUSE_NUMBER_CHANGED:
03845    case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
03846       /* Congestion Cases */
03847       /*
03848        * Not Queueing the Congestion anymore, since we want to hear
03849        * the inband message
03850        *
03851       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Congestion pid:%d\n", bc ? bc->pid : -1);
03852       ch->state = MISDN_BUSY;
03853       
03854       ast_queue_control(ast, AST_CONTROL_CONGESTION);
03855       */
03856       break;
03857 
03858    case AST_CAUSE_CALL_REJECTED:
03859    case AST_CAUSE_USER_BUSY:
03860       ch->state = MISDN_BUSY;
03861 
03862       if (!ch->need_busy) {
03863          chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
03864          break;
03865       }
03866 
03867       chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
03868       
03869       ast_queue_control(ast, AST_CONTROL_BUSY);
03870       
03871       ch->need_busy = 0;
03872       
03873       break;
03874    }
03875 }
03876 
03877 
03878 /*! \brief Import parameters from the dialplan environment variables */
03879 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03880 {
03881    const char *tmp;
03882 
03883    tmp = pbx_builtin_getvar_helper(chan, "MISDN_PID");
03884    if (tmp) {
03885       ch->other_pid = atoi(tmp);
03886       chan_misdn_log(3, bc->port, " --> IMPORT_PID: importing pid:%s\n", tmp);
03887       if (ch->other_pid > 0) {
03888          ch->other_ch = find_chan_by_pid(cl_te, ch->other_pid);
03889          if (ch->other_ch)
03890             ch->other_ch->other_ch = ch;
03891       }
03892    }
03893 
03894    tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
03895    if (tmp && (atoi(tmp) == 1)) {
03896       bc->sending_complete = 1;
03897    }
03898 
03899    tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
03900    if (tmp) {
03901       ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
03902       ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
03903       bc->uulen = strlen(bc->uu);
03904    }
03905 
03906    tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
03907    if (tmp) {
03908       ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
03909    }
03910 }
03911 
03912 /*! \brief Export parameters to the dialplan environment variables */
03913 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
03914 {
03915    char tmp[32];
03916    chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
03917    snprintf(tmp, sizeof(tmp), "%d", bc->pid);
03918    pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
03919 
03920    if (bc->sending_complete) {
03921       snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
03922       pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
03923    }
03924 
03925    if (bc->urate) {
03926       snprintf(tmp, sizeof(tmp), "%d", bc->urate);
03927       pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
03928    }
03929 
03930    if (bc->uulen && (bc->uulen < sizeof(bc->uu))) {
03931       bc->uu[bc->uulen] = 0;
03932       pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
03933    }
03934 
03935    if (!ast_strlen_zero(bc->keypad)) 
03936       pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
03937 }
03938 
03939 int add_in_calls(int port)
03940 {
03941    int max_in_calls;
03942    
03943    misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
03944    misdn_in_calls[port]++;
03945 
03946    if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
03947       ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
03948       return misdn_in_calls[port] - max_in_calls;
03949    }
03950    
03951    return 0;
03952 }
03953 
03954 int add_out_calls(int port)
03955 {
03956    int max_out_calls;
03957    
03958    misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
03959 
03960    if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
03961       ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
03962       return (misdn_out_calls[port] + 1) - max_out_calls;
03963    }
03964 
03965    misdn_out_calls[port]++;
03966    
03967    return 0;
03968 }
03969 
03970 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03971    if (pbx_start_chan(ch) < 0) {
03972       hangup_chan(ch);
03973       chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
03974       if (bc->nt) {
03975          hanguptone_indicate(ch);
03976          misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
03977       } else
03978          misdn_lib_send_event(bc, EVENT_RELEASE);
03979    }
03980 }
03981 
03982 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan) {
03983    ch->state=MISDN_WAITING4DIGS;
03984    misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
03985    if (bc->nt && !bc->dad[0])
03986       dialtone_indicate(ch);
03987 }
03988 
03989 
03990 /************************************************************/
03991 /*  Receive Events from isdn_lib  here                     */
03992 /************************************************************/
03993 static enum event_response_e
03994 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
03995 {
03996    int msn_valid;
03997    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
03998    
03999    if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) { /*  Debug Only Non-Bchan */
04000       int debuglevel = 1;
04001       if ( event == EVENT_CLEANUP && !user_data)
04002          debuglevel = 5;
04003 
04004       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");
04005       if (debuglevel == 1) {
04006          misdn_lib_log_ies(bc);
04007          chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
04008       }
04009    }
04010    
04011    if (!ch) {
04012       switch(event) {
04013       case EVENT_SETUP:
04014       case EVENT_DISCONNECT:
04015       case EVENT_PORT_ALARM:
04016       case EVENT_RETRIEVE:
04017       case EVENT_NEW_BC:
04018       case EVENT_FACILITY:
04019          break;
04020       case EVENT_RELEASE_COMPLETE:
04021          chan_misdn_log(1, bc->port, " --> no Ch, so we've already released.\n");
04022          break;
04023       case EVENT_CLEANUP:
04024       case EVENT_TONE_GENERATE:
04025       case EVENT_BCHAN_DATA:
04026          return -1;
04027       default:
04028          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);
04029          return -1;
04030       }
04031    }
04032    
04033    if (ch) {
04034       switch (event) {
04035       case EVENT_TONE_GENERATE:
04036          break;
04037       case EVENT_DISCONNECT:
04038       case EVENT_RELEASE:
04039       case EVENT_RELEASE_COMPLETE:
04040       case EVENT_CLEANUP:
04041       case EVENT_TIMEOUT:
04042          if (!ch->ast)
04043             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));
04044          break;
04045       default:
04046          if (!ch->ast  || !MISDN_ASTERISK_PVT(ch->ast) || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
04047             if (event != EVENT_BCHAN_DATA)
04048                ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
04049             return -1;
04050          }
04051       }
04052    }
04053    
04054    
04055    switch (event) {
04056    case EVENT_PORT_ALARM:
04057       {
04058          int boa = 0;
04059          misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(int));
04060          if (boa) {
04061             cb_log(1, bc->port, " --> blocking\n");
04062             misdn_lib_port_block(bc->port); 
04063          }
04064       }
04065       break;
04066    case EVENT_BCHAN_ACTIVATED:
04067       break;
04068       
04069    case EVENT_NEW_CHANNEL:
04070       update_name(ch->ast,bc->port,bc->channel);
04071       break;
04072       
04073    case EVENT_NEW_L3ID:
04074       ch->l3id=bc->l3_id;
04075       ch->addr=bc->addr;
04076       break;
04077 
04078    case EVENT_NEW_BC:
04079       if (!ch) {
04080          ch = find_holded(cl_te,bc);
04081       }
04082       
04083       if (!ch) {
04084          ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
04085          break;
04086       }
04087 
04088       if (bc)
04089          ch->bc = (struct misdn_bchannel *)user_data;
04090       break;
04091       
04092    case EVENT_DTMF_TONE:
04093    {
04094       /*  sending INFOS as DTMF-Frames :) */
04095       struct ast_frame fr;
04096 
04097       memset(&fr, 0, sizeof(fr));
04098       fr.frametype = AST_FRAME_DTMF;
04099       fr.subclass = bc->dtmf ;
04100       fr.src = NULL;
04101       fr.data = NULL;
04102       fr.datalen = 0;
04103       fr.samples = 0;
04104       fr.mallocd = 0;
04105       fr.offset = 0;
04106       fr.delivery = ast_tv(0,0);
04107       
04108       if (!ch->ignore_dtmf) {
04109          chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
04110          ast_queue_frame(ch->ast, &fr);
04111       } else {
04112          chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
04113       }
04114    }
04115       break;
04116    case EVENT_STATUS:
04117       break;
04118     
04119    case EVENT_INFORMATION:
04120    {
04121       if ( ch->state != MISDN_CONNECTED ) 
04122          stop_indicate(ch);
04123    
04124       if (!ch->ast)
04125          break;
04126 
04127       if (ch->state == MISDN_WAITING4DIGS ) {
04128          /*  Ok, incomplete Setup, waiting till extension exists */
04129          if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
04130             chan_misdn_log(1, bc->port, " --> using keypad as info\n");
04131             ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
04132          }
04133 
04134          strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04135          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04136 
04137          /* Check for Pickup Request first */
04138          if (!strcmp(ch->ast->exten, ast_pickup_ext())) {
04139             if (ast_pickup_call(ch->ast)) {
04140                hangup_chan(ch);
04141             } else {
04142                struct ast_channel *chan = ch->ast;
04143                ch->state = MISDN_CALLING_ACKNOWLEDGE;
04144                ast_setstate(chan, AST_STATE_DOWN);
04145                hangup_chan(ch);
04146                ch->ast = NULL;
04147                break;
04148             }
04149          }
04150          
04151          if (!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04152             if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04153                ast_log(LOG_WARNING,
04154                   "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04155                   bc->dad, ch->context, bc->port);
04156                strcpy(ch->ast->exten, "i");
04157 
04158                ch->state = MISDN_DIALING;
04159                start_pbx(ch, bc, ch->ast);
04160                break;
04161             }
04162 
04163             ast_log(LOG_WARNING,
04164                "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04165                "\tMaybe you want to add an 'i' extension to catch this case.\n",
04166                bc->dad, ch->context, bc->port);
04167 
04168             if (bc->nt)
04169                hanguptone_indicate(ch);
04170             ch->state = MISDN_EXTCANTMATCH;
04171             bc->out_cause = AST_CAUSE_UNALLOCATED;
04172 
04173             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04174             break;
04175          }
04176 
04177          if (ch->overlap_dial) {
04178             ast_mutex_lock(&ch->overlap_tv_lock);
04179             ch->overlap_tv = ast_tvnow();
04180             ast_mutex_unlock(&ch->overlap_tv_lock);
04181             if (ch->overlap_dial_task == -1) {
04182                ch->overlap_dial_task = 
04183                   misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04184             }
04185             break;
04186          }
04187 
04188          if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04189             
04190             ch->state = MISDN_DIALING;
04191             start_pbx(ch, bc, ch->ast);
04192          }
04193       } else {
04194          /*  sending INFOS as DTMF-Frames :) */
04195          struct ast_frame fr;
04196          int digits;
04197 
04198          memset(&fr, 0, sizeof(fr));
04199          fr.frametype = AST_FRAME_DTMF;
04200          fr.subclass = bc->info_dad[0] ;
04201          fr.src = NULL;
04202          fr.data = NULL;
04203          fr.datalen = 0;
04204          fr.samples = 0;
04205          fr.mallocd = 0;
04206          fr.offset = 0;
04207          fr.delivery = ast_tv(0,0);
04208 
04209          misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(int));
04210          if (ch->state != MISDN_CONNECTED ) {
04211             if (digits) {
04212                strncat(bc->dad, bc->info_dad, sizeof(bc->dad) - strlen(bc->dad) - 1);
04213                ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04214                ast_cdr_update(ch->ast);
04215             }
04216             
04217             ast_queue_frame(ch->ast, &fr);
04218          }
04219       }
04220    }
04221       break;
04222    case EVENT_SETUP:
04223    {
04224       struct chan_list *ch = find_chan_by_bc(cl_te, bc);
04225       struct ast_channel *chan;
04226       int exceed;
04227       int pres, screen;
04228       int ai;
04229       int im;
04230 
04231       if (ch) {
04232          switch (ch->state) {
04233          case MISDN_NOTHING:
04234             ch = NULL;
04235             break;
04236          default:
04237             chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
04238             return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE; /*  Ignore MSNs which are not in our List */
04239          }
04240       }
04241 
04242       msn_valid = misdn_cfg_is_msn_valid(bc->port, bc->dad);
04243       if (!bc->nt && ! msn_valid) {
04244          chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
04245          return RESPONSE_IGNORE_SETUP; /*  Ignore MSNs which are not in our List */
04246       }
04247 
04248       if (bc->cw) {
04249          int cause;
04250          chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
04251          misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
04252          bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
04253          return RESPONSE_RELEASE_SETUP;
04254       }
04255 
04256       print_bearer(bc);
04257 
04258       ch = init_chan_list(ORG_MISDN);
04259 
04260       if (!ch) {
04261          chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
04262          return 0;
04263       }
04264 
04265       ch->bc = bc;
04266       ch->l3id = bc->l3_id;
04267       ch->addr = bc->addr;
04268       ch->originator = ORG_MISDN;
04269 
04270       chan = misdn_new(ch, AST_STATE_RESERVED, bc->dad, bc->oad, AST_FORMAT_ALAW, bc->port, bc->channel);
04271       if (!chan) {
04272          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04273          ast_log(LOG_ERROR, "cb_events: misdn_new failed !\n"); 
04274          return 0;
04275       }
04276 
04277       ch->ast = chan;
04278 
04279       if ((exceed = add_in_calls(bc->port))) {
04280          char tmp[16];
04281          snprintf(tmp, sizeof(tmp), "%d", exceed);
04282          pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
04283       }
04284 
04285       read_config(ch, ORG_MISDN);
04286 
04287       export_ch(chan, bc, ch);
04288 
04289       ch->ast->rings = 1;
04290       ast_setstate(ch->ast, AST_STATE_RINGING);
04291 
04292       switch (bc->pres) {
04293       case 1:
04294          pres = AST_PRES_RESTRICTED;
04295          chan_misdn_log(2, bc->port, " --> PRES: Restricted (1)\n");
04296          break;
04297       case 2:
04298          pres = AST_PRES_UNAVAILABLE;
04299          chan_misdn_log(2, bc->port, " --> PRES: Unavailable (2)\n");
04300          break;
04301       default:
04302          pres = AST_PRES_ALLOWED;
04303          chan_misdn_log(2, bc->port, " --> PRES: Allowed (%d)\n", bc->pres);
04304          break;
04305       }
04306 
04307       switch (bc->screen) {
04308       default:
04309       case 0:
04310          screen = AST_PRES_USER_NUMBER_UNSCREENED;
04311          chan_misdn_log(2, bc->port, " --> SCREEN: Unscreened (%d)\n", bc->screen);
04312          break;
04313       case 1:
04314          screen = AST_PRES_USER_NUMBER_PASSED_SCREEN;
04315          chan_misdn_log(2, bc->port, " --> SCREEN: Passed screen (1)\n");
04316          break;
04317       case 2:
04318          screen = AST_PRES_USER_NUMBER_FAILED_SCREEN;
04319          chan_misdn_log(2, bc->port, " --> SCREEN: failed screen (2)\n");
04320          break;
04321       case 3:
04322          screen = AST_PRES_NETWORK_NUMBER;
04323          chan_misdn_log(2, bc->port, " --> SCREEN: Network Number (3)\n");
04324          break;
04325       }
04326 
04327       chan->cid.cid_pres = pres | screen;
04328 
04329       pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
04330       chan->transfercapability = bc->capability;
04331 
04332       switch (bc->capability) {
04333       case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
04334          pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
04335          break;
04336       default:
04337          pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
04338       }
04339 
04340       /** queue new chan **/
04341       cl_queue_chan(&cl_te, ch);
04342 
04343       if (!strstr(ch->allowed_bearers, "all")) {
04344          int i;
04345 
04346          for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
04347             if (allowed_bearers_array[i].cap == bc->capability) {
04348                if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
04349                   /* The bearer capability is allowed */
04350                   if (allowed_bearers_array[i].deprecated) {
04351                      chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
04352                         allowed_bearers_array[i].name);
04353                   }
04354                   break;
04355                }
04356             }
04357          }  /* end for */
04358          if (i == ARRAY_LEN(allowed_bearers_array)) {
04359             /* We did not find the bearer capability */
04360             chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
04361                bearer2str(bc->capability), bc->capability);
04362             bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
04363 
04364             ch->state = MISDN_EXTCANTMATCH;
04365             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
04366             return RESPONSE_OK;
04367          }
04368       }
04369 
04370       /* Check for Pickup Request first */
04371       if (!strcmp(chan->exten, ast_pickup_ext())) {
04372          if (!ch->noautorespond_on_setup) {
04373             int ret;/** Sending SETUP_ACK**/
04374             ret = misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04375          } else {
04376             ch->state = MISDN_INCOMING_SETUP;
04377          }
04378          if (ast_pickup_call(chan)) {
04379             hangup_chan(ch);
04380          } else {
04381             ch->state = MISDN_CALLING_ACKNOWLEDGE;
04382             ast_setstate(chan, AST_STATE_DOWN);
04383             hangup_chan(ch);
04384             ch->ast = NULL;
04385             break;
04386          }
04387       }
04388 
04389       /*
04390        * added support for s extension hope it will help those poor cretains
04391        * which haven't overlap dial.
04392        */
04393       misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
04394       if (ai) {
04395          do_immediate_setup(bc, ch, chan);
04396          break;
04397       }
04398 
04399       /* check if we should jump into s when we have no dad */
04400       misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
04401       if (im && ast_strlen_zero(bc->dad)) {
04402          do_immediate_setup(bc, ch, chan);
04403          break;
04404       }
04405 
04406       chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
04407       if(!ast_canmatch_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04408          if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->oad)) {
04409             ast_log(LOG_WARNING,
04410                "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
04411                bc->dad, ch->context, bc->port);
04412             strcpy(ch->ast->exten, "i");
04413             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
04414             ch->state = MISDN_DIALING;
04415             start_pbx(ch, bc, chan);
04416             break;
04417          }
04418 
04419          ast_log(LOG_WARNING,
04420             "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
04421             "\tMaybe you want to add an 'i' extension to catch this case.\n",
04422             bc->dad, ch->context, bc->port);
04423          if (bc->nt)
04424             hanguptone_indicate(ch);
04425 
04426          ch->state = MISDN_EXTCANTMATCH;
04427          bc->out_cause = AST_CAUSE_UNALLOCATED;
04428 
04429          if (bc->nt)
04430             misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE );
04431          else
04432             misdn_lib_send_event(bc, EVENT_RELEASE );
04433 
04434          break;
04435       }
04436 
04437       /* Whatever happens, when sending_complete is set or we are PTMP TE, we will definitely 
04438        * jump into the dialplan, when the dialed extension does not exist, the 's' extension 
04439        * will be used by Asterisk automatically. */
04440       if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
04441          if (!ch->noautorespond_on_setup) {
04442             ch->state=MISDN_DIALING;
04443             misdn_lib_send_event(bc, EVENT_PROCEEDING );
04444          } else {
04445             ch->state = MISDN_INCOMING_SETUP;
04446          }
04447          start_pbx(ch, bc, chan);
04448          break;
04449       }
04450 
04451 
04452       /*
04453        * When we are NT and overlapdial is set and if 
04454        * the number is empty, we wait for the ISDN timeout
04455        * instead of our own timer.
04456        */
04457       if (ch->overlap_dial && bc->nt && !bc->dad[0] ) {
04458          wait_for_digits(ch, bc, chan);
04459          break;
04460       }
04461 
04462       /* 
04463        * If overlapdial we will definitely send a SETUP_ACKNOWLEDGE and wait for more 
04464        * Infos with a Interdigit Timeout.
04465        * */
04466       if (ch->overlap_dial) {
04467          ast_mutex_lock(&ch->overlap_tv_lock);
04468          ch->overlap_tv = ast_tvnow();
04469          ast_mutex_unlock(&ch->overlap_tv_lock);
04470 
04471          wait_for_digits(ch, bc, chan);
04472          if (ch->overlap_dial_task == -1) 
04473             ch->overlap_dial_task = 
04474                misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
04475 
04476          break;
04477       }
04478 
04479       /* If the extension does not exist and we're not TE_PTMP we wait for more digits 
04480        * without interdigit timeout.
04481        * */
04482       if (!ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad))  {
04483          wait_for_digits(ch, bc, chan);
04484          break;
04485       }
04486 
04487       /*
04488        * If the extension exists let's just jump into it.
04489        * */
04490       if (ast_exists_extension(ch->ast, ch->context, bc->dad, 1, bc->oad)) {
04491          if (bc->need_more_infos)
04492             misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE );
04493          else
04494             misdn_lib_send_event(bc, EVENT_PROCEEDING);
04495 
04496          ch->state = MISDN_DIALING;
04497          start_pbx(ch, bc, chan);
04498          break;
04499       }
04500    }
04501    break;
04502 
04503    case EVENT_SETUP_ACKNOWLEDGE:
04504    {
04505       ch->state = MISDN_CALLING_ACKNOWLEDGE;
04506 
04507       if (bc->channel) 
04508          update_name(ch->ast,bc->port,bc->channel);
04509       
04510       if (!ast_strlen_zero(bc->infos_pending)) {
04511          /* TX Pending Infos */
04512          strncat(bc->dad, bc->infos_pending, sizeof(bc->dad) - strlen(bc->dad) - 1);
04513 
04514          if (!ch->ast)
04515             break;
04516          ast_copy_string(ch->ast->exten, bc->dad, sizeof(ch->ast->exten));
04517          ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
04518          ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
04519 
04520          misdn_lib_send_event(bc, EVENT_INFORMATION);
04521       }
04522    }
04523    break;
04524    case EVENT_PROCEEDING:
04525    {
04526       if (bc->channel) 
04527          update_name(ch->ast, bc->port, bc->channel);
04528 
04529       if (misdn_cap_is_speech(bc->capability) &&
04530            misdn_inband_avail(bc) ) {
04531          start_bc_tones(ch);
04532       }
04533 
04534       ch->state = MISDN_PROCEEDING;
04535       
04536       if (!ch->ast)
04537          break;
04538 
04539       ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
04540    }
04541    break;
04542    case EVENT_PROGRESS:
04543       if (bc->channel) 
04544          update_name(ch->ast, bc->port, bc->channel);
04545 
04546       if (!bc->nt ) {
04547          if ( misdn_cap_is_speech(bc->capability) &&
04548               misdn_inband_avail(bc)
04549             ) {
04550             start_bc_tones(ch);
04551          }
04552          
04553          ch->state = MISDN_PROGRESS;
04554 
04555          if (!ch->ast)
04556             break;
04557          ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
04558       }
04559       break;
04560       
04561       
04562    case EVENT_ALERTING:
04563    {
04564       if (bc->channel) 
04565          update_name(ch->ast, bc->port, bc->channel);
04566 
04567       ch->state = MISDN_ALERTING;
04568       
04569       if (!ch->ast)
04570          break;
04571 
04572       ast_queue_control(ch->ast, AST_CONTROL_RINGING);
04573       ast_setstate(ch->ast, AST_STATE_RINGING);
04574       
04575       cb_log(7, bc->port, " --> Set State Ringing\n");
04576       
04577       if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
04578          cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
04579          start_bc_tones(ch);
04580       } else {
04581          cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
04582          if (ch->far_alerting) {
04583             cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
04584             start_bc_tones(ch);
04585             /*tone_indicate(ch, TONE_FAR_ALERTING);*/
04586          }
04587       }
04588    }
04589    break;
04590    case EVENT_CONNECT:
04591    {
04592       struct ast_channel *bridged;
04593 
04594       /*we answer when we've got our very new L3 ID from the NT stack */
04595       misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
04596 
04597       if (!ch->ast)
04598          break;
04599 
04600       bridged = ast_bridged_channel(ch->ast);
04601       stop_indicate(ch);
04602 
04603       if (bridged && !strcasecmp(bridged->tech->type, "mISDN")) {
04604          struct chan_list *bridged_ch = MISDN_ASTERISK_TECH_PVT(bridged);
04605 
04606          chan_misdn_log(1, bc->port, " --> copying cpndialplan:%d and cad:%s to the A-Channel\n", bc->cpnnumplan, bc->cad);
04607          if (bridged_ch) {
04608             bridged_ch->bc->cpnnumplan = bc->cpnnumplan;
04609             ast_copy_string(bridged_ch->bc->cad, bc->cad, sizeof(bridged_ch->bc->cad));
04610          }
04611       }
04612    }
04613    ch->l3id=bc->l3_id;
04614    ch->addr=bc->addr;
04615 
04616    start_bc_tones(ch);
04617    
04618    ch->state = MISDN_CONNECTED;
04619    
04620    ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
04621    break;
04622    case EVENT_CONNECT_ACKNOWLEDGE:
04623    {
04624       ch->l3id = bc->l3_id;
04625       ch->addr = bc->addr;
04626 
04627       start_bc_tones(ch);
04628 
04629       ch->state = MISDN_CONNECTED;
04630    }
04631    break;
04632    case EVENT_DISCONNECT:
04633       /*we might not have an ch->ast ptr here anymore*/
04634       if (ch) {
04635          struct chan_list *holded_ch = find_holded(cl_te, bc);
04636 
04637          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);
04638          if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
04639             /* If there's inband information available (e.g. a
04640                recorded message saying what was wrong with the
04641                dialled number, or perhaps even giving an
04642                alternative number, then play it instead of
04643                immediately releasing the call */
04644             chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
04645       
04646             ch->state = MISDN_DISCONNECTED;
04647             start_bc_tones(ch);
04648 
04649             if (ch->ast) {
04650                ch->ast->hangupcause = bc->cause;
04651                if (bc->cause == AST_CAUSE_USER_BUSY)
04652                   ast_queue_control(ch->ast, AST_CONTROL_BUSY);
04653             }
04654             ch->need_busy = 0;
04655             break;
04656          }
04657 
04658          /*Check for holded channel, to implement transfer*/
04659          if (holded_ch && holded_ch != ch && ch->ast && ch->state == MISDN_CONNECTED) {
04660             cb_log(1, bc->port, " --> found holded ch\n");
04661             misdn_transfer_bc(ch, holded_ch) ;
04662          }
04663 
04664          bc->need_disconnect = 0;
04665 
04666          stop_bc_tones(ch);
04667          hangup_chan(ch);
04668 #if 0
04669       } else {
04670          ch = find_holded_l3(cl_te, bc->l3_id,1);
04671          if (ch) {
04672             hangup_chan(ch);
04673          }
04674 #endif
04675       }
04676       bc->out_cause = -1;
04677       if (bc->need_release)
04678          misdn_lib_send_event(bc, EVENT_RELEASE);
04679       break;
04680    
04681    case EVENT_RELEASE:
04682       {
04683          bc->need_disconnect = 0;
04684          bc->need_release = 0;
04685 
04686          hangup_chan(ch);
04687          release_chan(bc);
04688       }
04689       break;
04690    case EVENT_RELEASE_COMPLETE:
04691    {
04692       bc->need_disconnect = 0;
04693       bc->need_release = 0;
04694       bc->need_release_complete = 0;
04695 
04696       stop_bc_tones(ch);
04697       hangup_chan(ch);
04698 
04699       if (ch)
04700          ch->state = MISDN_CLEANING;
04701 
04702       release_chan(bc);
04703    }
04704    break;
04705    case EVENT_BCHAN_ERROR:
04706    case EVENT_CLEANUP:
04707    {
04708       stop_bc_tones(ch);
04709       
04710       switch (ch->state) {
04711       case MISDN_CALLING:
04712          bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
04713          break;
04714       default:
04715          break;
04716       }
04717       
04718       hangup_chan(ch);
04719       release_chan(bc);
04720    }
04721    break;
04722 
04723    case EVENT_TONE_GENERATE:
04724    {
04725       int tone_len = bc->tone_cnt;
04726       struct ast_channel *ast = ch->ast;
04727       void *tmp;
04728       int res;
04729       int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
04730 
04731       chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
04732 
04733       if (!ast)
04734          break;
04735 
04736       if (!ast->generator)
04737          break;
04738 
04739       tmp = ast->generatordata;
04740       ast->generatordata = NULL;
04741       generate = ast->generator->generate;
04742 
04743       if (tone_len < 0 || tone_len > 512 ) {
04744          ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
04745          tone_len = 128;
04746       }
04747 
04748       res = generate(ast, tmp, tone_len, tone_len);
04749       ast->generatordata = tmp;
04750       
04751       if (res) {
04752          ast_log(LOG_WARNING, "Auto-deactivating generator\n");
04753          ast_deactivate_generator(ast);
04754       } else {
04755          bc->tone_cnt = 0;
04756       }
04757    }
04758    break;
04759 
04760    case EVENT_BCHAN_DATA:
04761    {
04762       if (!misdn_cap_is_speech(ch->bc->capability)) {
04763          struct ast_frame frame;
04764          /*In Data Modes we queue frames*/
04765          frame.frametype  = AST_FRAME_VOICE; /*we have no data frames yet*/
04766          frame.subclass = AST_FORMAT_ALAW;
04767          frame.datalen = bc->bframe_len;
04768          frame.samples = bc->bframe_len;
04769          frame.mallocd = 0;
04770          frame.offset = 0;
04771          frame.delivery = ast_tv(0,0);
04772          frame.src = NULL;
04773          frame.data = bc->bframe;
04774 
04775          if (ch->ast) 
04776             ast_queue_frame(ch->ast, &frame);
04777       } else {
04778          fd_set wrfs;
04779          struct timeval tv = { 0, 0 };
04780          int t;
04781 
04782          FD_ZERO(&wrfs);
04783          FD_SET(ch->pipe[1], &wrfs);
04784 
04785          t = select(FD_SETSIZE, NULL, &wrfs, NULL, &tv);
04786 
04787          if (!t) {
04788             chan_misdn_log(9, bc->port, "Select Timed out\n");
04789             break;
04790          }
04791          
04792          if (t < 0) {
04793             chan_misdn_log(-1, bc->port, "Select Error (err=%s)\n", strerror(errno));
04794             break;
04795          }
04796          
04797          if (FD_ISSET(ch->pipe[1], &wrfs)) {
04798             chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
04799             if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
04800                chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
04801 
04802                stop_bc_tones(ch);
04803                hangup_chan(ch);
04804                release_chan(bc);
04805             }
04806          } else {
04807             chan_misdn_log(1, bc->port, "Write Pipe full!\n");
04808          }
04809       }
04810    }
04811    break;
04812    case EVENT_TIMEOUT:
04813    {
04814       if (ch && bc)
04815          chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
04816 
04817       switch (ch->state) {
04818       case MISDN_DIALING:
04819       case MISDN_PROGRESS:
04820          if (bc->nt && !ch->nttimeout)
04821             break;
04822          
04823       case MISDN_CALLING:
04824       case MISDN_ALERTING:
04825       case MISDN_PROCEEDING:
04826       case MISDN_CALLING_ACKNOWLEDGE:
04827          if (bc->nt) {
04828             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
04829             hanguptone_indicate(ch);
04830          }
04831             
04832          bc->out_cause = AST_CAUSE_UNALLOCATED;
04833          misdn_lib_send_event(bc, EVENT_DISCONNECT);
04834          break;
04835 
04836       case MISDN_WAITING4DIGS:
04837          if (bc->nt) {
04838             bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
04839             bc->out_cause = AST_CAUSE_UNALLOCATED;
04840             hanguptone_indicate(ch);
04841             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04842          } else {
04843             bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
04844             misdn_lib_send_event(bc, EVENT_RELEASE);
04845          }
04846             
04847          break;
04848 
04849       case MISDN_CLEANING: 
04850          chan_misdn_log(1,bc->port," --> in state cleaning .. so ignoring, the stack should clean it for us\n");
04851          break;
04852 
04853       default:
04854          misdn_lib_send_event(bc,EVENT_RELEASE_COMPLETE);
04855       }
04856    }
04857    break;
04858 
04859     
04860    /****************************/
04861    /** Supplementary Services **/
04862    /****************************/
04863    case EVENT_RETRIEVE:
04864    {
04865       struct ast_channel *hold_ast;
04866 
04867       if (!ch) {
04868          chan_misdn_log(4, bc->port, " --> no CH, searching in holded\n");
04869          ch = find_holded_l3(cl_te, bc->l3_id, 1);
04870       }
04871 
04872       if (!ch) {
04873          ast_log(LOG_WARNING, "Found no Holded channel, cannot Retrieve\n");
04874          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04875          break;
04876       }
04877 
04878       /*remember the channel again*/
04879       ch->bc = bc;
04880       ch->state = MISDN_CONNECTED;
04881 
04882       ch->hold_info.port = 0;
04883       ch->hold_info.channel = 0;
04884 
04885       hold_ast = ast_bridged_channel(ch->ast);
04886 
04887       if (hold_ast) {
04888          ast_moh_stop(hold_ast);
04889       }
04890    
04891       if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
04892          chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
04893          misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
04894       }
04895    }
04896    break;
04897     
04898    case EVENT_HOLD:
04899    {
04900       int hold_allowed;
04901       struct ast_channel *bridged;
04902 
04903       misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(int));
04904 
04905       if (!hold_allowed) {
04906 
04907          chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
04908          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04909          break;
04910       }
04911 
04912       bridged = ast_bridged_channel(ch->ast);
04913       if (bridged) {
04914          chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", bridged->tech->type);
04915          ch->state = MISDN_HOLDED;
04916          ch->l3id = bc->l3_id;
04917          
04918          misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
04919 
04920          /* XXX This should queue an AST_CONTROL_HOLD frame on this channel
04921           * instead of starting moh on the bridged channel directly */
04922          ast_moh_start(bridged, NULL, NULL);
04923 
04924          /*forget the channel now*/
04925          ch->bc = NULL;
04926          ch->hold_info.port = bc->port;
04927          ch->hold_info.channel = bc->channel;
04928 
04929       } else {
04930          misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
04931          chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
04932       }
04933    } 
04934    break;
04935    
04936    case EVENT_FACILITY:
04937       if (!ch) {
04938          /* This may come from a call we don't know nothing about, so we ignore it. */
04939          chan_misdn_log(-1, bc->port, "Got EVENT_FACILITY but we don't have a ch!\n");
04940          break;
04941       }
04942 
04943       print_facility(&(bc->fac_in), bc);
04944       
04945       switch (bc->fac_in.Function) {
04946       case Fac_CD:
04947          {
04948             struct ast_channel *bridged = ast_bridged_channel(ch->ast);
04949             struct chan_list *ch_br;
04950             if (bridged && MISDN_ASTERISK_TECH_PVT(bridged)) {
04951                ch_br = MISDN_ASTERISK_TECH_PVT(bridged);
04952                /*ch->state = MISDN_FACILITY_DEFLECTED;*/
04953                if (ch_br->bc) {
04954                   if (ast_exists_extension(bridged, ch->context, (char *)bc->fac_in.u.CDeflection.DeflectedToNumber, 1, bc->oad)) {
04955                      ch_br->state = MISDN_DIALING;
04956                      if (pbx_start_chan(ch_br) < 0) {
04957                         chan_misdn_log(-1, ch_br->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
04958                      }
04959                   }
04960                }
04961             }
04962             misdn_lib_send_event(bc, EVENT_DISCONNECT);
04963          } 
04964          break;
04965       case Fac_AOCDCurrency:
04966          {
04967             bc->AOCDtype = Fac_AOCDCurrency;
04968             memcpy(&(bc->AOCD.currency), &(bc->fac_in.u.AOCDcur), sizeof(struct FacAOCDCurrency));
04969             export_aoc_vars(ch->originator, ch->ast, bc);
04970          }
04971          break;
04972       case Fac_AOCDChargingUnit:
04973          {
04974             bc->AOCDtype = Fac_AOCDChargingUnit;
04975             memcpy(&(bc->AOCD.chargingUnit), &(bc->fac_in.u.AOCDchu), sizeof(struct FacAOCDChargingUnit));
04976             export_aoc_vars(ch->originator, ch->ast, bc);
04977          }
04978          break;
04979       default:
04980          chan_misdn_log(0, bc->port," --> not yet handled: facility type:%d\n", bc->fac_in.Function);
04981       }
04982       
04983       break;
04984 
04985    case EVENT_RESTART:
04986 
04987       if (!bc->dummy) {
04988          stop_bc_tones(ch);
04989          release_chan(bc);
04990       }
04991       break;
04992 
04993    default:
04994       chan_misdn_log(1, 0, "Got Unknown Event\n");
04995       break;
04996    }
04997    
04998    return RESPONSE_OK;
04999 }
05000 
05001 /** TE STUFF END **/
05002 
05003 /******************************************
05004  *
05005  *   Asterisk Channel Endpoint END
05006  *
05007  *
05008  *******************************************/
05009 
05010 
05011 
05012 static int unload_module(void)
05013 {
05014    /* First, take us out of the channel loop */
05015    ast_log(LOG_VERBOSE, "-- Unregistering mISDN Channel Driver --\n");
05016 
05017    misdn_tasks_destroy();
05018    
05019    if (!g_config_initialized)
05020       return 0;
05021    
05022    ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05023    
05024    /* ast_unregister_application("misdn_crypt"); */
05025    ast_unregister_application("misdn_set_opt");
05026    ast_unregister_application("misdn_facility");
05027    ast_unregister_application("misdn_check_l2l1");
05028   
05029    ast_channel_unregister(&misdn_tech);
05030 
05031    free_robin_list();
05032    misdn_cfg_destroy();
05033    misdn_lib_destroy();
05034   
05035    if (misdn_debug)
05036       free(misdn_debug);
05037    if (misdn_debug_only)
05038       free(misdn_debug_only);
05039    free(misdn_ports);
05040    
05041    return 0;
05042 }
05043 
05044 static int load_module(void)
05045 {
05046    int i, port;
05047    int ntflags = 0, ntkc = 0;
05048    char ports[256] = "";
05049    char tempbuf[BUFFERSIZE + 1];
05050    char ntfile[BUFFERSIZE + 1];
05051    struct misdn_lib_iface iface = {
05052       .cb_event = cb_events,
05053       .cb_log = chan_misdn_log,
05054       .cb_jb_empty = chan_misdn_jb_empty,
05055    };
05056 
05057    max_ports = misdn_lib_maxports_get();
05058    
05059    if (max_ports <= 0) {
05060       ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
05061       return AST_MODULE_LOAD_DECLINE;
05062    }
05063    
05064    if (misdn_cfg_init(max_ports)) {
05065       ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
05066       return AST_MODULE_LOAD_DECLINE;
05067    }
05068    g_config_initialized = 1;
05069    
05070    misdn_debug = (int *) malloc(sizeof(int) * (max_ports + 1));
05071    if (!misdn_debug) {
05072       ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
05073       return AST_MODULE_LOAD_DECLINE;
05074    }
05075    misdn_ports = (int *) malloc(sizeof(int) * (max_ports + 1));
05076    if (!misdn_ports) {
05077       ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
05078       return AST_MODULE_LOAD_DECLINE;
05079    }
05080    misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(int));
05081    for (i = 1; i <= max_ports; i++) {
05082       misdn_debug[i] = misdn_debug[0];
05083       misdn_ports[i] = i;
05084    }
05085    *misdn_ports = 0;
05086    misdn_debug_only = (int *) calloc(max_ports + 1, sizeof(int));
05087 
05088    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, BUFFERSIZE);
05089    if (!ast_strlen_zero(tempbuf))
05090       tracing = 1;
05091 
05092    misdn_in_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05093    misdn_out_calls = (int *) malloc(sizeof(int) * (max_ports + 1));
05094 
05095    for (i = 1; i <= max_ports; i++) {
05096       misdn_in_calls[i] = 0;
05097       misdn_out_calls[i] = 0;
05098    }
05099 
05100    ast_mutex_init(&cl_te_lock);
05101    ast_mutex_init(&release_lock);
05102 
05103    misdn_cfg_update_ptp();
05104    misdn_cfg_get_ports_string(ports);
05105 
05106    if (!ast_strlen_zero(ports))
05107       chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
05108    if (misdn_lib_init(ports, &iface, NULL))
05109       chan_misdn_log(0, 0, "No te ports initialized\n");
05110 
05111    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(int));
05112    misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, BUFFERSIZE);
05113    misdn_lib_nt_debug_init(ntflags, ntfile);
05114 
05115    misdn_cfg_get( 0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(int));
05116    misdn_lib_nt_keepcalls(ntkc);
05117 
05118    if (ast_channel_register(&misdn_tech)) {
05119       ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
05120       unload_module();
05121       return -1;
05122    }
05123   
05124    ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
05125 
05126    ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
05127       "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
05128       "Sets mISDN opts. and optargs\n"
05129       "\n"
05130       "The available options are:\n"
05131       "    a - Have Asterisk detect DTMF tones on called channel\n"
05132       "    c - Make crypted outgoing call, optarg is keyindex\n"
05133       "    d - Send display text to called phone, text is the optarg\n"
05134       "    e - Perform echo cancelation on this channel,\n"
05135       "        takes taps as optarg (32,64,128,256)\n"
05136       "   e! - Disable echo cancelation on this channel\n"
05137       "    f - Enable fax detection\n"
05138       "    h - Make digital outgoing call\n"
05139       "   h1 - Make HDLC mode digital outgoing call\n"
05140       "    i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
05141       "        they will be transported inband.\n"
05142       "   jb - Set jitter buffer length, optarg is length\n"
05143       "   jt - Set jitter buffer upper threshold, optarg is threshold\n"
05144       "   jn - Disable jitter buffer\n"
05145       "    n - Disable mISDN DSP on channel.\n"
05146       "        Disables: echo cancel, DTMF detection, and volume control.\n"
05147       "    p - Caller ID presentation,\n"
05148       "        optarg is either 'allowed' or 'restricted'\n"
05149       "    s - Send Non-inband DTMF as inband\n"
05150       "   vr - Rx gain control, optarg is gain\n"
05151       "   vt - Tx gain control, optarg is gain\n"
05152       );
05153 
05154    
05155    ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
05156              "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
05157              "Sends the Facility Message FACILITY_TYPE with \n"
05158              "the given Arguments to the current ISDN Channel\n"
05159              "Supported Facilities are:\n"
05160              "\n"
05161              "type=calldeflect args=Nr where to deflect\n"
05162       );
05163 
05164 
05165    ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
05166              "misdn_check_l2l1(<port>||g:<groupname>,timeout)"
05167              "Checks if the L2 and L1 are up on either the given <port> or\n"
05168              "on the ports in the group with <groupname>\n"
05169              "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
05170              "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
05171              "\n"
05172              "This application, ensures the L1/L2 state of the Ports in a group\n"
05173              "it is intended to make the pmp_l1_check option redundant and to\n"
05174              "fix a buggy switch config from your provider\n"
05175              "\n"
05176              "a sample dialplan would look like:\n\n"
05177              "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
05178              "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
05179              "\n"
05180       );
05181 
05182 
05183    misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
05184 
05185    /* start the l1 watchers */
05186    
05187    for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
05188       int l1timeout;
05189       misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
05190       if (l1timeout) {
05191          chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
05192          misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);  
05193       }
05194    }
05195 
05196    chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
05197 
05198    return 0;
05199 }
05200 
05201 
05202 
05203 static int reload(void)
05204 {
05205    reload_config();
05206 
05207    return 0;
05208 }
05209 
05210 /*** SOME APPS ;)***/
05211 
05212 static int misdn_facility_exec(struct ast_channel *chan, void *data)
05213 {
05214    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05215    char *tok, *tokb;
05216 
05217    chan_misdn_log(0, 0, "TYPE: %s\n", chan->tech->type);
05218    
05219    if (strcasecmp(chan->tech->type, "mISDN")) {
05220       ast_log(LOG_WARNING, "misdn_facility makes only sense with chan_misdn channels!\n");
05221       return -1;
05222    }
05223    
05224    if (ast_strlen_zero((char *)data)) {
05225       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05226       return -1;
05227    }
05228 
05229    tok = strtok_r((char*) data, "|", &tokb) ;
05230 
05231    if (!tok) {
05232       ast_log(LOG_WARNING, "misdn_facility Requires arguments\n");
05233       return -1;
05234    }
05235 
05236    if (!strcasecmp(tok, "calldeflect")) {
05237       tok = strtok_r(NULL, "|", &tokb) ;
05238       
05239       if (!tok) {
05240          ast_log(LOG_WARNING, "Facility: Call Defl Requires arguments\n");
05241       }
05242 
05243       if (strlen(tok) >= sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber)) {
05244          ast_log(LOG_WARNING, "Facility: Number argument too long (up to 15 digits are allowed). Ignoring.\n");
05245          return 0; 
05246       }
05247       ch->bc->fac_out.Function = Fac_CD;
05248       ast_copy_string((char *)ch->bc->fac_out.u.CDeflection.DeflectedToNumber, tok, sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber));
05249       misdn_lib_send_event(ch->bc, EVENT_FACILITY);
05250    } else {
05251       chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", tok);
05252    }
05253 
05254    return 0;
05255 }
05256 
05257 static int misdn_check_l2l1(struct ast_channel *chan, void *data)
05258 {
05259    char group[BUFFERSIZE + 1];
05260    char *port_str;
05261    int port = 0;
05262    int timeout;
05263    int dowait = 0;
05264    int port_up;
05265 
05266    AST_DECLARE_APP_ARGS(args,
05267          AST_APP_ARG(grouppar);
05268          AST_APP_ARG(timeout);
05269    );
05270 
05271    if (ast_strlen_zero((char *)data)) {
05272       ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
05273       return -1;
05274    }
05275 
05276    AST_STANDARD_APP_ARGS(args, data);
05277 
05278    if (args.argc != 2) {
05279       ast_log(LOG_WARNING, "Wrong argument count\n");
05280       return 0;
05281    }
05282 
05283    /*ast_log(LOG_NOTICE, "Arguments: group/port '%s' timeout '%s'\n", args.grouppar, args.timeout);*/
05284    timeout = atoi(args.timeout);
05285    port_str = args.grouppar;
05286 
05287    if (port_str[0] == 'g' && port_str[1] == ':' ) {
05288       /* We make a group call lets checkout which ports are in my group */
05289       port_str += 2;
05290       ast_copy_string(group, port_str, sizeof(group));
05291       chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
05292 
05293       for ( port = misdn_cfg_get_next_port(port); 
05294          port > 0;
05295          port = misdn_cfg_get_next_port(port)) {
05296          char cfg_group[BUFFERSIZE + 1];
05297 
05298          chan_misdn_log(2, 0, "trying port %d\n", port);
05299 
05300          misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, BUFFERSIZE);
05301 
05302          if (!strcasecmp(cfg_group, group)) {
05303             port_up = misdn_lib_port_up(port, 1);
05304 
05305             if (!port_up) {
05306                chan_misdn_log(2, 0, " --> port '%d'\n", port);
05307                misdn_lib_get_port_up(port);
05308                dowait = 1;
05309             }
05310          }
05311       }
05312 
05313    } else {
05314       port = atoi(port_str);
05315       chan_misdn_log(2, 0, "Checking Port: %d\n",port);
05316       port_up = misdn_lib_port_up(port, 1);
05317       if (!port_up) {
05318          misdn_lib_get_port_up(port);
05319          dowait = 1;
05320       }
05321    }
05322 
05323    if (dowait) {
05324       chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
05325       sleep(timeout);
05326    }
05327 
05328    return 0;
05329 }
05330 
05331 static int misdn_set_opt_exec(struct ast_channel *chan, void *data)
05332 {
05333    struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
05334    char *tok, *tokb;
05335    int  keyidx = 0;
05336    int rxgain = 0;
05337    int txgain = 0;
05338    int change_jitter = 0;
05339 
05340    if (strcasecmp(chan->tech->type, "mISDN")) {
05341       ast_log(LOG_WARNING, "misdn_set_opt makes only sense with chan_misdn channels!\n");
05342       return -1;
05343    }
05344    
05345    if (ast_strlen_zero((char *)data)) {
05346       ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
05347       return -1;
05348    }
05349 
05350    for (tok = strtok_r((char*) data, ":", &tokb);
05351         tok;
05352         tok = strtok_r(NULL, ":", &tokb) ) {
05353       int neglect = 0;
05354 
05355       if (tok[0] == '!' ) {
05356          neglect = 1;
05357          tok++;
05358       }
05359       
05360       switch(tok[0]) {
05361          
05362       case 'd' :
05363          ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
05364          chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
05365          break;
05366          
05367       case 'n':
05368          chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
05369          ch->bc->nodsp = 1;
05370          break;
05371 
05372       case 'j':
05373          chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
05374          tok++;
05375          change_jitter = 1;
05376 
05377          switch ( tok[0] ) {
05378          case 'b':
05379             ch->jb_len = atoi(++tok);
05380             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
05381             break;
05382          case 't' :
05383             ch->jb_upper_threshold = atoi(++tok);
05384             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
05385             break;
05386          case 'n':
05387             ch->bc->nojitter = 1;
05388             chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
05389             break;
05390          default:
05391             ch->jb_len = 4000;
05392             ch->jb_upper_threshold = 0;
05393             chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
05394             chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
05395          }
05396          break;
05397       case 'v':
05398          tok++;
05399 
05400          switch (tok[0]) {
05401          case 'r' :
05402             rxgain = atoi(++tok);
05403             if (rxgain < -8)
05404                rxgain = -8;
05405             if (rxgain > 8)
05406                rxgain = 8;
05407             ch->bc->rxgain = rxgain;
05408             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
05409             break;
05410          case 't':
05411             txgain = atoi(++tok);
05412             if (txgain < -8)
05413                txgain = -8;
05414             if (txgain > 8)
05415                txgain = 8;
05416             ch->bc->txgain = txgain;
05417             chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
05418             break;
05419          }
05420          break;
05421       
05422       case 'c':
05423          keyidx = atoi(++tok);
05424          {
05425             char keys[4096];
05426             char *key = NULL, *tmp = keys;
05427             int i;
05428             misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
05429 
05430             for (i = 0; i < keyidx; i++) {
05431                key = strsep(&tmp, ",");
05432             }
05433 
05434             if (key) {
05435                ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
05436             }
05437 
05438             chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
05439             break;
05440          }
05441       case 'e':
05442          chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
05443          
05444          if (neglect) {
05445             chan_misdn_log(1, ch->bc->port, " --> disabled\n");
05446 #ifdef MISDN_1_2
05447             *ch->bc->pipeline = 0;
05448 #else
05449             ch->bc->ec_enable = 0;
05450 #endif
05451          } else {
05452 #ifdef MISDN_1_2
05453             update_pipeline_config(ch->bc);
05454 #else
05455             ch->bc->ec_enable = 1;
05456             ch->bc->orig = ch->originator;
05457             tok++;
05458             if (*tok) {
05459                ch->bc->ec_deftaps = atoi(tok);
05460             }
05461 #endif
05462          }
05463          
05464          break;
05465       case 'h':
05466          chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
05467          
05468          if (strlen(tok) > 1 && tok[1] == '1') {
05469             chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
05470             if (!ch->bc->hdlc) {
05471                ch->bc->hdlc = 1;
05472             }
05473          }
05474          ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
05475          break;
05476             
05477       case 's':
05478          chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
05479          ch->bc->send_dtmf = 1;
05480          break;
05481          
05482       case 'f':
05483          chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
05484          ch->faxdetect = 1;
05485          misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
05486          break;
05487 
05488       case 'a':
05489          chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
05490          ch->ast_dsp = 1;
05491          break;
05492 
05493       case 'p':
05494          chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
05495          /* CRICH: callingpres!!! */
05496          if (strstr(tok,"allowed")) {
05497             ch->bc->pres = 0;
05498          } else if (strstr(tok, "restricted")) {
05499             ch->bc->pres = 1;
05500          } else if (strstr(tok, "not_screened")) {
05501             chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
05502             ch->bc->pres = 1;
05503          }
05504          break;
05505       case 'i' :
05506          chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
05507          ch->ignore_dtmf=1;
05508          break;
05509       default:
05510          break;
05511       }
05512    }
05513 
05514    if (change_jitter)
05515       config_jitterbuffer(ch);
05516 
05517    if (ch->faxdetect || ch->ast_dsp) {
05518       if (!ch->dsp)
05519          ch->dsp = ast_dsp_new();
05520       if (ch->dsp)
05521          ast_dsp_set_features(ch->dsp, DSP_FEATURE_DTMF_DETECT| DSP_FEATURE_FAX_DETECT);
05522       if (!ch->trans)
05523          ch->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, AST_FORMAT_ALAW);
05524    }
05525 
05526    if (ch->ast_dsp) {
05527       chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
05528       ch->bc->nodsp = 1;
05529    }
05530    
05531    return 0;
05532 }
05533 
05534 
05535 int chan_misdn_jb_empty ( struct misdn_bchannel *bc, char *buf, int len) 
05536 {
05537    struct chan_list *ch = find_chan_by_bc(cl_te, bc);
05538    
05539    if (ch && ch->jb) {
05540       return misdn_jb_empty(ch->jb, buf, len);
05541    }
05542    
05543    return -1;
05544 }
05545 
05546 
05547 
05548 /*******************************************************/
05549 /***************** JITTERBUFFER ************************/
05550 /*******************************************************/
05551 
05552 
05553 /* allocates the jb-structure and initialize the elements*/
05554 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
05555 {
05556    int i;
05557    struct misdn_jb *jb;
05558 
05559    jb = malloc(sizeof(struct misdn_jb));
05560    if (!jb) {
05561        chan_misdn_log(-1, 0, "No free Mem for jb\n");
05562        return NULL;
05563    }
05564    jb->size = size;
05565    jb->upper_threshold = upper_threshold;
05566    jb->wp = 0;
05567    jb->rp = 0;
05568    jb->state_full = 0;
05569    jb->state_empty = 0;
05570    jb->bytes_wrote = 0;
05571    jb->samples = malloc(size * sizeof(char));
05572    if (!jb->samples) {
05573       free(jb);
05574       chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
05575       return NULL;
05576    }
05577 
05578    jb->ok = malloc(size * sizeof(char));
05579    if (!jb->ok) {
05580       free(jb->samples);
05581       free(jb);
05582       chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
05583       return NULL;
05584    }
05585 
05586    for (i = 0; i < size; i++)
05587       jb->ok[i] = 0;
05588 
05589    ast_mutex_init(&jb->mutexjb);
05590 
05591    return jb;
05592 }
05593 
05594 /* frees the data and destroys the given jitterbuffer struct */
05595 void misdn_jb_destroy(struct misdn_jb *jb)
05596 {
05597    ast_mutex_destroy(&jb->mutexjb);
05598    
05599    free(jb->ok);
05600    free(jb->samples);
05601    free(jb);
05602 }
05603 
05604 /* fills the jitterbuffer with len data returns < 0 if there was an
05605    error (buffer overflow). */
05606 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
05607 {
05608    int i, j, rp, wp;
05609 
05610    if (!jb || ! data)
05611       return 0;
05612 
05613    ast_mutex_lock(&jb->mutexjb);
05614    
05615    wp = jb->wp;
05616    rp = jb->rp;
05617    
05618    for (i = 0; i < len; i++) {
05619       jb->samples[wp] = data[i];
05620       jb->ok[wp] = 1;
05621       wp = (wp != jb->size - 1) ? wp + 1 : 0;
05622 
05623       if (wp == jb->rp)
05624          jb->state_full = 1;
05625    }
05626 
05627    if (wp >= rp)
05628       jb->state_buffer = wp - rp;
05629    else
05630       jb->state_buffer = jb->size - rp + wp;
05631    chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05632 
05633    if (jb->state_full) {
05634       jb->wp = wp;
05635 
05636       rp = wp;
05637       for (j = 0; j < jb->upper_threshold; j++)
05638          rp = (rp != 0) ? rp - 1 : jb->size - 1;
05639       jb->rp = rp;
05640       jb->state_full = 0;
05641       jb->state_empty = 1;
05642 
05643       ast_mutex_unlock(&jb->mutexjb);
05644 
05645       return -1;
05646    }
05647 
05648    if (!jb->state_empty) {
05649       jb->bytes_wrote += len;
05650       if (jb->bytes_wrote >= jb->upper_threshold) {
05651          jb->state_empty = 1;
05652          jb->bytes_wrote = 0;
05653       }
05654    }
05655    jb->wp = wp;
05656 
05657    ast_mutex_unlock(&jb->mutexjb);
05658    
05659    return 0;
05660 }
05661 
05662 /* gets len bytes out of the jitterbuffer if available, else only the
05663 available data is returned and the return value indicates the number
05664 of data. */
05665 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
05666 {
05667    int i, wp, rp, read = 0;
05668 
05669    ast_mutex_lock(&jb->mutexjb);
05670 
05671    rp = jb->rp;
05672    wp = jb->wp;
05673 
05674    if (jb->state_empty) {  
05675       for (i = 0; i < len; i++) {
05676          if (wp == rp) {
05677             jb->rp = rp;
05678             jb->state_empty = 0;
05679 
05680             ast_mutex_unlock(&jb->mutexjb);
05681 
05682             return read;
05683          } else {
05684             if (jb->ok[rp] == 1) {
05685                data[i] = jb->samples[rp];
05686                jb->ok[rp] = 0;
05687                rp = (rp != jb->size - 1) ? rp + 1 : 0;
05688                read += 1;
05689             }
05690          }
05691       }
05692 
05693       if (wp >= rp)
05694          jb->state_buffer = wp - rp;
05695       else
05696          jb->state_buffer = jb->size - rp + wp;
05697       chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
05698 
05699       jb->rp = rp;
05700    } else
05701       chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
05702 
05703    ast_mutex_unlock(&jb->mutexjb);
05704 
05705    return read;
05706 }
05707 
05708 
05709 
05710 
05711 /*******************************************************/
05712 /*************** JITTERBUFFER  END *********************/
05713 /*******************************************************/
05714 
05715 
05716 
05717 
05718 static void chan_misdn_log(int level, int port, char *tmpl, ...)
05719 {
05720    va_list ap;
05721    char buf[1024];
05722    char port_buf[8];
05723 
05724    if (! ((0 <= port) && (port <= max_ports))) {
05725       ast_log(LOG_WARNING, "cb_log called with out-of-range port number! (%d)\n", port);
05726       port = 0;
05727       level = -1;
05728    }
05729 
05730    snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
05731 
05732    va_start(ap, tmpl);
05733    vsnprintf(buf, sizeof(buf), tmpl, ap);
05734    va_end(ap);
05735 
05736    if (level == -1)
05737       ast_log(LOG_WARNING, "%s", buf);
05738 
05739    else if (misdn_debug_only[port] ? 
05740          (level == 1 && misdn_debug[port]) || (level == misdn_debug[port]) 
05741        : level <= misdn_debug[port]) {
05742       
05743       ast_console_puts(port_buf);
05744       ast_console_puts(buf);
05745    }
05746    
05747    if ((level <= misdn_debug[0]) && !ast_strlen_zero(global_tracefile) ) {
05748       time_t tm = time(NULL);
05749       char *tmp = ctime(&tm), *p;
05750 
05751       FILE *fp = fopen(global_tracefile, "a+");
05752 
05753       p = strchr(tmp, '\n');
05754       if (p)
05755          *p = ':';
05756       
05757       if (!fp) {
05758          ast_console_puts("Error opening Tracefile: [ ");
05759          ast_console_puts(global_tracefile);
05760          ast_console_puts(" ] ");
05761          
05762          ast_console_puts(strerror(errno));
05763          ast_console_puts("\n");
05764          return ;
05765       }
05766       
05767       fputs(tmp, fp);
05768       fputs(" ", fp);
05769       fputs(port_buf, fp);
05770       fputs(" ", fp);
05771       fputs(buf, fp);
05772 
05773       fclose(fp);
05774    }
05775 }
05776 
05777 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Channel driver for mISDN Support (BRI/PRI)",
05778    .load = load_module,
05779    .unload = unload_module,
05780    .reload = reload,
05781 );

Generated on Thu Oct 8 00:58:58 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7