chan_ooh323.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2005 by Objective Systems, Inc.
00003  *
00004  * This software is furnished under an open source license and may be 
00005  * used and copied only in accordance with the terms of this license. 
00006  * The text of the license may generally be found in the root 
00007  * directory of this installation in the COPYING file.  It 
00008  * can also be viewed online at the following URL:
00009  *
00010  *   http://www.obj-sys.com/open/license.html
00011  *
00012  * Any redistributions of this file including modified versions must 
00013  * maintain this copyright notice.
00014  *
00015  *****************************************************************************/
00016 
00017 /* Reworked version I, Nov-2009, by Alexandr Anikin, may@telecom-service.ru */
00018 
00019 
00020 /*** MODULEINFO
00021    <defaultenabled>no</defaultenabled>
00022    <support_level>extended</support_level>
00023  ***/
00024 
00025 #include "chan_ooh323.h"
00026 #include <math.h>
00027 
00028 #define FORMAT_STRING_SIZE 512
00029 
00030 /* Defaults */
00031 #define DEFAULT_CONTEXT "default"
00032 #define DEFAULT_H323ID "Asterisk PBX"
00033 #define DEFAULT_LOGFILE "/var/log/asterisk/h323_log"
00034 #define DEFAULT_H323ACCNT "ast_h323"
00035 
00036 /* Flags */
00037 #define H323_SILENCESUPPRESSION (1<<0)
00038 #define H323_GKROUTED           (1<<1)
00039 #define H323_TUNNELING          (1<<2)
00040 #define H323_FASTSTART          (1<<3)
00041 #define H323_OUTGOING           (1<<4)
00042 #define H323_ALREADYGONE        (1<<5)
00043 #define H323_NEEDDESTROY        (1<<6)
00044 #define H323_DISABLEGK          (1<<7)
00045 #define H323_NEEDSTART     (1<<8)
00046 
00047 #define MAXT30 240
00048 #define T38TOAUDIOTIMEOUT 30
00049 #define T38_DISABLED 0
00050 #define T38_ENABLED 1
00051 #define T38_FAXGW 1
00052 
00053 #define FAXDETECT_CNG   1
00054 #define FAXDETECT_T38   2
00055 
00056 /* Channel description */
00057 static const char type[] = "OOH323";
00058 static const char tdesc[] = "Objective Systems H323 Channel Driver";
00059 static const char config[] = "ooh323.conf";
00060 
00061 struct ast_module *myself;
00062 
00063 static struct ast_jb_conf default_jbconf =
00064 {
00065    .flags = 0,
00066    .max_size = -1,
00067    .resync_threshold = -1,
00068    .impl = ""
00069 };
00070 static struct ast_jb_conf global_jbconf;
00071 
00072 /* Channel Definition */
00073 static struct ast_channel *ooh323_request(const char *type, struct ast_format_cap *cap,
00074          const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,  const char *data, int *cause);
00075 static int ooh323_digit_begin(struct ast_channel *ast, char digit);
00076 static int ooh323_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00077 static int ooh323_call(struct ast_channel *ast, const char *dest, int timeout);
00078 static int ooh323_hangup(struct ast_channel *ast);
00079 static int ooh323_answer(struct ast_channel *ast);
00080 static struct ast_frame *ooh323_read(struct ast_channel *ast);
00081 static int ooh323_write(struct ast_channel *ast, struct ast_frame *f);
00082 static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
00083 static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen);
00084 static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00085 static int function_ooh323_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
00086 static int function_ooh323_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
00087 
00088 static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
00089 static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
00090 static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, 
00091           struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active);
00092 static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *result);
00093 void setup_rtp_remote(ooCallData *call, const char *remoteIp, int remotePort);
00094 
00095 struct ooh323_peer *find_friend(const char *name, int port);
00096 
00097 
00098 static struct ast_channel_tech ooh323_tech = {
00099    .type = type,
00100    .description = tdesc,
00101    .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
00102    .requester = ooh323_request,
00103    .send_digit_begin = ooh323_digit_begin,
00104    .send_digit_end = ooh323_digit_end,
00105    .call = ooh323_call,
00106    .hangup = ooh323_hangup,
00107    .answer = ooh323_answer,
00108    .read = ooh323_read,
00109    .write = ooh323_write,
00110    .exception = ooh323_read,
00111    .indicate = ooh323_indicate,
00112    .fixup = ooh323_fixup,
00113    .send_html = 0,
00114    .queryoption = ooh323_queryoption,
00115    .early_bridge = ast_rtp_instance_early_bridge,
00116    .func_channel_read = function_ooh323_read,
00117    .func_channel_write = function_ooh323_write,
00118 };
00119 
00120 static struct ast_rtp_glue ooh323_rtp = {
00121    .type = type,
00122    .get_rtp_info = ooh323_get_rtp_peer,
00123    .get_vrtp_info = ooh323_get_vrtp_peer,
00124    .update_peer = ooh323_set_rtp_peer,
00125    .get_codec = ooh323_get_codec,
00126 };
00127 
00128 
00129 struct ooh323_user;
00130 
00131 /* H.323 channel private structure */
00132 static struct ooh323_pvt {
00133    ast_mutex_t lock;    /* Channel private lock */
00134    ast_cond_t rtpcond;     /* RTP condition */
00135    struct ast_rtp_instance *rtp;
00136    struct ast_sockaddr redirip;  /* redir ip */
00137    struct ast_rtp_instance *vrtp; /* Placeholder for now */
00138 
00139    int t38support;         /* T.38 mode - disable, transparent, faxgw */
00140    int faxdetect;
00141    int faxdetected;
00142    int rtptimeout;
00143    struct ast_udptl *udptl;
00144    int faxmode;
00145    int t38_tx_enable;
00146    int t38_init;
00147    struct ast_sockaddr udptlredirip;
00148    time_t lastTxT38;
00149    int chmodepend;
00150 
00151    struct ast_channel *owner; /* Master Channel */
00152       union {
00153          char  *user;   /* cooperating user/peer */
00154          char  *peer;
00155       } neighbor;
00156    time_t lastrtptx;
00157    time_t lastrtprx;
00158    unsigned int flags;
00159    unsigned int call_reference;
00160    char *callToken;
00161    char *username;
00162    char *host;
00163    char *callerid_name;
00164    char *callerid_num;
00165    char caller_h323id[AST_MAX_EXTENSION];
00166    char caller_dialedDigits[AST_MAX_EXTENSION];
00167    char caller_email[AST_MAX_EXTENSION];
00168    char caller_url[256];
00169    char callee_h323id[AST_MAX_EXTENSION];
00170    char callee_dialedDigits[AST_MAX_EXTENSION];
00171    char callee_email[AST_MAX_EXTENSION];
00172    char callee_url[AST_MAX_EXTENSION];
00173  
00174    int port;
00175    struct ast_format *readformat;   /* negotiated read format */
00176    struct ast_format *writeformat;  /* negotiated write format */
00177    struct ast_format_cap *cap;
00178    int dtmfmode;
00179    int dtmfcodec;
00180    char exten[AST_MAX_EXTENSION];   /* Requested extension */
00181    char context[AST_MAX_EXTENSION]; /* Context where to start */
00182    char accountcode[256];  /* Account code */
00183    int nat;
00184    int amaflags;
00185    int progsent;        /* progress is sent */
00186    int alertsent;       /* alerting is sent */
00187    int directrtp;       /* direct rtp */
00188    int earlydirect;     /* early direct rtp */
00189    int g729onlyA;       /* G.729 only A */
00190    struct ast_dsp *vad;
00191    struct OOH323Regex *rtpmask;  /* rtp ip regexp */
00192    char rtpmaskstr[120];
00193    int rtdrcount, rtdrinterval;  /* roundtripdelayreq */
00194    int faststart, h245tunneling; /* faststart & h245 tunneling */
00195    int aniasdni;        /* use dialed number as answering identification */
00196    struct ooh323_pvt *next;   /* Next entity */
00197 } *iflist = NULL;
00198 
00199 /* Protect the channel/interface list (ooh323_pvt) */
00200 AST_MUTEX_DEFINE_STATIC(iflock);
00201 
00202 /* Profile of H.323 user registered with PBX*/
00203 struct ooh323_user{
00204    ast_mutex_t lock;
00205    char     name[256];
00206    char     context[AST_MAX_EXTENSION];
00207    int      incominglimit;
00208    unsigned inUse;
00209    char     accountcode[20];
00210    int      amaflags;
00211    struct ast_format_cap *cap;
00212    int      dtmfmode;
00213    int      dtmfcodec;
00214    int      faxdetect;
00215    int      t38support;
00216    int      rtptimeout;
00217    int      mUseIP;        /* Use IP address or H323-ID to search user */
00218    char     mIP[4*8+7+2];  /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */
00219    struct OOH323Regex *rtpmask;
00220    char     rtpmaskstr[120];
00221    int      rtdrcount, rtdrinterval;
00222    int      nat;
00223    int      faststart, h245tunneling;
00224    int      directrtp;
00225    int      earlydirect;
00226    int      g729onlyA;
00227    int      aniasdni;
00228    struct ooh323_user *next;
00229 };
00230 
00231 /* Profile of valid asterisk peers */
00232 struct ooh323_peer{
00233    ast_mutex_t lock;
00234    char        name[256];
00235    unsigned    outgoinglimit;
00236    unsigned    outUse;
00237    struct ast_format_cap *cap;
00238    char        accountcode[20];
00239    int         amaflags;
00240    int         dtmfmode;
00241    int       dtmfcodec;
00242    int       faxdetect;
00243    int       t38support;
00244    int         mFriend;    /* indicates defined as friend */
00245    char        ip[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */
00246    int         port;
00247    char        *h323id;    /* H323-ID alias, which asterisk will register with gk to reach this peer*/
00248    char        *email;     /* Email alias, which asterisk will register with gk to reach this peer*/
00249    char        *url;       /* url alias, which asterisk will register with gk to reach this peer*/
00250    char        *e164;      /* e164 alias, which asterisk will register with gk to reach this peer*/
00251    int         rtptimeout;
00252    struct OOH323Regex       *rtpmask;
00253    char      rtpmaskstr[120];
00254    int       rtdrcount,rtdrinterval;
00255    int       nat;
00256    int       faststart, h245tunneling;
00257    int       directrtp;
00258    int       earlydirect;
00259    int       g729onlyA;
00260    struct ooh323_peer *next;
00261 };
00262 
00263 
00264 /* List of H.323 users known to PBX */
00265 static struct ast_user_list {
00266    struct ooh323_user *users;
00267    ast_mutex_t lock;
00268 } userl;
00269 
00270 static struct ast_peer_list {
00271    struct ooh323_peer *peers;
00272    ast_mutex_t lock;
00273 } peerl;
00274 
00275 /* Mutex to protect H.323 reload process */
00276 static int h323_reloading = 0;
00277 AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
00278 
00279 /* Mutex to protect usage counter */
00280 static int usecnt = 0;
00281 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
00282 
00283 static long callnumber = 0;
00284 AST_MUTEX_DEFINE_STATIC(ooh323c_cn_lock);
00285 
00286 /* stack callbacks */
00287 int onAlerting(ooCallData *call);
00288 int onProgress(ooCallData *call);
00289 int onNewCallCreated(ooCallData *call);
00290 int onOutgoingCall(ooCallData *call);
00291 int onCallEstablished(ooCallData *call);
00292 int onCallCleared(ooCallData *call);
00293 void onModeChanged(ooCallData *call, int t38mode);
00294 
00295 extern OOH323EndPoint gH323ep;
00296 
00297 static char gLogFile[256] = DEFAULT_LOGFILE;
00298 static int  gPort = 1720;
00299 static char gIP[2+8*4+7];  /* Max for IPv6 addr */
00300 struct ast_sockaddr bindaddr;
00301 int v6mode = 0;
00302 static char gCallerID[AST_MAX_EXTENSION] = "";
00303 static struct ooAliases *gAliasList;
00304 static struct ast_format_cap *gCap;
00305 static int  gDTMFMode = H323_DTMF_RFC2833;
00306 static int  gDTMFCodec = 101;
00307 static int  gFAXdetect = FAXDETECT_CNG;
00308 static int  gT38Support = T38_FAXGW;
00309 static char gGatekeeper[100];
00310 static enum RasGatekeeperMode gRasGkMode = RasNoGatekeeper;
00311 
00312 static int  gIsGateway = 0;
00313 static int  gFastStart = 1;
00314 static int  gTunneling = 1;
00315 static int  gBeMaster = 0;
00316 static int  gMediaWaitForConnect = 0;
00317 static int  gDirectRTP = 0;
00318 static int  gEarlyDirect = 0;
00319 static int  gTOS = 0;
00320 static int  gRTPTimeout = 60;
00321 static int  g729onlyA = 0;
00322 static char gAccountcode[80] = DEFAULT_H323ACCNT;
00323 static int  gAMAFLAGS;
00324 static char gContext[AST_MAX_EXTENSION] = DEFAULT_CONTEXT;
00325 static int  gIncomingLimit = 1024;
00326 static int  gOutgoingLimit = 1024;
00327 OOBOOL gH323Debug = FALSE;
00328 static int gTRCLVL = OOTRCLVLERR;
00329 static int gRTDRCount = 0, gRTDRInterval = 0;
00330 static int gNat = FALSE;
00331 static int gANIasDNI = 0;
00332 
00333 static int t35countrycode = 0;
00334 static int t35extensions = 0;
00335 static int manufacturer = 0;
00336 static char vendor[AST_MAX_EXTENSION] =  "";
00337 static char version[AST_MAX_EXTENSION] = "";
00338 
00339 static struct ooh323_config
00340 {
00341    int  mTCPPortStart;
00342    int  mTCPPortEnd;
00343 } ooconfig;
00344 
00345 /** Asterisk RTP stuff*/
00346 static struct ast_sched_context *sched;
00347 static struct io_context *io;
00348 
00349 /* Protect the monitoring thread, so only one process can kill or start it, 
00350    and not when it's doing something critical. */
00351 AST_MUTEX_DEFINE_STATIC(monlock);
00352 
00353 
00354 /* This is the thread for the monitor which checks for input on the channels
00355    which are not currently in use.  */
00356 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00357 
00358 
00359 static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
00360                                              const char *host, struct ast_format_cap *cap, 
00361                                   const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
00362 {
00363    struct ast_format_cap *caps = NULL;
00364    struct ast_channel *ch = NULL;
00365    struct ast_format *tmpfmt = NULL;
00366    int features = 0;
00367 
00368    if (gH323Debug) {
00369       ast_verb(0, "---   ooh323_new - %s\n", host);
00370    }
00371 
00372    caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
00373 
00374    /* Don't hold a h323 pvt lock while we allocate a channel */
00375    ast_mutex_unlock(&i->lock);
00376       ast_mutex_lock(&ooh323c_cn_lock);
00377       ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, 
00378             i->accountcode, i->exten, i->context, assignedids, requestor, i->amaflags,
00379             "OOH323/%s-%ld", host, callnumber);
00380       callnumber++;
00381       ast_mutex_unlock(&ooh323c_cn_lock);
00382    
00383    ast_mutex_lock(&i->lock);
00384 
00385    if (ch && caps) {
00386       ast_channel_tech_set(ch, &ooh323_tech);
00387 
00388       if (cap) {
00389          tmpfmt = ast_format_cap_get_format(cap, 0);
00390       }
00391       if (!tmpfmt) {
00392          tmpfmt = ast_format_cap_get_format(i->cap, 0);
00393       }
00394 
00395       ast_format_cap_append(caps, tmpfmt, 0);
00396       ast_channel_nativeformats_set(ch, caps);
00397       ao2_ref(caps, -1);
00398 
00399       ast_channel_set_rawwriteformat(ch, tmpfmt);
00400       ast_channel_set_rawreadformat(ch, tmpfmt);
00401       ast_set_write_format(ch, tmpfmt);
00402       ast_set_read_format(ch, tmpfmt);
00403       ao2_ref(tmpfmt, -1);
00404 
00405       ast_jb_configure(ch, &global_jbconf);
00406 
00407       if (state == AST_STATE_RING)
00408          ast_channel_rings_set(ch, 1);
00409 
00410       ast_channel_adsicpe_set(ch, AST_ADSI_UNAVAILABLE);
00411       ast_channel_tech_pvt_set(ch, i);
00412       i->owner = ch;
00413       ast_module_ref(myself);
00414 
00415       /* Allocate dsp for in-band DTMF support */
00416       if ((i->dtmfmode & H323_DTMF_INBAND) || (i->faxdetect & FAXDETECT_CNG)) {
00417          i->vad = ast_dsp_new();
00418       }
00419 
00420       /* inband DTMF*/
00421       if (i->dtmfmode & H323_DTMF_INBAND) {
00422          features |= DSP_FEATURE_DIGIT_DETECT;
00423          if (i->dtmfmode & H323_DTMF_INBANDRELAX) {
00424             ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
00425          }
00426       }
00427 
00428       /* fax detection*/
00429       if (i->faxdetect & FAXDETECT_CNG) {
00430          features |= DSP_FEATURE_FAX_DETECT;
00431          ast_dsp_set_faxmode(i->vad,
00432                DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED);
00433       }
00434 
00435       if (features) {
00436          ast_dsp_set_features(i->vad, features);
00437       }
00438 
00439       ast_mutex_lock(&usecnt_lock);
00440       usecnt++;
00441       ast_mutex_unlock(&usecnt_lock);
00442 
00443       /* Notify the module monitors that use count for resource has changed*/
00444       ast_update_use_count();
00445 
00446       ast_channel_context_set(ch, i->context);
00447       ast_channel_exten_set(ch, i->exten);
00448 
00449       ast_channel_priority_set(ch, 1);
00450 
00451             if(!ast_test_flag(i, H323_OUTGOING)) {
00452       
00453          if (!ast_strlen_zero(i->caller_h323id)) {
00454             pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id);
00455 
00456          }
00457          if (!ast_strlen_zero(i->caller_dialedDigits)) {
00458             pbx_builtin_setvar_helper(ch, "_CALLER_H323DIALEDDIGITS", 
00459             i->caller_dialedDigits);
00460          }
00461          if (!ast_strlen_zero(i->caller_email)) {
00462             pbx_builtin_setvar_helper(ch, "_CALLER_H323EMAIL", 
00463             i->caller_email);
00464          }
00465          if (!ast_strlen_zero(i->caller_url)) {
00466             pbx_builtin_setvar_helper(ch, "_CALLER_H323URL", i->caller_url);
00467          }
00468       }
00469 
00470       if (!ast_strlen_zero(i->accountcode))
00471          ast_channel_accountcode_set(ch, i->accountcode);
00472       
00473       if (i->amaflags)
00474          ast_channel_amaflags_set(ch, i->amaflags);
00475 
00476       ast_setstate(ch, state);
00477       if (state != AST_STATE_DOWN) {
00478                if (ast_pbx_start(ch)) {
00479             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch));
00480                      ast_channel_unlock(ch);
00481             ast_hangup(ch);
00482             ch = NULL;
00483          } 
00484       }
00485 
00486       if (ch) {
00487          ast_publish_channel_state(ch);
00488 
00489       }
00490    } else {
00491       ao2_cleanup(caps);
00492       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00493    }
00494 
00495 
00496       if(ch)   ast_channel_unlock(ch);
00497 
00498    if (gH323Debug) {
00499       ast_verb(0, "+++   h323_new\n");
00500    }
00501 
00502    return ch;
00503 }
00504 
00505 
00506 
00507 static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) 
00508 {
00509    struct ooh323_pvt *pvt = NULL;
00510 
00511    if (gH323Debug) {
00512       ast_verb(0, "---   ooh323_alloc\n");
00513    }
00514 
00515    if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
00516       ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
00517       return NULL;
00518    }
00519    if (!(pvt->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
00520       ast_free(pvt);
00521       ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
00522       return NULL;
00523    }
00524 
00525    ast_mutex_init(&pvt->lock);
00526    ast_mutex_lock(&pvt->lock);
00527 
00528    pvt->faxmode = 0;
00529    pvt->chmodepend = 0;
00530    pvt->faxdetected = 0;
00531    pvt->faxdetect = gFAXdetect;
00532    pvt->t38support = gT38Support;
00533    pvt->rtptimeout = gRTPTimeout;
00534    pvt->nat = gNat;
00535    pvt->rtdrinterval = gRTDRInterval;
00536    pvt->rtdrcount = gRTDRCount;
00537    pvt->g729onlyA = g729onlyA;
00538 
00539    pvt->call_reference = callref;
00540    if (callToken)
00541       pvt->callToken = ast_strdup(callToken);
00542 
00543    /* whether to use gk for this call */
00544    if (gRasGkMode == RasNoGatekeeper)
00545       OO_SETFLAG(pvt->flags, H323_DISABLEGK);
00546 
00547    pvt->dtmfmode = gDTMFMode;
00548    pvt->dtmfcodec = gDTMFCodec;
00549    ast_copy_string(pvt->context, gContext, sizeof(pvt->context));
00550    ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode));
00551 
00552    pvt->amaflags = gAMAFLAGS;
00553    ast_format_cap_append_from_cap(pvt->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
00554 
00555    pvt->aniasdni = gANIasDNI;
00556 
00557    ast_mutex_unlock(&pvt->lock); 
00558    /* Add to interface list */
00559    ast_mutex_lock(&iflock);
00560    pvt->next = iflist;
00561    iflist = pvt;
00562    ast_mutex_unlock(&iflock);
00563 
00564    if (gH323Debug) {
00565       ast_verb(0, "+++   ooh323_alloc\n");
00566    }
00567 
00568    return pvt;
00569 }
00570 
00571 
00572 /*
00573    Possible data values - peername, exten/peername, exten@ip
00574  */
00575 static struct ast_channel *ooh323_request(const char *type, struct ast_format_cap *cap,
00576       const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
00577 
00578 {
00579    struct ast_str *codec_buf = ast_str_alloca(64);
00580    struct ast_channel *chan = NULL;
00581    struct ooh323_pvt *p = NULL;
00582    struct ooh323_peer *peer = NULL;
00583    char *dest = NULL; 
00584    char *ext = NULL;
00585    char tmp[256];
00586    int port = 0;
00587 
00588    if (gH323Debug) {
00589       ast_verb(0, "---   ooh323_request - data %s format %s\n", data, ast_format_cap_get_names(cap, &codec_buf));
00590    }
00591 
00592    if (!(ast_format_cap_has_type(cap, AST_MEDIA_TYPE_AUDIO))) {
00593       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
00594       return NULL;
00595    }
00596 
00597    p = ooh323_alloc(0,0); /* Initial callRef is zero */
00598 
00599    if (!p) {
00600       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", data);
00601       return NULL;
00602    }
00603    ast_mutex_lock(&p->lock);
00604 
00605    /* This is an outgoing call, since ooh323_request is called */
00606    ast_set_flag(p, H323_OUTGOING);
00607 
00608 
00609       ast_copy_string(tmp, data, sizeof(tmp));
00610 
00611    dest = strchr(tmp, '/');
00612 
00613    if (dest) {  
00614       *dest = '\0';
00615       dest++;
00616       ext = dest;
00617       dest = tmp;
00618    } else if ((dest = strchr(tmp, '@'))) {
00619       *dest = '\0';
00620       dest++;
00621       ext = tmp;
00622    } else {
00623       dest = tmp;
00624       ext = NULL;
00625    }
00626 
00627 #if 0
00628    if ((sport = strchr(dest, ':'))) {
00629       *sport = '\0';
00630       sport++;
00631       port = atoi(sport);
00632    }
00633 #endif
00634 
00635    if (dest) {
00636       peer = find_peer(dest, port);
00637    } else{
00638       ast_mutex_lock(&iflock);
00639       ast_mutex_unlock(&p->lock);
00640       ooh323_destroy(p);
00641       ast_mutex_unlock(&iflock);
00642       ast_log(LOG_ERROR, "Destination format is not supported\n");
00643       *cause = AST_CAUSE_INVALID_NUMBER_FORMAT;
00644       return NULL;
00645    }
00646 
00647    if (peer) {
00648       p->username = ast_strdup(peer->name);
00649       p->host = ast_strdup(peer->ip);
00650       p->port = peer->port;
00651       /* Disable gk as we are going to call a known peer*/
00652       /* OO_SETFLAG(p->flags, H323_DISABLEGK); */
00653 
00654       if (ext)
00655          ast_copy_string(p->exten, ext, sizeof(p->exten));
00656 
00657       ast_format_cap_append_from_cap(p->cap, peer->cap, AST_MEDIA_TYPE_UNKNOWN);
00658       p->g729onlyA = peer->g729onlyA;
00659       p->dtmfmode |= peer->dtmfmode;
00660       p->dtmfcodec  = peer->dtmfcodec;
00661       p->faxdetect = peer->faxdetect;
00662       p->t38support = peer->t38support;
00663       p->rtptimeout = peer->rtptimeout;
00664       p->nat = peer->nat;
00665       p->faststart = peer->faststart;
00666       p->h245tunneling = peer->h245tunneling;
00667       p->directrtp = peer->directrtp;
00668       p->earlydirect = peer->earlydirect;
00669       if (peer->rtpmask && peer->rtpmaskstr[0]) {
00670          p->rtpmask = peer->rtpmask;
00671          ast_copy_string(p->rtpmaskstr, peer->rtpmaskstr, sizeof(p->rtpmaskstr));
00672       }
00673 
00674       if (peer->rtdrinterval) {
00675          p->rtdrinterval = peer->rtdrinterval;
00676          p->rtdrcount = peer->rtdrcount;
00677       }
00678 
00679       ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode));
00680       p->amaflags = peer->amaflags;
00681    } else {
00682       if (gRasGkMode ==  RasNoGatekeeper) {
00683          /* no gk and no peer */
00684          ast_log(LOG_ERROR, "Call to undefined peer %s", dest);
00685          ast_mutex_lock(&iflock);
00686          ast_mutex_unlock(&p->lock);
00687          ooh323_destroy(p);
00688          ast_mutex_unlock(&iflock);
00689          return NULL;
00690       } else if (!gH323ep.gkClient || (gH323ep.gkClient && gH323ep.gkClient->state != GkClientRegistered)) {
00691          ast_log(LOG_ERROR, "Gatekeeper client is configured but not registered\n");
00692          *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
00693          return NULL;
00694       }
00695       p->g729onlyA = g729onlyA;
00696       p->dtmfmode = gDTMFMode;
00697       p->dtmfcodec = gDTMFCodec;
00698       p->faxdetect = gFAXdetect;
00699       p->t38support = gT38Support;
00700       p->rtptimeout = gRTPTimeout;
00701       p->nat = gNat;
00702       ast_format_cap_append_from_cap(p->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
00703       p->rtdrinterval = gRTDRInterval;
00704       p->rtdrcount = gRTDRCount;
00705       p->faststart = gFastStart;
00706       p->h245tunneling = gTunneling;
00707       p->directrtp = gDirectRTP;
00708       p->earlydirect = gEarlyDirect;
00709 
00710       p->username = ast_strdup(dest);
00711 
00712       p->host = ast_strdup(dest);
00713       if (port > 0) {
00714          p->port = port;
00715       }
00716       if (ext) {
00717          ast_copy_string(p->exten, ext, sizeof(p->exten));
00718       }
00719    }
00720 
00721 
00722    chan = ooh323_new(p, AST_STATE_DOWN, p->username, cap,
00723              assignedids, requestor);
00724    
00725    ast_mutex_unlock(&p->lock);
00726 
00727    if (!chan) {
00728       ast_mutex_lock(&iflock);
00729       ooh323_destroy(p);
00730       ast_mutex_unlock(&iflock);
00731       } else {
00732             ast_mutex_lock(&p->lock);
00733             p->callToken = (char*)ast_calloc(1, AST_MAX_EXTENSION);
00734             if(!p->callToken) {
00735                ast_mutex_unlock(&p->lock);
00736                ast_mutex_lock(&iflock);
00737                ooh323_destroy(p);
00738                ast_mutex_unlock(&iflock);
00739                ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n");
00740                return NULL;
00741             }
00742 
00743       ast_cond_init(&p->rtpcond, NULL);
00744             ooMakeCall(data, p->callToken, AST_MAX_EXTENSION, NULL);
00745       if (!p->rtp) {
00746          ast_cond_wait(&p->rtpcond, &p->lock);
00747       }
00748       ast_mutex_unlock(&p->lock);
00749       ast_cond_destroy(&p->rtpcond);
00750    }
00751 
00752    restart_monitor();
00753    if (gH323Debug)
00754       ast_verb(0, "+++   ooh323_request\n");
00755 
00756    return chan;
00757 
00758 }
00759 
00760 
00761 static struct ooh323_pvt* find_call(ooCallData *call)
00762 {
00763    struct ooh323_pvt *p;
00764 
00765    if (gH323Debug)
00766       ast_verb(0, "---   find_call\n");
00767 
00768    ast_mutex_lock(&iflock);
00769 
00770    for (p = iflist; p; p = p->next) {
00771       if (p->callToken && !strcmp(p->callToken, call->callToken)) {
00772          break;
00773       }
00774    }
00775    ast_mutex_unlock(&iflock);
00776 
00777    if (gH323Debug)
00778       ast_verb(0, "+++   find_call\n");
00779 
00780    return p;
00781 }
00782 
00783 struct ooh323_user *find_user(const char * name, const char* ip)
00784 {
00785    struct ooh323_user *user;
00786 
00787    if (gH323Debug)
00788       ast_verb(0, "---   find_user: %s, %s\n",name,ip);
00789 
00790    ast_mutex_lock(&userl.lock);
00791 
00792    for (user = userl.users; user; user = user->next) {
00793       if (ip && user->mUseIP && !strcmp(user->mIP, ip)) {
00794          break;
00795       }
00796       if (name && !strcmp(user->name, name)) {
00797          break;
00798       }
00799    }
00800 
00801    ast_mutex_unlock(&userl.lock);
00802 
00803    if (gH323Debug)
00804       ast_verb(0, "+++   find_user\n");
00805 
00806    return user;
00807 }
00808 
00809 struct ooh323_peer *find_friend(const char *name, int port)
00810 {
00811    struct ooh323_peer *peer;  
00812 
00813    if (gH323Debug)
00814       ast_verb(0, "---   find_friend \"%s\"\n", name);
00815 
00816 
00817    ast_mutex_lock(&peerl.lock);
00818    for (peer = peerl.peers; peer; peer = peer->next) {
00819       if (gH323Debug) {
00820          ast_verb(0, "     comparing with \"%s\"\n", peer->ip);
00821       }
00822       if (!strcmp(peer->ip, name)) {
00823          if (port <= 0 || (port > 0 && peer->port == port)) {
00824             break;
00825          }
00826       }
00827    }
00828    ast_mutex_unlock(&peerl.lock);
00829 
00830    if (gH323Debug) {
00831       if (peer) {
00832          ast_verb(0, "     found matching friend\n");
00833       }
00834       ast_verb(0, "+++   find_friend \"%s\"\n", name);
00835    }
00836 
00837    return peer;      
00838 }
00839 
00840 
00841 struct ooh323_peer *find_peer(const char * name, int port)
00842 {
00843    struct ooh323_peer *peer;
00844 
00845    if (gH323Debug)
00846       ast_verb(0, "---   find_peer \"%s\"\n", name);
00847 
00848 
00849    ast_mutex_lock(&peerl.lock);
00850    for (peer = peerl.peers; peer; peer = peer->next) {
00851       if (gH323Debug) {
00852          ast_verb(0, "     comparing with \"%s\"\n", peer->ip);
00853       }
00854       if (!strcasecmp(peer->name, name))
00855          break;
00856       if (peer->h323id && !strcasecmp(peer->h323id, name))
00857          break;
00858       if (peer->e164 && !strcasecmp(peer->e164, name))
00859          break;
00860       /*
00861       if (!strcmp(peer->ip, name)) {
00862          if (port > 0 && peer->port == port) { break; }
00863          else if (port <= 0) { break; }
00864       }
00865       */
00866    }
00867    ast_mutex_unlock(&peerl.lock);
00868 
00869    if (gH323Debug) {
00870       if (peer) {
00871          ast_verb(0, "     found matching peer\n");
00872       }
00873       ast_verb(0, "+++   find_peer \"%s\"\n", name);
00874    }
00875 
00876    return peer;      
00877 }
00878 
00879 static int ooh323_digit_begin(struct ast_channel *chan, char digit)
00880 {
00881    char dtmf[2];
00882    struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan);
00883    int res = 0;
00884    
00885    if (gH323Debug)
00886       ast_verb(0, "---   ooh323_digit_begin\n");
00887 
00888    if (!p) {
00889       ast_log(LOG_ERROR, "No private structure for call\n");
00890       return -1;
00891    }
00892    ast_mutex_lock(&p->lock);
00893 
00894    if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO))) {
00895       ast_rtp_instance_dtmf_begin(p->rtp, digit);
00896    } else if (((p->dtmfmode & H323_DTMF_Q931) ||
00897                    (p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) ||
00898                    (p->dtmfmode & H323_DTMF_H245SIGNAL))) {
00899       dtmf[0] = digit;
00900       dtmf[1] = '\0';
00901       ooSendDTMFDigit(p->callToken, dtmf);
00902    } else if (p->dtmfmode & H323_DTMF_INBAND) {
00903       res = -1; // tell Asterisk to generate inband indications
00904    }
00905    ast_mutex_unlock(&p->lock);
00906 
00907    if (gH323Debug) {
00908       ast_verb(0, "+++   ooh323_digit_begin, res = %d\n", res);
00909    }
00910    return res;
00911 }
00912 
00913 static int ooh323_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
00914 {
00915    struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan);
00916    int res = 0;
00917 
00918    if (gH323Debug)
00919       ast_verb(0, "---   ooh323_digit_end\n");
00920 
00921    if (!p) {
00922       ast_log(LOG_ERROR, "No private structure for call\n");
00923       return -1;
00924    }
00925    ast_mutex_lock(&p->lock);
00926    if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO)) ) {
00927       ast_rtp_instance_dtmf_end(p->rtp, digit);
00928    } else if(p->dtmfmode & H323_DTMF_INBAND) {
00929       res = -1; // tell Asterisk to stop inband indications
00930    }
00931 
00932    ast_mutex_unlock(&p->lock);
00933 
00934    if (gH323Debug) {
00935       ast_verb(0, "+++   ooh323_digit_end, res = %d\n", res);
00936    }
00937    return res;
00938 }
00939 
00940 
00941 static int ooh323_call(struct ast_channel *ast, const char *dest, int timeout)
00942 {
00943    struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
00944    char destination[256];
00945       int res=0, i;
00946    const char *val = NULL;
00947    ooCallOptions opts = {
00948       .fastStart = TRUE,
00949       .tunneling = TRUE,
00950       .disableGk = TRUE,
00951             .callMode = OO_CALLMODE_AUDIOCALL,
00952             .transfercap = 0
00953    };
00954 
00955    if (gH323Debug)
00956       ast_verb(0, "---   ooh323_call- %s\n", dest);
00957 
00958 
00959       if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
00960       ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor "
00961                         "reserved\n", ast_channel_name(ast));
00962       return -1;
00963    }
00964    ast_mutex_lock(&p->lock);
00965    ast_set_flag(p, H323_OUTGOING);
00966    if (ast_channel_connected(ast)->id.number.valid && ast_channel_connected(ast)->id.number.str) {
00967       ast_free(p->callerid_num);
00968       p->callerid_num = ast_strdup(ast_channel_connected(ast)->id.number.str);
00969    }
00970 
00971    if (ast_channel_connected(ast)->id.name.valid && ast_channel_connected(ast)->id.name.str) {
00972       ast_free(p->callerid_name);
00973       p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.name.str);
00974    } else if (ast_channel_connected(ast)->id.number.valid && ast_channel_connected(ast)->id.number.str) {
00975       ast_free(p->callerid_name);
00976       p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.number.str);
00977    } else {
00978       ast_channel_connected(ast)->id.name.valid = 1;
00979       ast_free(ast_channel_connected(ast)->id.name.str);
00980       ast_channel_connected(ast)->id.name.str = ast_strdup(gCallerID);
00981       ast_free(p->callerid_name);
00982       p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.name.str);
00983    }
00984 
00985    /* Retrieve vars */
00986 
00987 
00988    if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323ID"))) {
00989       ast_copy_string(p->caller_h323id, val, sizeof(p->caller_h323id));
00990    }
00991    
00992    if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) {
00993       ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits));
00994             if(!p->callerid_num)
00995          p->callerid_num = ast_strdup(val);
00996    }
00997 
00998    if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) {
00999       ast_copy_string(p->caller_email, val, sizeof(p->caller_email));
01000    }
01001 
01002    if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323URL"))) {
01003       ast_copy_string(p->caller_url, val, sizeof(p->caller_url));
01004    }
01005 
01006    if (p->host && p->port != 0)
01007       snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port);
01008    else if (p->host)
01009       snprintf(destination, sizeof(destination), "%s", p->host);
01010    else
01011       ast_copy_string(destination, dest, sizeof(destination));
01012 
01013    destination[sizeof(destination)-1]='\0';
01014 
01015    opts.transfercap = ast_channel_transfercapability(ast);
01016    opts.fastStart = p->faststart;
01017    opts.tunneling = p->h245tunneling;
01018 
01019    for (i=0;i<480 && !isRunning(p->callToken);i++) usleep(12000);
01020 
01021    if(OO_TESTFLAG(p->flags, H323_DISABLEGK)) {
01022       res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
01023    } else {
01024       res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
01025    }
01026 
01027    ast_mutex_unlock(&p->lock);
01028    if (res != OO_OK) {
01029       ast_log(LOG_ERROR, "Failed to make call\n");
01030             return -1; /* ToDO: cleanup */
01031    }
01032    if (gH323Debug)
01033       ast_verb(0, "+++   ooh323_call\n");
01034 
01035   return 0;
01036 }
01037 
01038 static int ooh323_hangup(struct ast_channel *ast)
01039 {
01040    struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
01041       int q931cause = AST_CAUSE_NORMAL_CLEARING;
01042 
01043    if (gH323Debug)
01044       ast_verb(0, "---   ooh323_hangup\n");
01045 
01046    if (p) {
01047       ast_mutex_lock(&p->lock);
01048 
01049         if (ast_channel_hangupcause(ast)) {
01050                 q931cause = ast_channel_hangupcause(ast);
01051         } else {
01052                 const char *cause = pbx_builtin_getvar_helper(ast, "DIALSTATUS");
01053                 if (cause) {
01054                         if (!strcmp(cause, "CONGESTION")) {
01055                                 q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
01056                         } else if (!strcmp(cause, "BUSY")) {
01057                                 q931cause = AST_CAUSE_USER_BUSY;
01058                         } else if (!strcmp(cause, "CHANISUNVAIL")) {
01059                                 q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
01060                         } else if (!strcmp(cause, "NOANSWER")) {
01061                                 q931cause = AST_CAUSE_NO_ANSWER;
01062                         } else if (!strcmp(cause, "CANCEL")) {
01063                                 q931cause = AST_CAUSE_CALL_REJECTED;
01064                         }
01065                 }
01066         }
01067 
01068 
01069 
01070       if (gH323Debug)
01071          ast_verb(0, "    hanging %s with cause: %d\n", p->username, q931cause);
01072       ast_channel_tech_pvt_set(ast, NULL); 
01073       if (!ast_test_flag(p, H323_ALREADYGONE)) {
01074                ooHangCall(p->callToken, 
01075             ooh323_convert_hangupcause_asteriskToH323(q931cause), q931cause);
01076          ast_set_flag(p, H323_ALREADYGONE);
01077          /* ast_mutex_unlock(&p->lock); */
01078             } else 
01079          ast_set_flag(p, H323_NEEDDESTROY);
01080       /* detach channel here */
01081       if (p->owner) {
01082          ast_channel_tech_pvt_set(p->owner, NULL);
01083          p->owner = NULL;
01084          ast_module_unref(myself);
01085       }
01086 
01087       ast_mutex_unlock(&p->lock);
01088       ast_mutex_lock(&usecnt_lock);
01089       usecnt--;
01090       ast_mutex_unlock(&usecnt_lock);
01091 
01092       /* Notify the module monitors that use count for resource has changed */
01093       ast_update_use_count();
01094      
01095    } else {
01096       ast_debug(1, "No call to hangup\n" );
01097    }
01098    
01099    if (gH323Debug)
01100       ast_verb(0, "+++   ooh323_hangup\n");
01101 
01102   return 0;
01103 }
01104 
01105 static int ooh323_answer(struct ast_channel *ast)
01106 {
01107    struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
01108    char *callToken = (char *)NULL;
01109 
01110    if (gH323Debug)
01111       ast_verb(0, "--- ooh323_answer\n");
01112 
01113    if (p) {
01114 
01115       ast_mutex_lock(&p->lock);
01116       callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
01117       if (ast_channel_state(ast) != AST_STATE_UP) {
01118          ast_channel_lock(ast);
01119          if (!p->alertsent) {
01120                if (gH323Debug) {
01121                ast_debug(1, "Sending forced ringback for %s, res = %u\n", 
01122                   callToken, ooManualRingback(callToken));
01123             } else {
01124                   ooManualRingback(callToken);
01125             }
01126             p->alertsent = 1;
01127          }
01128          ast_setstate(ast, AST_STATE_UP);
01129                if (option_debug)
01130             ast_debug(1, "ooh323_answer(%s)\n", ast_channel_name(ast));
01131          ast_channel_unlock(ast);
01132          ooAnswerCall(p->callToken);
01133       }
01134       if (callToken) {
01135          ast_free(callToken);
01136       }
01137       ast_mutex_unlock(&p->lock);
01138    }
01139 
01140    if (gH323Debug)
01141       ast_verb(0, "+++ ooh323_answer\n");
01142 
01143   return 0;
01144 }
01145 
01146 static struct ast_frame *ooh323_read(struct ast_channel *ast)
01147 {
01148    struct ast_frame *fr;
01149    static struct ast_frame null_frame = { AST_FRAME_NULL, };
01150    struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
01151 
01152    if (!p) return &null_frame;
01153 
01154    ast_mutex_lock(&p->lock);
01155    if (p->rtp)
01156       fr = ooh323_rtp_read(ast, p);
01157    else
01158       fr = &null_frame;
01159    /* time(&p->lastrtprx); */
01160    ast_mutex_unlock(&p->lock);
01161    return fr;
01162 }
01163 
01164 static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
01165 {
01166    struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
01167    int res = 0;
01168 
01169    if (p) {
01170       ast_mutex_lock(&p->lock);
01171 
01172       p->lastrtptx = time(NULL);
01173 
01174       if (f->frametype == AST_FRAME_MODEM) {
01175          ast_debug(1, "Send UDPTL %u/%d len %d for %s\n",
01176             f->frametype, f->subclass.integer, f->datalen, ast_channel_name(ast));
01177          if (p->udptl)
01178             res = ast_udptl_write(p->udptl, f);
01179          ast_mutex_unlock(&p->lock);
01180          return res;
01181       }
01182 
01183    
01184       if (f->frametype == AST_FRAME_VOICE) {
01185 /* sending progress for first */
01186          if (!ast_test_flag(p, H323_OUTGOING) && !p->progsent &&
01187                p->callToken) {
01188             ooManualProgress(p->callToken);
01189             p->progsent = 1;
01190          }
01191 
01192 
01193          if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
01194             if (ast_format_cap_count(ast_channel_nativeformats(ast))) {
01195                struct ast_str *codec_buf = ast_str_alloca(64);
01196                ast_log(LOG_WARNING,
01197                      "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
01198                      ast_format_get_name(f->subclass.format),
01199                      ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
01200                      ast_format_get_name(ast_channel_readformat(ast)),
01201                      ast_format_get_name(ast_channel_writeformat(ast)));
01202 
01203                ast_set_write_format(ast, f->subclass.format);
01204             } else {
01205                /* ast_set_write_format(ast, f->subclass);
01206                ast->nativeformats = f->subclass; */
01207             }
01208          ast_mutex_unlock(&p->lock);
01209          return 0;
01210          }
01211 
01212       if (p->rtp)
01213          res = ast_rtp_instance_write(p->rtp, f);
01214 
01215       ast_mutex_unlock(&p->lock);
01216 
01217       } else if (f->frametype == AST_FRAME_IMAGE) {
01218          ast_mutex_unlock(&p->lock);
01219          return 0;
01220       } else {
01221          ast_log(LOG_WARNING, "Can't send %u type frames with OOH323 write\n", 
01222                             f->frametype);
01223          ast_mutex_unlock(&p->lock);
01224          return 0;
01225       }
01226 
01227    }
01228 
01229    return res;
01230 }
01231 
01232 static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
01233 {
01234 
01235    struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(ast);
01236    char *callToken = (char *)NULL;
01237    int res = -1;
01238 
01239    if (!p) return -1;
01240 
01241    ast_mutex_lock(&p->lock);
01242    callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
01243    ast_mutex_unlock(&p->lock);
01244 
01245    if (!callToken) {
01246       if (gH323Debug)
01247          ast_verb(0, "  ooh323_indicate - No callToken\n");
01248       return -1;
01249    }
01250 
01251    if (!ast_sockaddr_isnull(&p->redirip)) {
01252       res = 0;
01253    }
01254 
01255    if (gH323Debug) {
01256       ast_verb(0, "----- ooh323_indicate %d on call %s\n", condition, callToken);
01257    }
01258     
01259       ast_mutex_lock(&p->lock);
01260    switch (condition) {
01261    case AST_CONTROL_INCOMPLETE:
01262       /* While h323 does support overlapped dialing, this channel driver does not
01263        * at this time.  Treat a response of Incomplete as if it were congestion.
01264        */
01265    case AST_CONTROL_CONGESTION:
01266       if (!ast_test_flag(p, H323_ALREADYGONE)) {
01267          ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED, AST_CAUSE_SWITCH_CONGESTION);
01268       }
01269       break;
01270    case AST_CONTROL_BUSY:
01271       if (!ast_test_flag(p, H323_ALREADYGONE)) {
01272          ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY);
01273       }
01274       break;
01275    case AST_CONTROL_HOLD:
01276       ast_moh_start(ast, data, NULL);
01277       break;
01278    case AST_CONTROL_UNHOLD:
01279       ast_moh_stop(ast);
01280       break;
01281    case AST_CONTROL_PROGRESS:
01282       if (ast_channel_state(ast) != AST_STATE_UP) {
01283             if (!p->progsent) {
01284                if (gH323Debug) {
01285                ast_debug(1, "Sending manual progress for %s, res = %u\n", callToken,
01286                         ooManualProgress(callToken)); 
01287             } else {
01288                   ooManualProgress(callToken);
01289             }
01290                p->progsent = 1;
01291             }
01292       }
01293        break;
01294       case AST_CONTROL_RINGING:
01295       if (ast_channel_state(ast) == AST_STATE_RING || ast_channel_state(ast) == AST_STATE_RINGING) {
01296          if (!p->alertsent) {
01297             if (gH323Debug) {
01298                ast_debug(1, "Sending manual ringback for %s, res = %u\n",
01299                   callToken,
01300                   ooManualRingback(callToken));
01301             } else {
01302                ooManualRingback(callToken);
01303             }
01304             p->alertsent = 1;
01305          }
01306          p->alertsent = 1;
01307       }
01308     break;
01309    case AST_CONTROL_SRCUPDATE:
01310       if (p->rtp) {
01311          ast_rtp_instance_update_source(p->rtp);
01312       }
01313       break;
01314    case AST_CONTROL_SRCCHANGE:
01315       if (p->rtp) {
01316          ast_rtp_instance_change_source(p->rtp);
01317       }
01318       break;
01319    case AST_CONTROL_CONNECTED_LINE:
01320       if (!ast_channel_connected(ast)->id.name.valid
01321          || ast_strlen_zero(ast_channel_connected(ast)->id.name.str)) {
01322          break;
01323       }
01324       if (gH323Debug) {
01325          ast_debug(1, "Sending connected line info for %s (%s)\n",
01326             callToken, ast_channel_connected(ast)->id.name.str);
01327       }
01328       ooSetANI(callToken, ast_channel_connected(ast)->id.name.str);
01329       break;
01330 
01331       case AST_CONTROL_T38_PARAMETERS:
01332       if (p->t38support != T38_ENABLED) {
01333          struct ast_control_t38_parameters parameters = { .request_response = 0 };
01334          parameters.request_response = AST_T38_REFUSED;
01335          ast_queue_control_data(ast, AST_CONTROL_T38_PARAMETERS,
01336                    &parameters, sizeof(parameters));
01337          break;
01338       }
01339       if (datalen != sizeof(struct ast_control_t38_parameters)) {
01340          ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. "
01341                   "Expected %d, got %d\n",
01342             (int)sizeof(enum ast_control_t38), (int)datalen);
01343       } else {
01344          const struct ast_control_t38_parameters *parameters = data;
01345          struct ast_control_t38_parameters our_parameters;
01346          enum ast_control_t38 message = parameters->request_response;
01347          switch (message) {
01348 
01349          case AST_T38_NEGOTIATED:
01350             if (p->faxmode) {
01351                res = 0;
01352                break;
01353             }
01354          case AST_T38_REQUEST_NEGOTIATE:
01355 
01356             if (p->faxmode) {
01357                /* T.38 already negotiated */
01358                our_parameters.request_response = AST_T38_NEGOTIATED;
01359                our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
01360                our_parameters.rate = AST_T38_RATE_14400;
01361                ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
01362             } else if (!p->chmodepend) {
01363                p->chmodepend = 1;
01364                ooRequestChangeMode(p->callToken, 1);
01365                res = 0;
01366             }
01367             break;
01368 
01369          case AST_T38_REQUEST_TERMINATE:
01370 
01371             if (!p->faxmode) {
01372                /* T.38 already terminated */
01373                our_parameters.request_response = AST_T38_TERMINATED;
01374                ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
01375             } else if (!p->chmodepend) {
01376                p->chmodepend = 1;
01377                ooRequestChangeMode(p->callToken, 0);
01378                res = 0;
01379             }
01380             break;
01381 
01382          case AST_T38_REQUEST_PARMS:
01383             our_parameters.request_response = AST_T38_REQUEST_PARMS;
01384             our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
01385             our_parameters.rate = AST_T38_RATE_14400;
01386             ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
01387             res = AST_T38_REQUEST_PARMS;
01388             break;
01389 
01390          default:
01391             ;
01392 
01393          }
01394 
01395       }
01396       break;
01397    case AST_CONTROL_PROCEEDING:
01398    case AST_CONTROL_PVT_CAUSE_CODE:
01399    case AST_CONTROL_MASQUERADE_NOTIFY:
01400    case -1:
01401       break;
01402    default:
01403       ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n",
01404                            condition, callToken);
01405    }
01406 
01407       ast_mutex_unlock(&p->lock);
01408 
01409    if (gH323Debug) {
01410       ast_verb(0, "++++  ooh323_indicate %d on %s is %d\n", condition, callToken, res);
01411    }
01412 
01413       ast_free(callToken);
01414    return res;
01415 }
01416 
01417 static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
01418 {
01419 
01420    struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(ast);
01421    int res = -1;
01422    enum ast_t38_state state = T38_STATE_UNAVAILABLE;
01423    char* cp;
01424 
01425    if (!p) return -1;
01426 
01427    ast_mutex_lock(&p->lock);
01428 
01429    if (gH323Debug)
01430       ast_verb(0, "----- ooh323_queryoption %d on channel %s\n", option, ast_channel_name(ast));
01431     
01432    switch (option) {
01433 
01434       case AST_OPTION_T38_STATE:
01435 
01436          if (*datalen != sizeof(enum ast_t38_state)) {
01437             ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option."
01438             " Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen);
01439             break;
01440          }
01441 
01442          if (p->t38support != T38_DISABLED) {
01443             if (p->faxmode) {
01444                state = (p->chmodepend) ? T38_STATE_NEGOTIATING : T38_STATE_NEGOTIATED;
01445             } else {
01446                state = T38_STATE_UNKNOWN;
01447             }
01448          }
01449 
01450          *((enum ast_t38_state *) data) = state;
01451          res = 0;
01452          break;
01453 
01454 
01455       case AST_OPTION_DIGIT_DETECT:
01456 
01457          cp = (char *) data;
01458          *cp = p->vad ? 1 : 0;
01459          ast_debug(1, "Reporting digit detection %sabled on %s\n",
01460                       *cp ? "en" : "dis", ast_channel_name(ast));
01461 
01462          res = 0;
01463          break;
01464 
01465       default: ;
01466 
01467    }
01468 
01469    if (gH323Debug)
01470       ast_verb(0, "+++++ ooh323_queryoption %d on channel %s\n", option, ast_channel_name(ast));
01471     
01472       ast_mutex_unlock(&p->lock);
01473 
01474    return res;
01475 }
01476 
01477 
01478 
01479 static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
01480 {
01481    struct ooh323_pvt *p = ast_channel_tech_pvt(newchan);
01482 
01483    if (!p) return -1;
01484 
01485    if (gH323Debug)
01486       ast_verb(0, "--- ooh323c ooh323_fixup\n");
01487 
01488    ast_mutex_lock(&p->lock);
01489    if (p->owner != oldchan) {
01490       ast_log(LOG_WARNING, "Old channel wasn't %p but was %p\n", oldchan, p->owner);
01491       ast_mutex_unlock(&p->lock);
01492       return -1;
01493    }
01494 
01495    if (p->owner == oldchan) {
01496       p->owner = newchan;
01497    } else {
01498       p->owner = oldchan;
01499    }
01500 
01501    ast_mutex_unlock(&p->lock);
01502 
01503    if (gH323Debug)
01504       ast_verb(0, "+++ ooh323c ooh323_fixup \n");
01505 
01506    return 0;
01507 }
01508 
01509 
01510 void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes)
01511 {
01512    struct ooh323_pvt *p = NULL;
01513 
01514    if (gH323Debug)
01515       ast_verb(0, "---   ooh323_update_writeformat %s/%d\n", 
01516             ast_format_get_name(fmt), txframes);
01517    
01518    p = find_call(call);
01519    if (!p) {
01520       ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
01521       return;
01522    }
01523 
01524    ast_mutex_lock(&p->lock);
01525 
01526    ao2_replace(p->writeformat, fmt);
01527 
01528    if (p->owner) {
01529       struct ast_format_cap *caps;
01530 
01531       caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
01532       if (!caps) {
01533          ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
01534          return;
01535       }
01536 
01537       while (p->owner && ast_channel_trylock(p->owner)) {
01538          ast_debug(1,"Failed to grab lock, trying again\n");
01539          DEADLOCK_AVOIDANCE(&p->lock);
01540       }
01541       if (!p->owner) {
01542          ast_mutex_unlock(&p->lock);
01543          ast_log(LOG_ERROR, "Channel has no owner\n");
01544          ao2_ref(caps, -1);
01545          return;
01546       }
01547       if (gH323Debug) {
01548          struct ast_str *codec_buf = ast_str_alloca(64);
01549          ast_verb(0, "Writeformat before update %s/%s\n", 
01550            ast_format_get_name(ast_channel_writeformat(p->owner)),
01551            ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &codec_buf));
01552       }
01553 
01554       if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
01555          ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
01556              p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
01557       }
01558       if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) {
01559          ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
01560              p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
01561       }
01562 
01563       if (txframes) {
01564          ast_format_cap_set_framing(caps, txframes);
01565       }
01566       ast_format_cap_append(caps, fmt, 0);
01567       ast_channel_nativeformats_set(p->owner, caps);
01568       ao2_ref(caps, -1);
01569       ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
01570       ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
01571       ast_channel_unlock(p->owner);
01572       } else
01573       ast_log(LOG_ERROR, "No owner found\n");
01574 
01575 
01576    ast_mutex_unlock(&p->lock);
01577 
01578    if (gH323Debug)
01579       ast_verb(0, "+++   ooh323_update_writeformat\n");
01580 }
01581 
01582 void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
01583 {
01584    struct ooh323_pvt *p = NULL;
01585 
01586    if (gH323Debug)
01587       ast_verb(0, "---   ooh323_update_readformat %s\n", 
01588             ast_format_get_name(fmt));
01589    
01590    p = find_call(call);
01591    if (!p) {
01592       ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
01593       return;
01594    }
01595 
01596    ast_mutex_lock(&p->lock);
01597 
01598    ao2_replace(p->readformat, fmt);
01599 
01600    if (p->owner) {
01601       struct ast_format_cap *caps;
01602 
01603       caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
01604       if (!caps) {
01605          ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
01606          return;
01607       }
01608 
01609       while (p->owner && ast_channel_trylock(p->owner)) {
01610          ast_debug(1,"Failed to grab lock, trying again\n");
01611          DEADLOCK_AVOIDANCE(&p->lock);
01612       }
01613       if (!p->owner) {
01614          ast_mutex_unlock(&p->lock);
01615          ast_log(LOG_ERROR, "Channel has no owner\n");
01616          ao2_ref(caps, -1);
01617          return;
01618       }
01619 
01620       if (gH323Debug) {
01621          ast_verb(0, "Readformat before update %s\n", 
01622            ast_format_get_name(ast_channel_readformat(p->owner)));
01623       }
01624       ast_format_cap_append(caps, fmt, 0);
01625       ast_channel_nativeformats_set(p->owner, caps);
01626       ao2_ref(caps, -1);
01627       ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
01628       ast_channel_unlock(p->owner);
01629       } else
01630       ast_log(LOG_ERROR, "No owner found\n");
01631 
01632    ast_mutex_unlock(&p->lock);
01633 
01634    if (gH323Debug)
01635       ast_verb(0, "+++   ooh323_update_readformat\n");
01636 }
01637 
01638 
01639 int onAlerting(ooCallData *call)
01640 {
01641    struct ooh323_pvt *p = NULL;
01642    struct ast_channel *c = NULL;
01643 
01644    if (gH323Debug)
01645       ast_verb(0, "--- onAlerting %s\n", call->callToken);
01646 
01647       p = find_call(call);
01648 
01649       if(!p) {
01650       ast_log(LOG_ERROR, "No matching call found\n");
01651       return -1;
01652    }  
01653    ast_mutex_lock(&p->lock);
01654    if (!p->owner) {
01655       ast_mutex_unlock(&p->lock);
01656       ast_debug(1, "Channel has no owner\n");
01657       return 0;
01658    }
01659    while (p->owner && ast_channel_trylock(p->owner)) {
01660       ast_debug(1, "Failed to grab lock, trying again\n");
01661       DEADLOCK_AVOIDANCE(&p->lock);
01662    }
01663    if (!p->owner) {
01664       ast_mutex_unlock(&p->lock);
01665       ast_log(LOG_ERROR, "Channel has no owner\n");
01666       return 0;
01667    }
01668    c = p->owner;
01669 
01670    if (call->remoteDisplayName) {
01671       struct ast_party_connected_line connected;
01672       struct ast_set_party_connected_line update_connected;
01673 
01674       memset(&update_connected, 0, sizeof(update_connected));
01675       update_connected.id.name = 1;
01676       ast_party_connected_line_init(&connected);
01677       connected.id.name.valid = 1;
01678       connected.id.name.str = (char *) call->remoteDisplayName;
01679       connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
01680       ast_channel_queue_connected_line_update(c, &connected, &update_connected);
01681    }
01682    if (ast_channel_state(c) != AST_STATE_UP)
01683       ast_setstate(c, AST_STATE_RINGING);
01684 
01685    ast_queue_control(c, AST_CONTROL_RINGING);
01686          ast_channel_unlock(c);
01687          ast_mutex_unlock(&p->lock);
01688 
01689    if (gH323Debug)
01690       ast_verb(0, "+++ onAlerting %s\n", call->callToken);
01691 
01692    return OO_OK;
01693 }
01694 
01695 int onProgress(ooCallData *call)
01696 {
01697    struct ooh323_pvt *p = NULL;
01698    struct ast_channel *c = NULL;
01699 
01700    if (gH323Debug)
01701       ast_verb(0, "--- onProgress %s\n", call->callToken);
01702 
01703       p = find_call(call);
01704 
01705       if(!p) {
01706       ast_log(LOG_ERROR, "No matching call found\n");
01707       return -1;
01708    }  
01709    ast_mutex_lock(&p->lock);
01710    if (!p->owner) {
01711       ast_mutex_unlock(&p->lock);
01712       ast_log(LOG_ERROR, "Channel has no owner\n");
01713       return 0;
01714    }
01715    while (p->owner && ast_channel_trylock(p->owner)) {
01716       ast_debug(1, "Failed to grab lock, trying again\n");
01717       DEADLOCK_AVOIDANCE(&p->lock);
01718    }
01719    if (!p->owner) {
01720       ast_mutex_unlock(&p->lock);
01721       ast_log(LOG_ERROR, "Channel has no owner\n");
01722       return 0;
01723    }
01724    c = p->owner;
01725 
01726    if (call->remoteDisplayName) {
01727       struct ast_party_connected_line connected;
01728       struct ast_set_party_connected_line update_connected;
01729 
01730       memset(&update_connected, 0, sizeof(update_connected));
01731       update_connected.id.name = 1;
01732       ast_party_connected_line_init(&connected);
01733       connected.id.name.valid = 1;
01734       connected.id.name.str = (char *) call->remoteDisplayName;
01735       connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
01736       ast_channel_queue_connected_line_update(c, &connected, &update_connected);
01737    }
01738    if (ast_channel_state(c) != AST_STATE_UP)
01739       ast_setstate(c, AST_STATE_RINGING);
01740 
01741    ast_queue_control(c, AST_CONTROL_PROGRESS);
01742          ast_channel_unlock(c);
01743          ast_mutex_unlock(&p->lock);
01744 
01745    if (gH323Debug)
01746       ast_verb(0, "+++ onProgress %s\n", call->callToken);
01747 
01748    return OO_OK;
01749 }
01750 
01751 /**
01752   * Callback for sending digits from H.323 up to asterisk
01753   *
01754   */
01755 int ooh323_onReceivedDigit(OOH323CallData *call, const char *digit)
01756 {
01757    struct ooh323_pvt *p = NULL;
01758    struct ast_frame f;
01759    int res;
01760 
01761    ast_debug(1, "Received Digit: %c\n", digit[0]);
01762    p = find_call(call);
01763    if (!p) {
01764       ast_log(LOG_ERROR, "Failed to find a matching call.\n");
01765       return -1;
01766    }
01767    if (!p->owner) {
01768       ast_log(LOG_ERROR, "Channel has no owner\n");
01769       return -1;
01770    }
01771    ast_mutex_lock(&p->lock);
01772    memset(&f, 0, sizeof(f));
01773    f.frametype = AST_FRAME_DTMF;
01774    f.subclass.integer = digit[0];
01775    f.datalen = 0;
01776    f.samples = 800;
01777    f.offset = 0;
01778    f.data.ptr = NULL;
01779    f.mallocd = 0;
01780    f.src = "SEND_DIGIT";
01781 
01782    while (p->owner && ast_channel_trylock(p->owner)) {
01783       ast_debug(1, "Failed to grab lock, trying again\n");
01784       DEADLOCK_AVOIDANCE(&p->lock);
01785    }
01786    if (!p->owner) {
01787       ast_mutex_unlock(&p->lock);
01788       ast_log(LOG_ERROR, "Channel has no owner\n");
01789       return 0;
01790    }
01791    res = ast_queue_frame(p->owner, &f);
01792       ast_channel_unlock(p->owner);
01793       ast_mutex_unlock(&p->lock);
01794    return res;
01795 }
01796 
01797 int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
01798 {
01799    struct ooh323_pvt *p = NULL;
01800    struct ooh323_user *user = NULL;
01801       struct ast_channel *c = NULL;
01802    ooAliases *alias = NULL;
01803    char *at = NULL;
01804    char number [OO_MAX_NUMBER_LENGTH];
01805 
01806    if (gH323Debug)
01807       ast_verb(0, "---   ooh323_onReceivedSetup %s\n", call->callToken);
01808 
01809 
01810    if (!(p = ooh323_alloc(call->callReference, call->callToken))) {
01811       ast_log(LOG_ERROR, "Failed to create a new call.\n");
01812       return -1;
01813    }
01814    ast_mutex_lock(&p->lock);
01815    ast_clear_flag(p, H323_OUTGOING);
01816   
01817 
01818    if (call->remoteDisplayName) {
01819       p->callerid_name = ast_strdup(call->remoteDisplayName);
01820    }
01821 
01822    if (ooCallGetCallingPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
01823       p->callerid_num = ast_strdup(number);
01824    }
01825 
01826    if (call->remoteAliases) {
01827       for (alias = call->remoteAliases; alias; alias = alias->next) {
01828          if (alias->type == T_H225AliasAddress_h323_ID) {
01829             if (!p->callerid_name) {
01830                p->callerid_name = ast_strdup(alias->value);
01831             }
01832             ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id));
01833             }
01834          else if(alias->type == T_H225AliasAddress_dialedDigits)
01835          {
01836             if(!p->callerid_num)
01837                p->callerid_num = ast_strdup(alias->value);
01838             ast_copy_string(p->caller_dialedDigits, alias->value, 
01839                                              sizeof(p->caller_dialedDigits));
01840          }
01841          else if(alias->type == T_H225AliasAddress_email_ID)
01842          {
01843             ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email));
01844          }
01845          else if(alias->type == T_H225AliasAddress_url_ID)
01846          {
01847             ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url));
01848          }
01849       }
01850    }
01851 
01852    number[0] = '\0';
01853       if(ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH)== OO_OK) {
01854             ast_copy_string(p->exten, number, sizeof(p->exten));
01855       } else {
01856       update_our_aliases(call, p);
01857       if (!ast_strlen_zero(p->callee_dialedDigits)) {
01858                ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
01859             } else if(!ast_strlen_zero(p->callee_h323id)) {
01860          ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten));
01861             } else if(!ast_strlen_zero(p->callee_email)) {
01862          ast_copy_string(p->exten, p->callee_email, sizeof(p->exten));
01863          if ((at = strchr(p->exten, '@'))) {
01864             *at = '\0';
01865          }
01866       }
01867    }
01868 
01869    /* if no extension found, set to default 's' */
01870    if (ast_strlen_zero(p->exten)) {
01871             p->exten[0]='s';
01872             p->exten[1]='\0';
01873    }
01874 
01875          user = find_user(p->callerid_name, call->remoteIP);
01876          if(user && (user->incominglimit == 0 || user->inUse < user->incominglimit)) {
01877       ast_mutex_lock(&user->lock);
01878       p->username = ast_strdup(user->name);
01879       p->neighbor.user = user->mUseIP ? ast_strdup(user->mIP) :
01880                     ast_strdup(user->name);
01881       ast_copy_string(p->context, user->context, sizeof(p->context));
01882       ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
01883       p->amaflags = user->amaflags;
01884       ast_format_cap_append_from_cap(p->cap, user->cap, AST_MEDIA_TYPE_UNKNOWN);
01885       p->g729onlyA = user->g729onlyA;
01886       p->dtmfmode |= user->dtmfmode;
01887       p->dtmfcodec = user->dtmfcodec;
01888       p->faxdetect = user->faxdetect;
01889       p->t38support = user->t38support;
01890       p->rtptimeout = user->rtptimeout;
01891       p->nat = user->nat;
01892       p->h245tunneling = user->h245tunneling;
01893       p->faststart = user->faststart;
01894       p->directrtp = user->directrtp;
01895       p->earlydirect = user->earlydirect;
01896 
01897       if (p->faststart)
01898                OO_SETFLAG(call->flags, OO_M_FASTSTART);
01899       else
01900          OO_CLRFLAG(call->flags, OO_M_FASTSTART);
01901       /* if we disable h245tun for this user then we clear flag */
01902       /* in any other case we don't must touch this */
01903       /* ie if we receive setup without h245tun but enabled
01904                      we can't enable it per call */
01905       if (!p->h245tunneling)
01906          OO_CLRFLAG(call->flags, OO_M_TUNNELING);
01907 
01908       if (user->rtpmask && user->rtpmaskstr[0]) {
01909          p->rtpmask = user->rtpmask;
01910          ast_copy_string(p->rtpmaskstr, user->rtpmaskstr, 
01911                       sizeof(p->rtpmaskstr));
01912       }
01913       if (user->rtdrcount > 0 && user->rtdrinterval > 0) {
01914          p->rtdrcount = user->rtdrcount;
01915          p->rtdrinterval = user->rtdrinterval;
01916       }
01917 
01918       p->aniasdni = user->aniasdni;
01919 
01920       if (user->incominglimit) user->inUse++;
01921       ast_mutex_unlock(&user->lock);
01922    } else {
01923     if (!OO_TESTFLAG(p->flags,H323_DISABLEGK)) {
01924       p->username = ast_strdup(call->remoteIP);
01925       p->directrtp = gDirectRTP;
01926       p->earlydirect = gEarlyDirect;
01927    } else {
01928      ast_mutex_unlock(&p->lock);
01929      ast_log(LOG_ERROR, "Unacceptable ip %s\n", call->remoteIP);
01930      if (!user) {
01931       ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_CALL_REJECTED), AST_CAUSE_CALL_REJECTED);
01932       call->callEndReason = OO_REASON_REMOTE_REJECTED;
01933      }
01934      else {
01935       ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_NORMAL_CIRCUIT_CONGESTION), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
01936       call->callEndReason = OO_REASON_REMOTE_REJECTED;
01937      }
01938      ast_set_flag(p, H323_NEEDDESTROY);
01939      return -1;
01940     }
01941    }
01942 
01943    ooh323c_set_capability_for_call(call, p->cap, p->dtmfmode, p->dtmfcodec,
01944                 p->t38support, p->g729onlyA);
01945 /* Incoming call */
01946    c = ooh323_new(p, AST_STATE_RING, p->username, 0, NULL, NULL);
01947    if(!c) {
01948       ast_mutex_unlock(&p->lock);
01949       ast_log(LOG_ERROR, "Could not create ast_channel\n");
01950          return -1;
01951    }
01952 
01953    if (p->aniasdni) {
01954       ooCallSetCallerId(call, p->exten);
01955    }
01956    if (!configure_local_rtp(p, call)) {
01957       ast_mutex_unlock(&p->lock);
01958       ast_log(LOG_ERROR, "Couldn't create rtp structure\n");
01959       return -1;
01960    }
01961 
01962    ast_mutex_unlock(&p->lock);
01963 
01964    if (gH323Debug)
01965       ast_verb(0, "+++   ooh323_onReceivedSetup - Determined context %s, "
01966                   "extension %s\n", p->context, p->exten);
01967 
01968    return OO_OK;
01969 }
01970 
01971 
01972 
01973 int onOutgoingCall(ooCallData *call)
01974 {
01975    struct ooh323_pvt *p = NULL;
01976    int i = 0;
01977 
01978    if (gH323Debug)
01979       ast_verb(0, "---   onOutgoingCall %lx: %s\n", (long unsigned int) call, call->callToken);
01980 
01981    if (!strcmp(call->callType, "outgoing")) {
01982       p = find_call(call);
01983       if (!p) {
01984                ast_log(LOG_ERROR, "Failed to find a matching call.\n");
01985          return -1;
01986       }
01987       ast_mutex_lock(&p->lock);
01988 
01989       if (!ast_strlen_zero(p->callerid_name)) {
01990          ooCallSetCallerId(call, p->callerid_name);
01991       }
01992       if (!ast_strlen_zero(p->callerid_num)) {
01993          i = 0;
01994          while (*(p->callerid_num + i) != '\0') {
01995                      if(!isdigit(*(p->callerid_num+i))) { break; }
01996             i++;
01997          }
01998                if(*(p->callerid_num+i) == '\0')
01999             ooCallSetCallingPartyNumber(call, p->callerid_num);
02000                else {
02001                      if(!p->callerid_name)
02002                ooCallSetCallerId(call, p->callerid_num);
02003          }
02004       }
02005       
02006       if (!ast_strlen_zero(p->caller_h323id))
02007          ooCallAddAliasH323ID(call, p->caller_h323id);
02008 
02009       if (!ast_strlen_zero(p->caller_dialedDigits)) {
02010          if (gH323Debug) {
02011             ast_verb(0, "Setting dialed digits %s\n", p->caller_dialedDigits);
02012          }
02013          ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
02014       } else if (!ast_strlen_zero(p->callerid_num)) {
02015          if (ooIsDailedDigit(p->callerid_num)) {
02016             if (gH323Debug) {
02017                ast_verb(0, "setting callid number %s\n", p->callerid_num);
02018             }
02019             ooCallAddAliasDialedDigits(call, p->callerid_num);
02020          } else if (ast_strlen_zero(p->caller_h323id)) {
02021             ooCallAddAliasH323ID(call, p->callerid_num);
02022          }
02023       }
02024       if (p->rtpmask && p->rtpmaskstr[0]) {
02025          call->rtpMask = p->rtpmask;
02026          ast_mutex_lock(&call->rtpMask->lock);
02027          call->rtpMask->inuse++;
02028          ast_mutex_unlock(&call->rtpMask->lock);
02029          ast_copy_string(call->rtpMaskStr, p->rtpmaskstr, sizeof(call->rtpMaskStr));
02030       }
02031 
02032       if (!p->rtp && !configure_local_rtp(p, call)) {
02033          ast_mutex_unlock(&p->lock);
02034          return OO_FAILED;
02035       }
02036 
02037       ast_mutex_unlock(&p->lock);
02038    }
02039 
02040    if (gH323Debug)
02041       ast_verb(0, "+++   onOutgoingCall %s\n", call->callToken);
02042    return OO_OK;
02043 }
02044 
02045 
02046 int onNewCallCreated(ooCallData *call)
02047 {
02048    struct ooh323_pvt *p = NULL;
02049    int i = 0;
02050 
02051    if (gH323Debug)
02052       ast_verb(0, "---   onNewCallCreated %lx: %s\n", (long unsigned int) call, call->callToken);
02053 
02054       ast_mutex_lock(&call->Lock);
02055       if (ooh323c_start_call_thread(call)) {
02056          ast_log(LOG_ERROR,"Failed to create call thread.\n");
02057          ast_mutex_unlock(&call->Lock);
02058          return -1;
02059       }
02060 
02061    if (!strcmp(call->callType, "outgoing")) {
02062       p = find_call(call);
02063       if (!p) {
02064                ast_log(LOG_ERROR, "Failed to find a matching call.\n");
02065          ast_mutex_unlock(&call->Lock);
02066          return -1;
02067       }
02068       ast_mutex_lock(&p->lock);
02069 
02070       if (!ast_strlen_zero(p->callerid_name)) {
02071          ooCallSetCallerId(call, p->callerid_name);
02072       }
02073       if (!ast_strlen_zero(p->callerid_num)) {
02074          i = 0;
02075          while (*(p->callerid_num + i) != '\0') {
02076                      if(!isdigit(*(p->callerid_num+i))) { break; }
02077             i++;
02078          }
02079                if(*(p->callerid_num+i) == '\0')
02080             ooCallSetCallingPartyNumber(call, p->callerid_num);
02081                else {
02082                      if(ast_strlen_zero(p->callerid_name))
02083                ooCallSetCallerId(call, p->callerid_num);
02084          }
02085       }
02086       
02087       if (!ast_strlen_zero(p->caller_h323id))
02088          ooCallAddAliasH323ID(call, p->caller_h323id);
02089 
02090       if (!ast_strlen_zero(p->caller_dialedDigits)) {
02091          if (gH323Debug) {
02092             ast_verb(0, "Setting dialed digits %s\n", p->caller_dialedDigits);
02093          }
02094          ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
02095       } else if (!ast_strlen_zero(p->callerid_num)) {
02096          if (ooIsDailedDigit(p->callerid_num)) {
02097             if (gH323Debug) {
02098                ast_verb(0, "setting callid number %s\n", p->callerid_num);
02099             }
02100             ooCallAddAliasDialedDigits(call, p->callerid_num);
02101          } else if (ast_strlen_zero(p->caller_h323id)) {
02102             ooCallAddAliasH323ID(call, p->callerid_num);
02103          }
02104       }
02105   
02106 
02107       if (!ast_strlen_zero(p->exten))  {
02108          if (ooIsDailedDigit(p->exten)) {
02109             ooCallSetCalledPartyNumber(call, p->exten);
02110             ooCallAddRemoteAliasDialedDigits(call, p->exten);
02111          } else {
02112            ooCallAddRemoteAliasH323ID(call, p->exten);
02113          }
02114       }
02115 
02116       if (gH323Debug) {
02117          struct ast_str *codec_buf = ast_str_alloca(64);
02118 
02119          ast_verb(0, " Outgoing call %s(%s) - Codec prefs - %s\n", 
02120             p->username?p->username:"NULL", call->callToken,
02121             ast_format_cap_get_names(p->cap, &codec_buf));
02122       }
02123 
02124             ooh323c_set_capability_for_call(call, p->cap,
02125                                      p->dtmfmode, p->dtmfcodec, p->t38support, p->g729onlyA);
02126 
02127       configure_local_rtp(p, call);
02128       ast_cond_signal(&p->rtpcond);
02129       ast_mutex_unlock(&p->lock);
02130    }
02131 
02132       ast_mutex_unlock(&call->Lock);
02133    if (gH323Debug)
02134       ast_verb(0, "+++   onNewCallCreated %s\n", call->callToken);
02135    return OO_OK;
02136 }
02137 
02138 int onCallEstablished(ooCallData *call)
02139 {
02140    struct ooh323_pvt *p = NULL;
02141 
02142    if (gH323Debug)
02143       ast_verb(0, "---   onCallEstablished %s\n", call->callToken);
02144 
02145 
02146    if (!(p = find_call(call))) {
02147       ast_log(LOG_ERROR, "Failed to find a matching call.\n");
02148       return -1;
02149    }
02150 
02151       if(ast_test_flag(p, H323_OUTGOING)) {
02152       ast_mutex_lock(&p->lock);
02153       if (!p->owner) {
02154          ast_mutex_unlock(&p->lock);
02155          ast_log(LOG_ERROR, "Channel has no owner\n");
02156          return -1;
02157       }
02158    
02159       while (p->owner && ast_channel_trylock(p->owner)) {
02160          ast_debug(1, "Failed to grab lock, trying again\n");
02161          DEADLOCK_AVOIDANCE(&p->lock);
02162       }
02163       if (p->owner) {
02164          struct ast_channel* c = p->owner;
02165 
02166          if (call->remoteDisplayName) {
02167             struct ast_party_connected_line connected;
02168             struct ast_set_party_connected_line update_connected;
02169 
02170             memset(&update_connected, 0, sizeof(update_connected));
02171             update_connected.id.name = 1;
02172             ast_party_connected_line_init(&connected);
02173             connected.id.name.valid = 1;
02174             connected.id.name.str = (char *) call->remoteDisplayName;
02175             connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
02176             ast_channel_queue_connected_line_update(c, &connected, &update_connected);
02177          }
02178 
02179          ast_queue_control(c, AST_CONTROL_ANSWER);
02180          ast_publish_channel_state(c);
02181          ast_channel_unlock(p->owner);
02182       }
02183       ast_mutex_unlock(&p->lock);
02184 
02185    }
02186 
02187    if (gH323Debug)
02188       ast_verb(0, "+++   onCallEstablished %s\n", call->callToken);
02189 
02190    return OO_OK;
02191 }
02192 
02193 int onCallCleared(ooCallData *call)
02194 {
02195    struct ooh323_pvt *p = NULL;
02196    int ownerLock = 0;
02197 
02198    if (gH323Debug)
02199       ast_verb(0, "---   onCallCleared %s \n", call->callToken);
02200 
02201 
02202    if ((p = find_call(call))) {
02203    ast_mutex_lock(&p->lock);
02204   
02205    while (p->owner) {
02206       if (ast_channel_trylock(p->owner)) {
02207          ooTrace(OOTRCLVLINFO, "Failed to grab lock, trying again\n");
02208                ast_debug(1, "Failed to grab lock, trying again\n");
02209          DEADLOCK_AVOIDANCE(&p->lock);
02210       } else {
02211                ownerLock = 1; break;
02212       }
02213    }
02214 
02215    if (ownerLock) {
02216       if (!ast_test_flag(p, H323_ALREADYGONE)) { 
02217 
02218          ast_set_flag(p, H323_ALREADYGONE);
02219          ast_channel_hangupcause_set(p->owner, call->q931cause);
02220          ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
02221          ast_queue_hangup_with_cause(p->owner,call->q931cause);
02222       }
02223       }
02224 
02225       if(p->owner) {
02226          ast_channel_tech_pvt_set(p->owner, NULL);
02227       ast_channel_unlock(p->owner);
02228          p->owner = NULL;
02229       ast_module_unref(myself);
02230    }
02231 
02232    if (!p->rtp) {
02233       ast_cond_signal(&p->rtpcond);
02234    }
02235 
02236    ast_set_flag(p, H323_NEEDDESTROY);
02237 
02238       ooh323c_stop_call_thread(call);
02239 
02240    ast_mutex_unlock(&p->lock);
02241       ast_mutex_lock(&usecnt_lock);
02242       usecnt--;
02243       ast_mutex_unlock(&usecnt_lock);
02244 
02245     }
02246 
02247    if (gH323Debug)
02248       ast_verb(0, "+++   onCallCleared\n");
02249 
02250    return OO_OK;
02251 }
02252 
02253 /* static void ooh323_delete_user(struct ooh323_user *user)
02254 {
02255    struct ooh323_user *prev = NULL, *cur = NULL;
02256 
02257    if (gH323Debug)
02258       ast_verb(0, "---   ooh323_delete_user\n");
02259 
02260    if (user) { 
02261       cur = userl.users;
02262       ast_mutex_lock(&userl.lock);
02263       while (cur) {
02264          if (cur == user) break;
02265          prev = cur;
02266          cur = cur->next;
02267       }
02268 
02269       if (cur) {
02270          if (prev)
02271             prev->next = cur->next;
02272          else
02273             userl.users = cur->next;
02274       }
02275       ast_mutex_unlock(&userl.lock);
02276 
02277       ast_free(user);
02278    }  
02279 
02280    if (gH323Debug)
02281       ast_verb(0, "+++   ooh323_delete_user\n");
02282 
02283 } */
02284 
02285 void ooh323_delete_peer(struct ooh323_peer *peer)
02286 {
02287    struct ooh323_peer *prev = NULL, *cur = NULL;
02288 
02289    if (gH323Debug)
02290       ast_verb(0, "---   ooh323_delete_peer\n");
02291 
02292    if (peer) { 
02293       cur = peerl.peers;
02294       ast_mutex_lock(&peerl.lock);
02295       while(cur) {
02296          if(cur==peer) break;
02297          prev = cur;
02298          cur = cur->next;
02299       }
02300 
02301       if (cur) {
02302          if(prev)
02303             prev->next = cur->next;
02304          else
02305             peerl.peers = cur->next;
02306          }
02307       ast_mutex_unlock(&peerl.lock);
02308 
02309       ast_free(peer->h323id);
02310       ast_free(peer->email);
02311       ast_free(peer->url);
02312       ast_free(peer->e164);
02313 
02314       ao2_cleanup(peer->cap);
02315       ast_free(peer);
02316    }  
02317 
02318    if (gH323Debug)
02319       ast_verb(0, "+++   ooh323_delete_peer\n");
02320 
02321 }
02322 
02323 
02324 
02325 static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
02326 {
02327    struct ooh323_user *user = NULL;
02328 
02329    if (gH323Debug)
02330       ast_verb(0, "---   build_user\n");
02331 
02332       user = ast_calloc(1,sizeof(struct ooh323_user));
02333    if (user) {
02334       memset(user, 0, sizeof(struct ooh323_user));
02335       if (!(user->cap = ast_format_cap_alloc(0))) {
02336          ast_free(user);
02337          return NULL;
02338       }
02339       ast_mutex_init(&user->lock);
02340       ast_copy_string(user->name, name, sizeof(user->name));
02341       ast_format_cap_append_from_cap(user->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
02342       user->rtptimeout = gRTPTimeout;
02343       user->nat = gNat;
02344       user->dtmfmode = gDTMFMode;
02345       user->dtmfcodec = gDTMFCodec;
02346       user->faxdetect = gFAXdetect;
02347       user->t38support = gT38Support;
02348       user->faststart = gFastStart;
02349       user->h245tunneling = gTunneling;
02350       user->directrtp = gDirectRTP;
02351       user->earlydirect = gEarlyDirect;
02352       user->g729onlyA = g729onlyA;
02353       /* set default context */
02354       ast_copy_string(user->context, gContext, sizeof(user->context));
02355       ast_copy_string(user->accountcode, gAccountcode, sizeof(user->accountcode));
02356       user->amaflags = gAMAFLAGS;
02357 
02358       while (v) {
02359          if (!strcasecmp(v->name, "context")) {
02360             ast_copy_string(user->context, v->value, sizeof(user->context));
02361          } else if (!strcasecmp(v->name, "incominglimit")) {
02362             user->incominglimit = atoi(v->value);
02363             if (user->incominglimit < 0)
02364                user->incominglimit = 0;
02365          } else if (!strcasecmp(v->name, "accountcode")) {
02366                      ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
02367          } else if (!strcasecmp(v->name, "roundtrip")) {
02368             sscanf(v->value, "%d,%d", &user->rtdrcount, &user->rtdrinterval);
02369          } else if (!strcasecmp(v->name, "faststart")) {
02370             user->faststart = ast_true(v->value);
02371          } else if (!strcasecmp(v->name, "h245tunneling")) {
02372             user->h245tunneling = ast_true(v->value);
02373          } else if (!strcasecmp(v->name, "directrtp") || !strcasecmp(v->name, "directmedia")) {
02374             user->directrtp = ast_true(v->value);
02375             user->earlydirect = ast_true(v->value);
02376          } else if (!strcasecmp(v->name, "earlydirect") || !strcasecmp(v->name, "directrtpsetup")) {
02377             user->earlydirect = ast_true(v->value);
02378          } else if (!strcasecmp(v->name, "g729onlyA")) {
02379             user->g729onlyA = ast_true(v->value);
02380          } else if (!strcasecmp(v->name, "nat")) {
02381             user->nat = ast_true(v->value);
02382          } else if (!strcasecmp(v->name, "rtptimeout")) {
02383             user->rtptimeout = atoi(v->value);
02384             if (user->rtptimeout < 0)
02385                user->rtptimeout = gRTPTimeout;
02386          } else if (!strcasecmp(v->name, "rtpmask")) {
02387             if ((user->rtpmask = ast_calloc(1, sizeof(struct OOH323Regex))) &&
02388                (regcomp(&user->rtpmask->regex, v->value, REG_EXTENDED) 
02389                                  == 0)) {
02390                ast_mutex_init(&user->rtpmask->lock);
02391                user->rtpmask->inuse = 1;
02392                ast_copy_string(user->rtpmaskstr, v->value, 
02393                         sizeof(user->rtpmaskstr));
02394             } else user->rtpmask = NULL;
02395          } else if (!strcasecmp(v->name, "disallow")) {
02396             ast_format_cap_update_by_allow_disallow(user->cap,  v->value, 0);
02397          } else if (!strcasecmp(v->name, "allow")) {
02398             const char* tcodecs = v->value;
02399             if (!strcasecmp(v->value, "all")) {
02400                tcodecs = "ulaw,alaw,g729,g723,gsm";
02401             }
02402             ast_format_cap_update_by_allow_disallow(user->cap,  tcodecs, 1);
02403          } else if (!strcasecmp(v->name, "amaflags")) {
02404             user->amaflags = ast_channel_string2amaflag(v->value);
02405                } else if (!strcasecmp(v->name, "ip") || !strcasecmp(v->name, "host")) {
02406             struct ast_sockaddr p;
02407             if (!ast_parse_arg(v->value, PARSE_ADDR, &p)) {
02408                ast_copy_string(user->mIP, ast_sockaddr_stringify_addr(&p), sizeof(user->mIP)-1);
02409             } else { 
02410                         ast_copy_string(user->mIP, v->value, sizeof(user->mIP)-1);
02411             }
02412                      user->mUseIP = 1;
02413          } else if (!strcasecmp(v->name, "dtmfmode")) {
02414             if (!strcasecmp(v->value, "rfc2833"))
02415                user->dtmfmode = H323_DTMF_RFC2833;
02416             if (!strcasecmp(v->value, "cisco"))
02417                user->dtmfmode = H323_DTMF_CISCO;
02418             else if (!strcasecmp(v->value, "q931keypad"))
02419                user->dtmfmode = H323_DTMF_Q931;
02420             else if (!strcasecmp(v->value, "h245alphanumeric"))
02421                user->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
02422             else if (!strcasecmp(v->value, "h245signal"))
02423                user->dtmfmode = H323_DTMF_H245SIGNAL;
02424             else if (!strcasecmp(v->value, "inband"))
02425                user->dtmfmode = H323_DTMF_INBAND;
02426          } else if (!strcasecmp(v->name, "relaxdtmf")) {
02427             user->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
02428          } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
02429             user->dtmfcodec = atoi(v->value);
02430          } else if (!strcasecmp(v->name, "faxdetect")) {
02431             if (ast_true(v->value)) {
02432                user->faxdetect = FAXDETECT_CNG | FAXDETECT_T38;
02433             } else if (ast_false(v->value)) {
02434                user->faxdetect = 0;
02435             } else {
02436                char *buf = ast_strdupa(v->value);
02437                char *word, *next = buf;
02438                user->faxdetect = 0;
02439                while ((word = strsep(&next, ","))) {
02440                   if (!strcasecmp(word, "cng")) {
02441                      user->faxdetect |= FAXDETECT_CNG;
02442                   } else if (!strcasecmp(word, "t38")) {
02443                      user->faxdetect |= FAXDETECT_T38;
02444                   } else {
02445                      ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno);
02446                   }
02447                }
02448 
02449             }
02450          } else if (!strcasecmp(v->name, "t38support")) {
02451             if (!strcasecmp(v->value, "disabled"))
02452                user->t38support = T38_DISABLED;
02453             if (!strcasecmp(v->value, "no"))
02454                user->t38support = T38_DISABLED;
02455             else if (!strcasecmp(v->value, "faxgw"))
02456                user->t38support = T38_FAXGW;
02457             else if (!strcasecmp(v->value, "yes"))
02458                user->t38support = T38_ENABLED;
02459          } else if (!strcasecmp(v->name, "aniasdni")) {
02460             user->aniasdni = ast_true(v->value);
02461          }
02462          v = v->next;
02463       }
02464    }
02465 
02466    if (gH323Debug)
02467       ast_verb(0, "+++   build_user\n");
02468 
02469    return user;
02470 }
02471 
02472 static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v, int friend_type)
02473 {
02474    struct ooh323_peer *peer = NULL;
02475 
02476    if (gH323Debug)
02477       ast_verb(0, "---   build_peer\n");
02478 
02479    peer = ast_calloc(1, sizeof(*peer));
02480    if (peer) {
02481       memset(peer, 0, sizeof(struct ooh323_peer));
02482       if (!(peer->cap = ast_format_cap_alloc(0))) {
02483          ast_free(peer);
02484          return NULL;
02485       }
02486       ast_mutex_init(&peer->lock);
02487       ast_copy_string(peer->name, name, sizeof(peer->name));
02488       ast_format_cap_append_from_cap(peer->cap, gCap, AST_MEDIA_TYPE_UNKNOWN);
02489       peer->rtptimeout = gRTPTimeout;
02490       peer->nat = gNat;
02491       ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode));
02492       peer->amaflags = gAMAFLAGS;
02493       peer->dtmfmode = gDTMFMode;
02494       peer->dtmfcodec = gDTMFCodec;
02495       peer->faxdetect = gFAXdetect;
02496       peer->t38support = gT38Support;
02497       peer->faststart = gFastStart;
02498       peer->h245tunneling = gTunneling;
02499       peer->directrtp = gDirectRTP;
02500       peer->earlydirect = gEarlyDirect;
02501       peer->g729onlyA = g729onlyA;
02502       peer->port = 1720;
02503       if (0 == friend_type) {
02504          peer->mFriend = 1;
02505       }
02506 
02507       while (v) {
02508          if (!strcasecmp(v->name, "h323id")) {
02509        if (!(peer->h323id = ast_strdup(v->value))) {
02510                ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
02511                                   "peer %s\n", name);
02512                ooh323_delete_peer(peer);
02513                return NULL;
02514             }
02515          } else if (!strcasecmp(v->name, "e164")) {
02516             int valid = 1;
02517             const char *tmp;
02518             for(tmp = v->value; *tmp; tmp++) {
02519                if (!isdigit(*tmp)) {
02520                   valid = 0;
02521                   break;
02522                }
02523             }
02524             if (valid) {
02525                if (!(peer->e164 = ast_strdup(v->value))) {
02526                   ast_log(LOG_ERROR, "Could not allocate memory for e164 of "
02527                                   "peer %s\n", name);
02528                   ooh323_delete_peer(peer);
02529                   return NULL;
02530                }
02531             } else {
02532                ast_log(LOG_ERROR, "Invalid e164: %s for peer %s\n", v->value, name);
02533             }
02534          } else  if (!strcasecmp(v->name, "email")) {
02535             if (!(peer->email = ast_strdup(v->value))) {
02536                ast_log(LOG_ERROR, "Could not allocate memory for email of "
02537                                   "peer %s\n", name);
02538                ooh323_delete_peer(peer);
02539                return NULL;
02540             }
02541          } else if (!strcasecmp(v->name, "url")) {
02542             if (!(peer->url = ast_strdup(v->value))) {
02543                ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
02544                                   "peer %s\n", name);
02545                ooh323_delete_peer(peer);
02546                return NULL;
02547             }
02548          } else if (!strcasecmp(v->name, "port")) {
02549             peer->port = atoi(v->value);
02550                } else if (!strcasecmp(v->name, "host") || !strcasecmp(v->name, "ip")) {
02551             struct ast_sockaddr p;
02552             if (!ast_parse_arg(v->value, PARSE_ADDR, &p)) {
02553                ast_copy_string(peer->ip, ast_sockaddr_stringify_host(&p), sizeof(peer->ip));
02554             } else { 
02555                         ast_copy_string(peer->ip, v->value, sizeof(peer->ip));
02556             }
02557          
02558          } else if (!strcasecmp(v->name, "outgoinglimit")) {
02559                      peer->outgoinglimit = atoi(v->value);
02560                      if (peer->outgoinglimit < 0)
02561                peer->outgoinglimit = 0;
02562          } else if (!strcasecmp(v->name, "accountcode")) {
02563             ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode));
02564          } else if (!strcasecmp(v->name, "faststart")) {
02565             peer->faststart = ast_true(v->value);
02566          } else if (!strcasecmp(v->name, "h245tunneling")) {
02567             peer->h245tunneling = ast_true(v->value);
02568          } else if (!strcasecmp(v->name, "directrtp") || !strcasecmp(v->name, "directmedia")) {
02569             peer->directrtp = ast_true(v->value);
02570             peer->earlydirect = ast_true(v->value);
02571          } else if (!strcasecmp(v->name, "earlydirect") || !strcasecmp(v->name, "directrtpsetup")) {
02572             peer->earlydirect = ast_true(v->value);
02573          } else if (!strcasecmp(v->name, "g729onlyA")) {
02574             peer->g729onlyA = ast_true(v->value);
02575          } else if (!strcasecmp(v->name, "nat")) {
02576             peer->nat = ast_true(v->value);
02577          } else if (!strcasecmp(v->name, "rtptimeout")) {
02578                      peer->rtptimeout = atoi(v->value);
02579                      if(peer->rtptimeout < 0)
02580                peer->rtptimeout = gRTPTimeout;
02581          } else if (!strcasecmp(v->name, "rtpmask")) {
02582             if ((peer->rtpmask = ast_calloc(1, sizeof(struct OOH323Regex))) &&
02583                (regcomp(&peer->rtpmask->regex, v->value, REG_EXTENDED) 
02584                                  == 0)) {
02585                ast_mutex_init(&peer->rtpmask->lock);
02586                peer->rtpmask->inuse = 1;
02587                ast_copy_string(peer->rtpmaskstr, v->value, 
02588                         sizeof(peer->rtpmaskstr));
02589             } else peer->rtpmask = NULL;
02590          } else if (!strcasecmp(v->name, "disallow")) {
02591             ast_format_cap_update_by_allow_disallow(peer->cap, v->value, 0);
02592          } else if (!strcasecmp(v->name, "allow")) {
02593             const char* tcodecs = v->value;
02594             if (!strcasecmp(v->value, "all")) {
02595                tcodecs = "ulaw,alaw,g729,g723,gsm";
02596             }
02597             ast_format_cap_update_by_allow_disallow(peer->cap, tcodecs, 1);
02598          } else if (!strcasecmp(v->name,  "amaflags")) {
02599             peer->amaflags = ast_channel_string2amaflag(v->value);
02600          } else if (!strcasecmp(v->name, "roundtrip")) {
02601             sscanf(v->value, "%d,%d", &peer->rtdrcount, &peer->rtdrinterval);
02602          } else if (!strcasecmp(v->name, "dtmfmode")) {
02603             if (!strcasecmp(v->value, "rfc2833"))
02604                peer->dtmfmode = H323_DTMF_RFC2833;
02605             if (!strcasecmp(v->value, "cisco"))
02606                peer->dtmfmode = H323_DTMF_CISCO;
02607             else if (!strcasecmp(v->value, "q931keypad"))
02608                peer->dtmfmode = H323_DTMF_Q931;
02609             else if (!strcasecmp(v->value, "h245alphanumeric"))
02610                peer->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
02611             else if (!strcasecmp(v->value, "h245signal"))
02612                peer->dtmfmode = H323_DTMF_H245SIGNAL;
02613             else if (!strcasecmp(v->value, "inband"))
02614                peer->dtmfmode = H323_DTMF_INBAND;
02615          } else if (!strcasecmp(v->name, "relaxdtmf")) {
02616             peer->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
02617          } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
02618             peer->dtmfcodec = atoi(v->value);
02619          } else if (!strcasecmp(v->name, "faxdetect")) {
02620             if (ast_true(v->value)) {
02621                peer->faxdetect = FAXDETECT_CNG | FAXDETECT_T38;
02622             } else if (ast_false(v->value)) {
02623                peer->faxdetect = 0;
02624             } else {
02625                char *buf = ast_strdupa(v->value);
02626                char *word, *next = buf;
02627                peer->faxdetect = 0;
02628                while ((word = strsep(&next, ","))) {
02629                   if (!strcasecmp(word, "cng")) {
02630                      peer->faxdetect |= FAXDETECT_CNG;
02631                   } else if (!strcasecmp(word, "t38")) {
02632                      peer->faxdetect |= FAXDETECT_T38;
02633                   } else {
02634                      ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno);
02635                   }
02636                }
02637 
02638             }
02639          } else if (!strcasecmp(v->name, "t38support")) {
02640             if (!strcasecmp(v->value, "disabled"))
02641                peer->t38support = T38_DISABLED;
02642             if (!strcasecmp(v->value, "no"))
02643                peer->t38support = T38_DISABLED;
02644             else if (!strcasecmp(v->value, "faxgw"))
02645                peer->t38support = T38_FAXGW;
02646             else if (!strcasecmp(v->value, "yes"))
02647                peer->t38support = T38_ENABLED;
02648          }
02649          v = v->next;
02650       }
02651    }
02652 
02653    if (gH323Debug)
02654       ast_verb(0, "+++   build_peer\n");
02655 
02656    return peer;
02657 }
02658 
02659 static int ooh323_do_reload(void)
02660 {
02661    struct ooAliases * pNewAlias = NULL;
02662    struct ooh323_peer *peer = NULL;
02663 
02664    if (gH323Debug) {
02665       ast_verb(0, "---   ooh323_do_reload\n");
02666    }
02667 
02668    /* Gatekeeper */
02669    if (gH323ep.gkClient) {
02670       ooGkClientDestroy();
02671    }
02672 
02673       reload_config(1);
02674 
02675    /* Gatekeeper */
02676    if (gRasGkMode == RasUseSpecificGatekeeper || 
02677       gRasGkMode == RasDiscoverGatekeeper) {
02678       ooGkClientInit(gRasGkMode, (gRasGkMode == RasUseSpecificGatekeeper) ? 
02679                         gGatekeeper : 0, 0);
02680       ooGkClientStart(gH323ep.gkClient);
02681    }
02682 
02683    /* Set aliases if any */
02684    if (gH323Debug) {
02685       ast_verb(0, "updating local aliases\n");
02686    }
02687 
02688    for (pNewAlias = gAliasList; pNewAlias; pNewAlias = pNewAlias->next) {
02689       switch (pNewAlias->type) {
02690       case T_H225AliasAddress_h323_ID:
02691          ooH323EpAddAliasH323ID(pNewAlias->value);
02692          break;
02693       case T_H225AliasAddress_dialedDigits:  
02694          ooH323EpAddAliasDialedDigits(pNewAlias->value);
02695          break;
02696       case T_H225AliasAddress_email_ID:   
02697          ooH323EpAddAliasEmailID(pNewAlias->value);
02698          break;
02699       default:
02700                   ;
02701       }
02702    }
02703 
02704    ast_mutex_lock(&peerl.lock);
02705    peer = peerl.peers;
02706    while (peer) {
02707       if(peer->h323id) {
02708          ooH323EpAddAliasH323ID(peer->h323id);
02709       }
02710       if(peer->email) {
02711          ooH323EpAddAliasEmailID(peer->email);
02712       }
02713       if(peer->e164) {
02714          ooH323EpAddAliasDialedDigits(peer->e164);
02715       }
02716             if(peer->url) {
02717          ooH323EpAddAliasURLID(peer->url);
02718       }
02719       peer = peer->next;
02720    }
02721    ast_mutex_unlock(&peerl.lock);
02722 
02723    if (gH323Debug) {
02724       ast_verb(0, "+++   ooh323_do_reload\n");
02725    }
02726 
02727    return 0;
02728 }
02729 
02730 /*--- h323_reload: Force reload of module from cli ---*/
02731 
02732 char *handle_cli_ooh323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02733 {
02734 
02735        switch (cmd) {
02736        case CLI_INIT:
02737                e->command = "ooh323 reload";
02738                e->usage =
02739                        "Usage: ooh323 reload\n"
02740                        "                Reload OOH323 config.\n";
02741                return NULL;
02742        case CLI_GENERATE:
02743                return NULL;
02744        }
02745 
02746        if (a->argc != 2)
02747                return CLI_SHOWUSAGE;
02748 
02749    if (gH323Debug)
02750       ast_verb(0, "---   ooh323_reload\n");
02751 
02752    ast_mutex_lock(&h323_reload_lock);
02753    if (h323_reloading) {
02754       ast_verb(0, "Previous OOH323 reload not yet done\n");
02755    } else {
02756       h323_reloading = 1;
02757    }
02758    ast_mutex_unlock(&h323_reload_lock);
02759    restart_monitor();
02760 
02761    if (gH323Debug)
02762       ast_verb(0, "+++   ooh323_reload\n");
02763 
02764    return 0;
02765 }
02766 
02767 int reload_config(int reload)
02768 {
02769    int format;
02770    struct ooAliases  *pNewAlias = NULL, *cur, *prev;
02771    struct ast_config *cfg;
02772    struct ast_variable *v;
02773    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02774    struct ooh323_user *user = NULL;
02775    struct ooh323_peer *peer = NULL;
02776    char *cat;
02777    const char *utype;
02778 
02779    if (gH323Debug)
02780       ast_verb(0, "---   reload_config\n");
02781 
02782    cfg = ast_config_load((char*)config, config_flags);
02783 
02784    /* We *must* have a config file otherwise stop immediately */
02785    if (!cfg) {
02786       ast_log(LOG_NOTICE, "Unable to load config %s, OOH323 disabled\n", config);
02787       return 1;
02788    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
02789       return RESULT_SUCCESS;
02790 
02791    if (reload) {
02792       delete_users();
02793       delete_peers();
02794       if (gH323Debug) {
02795          ast_verb(0, "  reload_config - Freeing up alias list\n");
02796       }
02797       cur = gAliasList;
02798       while (cur) {
02799          prev = cur;
02800          cur = cur->next;
02801          ast_free(prev->value);
02802          ast_free(prev);
02803       }
02804       gAliasList = NULL;
02805       ooH323EpClearAllAliases();
02806    }
02807 
02808    /* Inintialize everything to default */
02809    strcpy(gLogFile, DEFAULT_LOGFILE);
02810    gPort = 1720;
02811    gIP[0] = '\0';
02812    strcpy(gCallerID, DEFAULT_H323ID);
02813    ast_format_cap_remove_by_type(gCap, AST_MEDIA_TYPE_UNKNOWN);
02814    ast_format_cap_append(gCap, ast_format_ulaw, 0);
02815    gDTMFMode = H323_DTMF_RFC2833;
02816    gDTMFCodec = 101;
02817    gFAXdetect = FAXDETECT_CNG;
02818    gT38Support = T38_FAXGW;
02819    gTRCLVL = OOTRCLVLERR;
02820    gRasGkMode = RasNoGatekeeper;
02821    gGatekeeper[0] = '\0';
02822    gRTPTimeout = 60;
02823    gNat = FALSE;
02824    gRTDRInterval = 0;
02825    gRTDRCount = 0;
02826    strcpy(gAccountcode, DEFAULT_H323ACCNT);
02827    gFastStart = 1;
02828    gTunneling = 1;
02829    gTOS = 0;
02830    strcpy(gContext, DEFAULT_CONTEXT);
02831    gAliasList = NULL;
02832    gMediaWaitForConnect = 0;
02833    ooconfig.mTCPPortStart = 12030;
02834    ooconfig.mTCPPortEnd = 12230;
02835    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02836 
02837    v = ast_variable_browse(cfg, "general");
02838    while (v) {
02839 
02840       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
02841          v = v->next;
02842          continue;
02843       }
02844    
02845       if (!strcasecmp(v->name, "port")) {
02846          gPort = (int)strtol(v->value, NULL, 10);
02847       } else if (!strcasecmp(v->name, "bindaddr")) {
02848          ast_copy_string(gIP, v->value, sizeof(gIP));
02849          if (ast_parse_arg(v->value, PARSE_ADDR, &bindaddr)) {
02850             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
02851             ast_config_destroy(cfg);
02852             return 1;
02853          }
02854          if (ast_sockaddr_is_ipv6(&bindaddr)) {
02855             v6mode = 1;
02856          }
02857       } else if (!strcasecmp(v->name, "h225portrange")) {
02858          char* endlimit = 0;
02859                char temp[512];
02860          ast_copy_string(temp, v->value, sizeof(temp));
02861          endlimit = strchr(temp, ',');
02862          if (endlimit) {
02863             *endlimit = '\0';
02864             endlimit++;
02865             ooconfig.mTCPPortStart = atoi(temp);
02866             ooconfig.mTCPPortEnd = atoi(endlimit);
02867 
02868          } else {
02869             ast_log(LOG_ERROR, "h225portrange: Invalid format, separate port range with \",\"\n");
02870          }
02871       } else if (!strcasecmp(v->name, "gateway")) {
02872          gIsGateway = ast_true(v->value);
02873             } else if (!strcasecmp(v->name, "faststart")) {
02874          gFastStart = ast_true(v->value);
02875          if (gFastStart)
02876             ooH323EpEnableFastStart();
02877          else
02878             ooH323EpDisableFastStart();
02879       } else if (!strcasecmp(v->name, "mediawaitforconnect")) {
02880          gMediaWaitForConnect = ast_true(v->value);
02881          if (gMediaWaitForConnect)
02882             ooH323EpEnableMediaWaitForConnect();
02883          else 
02884             ooH323EpDisableMediaWaitForConnect();
02885       } else if (!strcasecmp(v->name, "h245tunneling")) {
02886          gTunneling = ast_true(v->value);
02887          if (gTunneling)
02888             ooH323EpEnableH245Tunneling();
02889          else
02890             ooH323EpDisableH245Tunneling();
02891       } else if (!strcasecmp(v->name, "directrtp") || !strcasecmp(v->name, "directmedia")) {
02892          gDirectRTP = ast_true(v->value);
02893          gEarlyDirect = ast_true(v->value);
02894       } else if (!strcasecmp(v->name, "earlydirect") || !strcasecmp(v->name, "directrtpsetup")) {
02895          gEarlyDirect = ast_true(v->value);
02896       } else if (!strcasecmp(v->name, "g729onlyA")) {
02897          g729onlyA = ast_true(v->value);
02898       } else if (!strcasecmp(v->name, "roundtrip")) {
02899          sscanf(v->value, "%d,%d", &gRTDRCount, &gRTDRInterval);
02900             } else if (!strcasecmp(v->name, "trybemaster")) {
02901          gBeMaster = ast_true(v->value);
02902          if (gBeMaster)
02903             ooH323EpTryBeMaster(1);
02904          else 
02905             ooH323EpTryBeMaster(0);
02906       } else if (!strcasecmp(v->name, "h323id")) {
02907                pNewAlias = ast_calloc(1, sizeof(struct ooAliases));
02908          if (!pNewAlias) {
02909             ast_log(LOG_ERROR, "Failed to allocate memory for h323id alias\n");
02910             ast_config_destroy(cfg);
02911             return 1;
02912          }
02913          if (gAliasList == NULL) { /* first h323id - set as callerid if callerid is not set */
02914             ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
02915          }
02916          pNewAlias->type =  T_H225AliasAddress_h323_ID;
02917          pNewAlias->value = ast_strdup(v->value);
02918          pNewAlias->next = gAliasList;
02919          gAliasList = pNewAlias;
02920          pNewAlias = NULL;
02921       } else if (!strcasecmp(v->name, "e164")) {
02922          int valid = 1;
02923          const char *tmp;
02924          for(tmp = v->value; *tmp; tmp++) {
02925             if (!isdigit(*tmp)) {
02926                valid = 0;
02927                break;
02928             }
02929          }
02930          if (valid) {
02931                   pNewAlias = ast_calloc(1, sizeof(struct ooAliases));
02932             if (!pNewAlias) {
02933                ast_log(LOG_ERROR, "Failed to allocate memory for e164 alias\n");
02934                ast_config_destroy(cfg);
02935                return 1;
02936             }
02937             pNewAlias->type =  T_H225AliasAddress_dialedDigits;
02938             pNewAlias->value = ast_strdup(v->value);
02939             pNewAlias->next = gAliasList;
02940             gAliasList = pNewAlias;
02941             pNewAlias = NULL;
02942          } else {
02943             ast_log(LOG_ERROR, "Invalid e164: %s\n", v->value);
02944          }
02945       } else if (!strcasecmp(v->name, "email")) {
02946                pNewAlias = ast_calloc(1, sizeof(struct ooAliases));
02947          if (!pNewAlias) {
02948             ast_log(LOG_ERROR, "Failed to allocate memory for email alias\n");
02949             ast_config_destroy(cfg);
02950             return 1;
02951          }
02952          pNewAlias->type =  T_H225AliasAddress_email_ID;
02953          pNewAlias->value = ast_strdup(v->value);
02954          pNewAlias->next = gAliasList;
02955          gAliasList = pNewAlias;
02956          pNewAlias = NULL;
02957       } else if (!strcasecmp(v->name, "t35country")) {
02958          t35countrycode = atoi(v->value);
02959       } else if (!strcasecmp(v->name, "t35extensions")) {
02960          t35extensions = atoi(v->value);
02961       } else if (!strcasecmp(v->name, "manufacturer")) {
02962          manufacturer = atoi(v->value);
02963       } else if (!strcasecmp(v->name, "vendorid")) {
02964          ast_copy_string(vendor, v->value, sizeof(vendor));
02965       } else if (!strcasecmp(v->name, "versionid")) {
02966          ast_copy_string(version, v->value, sizeof(version));
02967       } else if (!strcasecmp(v->name, "callerid")) {
02968          ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
02969       } else if (!strcasecmp(v->name, "incominglimit")) {
02970          gIncomingLimit = atoi(v->value);
02971       } else if (!strcasecmp(v->name, "outgoinglimit")) {
02972          gOutgoingLimit = atoi(v->value);
02973       } else if (!strcasecmp(v->name, "gatekeeper")) {
02974          if (!strcasecmp(v->value, "DISABLE")) {
02975             gRasGkMode = RasNoGatekeeper;
02976          } else if (!strcasecmp(v->value, "DISCOVER")) {
02977             gRasGkMode = RasDiscoverGatekeeper;
02978          } else {
02979             gRasGkMode = RasUseSpecificGatekeeper;
02980                      ast_copy_string(gGatekeeper, v->value, sizeof(gGatekeeper));
02981          }
02982       } else if (!strcasecmp(v->name, "logfile")) {
02983                ast_copy_string(gLogFile, v->value, sizeof(gLogFile));
02984       } else if (!strcasecmp(v->name, "context")) {
02985                ast_copy_string(gContext, v->value, sizeof(gContext));
02986                ast_verb(3, "  == Setting default context to %s\n", gContext);
02987       } else if (!strcasecmp(v->name, "nat")) {
02988          gNat = ast_true(v->value);
02989       } else if (!strcasecmp(v->name, "rtptimeout")) {
02990          gRTPTimeout = atoi(v->value);
02991          if (gRTPTimeout < 0)
02992             gRTPTimeout = 60;
02993       } else if (!strcasecmp(v->name, "tos")) {
02994          if (sscanf(v->value, "%30i", &format) == 1)
02995             gTOS = format & 0xff;
02996          else if (!strcasecmp(v->value, "lowdelay"))
02997             gTOS = IPTOS_LOWDELAY;
02998          else if (!strcasecmp(v->value, "throughput"))
02999             gTOS = IPTOS_THROUGHPUT;
03000          else if (!strcasecmp(v->value, "reliability"))
03001             gTOS = IPTOS_RELIABILITY;
03002          else if (!strcasecmp(v->value, "mincost"))
03003             gTOS = IPTOS_MINCOST;
03004          else if (!strcasecmp(v->value, "none"))
03005             gTOS = 0;
03006          else
03007             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be "
03008                                  "'lowdelay', 'throughput', 'reliability', "
03009                                  "'mincost', or 'none'\n", v->lineno);
03010       } else if (!strcasecmp(v->name, "amaflags")) {
03011          gAMAFLAGS = ast_channel_string2amaflag(v->value);
03012       } else if (!strcasecmp(v->name, "accountcode")) {
03013          ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode));
03014       } else if (!strcasecmp(v->name, "disallow")) {
03015          ast_format_cap_update_by_allow_disallow(gCap, v->value, 0);
03016       } else if (!strcasecmp(v->name, "allow")) {
03017          const char* tcodecs = v->value;
03018          if (!strcasecmp(v->value, "all")) {
03019             tcodecs = "ulaw,alaw,g729,g723,gsm";
03020          }
03021          ast_format_cap_update_by_allow_disallow(gCap, tcodecs, 1);
03022       } else if (!strcasecmp(v->name, "dtmfmode")) {
03023          if (!strcasecmp(v->value, "inband"))
03024             gDTMFMode = H323_DTMF_INBAND;
03025          else if (!strcasecmp(v->value, "rfc2833"))
03026             gDTMFMode = H323_DTMF_RFC2833;
03027          else if (!strcasecmp(v->value, "cisco"))
03028             gDTMFMode = H323_DTMF_CISCO;
03029          else if (!strcasecmp(v->value, "q931keypad"))
03030             gDTMFMode = H323_DTMF_Q931;
03031          else if (!strcasecmp(v->value, "h245alphanumeric"))
03032             gDTMFMode = H323_DTMF_H245ALPHANUMERIC;
03033          else if (!strcasecmp(v->value, "h245signal"))
03034             gDTMFMode = H323_DTMF_H245SIGNAL;
03035          else {
03036             ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", 
03037                                                                     v->value);
03038             gDTMFMode = H323_DTMF_RFC2833;
03039          }
03040       } else if (!strcasecmp(v->name, "relaxdtmf")) {
03041          gDTMFMode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
03042       } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
03043          gDTMFCodec = atoi(v->value);
03044       } else if (!strcasecmp(v->name, "faxdetect")) {
03045          if (ast_true(v->value)) {
03046             gFAXdetect = FAXDETECT_CNG | FAXDETECT_T38;
03047          } else if (ast_false(v->value)) {
03048             gFAXdetect = 0;
03049          } else {
03050             char *buf = ast_strdupa(v->value);
03051             char *word, *next = buf;
03052             gFAXdetect = 0;
03053             while ((word = strsep(&next, ","))) {
03054                if (!strcasecmp(word, "cng")) {
03055                   gFAXdetect |= FAXDETECT_CNG;
03056                } else if (!strcasecmp(word, "t38")) {
03057                   gFAXdetect |= FAXDETECT_T38;
03058                } else {
03059                   ast_log(LOG_WARNING, "Unknown faxdetect mode '%s' on line %d.\n", word, v->lineno);
03060                }
03061             }
03062 
03063          }
03064       } else if (!strcasecmp(v->name, "t38support")) {
03065          if (!strcasecmp(v->value, "disabled"))
03066             gT38Support = T38_DISABLED;
03067          if (!strcasecmp(v->value, "no"))
03068             gT38Support = T38_DISABLED;
03069          else if (!strcasecmp(v->value, "faxgw"))
03070             gT38Support = T38_FAXGW;
03071          else if (!strcasecmp(v->value, "yes"))
03072             gT38Support = T38_ENABLED;
03073       } else if (!strcasecmp(v->name, "tracelevel")) {
03074          gTRCLVL = atoi(v->value);
03075          ooH323EpSetTraceLevel(gTRCLVL);
03076       } else if (!strcasecmp(v->name, "aniasdni")) {
03077          gANIasDNI = ast_true(v->value);
03078       }
03079       v = v->next;
03080    }
03081    
03082    for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
03083       if (strcasecmp(cat, "general")) {
03084          int friend_type = 0;
03085          utype = ast_variable_retrieve(cfg, cat, "type");
03086          if (utype) {
03087             friend_type = strcasecmp(utype, "friend");
03088             if (!strcmp(utype, "user") || 0 == friend_type) {
03089                user = build_user(cat, ast_variable_browse(cfg, cat));
03090                if (user) {
03091                   ast_mutex_lock(&userl.lock);
03092                   user->next = userl.users;
03093                   userl.users = user;
03094                   ast_mutex_unlock(&userl.lock);
03095                } else {
03096                   ast_log(LOG_WARNING, "Failed to build user %s\n", cat);
03097                }
03098             }
03099             if (!strcasecmp(utype, "peer") || 0 == friend_type) {
03100                peer = build_peer(cat, ast_variable_browse(cfg, cat), friend_type);
03101                if (peer) {
03102                   ast_mutex_lock(&peerl.lock);
03103                   peer->next = peerl.peers;
03104                   peerl.peers = peer;
03105                   ast_mutex_unlock(&peerl.lock);
03106                } else {
03107                   ast_log(LOG_WARNING, "Failed to build peer %s\n", cat);
03108                }
03109             }
03110          }
03111       }
03112    }
03113    ast_config_destroy(cfg);
03114 
03115 
03116    /* Determine ip address if neccessary */
03117    if (ast_strlen_zero(gIP)) {
03118       ooGetLocalIPAddress(gIP);
03119       if (!strcmp(gIP, "127.0.0.1") || !strcmp(gIP, "::1")) {
03120          ast_log(LOG_NOTICE, "Failed to determine local ip address. Please "
03121                             "specify it in ooh323.conf. OOH323 Disabled\n");
03122          return 1;
03123       }
03124    }
03125 
03126    if (gH323Debug)
03127       ast_verb(0, "+++   reload_config\n");
03128 
03129    return 0;
03130 
03131 }
03132 
03133 
03134 static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03135 {
03136    char ip_port[30];
03137    struct ooh323_peer *prev = NULL, *peer = NULL;
03138    
03139    switch (cmd) {
03140    case CLI_INIT:
03141       e->command = "ooh323 show peer";
03142       e->usage =
03143          "Usage: ooh323 show peer <name>\n"
03144          "      List details of specific OOH323 peer.\n";
03145       return NULL;
03146    case CLI_GENERATE:
03147       return NULL;
03148    }
03149 
03150    if (a->argc != 4)
03151       return CLI_SHOWUSAGE;
03152 
03153    ast_mutex_lock(&peerl.lock);
03154    peer = peerl.peers;
03155    while (peer) {
03156       ast_mutex_lock(&peer->lock);
03157       if (!strcmp(peer->name, a->argv[3])) {
03158          break;
03159       } else {
03160          prev = peer;
03161          peer = peer->next;
03162          ast_mutex_unlock(&prev->lock);
03163       }
03164    }
03165 
03166    if (peer) {
03167       sprintf(ip_port, "%s:%d", peer->ip, peer->port);
03168       ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name);
03169       ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", peer->faststart?"yes":"no",
03170                peer->h245tunneling?"yes":"no");
03171       ast_cli(a->fd, "%-15s%s\n", "DirectRTP", peer->directrtp ? "yes" : "no");
03172       ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", peer->earlydirect ? "yes" : "no");
03173       ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
03174       if (peer->dtmfmode & H323_DTMF_CISCO) {
03175          ast_cli(a->fd, "%s\n", "cisco");
03176          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec);
03177       } else if (peer->dtmfmode & H323_DTMF_RFC2833) {
03178          ast_cli(a->fd, "%s\n", "rfc2833");
03179          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec);
03180       } else if (peer->dtmfmode & H323_DTMF_Q931) {
03181          ast_cli(a->fd, "%s\n", "q931keypad");
03182       } else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC) {
03183          ast_cli(a->fd, "%s\n", "h245alphanumeric");
03184       } else if (peer->dtmfmode & H323_DTMF_H245SIGNAL) {
03185          ast_cli(a->fd, "%s\n", "h245signal");
03186       } else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX) {
03187          ast_cli(a->fd, "%s\n", "inband-relaxed");
03188       } else if (peer->dtmfmode & H323_DTMF_INBAND) {
03189          ast_cli(a->fd, "%s\n", "inband");
03190       } else {
03191          ast_cli(a->fd, "%s\n", "unknown");
03192       }
03193       ast_cli(a->fd,"%-15s", "T.38 Mode: ");
03194       if (peer->t38support == T38_DISABLED) {
03195          ast_cli(a->fd, "%s\n", "disabled");
03196       } else if (peer->t38support == T38_FAXGW) {
03197          ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
03198       }
03199       if (peer->faxdetect == (FAXDETECT_CNG | FAXDETECT_T38)) {
03200          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes");
03201       } else if (peer->faxdetect & FAXDETECT_CNG) {
03202          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng");
03203       } else if (peer->faxdetect & FAXDETECT_T38) {
03204          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38");
03205       } else {
03206          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No");
03207       }
03208 
03209       ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode);
03210       ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_channel_amaflags2string(peer->amaflags));
03211       ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port);
03212       ast_cli(a->fd, "%-15.15s%u\n", "OutgoingLimit: ", peer->outgoinglimit);
03213       ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout);
03214       ast_cli(a->fd, "%-15.15s%s\n", "nat: ", peer->nat?"yes":"no");
03215       if (peer->rtpmaskstr[0]) {
03216          ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr);
03217       }
03218       if (peer->rtdrcount && peer->rtdrinterval) {
03219          ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", peer->rtdrcount, peer->rtdrinterval);
03220       }
03221       ast_mutex_unlock(&peer->lock);
03222    } else {
03223       ast_cli(a->fd, "Peer %s not found\n", a->argv[3]);
03224       ast_cli(a->fd, "\n");
03225    }
03226    ast_mutex_unlock(&peerl.lock);
03227 
03228    return CLI_SUCCESS;
03229 }
03230 
03231 static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03232 {
03233    struct ooh323_peer *prev = NULL, *peer = NULL;
03234    struct ast_str *codec_buf = ast_str_alloca(64);
03235    char ip_port[30];
03236 #define FORMAT  "%-15.15s  %-15.15s  %-23.23s  %-s\n"
03237 
03238    switch (cmd) {
03239    case CLI_INIT:
03240       e->command = "ooh323 show peers";
03241       e->usage =
03242          "Usage: ooh323 show peers\n"
03243          "      Lists all known OOH323 peers.\n";
03244       return NULL;
03245    case CLI_GENERATE:
03246       return NULL;
03247    }
03248 
03249    if (a->argc != 3)
03250       return CLI_SHOWUSAGE;
03251 
03252    ast_cli(a->fd, FORMAT, "Name", "Accountcode", "ip:port", "Formats");
03253 
03254    ast_mutex_lock(&peerl.lock);
03255    peer = peerl.peers;
03256    while (peer) {
03257       ast_mutex_lock(&peer->lock);
03258       snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
03259       ast_cli(a->fd, FORMAT, peer->name, 
03260                peer->accountcode,
03261                ip_port,
03262                ast_format_cap_get_names(peer->cap, &codec_buf));
03263       prev = peer;
03264       peer = peer->next;
03265       ast_mutex_unlock(&prev->lock);
03266 
03267    }
03268    ast_mutex_unlock(&peerl.lock);
03269 #undef FORMAT
03270    return CLI_SUCCESS;
03271 }
03272 
03273 static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03274 {
03275    struct ooh323_user *prev = NULL, *user = NULL;
03276 
03277    switch (cmd) {
03278    case CLI_INIT:
03279       e->command = "ooh323 show user";
03280       e->usage =
03281          "Usage: ooh323 show user <name>\n"
03282          "      List details of specific OOH323 user.\n";
03283       return NULL;
03284    case CLI_GENERATE:
03285       return NULL;
03286    }
03287 
03288    if (a->argc != 4)
03289       return CLI_SHOWUSAGE;
03290 
03291 
03292    ast_mutex_lock(&userl.lock);
03293    user = userl.users;
03294    while (user) {
03295       ast_mutex_lock(&user->lock);
03296       if (!strcmp(user->name, a->argv[3])) {
03297          break;
03298       } else {
03299          prev = user;
03300          user = user->next;
03301          ast_mutex_unlock(&prev->lock);
03302       }
03303    }
03304 
03305    if (user) {
03306       ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name);
03307       ast_cli(a->fd, "%s:%s,%s\n", "FastStart/H.245 Tunneling", user->faststart?"yes":"no",
03308                user->h245tunneling?"yes":"no");
03309       ast_cli(a->fd, "%-15s%s\n", "DirectRTP", user->directrtp ? "yes" : "no");
03310       ast_cli(a->fd, "%-15s%s\n", "EarlyDirectRTP", user->earlydirect ? "yes" : "no");
03311       ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
03312       if (user->dtmfmode & H323_DTMF_CISCO) {
03313          ast_cli(a->fd, "%s\n", "cisco");
03314          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec);
03315       } else if (user->dtmfmode & H323_DTMF_RFC2833) {
03316          ast_cli(a->fd, "%s\n", "rfc2833");
03317          ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec);
03318       } else if (user->dtmfmode & H323_DTMF_Q931) {
03319          ast_cli(a->fd, "%s\n", "q931keypad");
03320       } else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC) {
03321          ast_cli(a->fd, "%s\n", "h245alphanumeric");
03322       } else if (user->dtmfmode & H323_DTMF_H245SIGNAL) {
03323          ast_cli(a->fd, "%s\n", "h245signal");
03324       } else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX) {
03325          ast_cli(a->fd, "%s\n", "inband-relaxed");
03326       } else if (user->dtmfmode & H323_DTMF_INBAND) {
03327          ast_cli(a->fd, "%s\n", "inband");
03328       } else {
03329          ast_cli(a->fd, "%s\n", "unknown");
03330       }
03331       ast_cli(a->fd,"%-15s", "T.38 Mode: ");
03332       if (user->t38support == T38_DISABLED) {
03333          ast_cli(a->fd, "%s\n", "disabled");
03334       } else if (user->t38support == T38_FAXGW) {
03335          ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
03336       }
03337       if (user->faxdetect == (FAXDETECT_CNG | FAXDETECT_T38)) {
03338          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes");
03339       } else if (user->faxdetect & FAXDETECT_CNG) {
03340          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng");
03341       } else if (user->faxdetect & FAXDETECT_T38) {
03342          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38");
03343       } else {
03344          ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No");
03345       }
03346 
03347       ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode);
03348       ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_channel_amaflags2string(user->amaflags));
03349       ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context);
03350       ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit);
03351       ast_cli(a->fd, "%-15.15s%u\n", "InUse: ", user->inUse);
03352       ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout);
03353       ast_cli(a->fd, "%-15.15s%s\n", "nat: ", user->nat?"yes":"no");
03354       if (user->rtpmaskstr[0]) {
03355          ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr);
03356       }
03357       ast_mutex_unlock(&user->lock);
03358       if (user->rtdrcount && user->rtdrinterval) {
03359          ast_cli(a->fd, "%-15.15s%d,%d\n", "RoundTrip: ", user->rtdrcount, user->rtdrinterval);
03360       }
03361    } else {
03362       ast_cli(a->fd, "User %s not found\n", a->argv[3]);
03363       ast_cli(a->fd, "\n");
03364    }
03365    ast_mutex_unlock(&userl.lock);
03366 
03367    return CLI_SUCCESS;
03368 }
03369 
03370 static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03371 {
03372    struct ooh323_user *prev = NULL, *user = NULL;
03373    struct ast_str *codec_buf = ast_str_alloca(64);
03374 #define FORMAT1  "%-15.15s  %-15.15s  %-15.15s  %-s\n"
03375 
03376    switch (cmd) {
03377    case CLI_INIT:
03378       e->command = "ooh323 show users";
03379       e->usage =
03380          "Usage: ooh323 show users \n"
03381          "      Lists all known OOH323 users.\n";
03382       return NULL;
03383    case CLI_GENERATE:
03384       return NULL;
03385    }
03386 
03387    if (a->argc != 3)
03388       return CLI_SHOWUSAGE;
03389 
03390 
03391    ast_cli(a->fd, FORMAT1, "Username", "Accountcode", "Context", "Formats");
03392 
03393    ast_mutex_lock(&userl.lock);
03394    user = userl.users;
03395    while(user)
03396    {
03397       ast_mutex_lock(&user->lock);
03398          ast_cli(a->fd, FORMAT1, user->name, 
03399                user->accountcode, user->context,
03400                ast_format_cap_get_names(user->cap, &codec_buf));
03401       prev = user;
03402       user = user->next;
03403       ast_mutex_unlock(&prev->lock);
03404 
03405    }
03406    ast_mutex_unlock(&userl.lock);
03407 #undef FORMAT1
03408    return RESULT_SUCCESS;
03409 
03410 }
03411 
03412 static char *handle_cli_ooh323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03413 {
03414    switch (cmd) {
03415    case CLI_INIT:
03416       e->command = "ooh323 set debug [off]";
03417       e->usage =
03418          "Usage: ooh323 set debug [off]\n"
03419          "      Enables/Disables debugging of OOH323 channel driver\n";
03420       return NULL;
03421    case CLI_GENERATE:
03422       return NULL;
03423    }
03424 
03425    if (a->argc < 3 || a->argc > 4)
03426       return CLI_SHOWUSAGE;
03427    if (a->argc == 4 && strcasecmp(a->argv[3], "off"))
03428       return CLI_SHOWUSAGE;
03429 
03430    gH323Debug = (a->argc == 4) ? FALSE : TRUE;
03431    ast_cli(a->fd, "OOH323 Debugging %s\n", gH323Debug ? "Enabled" : "Disabled");
03432 
03433    return CLI_SUCCESS;
03434 }
03435 
03436 #if 0
03437 static int ooh323_show_channels(int fd, int argc, char *argv[])
03438 {
03439    return RESULT_SUCCESS;
03440 }
03441 #endif
03442 
03443 static char *handle_cli_ooh323_show_gk(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03444 {
03445    char value[FORMAT_STRING_SIZE];
03446 
03447    switch (cmd) {
03448    case CLI_INIT:
03449       e->command = "ooh323 show gk";
03450       e->usage =
03451          "Usage: ooh323 show gk\n"
03452          "      Shows Gatekeeper connection state\n";
03453       return NULL;
03454    case CLI_GENERATE:
03455       return NULL;
03456    }
03457 
03458    if (a->argc != 3)
03459       return CLI_SHOWUSAGE;
03460 
03461    ast_cli(a->fd, "\nGateKeeper connection state:\n");
03462    if (!gH323ep.gkClient) {
03463       ast_cli(a->fd, "No Gatekeeper is configured\n");
03464       return CLI_SUCCESS;
03465    }
03466 
03467    if (gRasGkMode == RasNoGatekeeper) {
03468       snprintf(value, sizeof(value), "%s", "No Gatekeeper");
03469    } else if (gRasGkMode == RasDiscoverGatekeeper) {
03470       snprintf(value, sizeof(value), "%s", "Discover");
03471    } else {
03472       snprintf(value, sizeof(value), "%s", gGatekeeper);
03473    }
03474    ast_cli(a->fd,  "%-20s%s\n", "Gatekeeper:", value);
03475    switch(gH323ep.gkClient->state) {
03476    case GkClientIdle:
03477       ast_cli(a->fd, "%-20s%s\n", "GK state:", "Idle");
03478       break;
03479    case GkClientDiscovered:
03480       ast_cli(a->fd, "%-20s%s\n", "GK state:", "Discovered");
03481       break;
03482    case GkClientRegistered:
03483       ast_cli(a->fd, "%-20s%s\n", "GK state:", "Registered");
03484       break;
03485    case GkClientUnregistered:
03486       ast_cli(a->fd, "%-20s%s\n", "GK state:", "Unregistered");
03487       break;
03488    case GkClientGkErr:
03489       ast_cli(a->fd, "%-20s%s\n", "GK state:", "Error");
03490       break;
03491    case GkClientFailed:
03492       ast_cli(a->fd, "%-20s%s\n", "GK state:", "Failed");
03493       break;
03494    case GkClientStopped:
03495       ast_cli(a->fd, "%-20s%s\n", "GK state:", "Shutdown");
03496       break;
03497    default:
03498       break;
03499    }
03500 
03501    return CLI_SUCCESS;
03502 }
03503 
03504 static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03505 {
03506    char value[FORMAT_STRING_SIZE];
03507    struct ast_str *codec_buf = ast_str_alloca(64);
03508    ooAliases *pAlias = NULL, *pAliasNext = NULL;;
03509 
03510    switch (cmd) {
03511    case CLI_INIT:
03512       e->command = "ooh323 show config";
03513       e->usage =
03514          "Usage: ooh323 show config\n"
03515          "      Shows global configuration of H.323 channel driver\n";
03516       return NULL;
03517    case CLI_GENERATE:
03518       return NULL;
03519    }
03520 
03521    if (a->argc != 3)
03522       return CLI_SHOWUSAGE;
03523 
03524    ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n");
03525    snprintf(value, sizeof(value), "%s:%d", gIP, gPort);
03526    ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value);
03527    ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ", ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd);
03528    ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no");
03529    ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no");
03530    ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID);
03531    ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect?"yes":"no");
03532    ast_cli(a->fd, "%-20s%s\n", "DirectRTP", gDirectRTP ? "yes" : "no");
03533    ast_cli(a->fd, "%-20s%s\n", "EarlyDirectRTP", gEarlyDirect ? "yes" : "no");
03534 
03535 #if (0)
03536       extern OOH323EndPoint gH323ep;
03537    ast_cli(a->fd, "%-20s%s\n", "FASTSTART",
03538       (OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no");
03539    ast_cli(a->fd, "%-20s%s\n", "TUNNELING",
03540       (OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no");
03541    ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN",
03542       (OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no");
03543 #endif
03544 
03545    if (gRasGkMode == RasNoGatekeeper) {
03546       snprintf(value, sizeof(value), "%s", "No Gatekeeper");
03547    } else if (gRasGkMode == RasDiscoverGatekeeper) {
03548       snprintf(value, sizeof(value), "%s", "Discover");
03549    } else {
03550       snprintf(value, sizeof(value), "%s", gGatekeeper);
03551    }
03552    ast_cli(a->fd,  "%-20s%s\n", "Gatekeeper:", value);
03553    ast_cli(a->fd,  "%-20s%s\n", "H.323 LogFile:", gLogFile);
03554    ast_cli(a->fd,  "%-20s%s\n", "Context:", gContext);
03555    ast_cli(a->fd,  "%-20s%s\n", "Capability:",
03556       ast_format_cap_get_names(gCap, &codec_buf));
03557    ast_cli(a->fd, "%-20s", "DTMF Mode: ");
03558    if (gDTMFMode & H323_DTMF_CISCO) {
03559       ast_cli(a->fd, "%s\n", "cisco");
03560       ast_cli(a->fd, "%-20.15s%d\n", "DTMF Codec: ", gDTMFCodec);
03561    } else if (gDTMFMode & H323_DTMF_RFC2833) {
03562       ast_cli(a->fd, "%s\n", "rfc2833");
03563       ast_cli(a->fd, "%-20.15s%d\n", "DTMF Codec: ", gDTMFCodec);
03564    } else if (gDTMFMode & H323_DTMF_Q931) {
03565       ast_cli(a->fd, "%s\n", "q931keypad");
03566    } else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC) {
03567       ast_cli(a->fd, "%s\n", "h245alphanumeric");
03568    } else if (gDTMFMode & H323_DTMF_H245SIGNAL) {
03569       ast_cli(a->fd, "%s\n", "h245signal");
03570    } else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX) {
03571       ast_cli(a->fd, "%s\n", "inband-relaxed");
03572    } else if (gDTMFMode & H323_DTMF_INBAND) {
03573       ast_cli(a->fd, "%s\n", "inband");
03574    } else {
03575       ast_cli(a->fd, "%s\n", "unknown");
03576    }
03577 
03578    ast_cli(a->fd,"%-20s", "T.38 Mode: ");
03579    if (gT38Support == T38_DISABLED) {
03580       ast_cli(a->fd, "%s\n", "disabled");
03581    } else if (gT38Support == T38_FAXGW) {
03582       ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
03583    }
03584    if (gFAXdetect == (FAXDETECT_CNG | FAXDETECT_T38)) {
03585       ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Yes");
03586    } else if (gFAXdetect & FAXDETECT_CNG) {
03587       ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "Cng");
03588    } else if (gFAXdetect & FAXDETECT_T38) {
03589       ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "T.38");
03590    } else {
03591       ast_cli(a->fd,"%-20s%s\n", "FAX Detect:", "No");
03592    }
03593 
03594    if (gRTDRCount && gRTDRInterval) {
03595       ast_cli(a->fd, "%-20.15s%d,%d\n", "RoundTrip: ", gRTDRCount, gRTDRInterval);
03596    }
03597 
03598    ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber);
03599    ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode);
03600    ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_channel_amaflags2string(gAMAFLAGS));
03601 
03602    pAlias = gAliasList;
03603    if(pAlias) {
03604       ast_cli(a->fd, "%-20s\n", "Aliases: ");
03605    }
03606    while (pAlias) {
03607       pAliasNext = pAlias->next;
03608       if (pAliasNext) {
03609          ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value);
03610          pAlias = pAliasNext->next;
03611       } else {
03612          ast_cli(a->fd,"\t%-30s\n",pAlias->value);
03613          pAlias = pAlias->next;
03614       }
03615    }
03616    return CLI_SUCCESS;
03617 }
03618 
03619 static struct ast_cli_entry cli_ooh323[] = {
03620    AST_CLI_DEFINE(handle_cli_ooh323_set_debug,  "Enable/Disable OOH323 debugging"),
03621    AST_CLI_DEFINE(handle_cli_ooh323_show_config, "Show details on global configuration of H.323 channel driver"),
03622    AST_CLI_DEFINE(handle_cli_ooh323_show_gk, "Show OOH323 Gatekeeper connection status"),
03623    AST_CLI_DEFINE(handle_cli_ooh323_show_peer,  "Show details on specific OOH323 peer"),
03624    AST_CLI_DEFINE(handle_cli_ooh323_show_peers,  "Show defined OOH323 peers"),
03625    AST_CLI_DEFINE(handle_cli_ooh323_show_user,  "Show details on specific OOH323 user"),
03626    AST_CLI_DEFINE(handle_cli_ooh323_show_users,  "Show defined OOH323 users"),
03627         AST_CLI_DEFINE(handle_cli_ooh323_reload, "reload ooh323 config")
03628 };
03629 
03630 /*! \brief OOH323 Dialplan function - reads ooh323 settings */
03631 static int function_ooh323_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
03632 {
03633    struct ooh323_pvt *p = ast_channel_tech_pvt(chan);
03634 
03635    ast_channel_lock(chan);
03636    if (!p) {
03637       ast_channel_unlock(chan);
03638       return -1;
03639    }
03640 
03641    if (strcmp(ast_channel_tech(chan)->type, "OOH323")) {
03642       ast_log(LOG_ERROR, "This function is only supported on OOH323 channels, Channel is %s\n", ast_channel_tech(chan)->type);
03643       ast_channel_unlock(chan);
03644       return -1;
03645    }
03646 
03647    ast_mutex_lock(&p->lock);
03648    if (!strcasecmp(data, "faxdetect")) {
03649       ast_copy_string(buf, p->faxdetect ? "1" : "0", len);
03650    } else if (!strcasecmp(data, "t38support")) {
03651       ast_copy_string(buf, p->t38support ? "1" : "0", len);
03652    } else if (!strcasecmp(data, "caller_h323id")) {
03653       ast_copy_string(buf, p->caller_h323id, len);
03654    } else if (!strcasecmp(data, "caller_dialeddigits")) {
03655       ast_copy_string(buf, p->caller_dialedDigits, len);
03656    } else if (!strcasecmp(data, "caller_email")) {
03657       ast_copy_string(buf, p->caller_email, len);
03658    } else if (!strcasecmp(data, "h323id_url")) {
03659       ast_copy_string(buf, p->caller_url, len);
03660    } else if (!strcasecmp(data, "callee_h323id")) {
03661       ast_copy_string(buf, p->callee_h323id, len);
03662    } else if (!strcasecmp(data, "callee_dialeddigits")) {
03663       ast_copy_string(buf, p->callee_dialedDigits, len);
03664    } else if (!strcasecmp(data, "callee_email")) {
03665       ast_copy_string(buf, p->callee_email, len);
03666    } else if (!strcasecmp(data, "callee_url")) {
03667       ast_copy_string(buf, p->callee_url, len);
03668    }
03669    ast_mutex_unlock(&p->lock);
03670 
03671    ast_channel_unlock(chan);
03672    return 0;
03673 }
03674 
03675 /*! \brief OOH323 Dialplan function - writes ooh323 settings */
03676 static int function_ooh323_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
03677 {
03678    struct ooh323_pvt *p = ast_channel_tech_pvt(chan);
03679    int res = -1;
03680 
03681    ast_channel_lock(chan);
03682    if (!p) {
03683       ast_channel_unlock(chan);
03684       return -1;
03685    }
03686 
03687    if (strcmp(ast_channel_tech(chan)->type, "OOH323")) {
03688       ast_log(LOG_ERROR, "This function is only supported on OOH323 channels, Channel is %s\n", ast_channel_tech(chan)->type);
03689       ast_channel_unlock(chan);
03690       return -1;
03691    }
03692 
03693    ast_mutex_lock(&p->lock);
03694    if (!strcasecmp(data, "faxdetect")) {
03695       if (ast_true(value)) {
03696          p->faxdetect = 1;
03697          res = 0;
03698       } else if (ast_false(value)) {
03699          p->faxdetect = 0;
03700          res = 0;
03701       } else {
03702          char *buf = ast_strdupa(value);
03703          char *word, *next = buf;
03704          p->faxdetect = 0;
03705          res = 0;
03706          while ((word = strsep(&next, ","))) {
03707             if (!strcasecmp(word, "cng")) {
03708                p->faxdetect |= FAXDETECT_CNG;
03709             } else if (!strcasecmp(word, "t38")) {
03710                p->faxdetect |= FAXDETECT_T38;
03711             } else {
03712                ast_log(LOG_WARNING, "Unknown faxdetect mode '%s'.\n", word);
03713                res = -1;
03714             }
03715          }
03716 
03717       }
03718    } else if (!strcasecmp(data, "t38support")) {
03719       if (ast_true(value)) {
03720          p->t38support = 1;
03721          res = 0;
03722       } else {
03723          p->t38support = 0;
03724          res = 0;
03725       }
03726    }
03727    ast_mutex_unlock(&p->lock);
03728    ast_channel_unlock(chan);
03729 
03730    return res;
03731 }
03732 
03733 static int load_module(void)
03734 {
03735    struct ooAliases * pNewAlias = NULL;
03736    struct ooh323_peer *peer = NULL;
03737    OOH225MsgCallbacks h225Callbacks = {0, 0, 0, 0};
03738 
03739    OOH323CALLBACKS h323Callbacks = {
03740       .onNewCallCreated = onNewCallCreated,
03741       .onAlerting = onAlerting,
03742       .onProgress = onProgress,
03743       .onIncomingCall = NULL,
03744       .onOutgoingCall = onOutgoingCall,
03745       .onCallEstablished = onCallEstablished,
03746       .onCallCleared = onCallCleared,
03747       .openLogicalChannels = NULL,
03748       .onReceivedDTMF = ooh323_onReceivedDigit,
03749       .onModeChanged = onModeChanged,
03750       .onMediaChanged = (cb_OnMediaChanged) setup_rtp_remote,
03751    };
03752    if (!(gCap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
03753       return AST_MODULE_LOAD_DECLINE; 
03754    }
03755    if (!(ooh323_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
03756       ao2_ref(gCap, -1);
03757       gCap = NULL;
03758       return AST_MODULE_LOAD_DECLINE;
03759    }
03760    ast_format_cap_append(gCap, ast_format_ulaw, 0);
03761    ast_format_cap_append_by_type(ooh323_tech.capabilities, AST_MEDIA_TYPE_UNKNOWN);
03762 
03763    myself = ast_module_info->self;
03764 
03765    h225Callbacks.onReceivedSetup = &ooh323_onReceivedSetup;
03766 
03767    userl.users = NULL;
03768    ast_mutex_init(&userl.lock);
03769    peerl.peers = NULL;
03770    ast_mutex_init(&peerl.lock);
03771  
03772 #if 0    
03773    ast_register_atexit(&ast_ooh323c_exit);
03774 #endif
03775 
03776    if (!(sched = ast_sched_context_create())) {
03777       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03778    }
03779    if (!(io = io_context_create())) {
03780       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03781    }
03782 
03783 
03784    if (!reload_config(0)) {
03785 
03786       /* fire up the H.323 Endpoint */     
03787       if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) {
03788                ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-"
03789                             "OOH323 Disabled\n");
03790          ao2_ref(gCap, -1);
03791          gCap = NULL;
03792          ao2_ref(ooh323_tech.capabilities, -1);
03793          ooh323_tech.capabilities = NULL;
03794          return AST_MODULE_LOAD_DECLINE;
03795       }
03796 
03797       /* Make sure we can register our OOH323 channel type */
03798       if (ast_channel_register(&ooh323_tech)) {
03799          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
03800          ao2_ref(gCap, -1);
03801          gCap = NULL;
03802          ao2_ref(ooh323_tech.capabilities, -1);
03803          ooh323_tech.capabilities = NULL;
03804          return AST_MODULE_LOAD_DECLINE;
03805       }
03806       ast_rtp_glue_register(&ooh323_rtp);
03807       ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
03808 
03809       if (gIsGateway)
03810          ooH323EpSetAsGateway();
03811 
03812             ooH323EpSetVersionInfo(t35countrycode, t35extensions, manufacturer,
03813                             vendor, version);
03814       ooH323EpDisableAutoAnswer();
03815       ooH323EpSetH225MsgCallbacks(h225Callbacks);
03816             ooH323EpSetTraceLevel(gTRCLVL);
03817       ooH323EpSetLocalAddress(gIP, gPort);
03818       if (v6mode) {
03819          ast_debug(1, "OOH323 channel is in IP6 mode\n");
03820       }
03821       ooH323EpSetCallerID(gCallerID);
03822  
03823       if(ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd) == OO_FAILED) {
03824          ast_log(LOG_ERROR, "h225portrange: Failed to set range\n");
03825       }
03826 
03827       /* Set aliases if any */
03828       for (pNewAlias = gAliasList; pNewAlias; pNewAlias = pNewAlias->next) {
03829          switch (pNewAlias->type) {
03830          case T_H225AliasAddress_h323_ID:
03831             ooH323EpAddAliasH323ID(pNewAlias->value);
03832             break;
03833          case T_H225AliasAddress_dialedDigits:  
03834             ooH323EpAddAliasDialedDigits(pNewAlias->value);
03835             break;
03836          case T_H225AliasAddress_email_ID:   
03837             ooH323EpAddAliasEmailID(pNewAlias->value);
03838             break;
03839          default:
03840             ;
03841          }
03842       }
03843 
03844       ast_mutex_lock(&peerl.lock);
03845       peer = peerl.peers;
03846       while (peer) {
03847          if(peer->h323id) ooH323EpAddAliasH323ID(peer->h323id);
03848          if(peer->email)  ooH323EpAddAliasEmailID(peer->email);
03849          if(peer->e164)   ooH323EpAddAliasDialedDigits(peer->e164);
03850                if(peer->url)    ooH323EpAddAliasURLID(peer->url);
03851          peer = peer->next;
03852       }
03853       ast_mutex_unlock(&peerl.lock);
03854    
03855 
03856       if (gMediaWaitForConnect)
03857          ooH323EpEnableMediaWaitForConnect();
03858       else 
03859          ooH323EpDisableMediaWaitForConnect();
03860 
03861       /* Fast start and tunneling options */
03862       if (gFastStart)
03863          ooH323EpEnableFastStart();
03864       else
03865          ooH323EpDisableFastStart();
03866 
03867       if (!gTunneling)
03868          ooH323EpDisableH245Tunneling();
03869 
03870       if (gBeMaster)
03871          ooH323EpTryBeMaster(1);
03872 
03873             ooH323EpEnableManualRingback();
03874 
03875       /* Gatekeeper */
03876       if (gRasGkMode == RasUseSpecificGatekeeper)
03877          ooGkClientInit(gRasGkMode, gGatekeeper, 0);
03878       else if (gRasGkMode == RasDiscoverGatekeeper)
03879          ooGkClientInit(gRasGkMode, 0, 0);
03880 
03881       /* Register callbacks */
03882       ooH323EpSetH323Callbacks(h323Callbacks);
03883 
03884       /* Add endpoint capabilities */
03885       if (ooh323c_set_capability(gCap, gDTMFMode, gDTMFCodec) < 0) {
03886          ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
03887          ao2_ref(gCap, -1);
03888          gCap = NULL;
03889          ao2_ref(ooh323_tech.capabilities, -1);
03890          ooh323_tech.capabilities = NULL;
03891          return 1;
03892       }
03893   
03894       /* Create H.323 listener */
03895       if (ooCreateH323Listener() != OO_OK) {
03896                ast_log(LOG_ERROR, "OOH323 Listener Creation failure. "
03897                             "OOH323 DISABLED\n");
03898       
03899          ooH323EpDestroy();
03900          ao2_ref(gCap, -1);
03901          gCap = NULL;
03902          ao2_ref(ooh323_tech.capabilities, -1);
03903          ooh323_tech.capabilities = NULL;
03904          return 1;
03905       }
03906 
03907       if (ooh323c_start_stack_thread() < 0) {
03908          ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. "
03909                             "OOH323 DISABLED\n");
03910          ooH323EpDestroy();
03911          ao2_ref(gCap, -1);
03912          gCap = NULL;
03913          ao2_ref(ooh323_tech.capabilities, -1);
03914          ooh323_tech.capabilities = NULL;
03915          return 1;
03916       }
03917       /* And start the monitor for the first time */
03918       restart_monitor();
03919    } else {
03920       ast_log(LOG_ERROR, "Can't load ooh323 config file, OOH323 Disabled\n");
03921       return AST_MODULE_LOAD_DECLINE;
03922    }
03923 
03924    return 0;
03925 }
03926 
03927 static int reload_module(void)
03928 {
03929    ast_mutex_lock(&h323_reload_lock);
03930    if (h323_reloading) {
03931       ast_verb(0, "Previous OOH323 reload not yet done\n");
03932    } else {
03933       h323_reloading = 1;
03934    }
03935    ast_mutex_unlock(&h323_reload_lock);
03936    restart_monitor();
03937 
03938    if (gH323Debug)
03939       ast_verb(0, "+++   ooh323_reload\n");
03940 
03941    return 0;
03942 }
03943 
03944 static void *do_monitor(void *data)
03945 {
03946    int res;
03947    int reloading;
03948    struct ooh323_pvt *h323 = NULL;
03949    time_t t;
03950 
03951    for (;;) {
03952       struct ooh323_pvt *h323_next;
03953       /* Check for a reload request */
03954       ast_mutex_lock(&h323_reload_lock);
03955       reloading = h323_reloading;
03956       h323_reloading = 0;
03957       ast_mutex_unlock(&h323_reload_lock);
03958       if (reloading) {
03959          ast_verb(1, "Reloading H.323\n");
03960          ooh323_do_reload();
03961       }
03962       if (gH323ep.gkClient && gH323ep.gkClient->state == GkClientStopped) {
03963          ooGkClientDestroy();
03964          ast_verb(0, "Restart stopped gatekeeper client\n");
03965          ooGkClientInit(gRasGkMode, (gRasGkMode == RasUseSpecificGatekeeper) ? 
03966                            gGatekeeper : 0, 0);
03967          ooGkClientStart(gH323ep.gkClient);
03968       }
03969 
03970       /* Check for interfaces needing to be killed */
03971       ast_mutex_lock(&iflock);
03972       time(&t);
03973       h323 = iflist;
03974       while (h323) {
03975          h323_next = h323->next;
03976 
03977          if (h323->rtp && h323->rtptimeout && h323->lastrtptx &&
03978             h323->lastrtptx + h323->rtptimeout < t) {
03979             ast_rtp_instance_sendcng(h323->rtp, 0);
03980             h323->lastrtptx = time(NULL);
03981          }
03982 
03983          if (h323->rtp && h323->owner && h323->rtptimeout &&
03984             h323->lastrtprx && ast_sockaddr_isnull(&h323->redirip) &&
03985             h323->lastrtprx + h323->rtptimeout < t) {
03986             if (!ast_channel_trylock(h323->owner)) {
03987                ast_softhangup_nolock(h323->owner, AST_SOFTHANGUP_DEV);
03988                ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", ast_channel_name(h323->owner), (long) (t - h323->lastrtprx));
03989                ast_channel_unlock(h323->owner);
03990             }
03991             
03992          }
03993 
03994          if (ast_test_flag(h323, H323_NEEDDESTROY)) {
03995             ooh323_destroy (h323);
03996          } /* else if (ast_test_flag(h323, H323_NEEDSTART) && h323->owner) {
03997      ast_channel_lock(h323->owner);
03998           if (ast_pbx_start(h323->owner)) {
03999             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", h323->owner->name);
04000             ast_channel_unlock(h323->owner);
04001             ast_hangup(h323->owner);
04002           }
04003           ast_channel_unlock(h323->owner);
04004      ast_clear_flag(h323, H323_NEEDSTART);
04005     } */
04006          h323 = h323_next;
04007       }
04008       ast_mutex_unlock(&iflock);
04009       pthread_testcancel();
04010 
04011       /* Wait for sched or io */
04012       res = ast_sched_wait(sched);
04013       if ((res < 0) || (res > 1000)) {
04014          res = 1000;
04015       }
04016       res = ast_io_wait(io, res);
04017       pthread_testcancel();
04018       ast_mutex_lock(&monlock);
04019       if (res >= 0) {
04020          ast_sched_runq(sched);
04021       }
04022       ast_mutex_unlock(&monlock);
04023    }
04024    /* Never reached */
04025    return NULL;
04026 }
04027 
04028 int restart_monitor(void)
04029 {
04030    pthread_attr_t attr;
04031 
04032    /* If we're supposed to be stopped -- stay stopped */
04033    if (monitor_thread == AST_PTHREADT_STOP)
04034       return 0;
04035    if (ast_mutex_lock(&monlock)) {
04036       ast_log(LOG_WARNING, "Unable to lock monitor\n");
04037       return -1;
04038    }
04039    if (monitor_thread == pthread_self()) {
04040       ast_mutex_unlock(&monlock);
04041       ast_log(LOG_WARNING, "Cannot kill myself\n");
04042       return -1;
04043    }
04044    if (monitor_thread != AST_PTHREADT_NULL) {
04045       /* Wake up the thread */
04046       pthread_kill(monitor_thread, SIGURG);
04047    } else {
04048       pthread_attr_init(&attr);
04049       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04050       /* Start a new monitor */
04051       if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
04052          ast_mutex_unlock(&monlock);
04053          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
04054          return -1;
04055       }
04056    }
04057    ast_mutex_unlock(&monlock);
04058    return 0;
04059 }
04060 
04061 
04062 
04063 int ooh323_destroy(struct ooh323_pvt *p)
04064 {
04065    /* NOTE: Assumes iflock already acquired */
04066    struct ooh323_pvt *prev = NULL, *cur = NULL;
04067    struct ooh323_user *user = NULL;
04068 
04069    if (gH323Debug) {
04070       ast_verb(0, "---   ooh323_destroy \n");
04071 
04072       if (p)
04073          ast_verb(0, " Destroying %s\n", p->username);
04074    }
04075 
04076    cur = iflist;
04077    while (cur) {
04078       if (cur == p) { break; }
04079       prev = cur;
04080       cur = cur->next;
04081    }
04082 
04083    if (cur) {
04084       ast_mutex_lock(&cur->lock);
04085       if (prev)
04086          prev->next = cur->next;
04087       else
04088          iflist = cur->next;
04089 
04090       if (cur->callToken) {
04091          if (gH323Debug) 
04092             ast_verb(0, " Destroying %s\n", cur->callToken);
04093          ast_free(cur->callToken);
04094          cur->callToken = 0;
04095       }
04096 
04097       if (cur->username) {
04098          ast_free(cur->username);
04099          cur->username = 0;
04100       }
04101 
04102       if (cur->host) {
04103          ast_free(cur->host);
04104          cur->host = 0;
04105       }
04106 
04107       if (cur->callerid_name) {
04108          ast_free(cur->callerid_name);
04109          cur->callerid_name = 0;
04110       }
04111       
04112       if (cur->callerid_num) {
04113          ast_free(cur->callerid_num);
04114          cur->callerid_num = 0;
04115       }
04116 
04117       if (cur->rtp) {
04118          ast_rtp_instance_destroy(cur->rtp);
04119          cur->rtp = NULL;
04120       }
04121 
04122       if (cur->udptl) {
04123          ast_udptl_destroy(cur->udptl);
04124          cur->udptl = NULL;
04125       }
04126    
04127       /* Unlink us from the owner if we have one */
04128       if (cur->owner) {
04129                while(ast_channel_trylock(cur->owner)) {
04130                      ast_debug(1, "Failed to grab lock, trying again\n");
04131             DEADLOCK_AVOIDANCE(&cur->lock);
04132                }           
04133          ast_debug(1, "Detaching from %s\n", ast_channel_name(cur->owner));
04134          ast_channel_tech_pvt_set(cur->owner, NULL);
04135          ast_channel_unlock(cur->owner);
04136          cur->owner = NULL;
04137          ast_module_unref(myself);
04138       }
04139   
04140       if (cur->vad) {
04141          ast_dsp_free(cur->vad);
04142          cur->vad = NULL;
04143       }
04144 
04145 /* decrement user/peer count */
04146 
04147       if(!ast_test_flag(cur, H323_OUTGOING)) {
04148     if (cur->neighbor.user) {
04149      user = find_user(p->callerid_name, cur->neighbor.user);
04150      if(user && user->inUse > 0) {
04151       ast_mutex_lock(&user->lock);
04152       user->inUse--;
04153       ast_mutex_unlock(&user->lock);
04154      }
04155      ast_free(cur->neighbor.user);
04156     }
04157       } else {
04158 /* outgoing limit decrement here !!! */
04159       }
04160 
04161       ast_mutex_unlock(&cur->lock);
04162       ast_mutex_destroy(&cur->lock);
04163       ao2_cleanup(cur->writeformat);
04164       ao2_cleanup(cur->readformat);
04165       ao2_cleanup(cur->cap);
04166       ast_free(cur);
04167    }
04168 
04169    if (gH323Debug)
04170       ast_verb(0, "+++   ooh323_destroy\n");
04171 
04172    return 0;
04173 }
04174 
04175 int delete_peers()
04176 {
04177    struct ooh323_peer *cur = NULL, *prev = NULL;
04178    ast_mutex_lock(&peerl.lock);
04179    cur = peerl.peers;
04180    while (cur) {
04181       prev = cur;
04182       cur = cur->next;
04183 
04184       ast_mutex_destroy(&prev->lock);
04185       ast_free(prev->h323id);
04186       ast_free(prev->email);
04187       ast_free(prev->url);
04188       ast_free(prev->e164);
04189       if(prev->rtpmask) {
04190       ast_mutex_lock(&prev->rtpmask->lock);
04191       prev->rtpmask->inuse--;
04192       ast_mutex_unlock(&prev->rtpmask->lock);
04193       if (prev->rtpmask->inuse == 0) {
04194          regfree(&prev->rtpmask->regex);
04195          ast_mutex_destroy(&prev->rtpmask->lock);
04196          ast_free(prev->rtpmask);
04197             }
04198       }
04199       ast_free(prev);
04200 
04201       if (cur == peerl.peers) {
04202          break;
04203       }
04204    }
04205    peerl.peers = NULL;
04206    ast_mutex_unlock(&peerl.lock);
04207    return 0;
04208 }
04209 
04210 int delete_users()
04211 {
04212    struct ooh323_user *cur = NULL, *prev = NULL;
04213    ast_mutex_lock(&userl.lock);
04214    cur = userl.users;
04215    while (cur) {
04216       prev = cur;
04217       cur = cur->next;
04218       ast_mutex_destroy(&prev->lock);
04219 
04220             if(prev->rtpmask) {
04221          ast_mutex_lock(&prev->rtpmask->lock);
04222          prev->rtpmask->inuse--;
04223          ast_mutex_unlock(&prev->rtpmask->lock);
04224          if (prev->rtpmask->inuse == 0) {
04225             regfree(&prev->rtpmask->regex);
04226             ast_mutex_destroy(&prev->rtpmask->lock);
04227             ast_free(prev->rtpmask);
04228                }
04229             }
04230          ao2_cleanup(prev->cap);
04231       ast_free(prev);
04232       if (cur == userl.users) {
04233          break;
04234       }
04235    }
04236    userl.users = NULL;
04237    ast_mutex_unlock(&userl.lock);
04238    return 0;
04239 }
04240 
04241 static int unload_module(void)
04242 {
04243    struct ooh323_pvt *p;
04244    struct ooAliases *cur = NULL, *prev = NULL;
04245 
04246    if (gH323Debug) {
04247       ast_verb(0, "--- ooh323  unload_module \n");
04248    }
04249    /* First, take us out of the channel loop */
04250    ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
04251    ast_rtp_glue_unregister(&ooh323_rtp);
04252    ast_channel_unregister(&ooh323_tech);
04253 #if 0
04254    ast_unregister_atexit(&ast_ooh323c_exit);
04255 #endif
04256 
04257    if (gH323Debug) {
04258       ast_verb(0, "  unload_module - hanging up all interfaces\n");
04259    }
04260    if (!ast_mutex_lock(&iflock)) {
04261       /* Hangup all interfaces if they have an owner */
04262       p = iflist;
04263       while (p) {
04264          if (p->owner) {
04265             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
04266          }
04267          p = p->next;
04268       }
04269       iflist = NULL;
04270       ast_mutex_unlock(&iflock);
04271    } else {
04272       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
04273       return -1;
04274    }
04275 
04276 
04277    if (gH323Debug) {
04278       ast_verb(0, "  unload_module - stopping monitor thread\n");
04279    }  
04280    if (monitor_thread != AST_PTHREADT_NULL) {
04281       if (!ast_mutex_lock(&monlock)) {
04282          if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
04283             pthread_cancel(monitor_thread);
04284             pthread_kill(monitor_thread, SIGURG);
04285             pthread_join(monitor_thread, NULL);
04286          }
04287          monitor_thread = AST_PTHREADT_STOP;
04288          ast_mutex_unlock(&monlock);
04289       } else {
04290          ast_log(LOG_WARNING, "Unable to lock the monitor\n");
04291          return -1;
04292       }
04293    }
04294 
04295 
04296    if (gH323Debug) {
04297       ast_verb(0, "   unload_module - stopping stack thread\n");
04298    }
04299    ooh323c_stop_stack_thread();
04300 
04301 
04302    if (gH323Debug) {
04303       ast_verb(0, "   unload_module - freeing up memory used by interfaces\n");
04304    }
04305    if (!ast_mutex_lock(&iflock)) {
04306       struct ooh323_pvt *pl;
04307 
04308       /* Destroy all the interfaces and free their memory */
04309       p = iflist;
04310       while (p) {
04311          pl = p;
04312          p = p->next;
04313          /* Free associated memory */
04314          ooh323_destroy(pl);
04315       }
04316       iflist = NULL;
04317       ast_mutex_unlock(&iflock);
04318    } else {
04319       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
04320       return -1;
04321    }
04322  
04323 
04324    if (gH323Debug) {
04325       ast_verb(0, "  unload_module - deleting users\n");
04326    }
04327    delete_users();
04328 
04329 
04330    if (gH323Debug) {
04331       ast_verb(0, "  unload_module - deleting peers\n");
04332    }
04333    delete_peers();
04334 
04335 
04336    if (gH323Debug) {
04337       ast_verb(0, "  unload_module - Freeing up alias list\n");
04338    }
04339    cur = gAliasList;
04340    while (cur) {
04341      prev = cur;
04342      cur = cur->next;
04343      ast_free(prev->value);
04344      ast_free(prev);
04345    }
04346    gAliasList = NULL;
04347 
04348 
04349    if (gH323Debug) {
04350       ast_verb(0, "  unload_module- destroying OOH323 endpoint \n");
04351    }
04352    ooH323EpDestroy();
04353 
04354    if (gH323Debug) {
04355       ast_verb(0, "+++ ooh323  unload_module \n");
04356    }
04357 
04358    ao2_ref(gCap, -1);
04359    gCap = NULL;
04360    ao2_ref(ooh323_tech.capabilities, -1);
04361    ooh323_tech.capabilities = NULL;
04362    return 0;
04363 }
04364 
04365 static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
04366 {
04367    struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan);
04368    if (gH323Debug) {
04369       ast_verb(0, "+++ ooh323  get_codec, %s\n", ast_channel_name(chan));
04370    }
04371 
04372    if (p) {
04373       if (ast_format_cap_count(ast_channel_nativeformats(chan))) {
04374          ast_format_cap_append_from_cap(result, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_UNKNOWN);
04375       } else if (ast_format_cap_count(p->cap)) {
04376          ast_format_cap_append_from_cap(result, p->cap, AST_MEDIA_TYPE_UNKNOWN);
04377       }
04378    }
04379 
04380    if (gH323Debug) {
04381       ast_verb(0, "--- ooh323  get_codec, %s\n", ast_channel_name(chan));
04382    }
04383 }
04384 
04385 
04386 
04387 static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
04388 {
04389    struct ooh323_pvt *p = NULL;
04390    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
04391    struct ast_sockaddr tmp;
04392 
04393    if (gH323Debug) {
04394       ast_verb(0, "+++ ooh323  get_rtp_peer \n");
04395    }
04396 
04397    if (!(p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan)))
04398       return AST_RTP_GLUE_RESULT_FORBID;
04399 
04400    if (!(p->rtp)) {
04401       return AST_RTP_GLUE_RESULT_FORBID;
04402    }
04403 
04404    *rtp = p->rtp ? ao2_ref(p->rtp, +1), p->rtp : NULL;
04405 
04406    /* there must be checking of directmedia setting */
04407 
04408    if ((ast_channel_state(chan) != AST_STATE_UP && !p->earlydirect) || !p->directrtp) {
04409       res = AST_RTP_GLUE_RESULT_LOCAL;
04410    } else {
04411       res = AST_RTP_GLUE_RESULT_REMOTE;
04412    }
04413 
04414    if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) {
04415       res = AST_RTP_GLUE_RESULT_FORBID;
04416    }
04417 
04418    ast_rtp_instance_get_remote_address(*rtp, &tmp);
04419    if (gH323Debug) {
04420       ast_verb(0, "ooh323_get_rtp_peer  %s -> %s:%d, %u\n", ast_channel_name(chan), ast_sockaddr_stringify_addr(&tmp),
04421                   ast_sockaddr_port(&tmp), res);
04422    }
04423    if (gH323Debug) {
04424       ast_verb(0, "--- ooh323  get_rtp_peer, res = %d\n", (int) res);
04425    }
04426 
04427    return res;
04428 }
04429 
04430 static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
04431 {
04432    struct ooh323_pvt *p = NULL;
04433    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
04434 
04435    if (!(p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan)))
04436       return AST_RTP_GLUE_RESULT_FORBID;
04437 
04438    if (!(p->rtp)) {
04439       return AST_RTP_GLUE_RESULT_FORBID;
04440    }
04441 
04442    *rtp = p->vrtp ? ao2_ref(p->vrtp, +1), p->vrtp : NULL;
04443 
04444    /* there must check of supporting video per call */
04445 
04446    res = AST_RTP_GLUE_RESULT_FORBID;
04447 
04448    return res;
04449 }
04450 
04451 int ooh323_convertAsteriskCapToH323Cap(struct ast_format *format)
04452 {
04453    if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
04454       return OO_G711ULAW64K;
04455    } else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
04456       return OO_G711ALAW64K;
04457    } else if (ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL) {
04458       return OO_GSMFULLRATE;
04459    } else if (ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL) {
04460       return OO_SPEEX;
04461    } else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
04462       return OO_G729A;
04463    } else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
04464       return OO_G726;
04465    } else if (ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
04466       return OO_G726AAL2;
04467    } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
04468       return OO_G7231;
04469    } else if (ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
04470       return OO_H263VIDEO;
04471    } else {
04472       ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_format_get_name(format));
04473       return -1;
04474    }
04475 }
04476 
04477 static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp,
04478     struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *cap, int nat_active)
04479 {
04480    /* XXX Deal with Video */
04481    struct ooh323_pvt *p;
04482    int changed = 0;
04483    char *callToken = NULL;
04484 
04485    if (gH323Debug) {
04486       ast_verb(0, "---   ooh323_set_peer - %s\n", ast_channel_name(chan));
04487    }
04488 
04489    if (ooh323_convertAsteriskCapToH323Cap(ast_channel_writeformat(chan)) < 0) {
04490       ast_log(LOG_WARNING, "Unknown format.\n");
04491       return -1;
04492    }
04493    p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan);
04494    if (!p) {
04495       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
04496       return -1;
04497    }
04498 
04499    ast_mutex_lock(&p->lock);
04500 
04501    if (rtp) {
04502       changed |= ast_rtp_instance_get_and_cmp_remote_address(rtp, &p->redirip);
04503    } else if (!ast_sockaddr_isnull(&p->redirip)) {
04504       changed = 1;
04505       memset(&p->redirip, 0, sizeof(p->redirip));
04506    }
04507 
04508    callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
04509 
04510    if (!callToken) {
04511       if (gH323Debug) {
04512          ast_verb(0, "  set_rtp_peer - No callToken\n");
04513       }
04514       ast_mutex_unlock(&p->lock);
04515       return -1;
04516    }
04517 
04518 
04519    if (changed) {
04520       if (!ast_sockaddr_isnull(&p->redirip)) {
04521          if (gH323Debug) {
04522             ast_verb(0, "ooh323_set_rtp_peer  %s -> %s:%d\n", ast_channel_name(chan), ast_sockaddr_stringify_addr(&p->redirip),
04523                      ast_sockaddr_port(&p->redirip));
04524          }
04525          ooUpdateLogChannels(callToken, ast_sockaddr_stringify_addr(&p->redirip),
04526                      ast_sockaddr_port(&p->redirip));
04527       } else {
04528          if (gH323Debug) {
04529             ast_verb(0, "ooh323_set_rtp_peer  return back to local\n");
04530          }
04531          ooUpdateLogChannels(callToken, "0.0.0.0" , 0);
04532       }
04533    }
04534 
04535    ast_mutex_unlock(&p->lock);
04536    ast_free(callToken);
04537    return 0;
04538 
04539 }
04540 
04541 
04542 
04543 
04544 int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
04545 {
04546    char lhost[INET6_ADDRSTRLEN];
04547    unsigned lport = 0;
04548    struct ast_sockaddr tmp;
04549    ooMediaInfo mediaInfo;
04550    int x;
04551 
04552    if (gH323Debug)
04553       ast_verb(0, "---   configure_local_rtp\n");
04554 
04555    memset(&mediaInfo, 0, sizeof(mediaInfo));
04556    if (ast_parse_arg(call->localIP, PARSE_ADDR, &tmp)) {
04557       ast_sockaddr_copy(&tmp, &bindaddr);
04558    }
04559    if (!(p->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
04560       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n",
04561          strerror(errno));
04562       return 0;
04563    }
04564 
04565    ast_rtp_instance_set_qos(p->rtp, gTOS, 0, "ooh323-rtp");
04566 
04567    if (!(p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &tmp))) {
04568       ast_log(LOG_WARNING, "Unable to create UDPTL session: %s\n",
04569          strerror(errno));
04570       return 0;
04571    }
04572    ast_udptl_set_far_max_datagram(p->udptl, 144);
04573 
04574    if (p->owner) {
04575       while (p->owner && ast_channel_trylock(p->owner)) {
04576          ast_debug(1,"Failed to grab lock, trying again\n");
04577          DEADLOCK_AVOIDANCE(&p->lock);
04578       }
04579       if (!p->owner) {
04580          ast_mutex_unlock(&p->lock);
04581          ast_log(LOG_ERROR, "Channel has no owner\n");
04582          return 0;
04583       }
04584    } else {
04585       ast_log(LOG_ERROR, "Channel has no owner\n");
04586       return 0;
04587    }
04588 
04589    ast_channel_set_fd(p->owner, 0, ast_rtp_instance_fd(p->rtp, 0));
04590    ast_channel_set_fd(p->owner, 1, ast_rtp_instance_fd(p->rtp, 1));
04591    ast_channel_set_fd(p->owner, 5, ast_udptl_fd(p->udptl));
04592 
04593    ast_channel_unlock(p->owner);
04594 
04595    if (p->rtp) {
04596       if (p->cap) {
04597          ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp),
04598             ast_format_cap_get_framing(p->cap));
04599       }
04600       if (p->nat) {
04601          ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, 1);
04602       }
04603       if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
04604          ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
04605          ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
04606              p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
04607       }
04608       if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) {
04609          ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
04610          ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
04611              p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
04612       }
04613       /* figure out our local RTP port and tell the H.323 stack about it*/
04614       ast_rtp_instance_get_local_address(p->rtp, &tmp);
04615       ast_copy_string(lhost, ast_sockaddr_stringify_addr(&tmp), sizeof(lhost));
04616       lport = ast_sockaddr_port(&tmp);
04617 
04618       if (p->rtptimeout) {
04619          ast_rtp_instance_set_timeout(p->rtp, p->rtptimeout);
04620       }
04621       ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1);
04622       
04623    }
04624 
04625    if (p->rtdrcount) {
04626       if (gH323Debug)
04627          ast_verb(0, "Setup RTDR info: %d, %d\n", p->rtdrinterval, p->rtdrcount);
04628       call->rtdrInterval = p->rtdrinterval;
04629       call->rtdrCount = p->rtdrcount;
04630    }
04631 
04632 
04633    ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
04634    mediaInfo.lMediaPort = lport;
04635    mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort + 1;
04636    for (x = 0; x < ast_format_cap_count(p->cap); x++) {
04637       struct ast_format *format = ast_format_cap_get_format(p->cap, x);
04638 
04639       strcpy(mediaInfo.dir, "transmit");
04640       mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format);
04641       ooAddMediaInfo(call, mediaInfo);
04642       strcpy(mediaInfo.dir, "receive");
04643       ooAddMediaInfo(call, mediaInfo);
04644       if (mediaInfo.cap == OO_G729A) {
04645          strcpy(mediaInfo.dir, "transmit");
04646          mediaInfo.cap = OO_G729;
04647          ooAddMediaInfo(call, mediaInfo);
04648          strcpy(mediaInfo.dir, "receive");
04649          ooAddMediaInfo(call, mediaInfo);
04650 
04651          strcpy(mediaInfo.dir, "transmit");
04652          mediaInfo.cap = OO_G729B;
04653          ooAddMediaInfo(call, mediaInfo);
04654          strcpy(mediaInfo.dir, "receive");
04655          ooAddMediaInfo(call, mediaInfo);
04656       }
04657 
04658       ao2_ref(format, -1);
04659    }
04660 
04661    if (p->udptl) {
04662       ast_udptl_get_us(p->udptl, &tmp);
04663       ast_copy_string(lhost, ast_sockaddr_stringify_addr(&tmp), sizeof(lhost));
04664       lport = ast_sockaddr_port(&tmp);
04665       ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
04666       mediaInfo.lMediaPort = lport;
04667       mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
04668       mediaInfo.cap = OO_T38;
04669       strcpy(mediaInfo.dir, "transmit");
04670       ooAddMediaInfo(call, mediaInfo);
04671       strcpy(mediaInfo.dir, "receive");
04672       ooAddMediaInfo(call, mediaInfo);
04673    }
04674 
04675    if (gH323Debug)
04676       ast_verb(0, "+++   configure_local_rtp\n");
04677 
04678    return 1;
04679 }
04680 
04681 void setup_rtp_remote(ooCallData *call, const char *remoteIp, int remotePort)
04682 {
04683    struct ooh323_pvt *p = NULL;
04684    struct ast_sockaddr tmp;
04685 
04686    if (gH323Debug) {
04687       ast_verb(0, "---   setup_rtp_remote %s:%d\n", remoteIp, remotePort);
04688    }
04689    if (!remoteIp || !remoteIp[0] || !remotePort) {
04690       if (gH323Debug) {
04691          ast_verb(0, "+++ setup_rtp_remote no data\n");
04692       }
04693       return;
04694    }
04695 
04696    /* Find the call or allocate a private structure if call not found */
04697    p = find_call(call);
04698 
04699    if (!p || !p->rtp) {
04700       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
04701       return;
04702    }
04703 
04704    ast_mutex_lock(&p->lock);
04705 
04706    ast_parse_arg(remoteIp, PARSE_ADDR, &tmp);
04707    ast_sockaddr_set_port(&tmp, remotePort);
04708    ast_rtp_instance_set_remote_address(p->rtp, &tmp);
04709 
04710    ast_mutex_unlock(&p->lock);
04711 
04712    if (gH323Debug) {
04713       ast_verb(0, "+++   setup_rtp_remote\n");
04714    }
04715 
04716    return;
04717 }
04718 
04719 
04720 void setup_rtp_connection(ooCallData *call, const char *remoteIp, int remotePort)
04721 {
04722    struct ooh323_pvt *p = NULL;
04723    struct ast_sockaddr tmp;
04724 
04725    if (gH323Debug)
04726       ast_verb(0, "---   setup_rtp_connection %s:%d\n", remoteIp, remotePort);
04727 
04728    /* Find the call or allocate a private structure if call not found */
04729    p = find_call(call);
04730 
04731    if (!p || !p->rtp) {
04732       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
04733       return;
04734    }
04735 
04736    ast_mutex_lock(&p->lock);
04737 
04738    ast_parse_arg(remoteIp, PARSE_ADDR, &tmp);
04739    ast_sockaddr_set_port(&tmp, remotePort);
04740    ast_rtp_instance_set_remote_address(p->rtp, &tmp);
04741 
04742    if (ast_format_cmp(p->writeformat, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
04743                 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, 2,
04744                      "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
04745    }
04746 
04747    ast_mutex_unlock(&p->lock);
04748 
04749    if(gH323Debug)
04750       ast_verb(0, "+++   setup_rtp_connection\n");
04751 
04752    return;
04753 }
04754 
04755 void close_rtp_connection(ooCallData *call)
04756 {
04757    struct ooh323_pvt *p = NULL;
04758 
04759    if(gH323Debug)
04760       ast_verb(0, "---   close_rtp_connection\n");
04761 
04762    p = find_call(call);
04763    if (!p) {
04764       ast_log(LOG_ERROR, "Couldn't find matching call to close rtp "
04765                          "connection\n");
04766       return;
04767    }
04768    ast_mutex_lock(&p->lock);
04769    if (p->rtp) {
04770       ast_rtp_instance_stop(p->rtp);
04771    }
04772    ast_mutex_unlock(&p->lock);
04773 
04774    if(gH323Debug)
04775       ast_verb(0, "+++   close_rtp_connection\n");
04776 
04777    return;
04778 }
04779 
04780 /*
04781  udptl handling functions
04782  */
04783 
04784 void setup_udptl_connection(ooCallData *call, const char *remoteIp, 
04785                           int remotePort)
04786 {
04787    struct ooh323_pvt *p = NULL;
04788    struct ast_sockaddr them;
04789 
04790    if (gH323Debug)
04791       ast_verb(0, "---   setup_udptl_connection\n");
04792 
04793    /* Find the call or allocate a private structure if call not found */
04794    p = find_call(call); 
04795 
04796    if (!p) {
04797       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
04798       return;
04799    }
04800 
04801    ast_mutex_lock(&p->lock);
04802    if (p->owner) {
04803       while (p->owner && ast_channel_trylock(p->owner)) {
04804          ast_debug(1, "Failed to grab lock, trying again\n");
04805          DEADLOCK_AVOIDANCE(&p->lock);
04806       }
04807       if (!p->owner) {
04808          ast_mutex_unlock(&p->lock);
04809          ast_log(LOG_ERROR, "Channel has no owner\n");
04810          return;
04811       }
04812    } else {
04813       ast_mutex_unlock(&p->lock);
04814       ast_log(LOG_ERROR, "Channel has no owner\n");
04815       return;
04816    }
04817 
04818    ast_parse_arg(remoteIp, PARSE_ADDR, &them);
04819    ast_sockaddr_set_port(&them, remotePort);
04820 
04821    ast_udptl_set_peer(p->udptl, &them);
04822    ast_udptl_set_tag(p->udptl, "%s", ast_channel_name(p->owner));
04823    p->t38_tx_enable = 1;
04824    p->lastTxT38 = time(NULL);
04825    if (p->t38support == T38_ENABLED) {
04826       struct ast_control_t38_parameters parameters = { .request_response = 0 };
04827       parameters.request_response = AST_T38_NEGOTIATED;
04828       parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
04829       parameters.rate = AST_T38_RATE_14400;
04830       ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
04831    }
04832    if (gH323Debug) {
04833       ast_debug(1, "Receiving UDPTL  %s:%d\n", ast_sockaddr_stringify_host(&them),
04834                      ast_sockaddr_port(&them));
04835    }
04836 
04837    ast_channel_unlock(p->owner);
04838    ast_mutex_unlock(&p->lock);
04839 
04840    if(gH323Debug)
04841       ast_verb(0, "+++   setup_udptl_connection\n");
04842 
04843    return;
04844 }
04845 
04846 void close_udptl_connection(ooCallData *call)
04847 {
04848    struct ooh323_pvt *p = NULL;
04849 
04850       if(gH323Debug)
04851       ast_verb(0, "---   close_udptl_connection\n");
04852 
04853    p = find_call(call);
04854    if (!p) {
04855             ast_log(LOG_ERROR, "Couldn't find matching call to close udptl "
04856                          "connection\n");
04857       return;
04858    }
04859    ast_mutex_lock(&p->lock);
04860    if (p->owner) {
04861       while (p->owner && ast_channel_trylock(p->owner)) {
04862          ast_debug(1, "Failed to grab lock, trying again\n");
04863          DEADLOCK_AVOIDANCE(&p->lock);
04864       }
04865       if (!p->owner) {
04866          ast_mutex_unlock(&p->lock);
04867          ast_log(LOG_ERROR, "Channel has no owner\n");
04868          return;
04869       }
04870    } else {
04871       ast_mutex_unlock(&p->lock);
04872       ast_log(LOG_ERROR, "Channel has no owner\n");
04873       return;
04874    }
04875 
04876    p->t38_tx_enable = 0;
04877    if (p->t38support == T38_ENABLED) {
04878       struct ast_control_t38_parameters parameters = { .request_response = 0 };
04879       parameters.request_response = AST_T38_TERMINATED;
04880       ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
04881    }
04882 
04883    ast_channel_unlock(p->owner);
04884    ast_mutex_unlock(&p->lock);
04885 
04886       if(gH323Debug)
04887       ast_verb(0, "+++   close_udptl_connection\n");
04888 
04889    return;
04890 }
04891 
04892 /* end of udptl handling */
04893 
04894 int update_our_aliases(ooCallData *call, struct ooh323_pvt *p)
04895 {
04896    int updated = -1;
04897    ooAliases *psAlias = NULL;
04898    
04899    if (!call->ourAliases)
04900       return updated;
04901    for (psAlias = call->ourAliases; psAlias; psAlias = psAlias->next) {
04902       if (psAlias->type == T_H225AliasAddress_h323_ID) {
04903          ast_copy_string(p->callee_h323id, psAlias->value, sizeof(p->callee_h323id));
04904          updated = 1;
04905       }
04906       if (psAlias->type == T_H225AliasAddress_dialedDigits) {
04907          ast_copy_string(p->callee_dialedDigits, psAlias->value, 
04908                                         sizeof(p->callee_dialedDigits));
04909          updated = 1;
04910       }
04911       if (psAlias->type == T_H225AliasAddress_url_ID) {
04912          ast_copy_string(p->callee_url, psAlias->value, sizeof(p->callee_url));
04913          updated = 1;
04914       }
04915       if (psAlias->type == T_H225AliasAddress_email_ID) {
04916          ast_copy_string(p->callee_email, psAlias->value, sizeof(p->callee_email));
04917          updated = 1;
04918       }
04919    }
04920    return updated;
04921 }
04922 
04923 struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p)
04924 {
04925    /* Retrieve audio/etc from channel.  Assumes p->lock is already held. */
04926    struct ast_frame *f;
04927    struct ast_frame *dfr = NULL;
04928    static struct ast_frame null_frame = { AST_FRAME_NULL, };
04929    switch (ast_channel_fdno(ast)) {
04930    case 0:
04931       f = ast_rtp_instance_read(p->rtp, 0);  /* RTP Audio */
04932       p->lastrtprx = time(NULL);
04933       break;
04934    case 1:
04935       f = ast_rtp_instance_read(p->rtp, 1);  /* RTCP Control Channel */
04936       break;
04937    case 2:
04938       f = ast_rtp_instance_read(p->vrtp, 0); /* RTP Video */
04939       p->lastrtprx = time(NULL);
04940       break;
04941    case 3:
04942       f = ast_rtp_instance_read(p->vrtp, 1); /* RTCP Control Channel for video */
04943       break;
04944    case 5:
04945       f = ast_udptl_read(p->udptl);    /* UDPTL t.38 data */
04946       if (gH323Debug) {
04947           ast_debug(1, "Got UDPTL %u/%d len %d for %s\n",
04948             f->frametype, f->subclass.integer, f->datalen, ast_channel_name(ast));
04949       }
04950       p->lastrtprx = time(NULL);
04951       break;
04952 
04953    default:
04954       f = &null_frame;
04955    }
04956 
04957    if (f && p->owner && !p->faxmode && (f->frametype == AST_FRAME_VOICE)) {
04958       /* We already hold the channel lock */
04959       if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(p->owner), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
04960          struct ast_format_cap *caps;
04961 
04962          ast_debug(1, "Oooh, voice format changed to %s\n", ast_format_get_name(f->subclass.format));
04963 
04964          caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
04965          if (caps) {
04966             ast_format_cap_append(caps, f->subclass.format, 0);
04967             ast_channel_nativeformats_set(p->owner, caps);
04968             ao2_ref(caps, -1);
04969          }
04970          ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
04971          ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
04972       }
04973       if (((p->dtmfmode & H323_DTMF_INBAND) || (p->faxdetect & FAXDETECT_CNG)) && p->vad &&
04974          ((ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL) ||
04975          (ast_format_cmp(f->subclass.format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) ||
04976          (ast_format_cmp(f->subclass.format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL))) {
04977          dfr = ast_frdup(f);
04978          dfr = ast_dsp_process(p->owner, p->vad, dfr);
04979       }
04980    } else {
04981       return f;
04982    }
04983 
04984    /* process INBAND DTMF*/
04985    if (dfr && (dfr->frametype == AST_FRAME_DTMF) && ((dfr->subclass.integer == 'f') || (dfr->subclass.integer == 'e'))) {
04986       ast_debug(1, "* Detected FAX Tone %s\n", (dfr->subclass.integer == 'e') ? "CED" : "CNG");
04987       /* Switch to T.38 ON CED*/
04988       if (!p->faxmode && !p->chmodepend && (dfr->subclass.integer == 'e') && (p->t38support != T38_DISABLED)) {
04989          if (gH323Debug)
04990             ast_verb(0, "request to change %s to t.38 because fax ced\n", p->callToken);
04991          p->chmodepend = 1;
04992          p->faxdetected = 1;
04993          ooRequestChangeMode(p->callToken, 1);
04994       } else if ((dfr->subclass.integer == 'f') && !p->faxdetected) {
04995          const char *target_context = S_OR(ast_channel_macrocontext(p->owner), ast_channel_context(p->owner));
04996          if ((strcmp(ast_channel_exten(p->owner), "fax")) &&
04997              (ast_exists_extension(p->owner, target_context, "fax", 1,
04998                   S_COR(ast_channel_caller(p->owner)->id.number.valid, ast_channel_caller(p->owner)->id.number.str, NULL)))) {
04999             ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", ast_channel_name(p->owner));
05000             pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", ast_channel_exten(p->owner));
05001             if (ast_async_goto(p->owner, target_context, "fax", 1)) {
05002                ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(p->owner),target_context);
05003             }
05004             p->faxdetected = 1;
05005             if (dfr) {
05006                ast_frfree(dfr);
05007             }
05008             return &ast_null_frame;
05009          }
05010       }
05011    } else if (dfr && dfr->frametype == AST_FRAME_DTMF) {
05012       ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass.integer);
05013       ast_frfree(f);
05014       return dfr;
05015    }
05016 
05017    if (dfr) {
05018       ast_frfree(dfr);
05019    }
05020    return f;
05021 }
05022 
05023 void onModeChanged(ooCallData *call, int t38mode) {
05024         struct ooh323_pvt *p;
05025 
05026    p = find_call(call);
05027    if (!p) {
05028       ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
05029       return;
05030    }
05031 
05032    ast_mutex_lock(&p->lock);
05033 
05034    if (gH323Debug)
05035             ast_debug(1, "change mode to %d for %s\n", t38mode, call->callToken);
05036 
05037    if (t38mode == p->faxmode) {
05038       if (gH323Debug)
05039          ast_debug(1, "mode for %s is already %d\n", call->callToken,
05040                t38mode);
05041       p->chmodepend = 0;
05042       ast_mutex_unlock(&p->lock);
05043       return;
05044    }
05045 
05046    if (p->owner) {
05047       while (p->owner && ast_channel_trylock(p->owner)) {
05048          ast_debug(1,"Failed to grab lock, trying again\n");
05049          DEADLOCK_AVOIDANCE(&p->lock);
05050       }
05051       if (!p->owner) {
05052          p->chmodepend = 0;
05053          ast_mutex_unlock(&p->lock);
05054          ast_log(LOG_ERROR, "Channel has no owner\n");
05055          return;
05056       }
05057    } else {
05058       p->chmodepend = 0;
05059       ast_mutex_unlock(&p->lock);
05060       ast_log(LOG_ERROR, "Channel has no owner\n");
05061       return;
05062    }
05063 
05064    if (t38mode) {
05065 
05066 
05067       if (p->t38support == T38_ENABLED) {
05068          struct ast_control_t38_parameters parameters = { .request_response = 0 };
05069 
05070          if ((p->faxdetect & FAXDETECT_T38) && !p->faxdetected) {
05071                            const char *target_context;
05072             ast_debug(1, "* Detected T.38 Request\n");
05073             target_context = S_OR(ast_channel_macrocontext(p->owner), ast_channel_context(p->owner));
05074                            if ((strcmp(ast_channel_exten(p->owner), "fax")) &&
05075                                  (ast_exists_extension(p->owner, target_context, "fax", 1,
05076                                  S_COR(ast_channel_caller(p->owner)->id.number.valid, ast_channel_caller(p->owner)->id.number.str, NULL)))) {
05077                                  ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n", ast_channel_name(p->owner));
05078                                  pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", ast_channel_exten(p->owner));
05079                                  if (ast_async_goto(p->owner, target_context, "fax", 1)) {
05080                                           ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(p->owner),target_context);
05081                }
05082                                 }
05083                                 p->faxdetected = 1;
05084          }
05085 
05086 /* AST_T38_CONTROL mode */
05087 
05088          parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
05089          if (call->T38FarMaxDatagram) {
05090             ast_udptl_set_far_max_datagram(p->udptl, call->T38FarMaxDatagram);
05091          } else {
05092             ast_udptl_set_far_max_datagram(p->udptl, 144);
05093          }
05094          if (call->T38Version) {
05095             parameters.version = call->T38Version;
05096          }
05097          parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
05098          parameters.rate = AST_T38_RATE_14400;
05099          ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, 
05100                      &parameters, sizeof(parameters));
05101          p->faxmode = 1;
05102 
05103 
05104       }
05105    } else {
05106       if (p->t38support == T38_ENABLED) {
05107          struct ast_control_t38_parameters parameters = { .request_response = 0 };
05108          parameters.request_response = AST_T38_REQUEST_TERMINATE;
05109          parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
05110          parameters.rate = AST_T38_RATE_14400;
05111          ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, 
05112                      &parameters, sizeof(parameters));
05113       }
05114       p->faxmode = 0;
05115       p->faxdetected = 0;
05116       p->t38_init = 0;
05117    }
05118 
05119    p->chmodepend = 0;
05120    ast_channel_unlock(p->owner);
05121    ast_mutex_unlock(&p->lock);
05122 }
05123 
05124 
05125 
05126 int ooh323_convert_hangupcause_asteriskToH323(int cause)
05127 {
05128    switch (cause) {
05129    case AST_CAUSE_CALL_REJECTED:
05130       return OO_REASON_REMOTE_REJECTED;
05131    case AST_CAUSE_UNALLOCATED:
05132       return OO_REASON_NOUSER;
05133    case AST_CAUSE_BUSY:
05134       return OO_REASON_REMOTE_BUSY;
05135    case AST_CAUSE_BEARERCAPABILITY_NOTAVAIL:
05136       return OO_REASON_NOCOMMON_CAPABILITIES;
05137    case AST_CAUSE_CONGESTION:
05138       return OO_REASON_REMOTE_BUSY;
05139    case AST_CAUSE_NO_ANSWER:
05140       return OO_REASON_REMOTE_NOANSWER;
05141    case AST_CAUSE_NORMAL:
05142       return OO_REASON_REMOTE_CLEARED;
05143    case AST_CAUSE_FAILURE:
05144    default:
05145       return OO_REASON_UNKNOWN;
05146    }
05147 
05148    return 0;
05149 
05150 
05151 }
05152 
05153 int ooh323_convert_hangupcause_h323ToAsterisk(int cause)
05154 {
05155    switch (cause) {
05156    case OO_REASON_REMOTE_REJECTED:
05157       return AST_CAUSE_CALL_REJECTED;
05158    case OO_REASON_NOUSER: 
05159       return AST_CAUSE_UNALLOCATED;
05160    case OO_REASON_REMOTE_BUSY:
05161    case OO_REASON_LOCAL_BUSY:
05162       return AST_CAUSE_BUSY;
05163    case OO_REASON_NOCOMMON_CAPABILITIES:  /* No codecs approved */
05164       return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
05165    case OO_REASON_REMOTE_CONGESTED:
05166    case OO_REASON_LOCAL_CONGESTED:
05167       return AST_CAUSE_CONGESTION;
05168    case OO_REASON_REMOTE_NOANSWER:
05169       return AST_CAUSE_NO_ANSWER;
05170    case OO_REASON_UNKNOWN: 
05171    case OO_REASON_INVALIDMESSAGE:
05172    case OO_REASON_TRANSPORTFAILURE:
05173       return AST_CAUSE_FAILURE;
05174    case OO_REASON_REMOTE_CLEARED:
05175       return AST_CAUSE_NORMAL;
05176    default:
05177       return AST_CAUSE_NORMAL;
05178    }
05179    /* Never reached */
05180    return 0;
05181 }
05182 
05183 #if 0
05184 void ast_ooh323c_exit()
05185 {
05186    ooGkClientDestroy();
05187 }
05188 #endif
05189 
05190 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Objective Systems H323 Channel",
05191       .support_level = AST_MODULE_SUPPORT_EXTENDED,
05192          .load = load_module,
05193          .unload = unload_module,
05194          .reload = reload_module,
05195          .load_pri = AST_MODPRI_CHANNEL_DRIVER
05196          );

Generated on Thu Apr 16 06:27:23 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6