Tue Nov 4 13:20:16 2008

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

Generated on Tue Nov 4 13:20:16 2008 for Asterisk - the Open Source PBX by  doxygen 1.4.7