Thu Jul 9 13:40:25 2009

Asterisk developer's documentation


chan_h323.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005
00005  *
00006  * OpenH323 Channel Driver for ASTERISK PBX.
00007  *       By Jeremy McNamara
00008  *                      For The NuFone Network
00009  *
00010  * chan_h323 has been derived from code created by
00011  *               Michael Manousos and Mark Spencer
00012  *
00013  * See http://www.asterisk.org for more information about
00014  * the Asterisk project. Please do not directly contact
00015  * any of the maintainers of this project for assistance;
00016  * the project provides a web site, mailing lists and IRC
00017  * channels for your use.
00018  *
00019  * This program is free software, distributed under the terms of
00020  * the GNU General Public License Version 2. See the LICENSE file
00021  * at the top of the source tree.
00022  */
00023 
00024 /*! \file
00025  *
00026  * \brief This file is part of the chan_h323 driver for Asterisk
00027  *
00028  * \author Jeremy McNamara
00029  *
00030  * \par See also
00031  * \arg Config_h323
00032  * \extref OpenH323 http://www.voxgratia.org/
00033  *
00034  * \ingroup channel_drivers
00035  */
00036 
00037 /*** MODULEINFO
00038    <depend>openh323</depend>
00039    <defaultenabled>yes</defaultenabled>
00040  ***/
00041 
00042 #ifdef __cplusplus
00043 extern "C" {
00044 #endif
00045 
00046 #include "asterisk.h"
00047 
00048 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 191222 $")
00049 
00050 #ifdef __cplusplus
00051 }
00052 #endif
00053 
00054 #include <sys/types.h>
00055 #include <sys/socket.h>
00056 #include <sys/signal.h>
00057 #include <sys/param.h>
00058 #include <arpa/inet.h>
00059 #include <net/if.h>
00060 #include <netinet/in.h>
00061 #include <netinet/in_systm.h>
00062 #include <netinet/ip.h>
00063 #include <netdb.h>
00064 #include <fcntl.h>
00065 
00066 #ifdef __cplusplus
00067 extern "C" {
00068 #endif
00069 
00070 #include "asterisk/lock.h"
00071 #include "asterisk/channel.h"
00072 #include "asterisk/config.h"
00073 #include "asterisk/module.h"
00074 #include "asterisk/musiconhold.h"
00075 #include "asterisk/pbx.h"
00076 #include "asterisk/utils.h"
00077 #include "asterisk/sched.h"
00078 #include "asterisk/io.h"
00079 #include "asterisk/rtp.h"
00080 #include "asterisk/acl.h"
00081 #include "asterisk/callerid.h"
00082 #include "asterisk/cli.h"
00083 #include "asterisk/dsp.h"
00084 #include "asterisk/causes.h"
00085 #include "asterisk/stringfields.h"
00086 #include "asterisk/abstract_jb.h"
00087 #include "asterisk/astobj.h"
00088 
00089 #ifdef __cplusplus
00090 }
00091 #endif
00092 
00093 #undef open
00094 #undef close
00095 #include "h323/chan_h323.h"
00096 
00097 receive_digit_cb on_receive_digit;
00098 on_rtp_cb on_external_rtp_create;
00099 start_rtp_cb on_start_rtp_channel;
00100 setup_incoming_cb on_incoming_call;
00101 setup_outbound_cb on_outgoing_call;
00102 chan_ringing_cb   on_chan_ringing;
00103 con_established_cb on_connection_established;
00104 clear_con_cb on_connection_cleared;
00105 answer_call_cb on_answer_call;
00106 progress_cb on_progress;
00107 rfc2833_cb on_set_rfc2833_payload;
00108 hangup_cb on_hangup;
00109 setcapabilities_cb on_setcapabilities;
00110 setpeercapabilities_cb on_setpeercapabilities;
00111 onhold_cb on_hold;
00112 
00113 int h323debug; /*!< global debug flag */
00114 
00115 /*! \brief Global jitterbuffer configuration - by default, jb is disabled */
00116 static struct ast_jb_conf default_jbconf =
00117 {
00118    .flags = 0,
00119    .max_size = -1,
00120    .resync_threshold = -1,
00121    .impl = ""
00122 };
00123 static struct ast_jb_conf global_jbconf;
00124 
00125 /** Variables required by Asterisk */
00126 static const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver";
00127 static const char config[] = "h323.conf";
00128 static char default_context[AST_MAX_CONTEXT] = "default";
00129 static struct sockaddr_in bindaddr;
00130 
00131 #define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261)
00132 
00133 /** H.323 configuration values */
00134 static int h323_signalling_port = 1720;
00135 static char gatekeeper[100];
00136 static int gatekeeper_disable = 1;
00137 static int gatekeeper_discover = 0;
00138 static int gkroute = 0;
00139 /* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/
00140 static int userbyalias = 1;
00141 static int acceptAnonymous = 1;
00142 static unsigned int tos = 0;
00143 static unsigned int cos = 0;
00144 static char secret[50];
00145 static unsigned int unique = 0;
00146 
00147 static call_options_t global_options;
00148 
00149 /*! \brief Private structure of a OpenH323 channel */
00150 struct oh323_pvt {
00151    ast_mutex_t lock;       /*!< Channel private lock */
00152    call_options_t options;       /*!<!< Options to be used during call setup */
00153    int alreadygone;        /*!< Whether or not we've already been destroyed by our peer */
00154    int needdestroy;        /*!< if we need to be destroyed */
00155    call_details_t cd;         /*!< Call details */
00156    struct ast_channel *owner;    /*!< Who owns us */
00157    struct sockaddr_in sa;        /*!< Our peer */
00158    struct sockaddr_in redirip;      /*!< Where our RTP should be going if not to us */
00159    int nonCodecCapability;       /*!< non-audio capability */
00160    int outgoing;           /*!< Outgoing or incoming call? */
00161    char exten[AST_MAX_EXTENSION];      /*!< Requested extension */
00162    char context[AST_MAX_CONTEXT];      /*!< Context where to start */
00163    char accountcode[256];        /*!< Account code */
00164    char rdnis[80];            /*!< Referring DNIS, if available */
00165    int amaflags;           /*!< AMA Flags */
00166    struct ast_rtp *rtp;       /*!< RTP Session */
00167    struct ast_dsp *vad;       /*!< Used for in-band DTMF detection */
00168    int nativeformats;         /*!< Codec formats supported by a channel */
00169    int needhangup;            /*!< Send hangup when Asterisk is ready */
00170    int hangupcause;        /*!< Hangup cause from OpenH323 layer */
00171    int newstate;           /*!< Pending state change */
00172    int newcontrol;            /*!< Pending control to send */
00173    int newdigit;           /*!< Pending DTMF digit to send */
00174    int newduration;        /*!< Pending DTMF digit duration to send */
00175    int pref_codec;            /*!< Preferred codec */
00176    int peercapability;        /*!< Capabilities learned from peer */
00177    int jointcapability;       /*!< Common capabilities for local and remote side */
00178    struct ast_codec_pref peer_prefs;   /*!< Preferenced list of codecs which remote side supports */
00179    int dtmf_pt[2];            /*!< Payload code used for RFC2833/CISCO messages */
00180    int curDTMF;            /*!< DTMF tone being generated to Asterisk side */
00181    int DTMFsched;          /*!< Scheduler descriptor for DTMF */
00182    int update_rtp_info;       /*!< Configuration of fd's array is pending */
00183    int recvonly;           /*!< Peer isn't wish to receive our voice stream */
00184    int txDtmfDigit;        /*!< DTMF digit being to send to H.323 side */
00185    int noInbandDtmf;       /*!< Inband DTMF processing by DSP isn't available */
00186    int connection_established;      /*!< Call got CONNECT message */
00187    int got_progress;       /*!< Call got PROGRESS message, pass inband audio */
00188    struct oh323_pvt *next;       /*!< Next channel in list */
00189 } *iflist = NULL;
00190 
00191 /*! \brief H323 User list */
00192 static struct h323_user_list {
00193    ASTOBJ_CONTAINER_COMPONENTS(struct oh323_user);
00194 } userl;
00195 
00196 /*! \brief H323 peer list */
00197 static struct h323_peer_list {
00198    ASTOBJ_CONTAINER_COMPONENTS(struct oh323_peer);
00199 } peerl;
00200 
00201 /*! \brief H323 alias list */
00202 static struct h323_alias_list {
00203    ASTOBJ_CONTAINER_COMPONENTS(struct oh323_alias);
00204 } aliasl;
00205 
00206 /* Asterisk RTP stuff */
00207 static struct sched_context *sched;
00208 static struct io_context *io;
00209 
00210 AST_MUTEX_DEFINE_STATIC(iflock); /*!< Protect the interface list (oh323_pvt) */
00211 
00212 /*! \brief  Protect the H.323 monitoring thread, so only one process can kill or start it, and not
00213    when it's doing something critical. */
00214 AST_MUTEX_DEFINE_STATIC(monlock);
00215 
00216 /*! \brief Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */
00217 AST_MUTEX_DEFINE_STATIC(caplock);
00218 
00219 /*! \brief Protect the reload process */
00220 AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
00221 static int h323_reloading = 0;
00222 
00223 /*! \brief This is the thread for the monitor which checks for input on the channels
00224    which are not currently in use. */
00225 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00226 static int restart_monitor(void);
00227 static int h323_do_reload(void);
00228 
00229 static void delete_users(void);
00230 static void delete_aliases(void);
00231 static void prune_peers(void);
00232 
00233 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);
00234 static int oh323_digit_begin(struct ast_channel *c, char digit);
00235 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration);
00236 static int oh323_call(struct ast_channel *c, char *dest, int timeout);
00237 static int oh323_hangup(struct ast_channel *c);
00238 static int oh323_answer(struct ast_channel *c);
00239 static struct ast_frame *oh323_read(struct ast_channel *c);
00240 static int oh323_write(struct ast_channel *c, struct ast_frame *frame);
00241 static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen);
00242 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00243 
00244 static const struct ast_channel_tech oh323_tech = {
00245    .type = "H323",
00246    .description = tdesc,
00247    .capabilities = AST_FORMAT_AUDIO_MASK,
00248    .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
00249    .requester = oh323_request,
00250    .send_digit_begin = oh323_digit_begin,
00251    .send_digit_end = oh323_digit_end,
00252    .call = oh323_call,
00253    .hangup = oh323_hangup,
00254    .answer = oh323_answer,
00255    .read = oh323_read,
00256    .write = oh323_write,
00257    .indicate = oh323_indicate,
00258    .fixup = oh323_fixup,
00259    /* disable, for now */
00260 #if 0
00261    .bridge = ast_rtp_bridge,
00262 #endif
00263 };
00264 
00265 static const char* redirectingreason2str(int redirectingreason)
00266 {
00267    switch (redirectingreason) {
00268    case 0:
00269       return "UNKNOWN";
00270    case 1:
00271       return "BUSY";
00272    case 2:
00273       return "NO_REPLY";
00274    case 0xF:
00275       return "UNCONDITIONAL";
00276    default:
00277       return "NOREDIRECT";
00278    }
00279 }
00280 
00281 static void oh323_destroy_alias(struct oh323_alias *alias)
00282 {
00283    if (h323debug)
00284       ast_debug(1, "Destroying alias '%s'\n", alias->name);
00285    ast_free(alias);
00286 }
00287 
00288 static void oh323_destroy_user(struct oh323_user *user)
00289 {
00290    if (h323debug)
00291       ast_debug(1, "Destroying user '%s'\n", user->name);
00292    ast_free_ha(user->ha);
00293    ast_free(user);
00294 }
00295 
00296 static void oh323_destroy_peer(struct oh323_peer *peer)
00297 {
00298    if (h323debug)
00299       ast_debug(1, "Destroying peer '%s'\n", peer->name);
00300    ast_free_ha(peer->ha);
00301    ast_free(peer);
00302 }
00303 
00304 static int oh323_simulate_dtmf_end(const void *data)
00305 {
00306    struct oh323_pvt *pvt = (struct oh323_pvt *)data;
00307 
00308    if (pvt) {
00309       ast_mutex_lock(&pvt->lock);
00310       /* Don't hold pvt lock while trying to lock the channel */
00311       while(pvt->owner && ast_channel_trylock(pvt->owner)) {
00312          ast_mutex_unlock(&pvt->lock);
00313          usleep(1);
00314          ast_mutex_lock(&pvt->lock);
00315       }
00316 
00317       if (pvt->owner) {
00318          struct ast_frame f = {
00319             .frametype = AST_FRAME_DTMF_END,
00320             .subclass = pvt->curDTMF,
00321             .samples = 0,
00322             .src = "SIMULATE_DTMF_END",
00323          };
00324          ast_queue_frame(pvt->owner, &f);
00325          ast_channel_unlock(pvt->owner);
00326       }
00327 
00328       pvt->DTMFsched = -1;
00329       ast_mutex_unlock(&pvt->lock);
00330    }
00331 
00332    return 0;
00333 }
00334 
00335 /*! \brief Channel and private structures should be already locked */
00336 static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt)
00337 {
00338    if (c->nativeformats != pvt->nativeformats) {
00339       if (h323debug)
00340          ast_debug(1, "Preparing %s for new native format\n", c->name);
00341       c->nativeformats = pvt->nativeformats;
00342       ast_set_read_format(c, c->readformat);
00343       ast_set_write_format(c, c->writeformat);
00344    }
00345    if (pvt->needhangup) {
00346       if (h323debug)
00347          ast_debug(1, "Process pending hangup for %s\n", c->name);
00348       c->_softhangup |= AST_SOFTHANGUP_DEV;
00349       c->hangupcause = pvt->hangupcause;
00350       ast_queue_hangup(c);
00351       pvt->needhangup = 0;
00352       pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->DTMFsched = -1;
00353    }
00354    if (pvt->newstate >= 0) {
00355       ast_setstate(c, pvt->newstate);
00356       pvt->newstate = -1;
00357    }
00358    if (pvt->newcontrol >= 0) {
00359       ast_queue_control(c, pvt->newcontrol);
00360       pvt->newcontrol = -1;
00361    }
00362    if (pvt->newdigit >= 0) {
00363       struct ast_frame f = {
00364          .frametype = AST_FRAME_DTMF_END,
00365          .subclass = pvt->newdigit,
00366          .samples = pvt->newduration * 8,
00367          .len = pvt->newduration,
00368          .src = "UPDATE_INFO",
00369       };
00370       if (pvt->newdigit == ' ') {      /* signalUpdate message */
00371          f.subclass = pvt->curDTMF;
00372          if (pvt->DTMFsched >= 0) {
00373             AST_SCHED_DEL(sched, pvt->DTMFsched);
00374          }
00375       } else {                /* Regular input or signal message */
00376          if (pvt->newduration) {    /* This is a signal, signalUpdate follows */
00377             f.frametype = AST_FRAME_DTMF_BEGIN;
00378             AST_SCHED_DEL(sched, pvt->DTMFsched);
00379             pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt);
00380             if (h323debug)
00381                ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched);
00382          }
00383          pvt->curDTMF = pvt->newdigit;
00384       }
00385       ast_queue_frame(c, &f);
00386       pvt->newdigit = -1;
00387    }
00388    if (pvt->update_rtp_info > 0) {
00389       if (pvt->rtp) {
00390          ast_jb_configure(c, &global_jbconf);
00391          ast_channel_set_fd(c, 0, ast_rtp_fd(pvt->rtp));
00392          ast_channel_set_fd(c, 1, ast_rtcp_fd(pvt->rtp));
00393          ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
00394       }
00395       pvt->update_rtp_info = -1;
00396    }
00397 }
00398 
00399 /*! \brief Only channel structure should be locked */
00400 static void oh323_update_info(struct ast_channel *c)
00401 {
00402    struct oh323_pvt *pvt = c->tech_pvt;
00403 
00404    if (pvt) {
00405       ast_mutex_lock(&pvt->lock);
00406       __oh323_update_info(c, pvt);
00407       ast_mutex_unlock(&pvt->lock);
00408    }
00409 }
00410 
00411 static void cleanup_call_details(call_details_t *cd)
00412 {
00413    if (cd->call_token) {
00414       ast_free(cd->call_token);
00415       cd->call_token = NULL;
00416    }
00417    if (cd->call_source_aliases) {
00418       ast_free(cd->call_source_aliases);
00419       cd->call_source_aliases = NULL;
00420    }
00421    if (cd->call_dest_alias) {
00422       ast_free(cd->call_dest_alias);
00423       cd->call_dest_alias = NULL;
00424    }
00425    if (cd->call_source_name) {
00426       ast_free(cd->call_source_name);
00427       cd->call_source_name = NULL;
00428    }
00429    if (cd->call_source_e164) {
00430       ast_free(cd->call_source_e164);
00431       cd->call_source_e164 = NULL;
00432    }
00433    if (cd->call_dest_e164) {
00434       ast_free(cd->call_dest_e164);
00435       cd->call_dest_e164 = NULL;
00436    }
00437    if (cd->sourceIp) {
00438       ast_free(cd->sourceIp);
00439       cd->sourceIp = NULL;
00440    }
00441    if (cd->redirect_number) {
00442       ast_free(cd->redirect_number);
00443       cd->redirect_number = NULL;
00444    }
00445 }
00446 
00447 static void __oh323_destroy(struct oh323_pvt *pvt)
00448 {
00449    struct oh323_pvt *cur, *prev = NULL;
00450 
00451    AST_SCHED_DEL(sched, pvt->DTMFsched);
00452 
00453    if (pvt->rtp) {
00454       ast_rtp_destroy(pvt->rtp);
00455    }
00456 
00457    /* Free dsp used for in-band DTMF detection */
00458    if (pvt->vad) {
00459       ast_dsp_free(pvt->vad);
00460    }
00461    cleanup_call_details(&pvt->cd);
00462 
00463    /* Unlink us from the owner if we have one */
00464    if (pvt->owner) {
00465       ast_channel_lock(pvt->owner);
00466       if (h323debug)
00467          ast_debug(1, "Detaching from %s\n", pvt->owner->name);
00468       pvt->owner->tech_pvt = NULL;
00469       ast_channel_unlock(pvt->owner);
00470    }
00471    cur = iflist;
00472    while(cur) {
00473       if (cur == pvt) {
00474          if (prev)
00475             prev->next = cur->next;
00476          else
00477             iflist = cur->next;
00478          break;
00479       }
00480       prev = cur;
00481       cur = cur->next;
00482    }
00483    if (!cur) {
00484       ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur);
00485    } else {
00486       ast_mutex_unlock(&pvt->lock);
00487       ast_mutex_destroy(&pvt->lock);
00488       ast_free(pvt);
00489    }
00490 }
00491 
00492 static void oh323_destroy(struct oh323_pvt *pvt)
00493 {
00494    if (h323debug) {
00495       ast_debug(1, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
00496    }
00497    ast_mutex_lock(&iflock);
00498    ast_mutex_lock(&pvt->lock);
00499    __oh323_destroy(pvt);
00500    ast_mutex_unlock(&iflock);
00501 }
00502 
00503 static int oh323_digit_begin(struct ast_channel *c, char digit)
00504 {
00505    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00506    char *token;
00507 
00508    if (!pvt) {
00509       ast_log(LOG_ERROR, "No private structure?! This is bad\n");
00510       return -1;
00511    }
00512    ast_mutex_lock(&pvt->lock);
00513    if (pvt->rtp &&
00514       (((pvt->options.dtmfmode & H323_DTMF_RFC2833) && pvt->dtmf_pt[0])
00515        /*|| ((pvt->options.dtmfmode & H323_DTMF_CISCO) && pvt->dtmf_pt[1]))*/)) {
00516       /* out-of-band DTMF */
00517       if (h323debug) {
00518          ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name);
00519       }
00520       ast_rtp_senddigit_begin(pvt->rtp, digit);
00521       ast_mutex_unlock(&pvt->lock);
00522    } else if (pvt->txDtmfDigit != digit) {
00523       /* in-band DTMF */
00524       if (h323debug) {
00525          ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, c->name);
00526       }
00527       pvt->txDtmfDigit = digit;
00528       token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
00529       ast_mutex_unlock(&pvt->lock);
00530       h323_send_tone(token, digit);
00531       if (token) {
00532          ast_free(token);
00533       }
00534    } else
00535       ast_mutex_unlock(&pvt->lock);
00536    oh323_update_info(c);
00537    return 0;
00538 }
00539 
00540 /*! \brief
00541  * Send (play) the specified digit to the channel.
00542  *
00543  */
00544 static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration)
00545 {
00546    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00547    char *token;
00548 
00549    if (!pvt) {
00550       ast_log(LOG_ERROR, "No private structure?! This is bad\n");
00551       return -1;
00552    }
00553    ast_mutex_lock(&pvt->lock);
00554    if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && ((pvt->dtmf_pt[0] > 0) || (pvt->dtmf_pt[0] > 0))) {
00555       /* out-of-band DTMF */
00556       if (h323debug) {
00557          ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
00558       }
00559       ast_rtp_senddigit_end(pvt->rtp, digit);
00560       ast_mutex_unlock(&pvt->lock);
00561    } else {
00562       /* in-band DTMF */
00563       if (h323debug) {
00564          ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, c->name, duration);
00565       }
00566       pvt->txDtmfDigit = ' ';
00567       token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
00568       ast_mutex_unlock(&pvt->lock);
00569       h323_send_tone(token, ' ');
00570       if (token) {
00571          ast_free(token);
00572       }
00573    }
00574    oh323_update_info(c);
00575    return 0;
00576 }
00577 
00578 /*! \brief
00579  * Make a call over the specified channel to the specified
00580  * destination.
00581  * Returns -1 on error, 0 on success.
00582  */
00583 static int oh323_call(struct ast_channel *c, char *dest, int timeout)
00584 {
00585    int res = 0;
00586    struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
00587    const char *addr;
00588    char called_addr[1024];
00589 
00590    if (h323debug) {
00591       ast_debug(1, "Calling to %s on %s\n", dest, c->name);
00592    }
00593    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
00594       ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
00595       return -1;
00596    }
00597    ast_mutex_lock(&pvt->lock);
00598    if (!gatekeeper_disable) {
00599       if (ast_strlen_zero(pvt->exten)) {
00600          ast_copy_string(called_addr, dest, sizeof(called_addr));
00601       } else {
00602          snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
00603       }
00604    } else {
00605       res = htons(pvt->sa.sin_port);
00606       addr = ast_inet_ntoa(pvt->sa.sin_addr);
00607       if (ast_strlen_zero(pvt->exten)) {
00608          snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);
00609       } else {
00610          snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);
00611       }
00612    }
00613    /* make sure null terminated */
00614    called_addr[sizeof(called_addr) - 1] = '\0';
00615 
00616    if (c->cid.cid_num)
00617       ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
00618 
00619    if (c->cid.cid_name)
00620       ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
00621 
00622    if (c->cid.cid_rdnis) {
00623       ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
00624    }
00625 
00626    pvt->options.presentation = c->cid.cid_pres;
00627    pvt->options.type_of_number = c->cid.cid_ton;
00628 
00629    if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
00630       if (!strcasecmp(addr, "UNKNOWN"))
00631          pvt->options.redirect_reason = 0;
00632       else if (!strcasecmp(addr, "BUSY"))
00633          pvt->options.redirect_reason = 1;
00634       else if (!strcasecmp(addr, "NO_REPLY"))
00635          pvt->options.redirect_reason = 2;
00636       else if (!strcasecmp(addr, "UNCONDITIONAL"))
00637          pvt->options.redirect_reason = 15;
00638       else
00639          pvt->options.redirect_reason = -1;
00640    } else
00641       pvt->options.redirect_reason = -1;
00642 
00643    pvt->options.transfer_capability = c->transfercapability;
00644 
00645    /* indicate that this is an outgoing call */
00646    pvt->outgoing = 1;
00647 
00648    ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability));
00649    if (h323debug)
00650       ast_debug(1, "Placing outgoing call to %s, %d/%d\n", called_addr, pvt->options.dtmfcodec[0], pvt->options.dtmfcodec[1]);
00651    ast_mutex_unlock(&pvt->lock);
00652    res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
00653    if (res) {
00654       ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
00655       return -1;
00656    }
00657    oh323_update_info(c);
00658    return 0;
00659 }
00660 
00661 static int oh323_answer(struct ast_channel *c)
00662 {
00663    int res;
00664    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00665    char *token;
00666 
00667    if (h323debug)
00668       ast_debug(1, "Answering on %s\n", c->name);
00669 
00670    ast_mutex_lock(&pvt->lock);
00671    token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
00672    ast_mutex_unlock(&pvt->lock);
00673    res = h323_answering_call(token, 0);
00674    if (token)
00675       ast_free(token);
00676 
00677    oh323_update_info(c);
00678    if (c->_state != AST_STATE_UP) {
00679       ast_setstate(c, AST_STATE_UP);
00680    }
00681    return res;
00682 }
00683 
00684 static int oh323_hangup(struct ast_channel *c)
00685 {
00686    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00687    int q931cause = AST_CAUSE_NORMAL_CLEARING;
00688    char *call_token;
00689 
00690 
00691    if (h323debug)
00692       ast_debug(1, "Hanging up and scheduling destroy of call %s\n", c->name);
00693 
00694    if (!c->tech_pvt) {
00695       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00696       return 0;
00697    }
00698    ast_mutex_lock(&pvt->lock);
00699    /* Determine how to disconnect */
00700    if (pvt->owner != c) {
00701       ast_log(LOG_WARNING, "Huh?  We aren't the owner?\n");
00702       ast_mutex_unlock(&pvt->lock);
00703       return 0;
00704    }
00705 
00706    pvt->owner = NULL;
00707    c->tech_pvt = NULL;
00708 
00709    if (c->hangupcause) {
00710       q931cause = c->hangupcause;
00711    } else {
00712       const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
00713       if (cause) {
00714          if (!strcmp(cause, "CONGESTION")) {
00715             q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
00716          } else if (!strcmp(cause, "BUSY")) {
00717             q931cause = AST_CAUSE_USER_BUSY;
00718          } else if (!strcmp(cause, "CHANISUNVAIL")) {
00719             q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
00720          } else if (!strcmp(cause, "NOANSWER")) {
00721             q931cause = AST_CAUSE_NO_ANSWER;
00722          } else if (!strcmp(cause, "CANCEL")) {
00723             q931cause = AST_CAUSE_CALL_REJECTED;
00724          }
00725       }
00726    }
00727 
00728    /* Start the process if it's not already started */
00729    if (!pvt->alreadygone && !pvt->hangupcause) {
00730       call_token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
00731       if (call_token) {
00732          /* Release lock to eliminate deadlock */
00733          ast_mutex_unlock(&pvt->lock);
00734          if (h323_clear_call(call_token, q931cause)) {
00735             ast_log(LOG_WARNING, "ClearCall failed.\n");
00736          }
00737          ast_free(call_token);
00738          ast_mutex_lock(&pvt->lock);
00739       }
00740    }
00741    pvt->needdestroy = 1;
00742    ast_mutex_unlock(&pvt->lock);
00743 
00744    /* Update usage counter */
00745    ast_module_unref(ast_module_info->self);
00746 
00747    return 0;
00748 }
00749 
00750 /*! \brief Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
00751 static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
00752 {
00753    struct ast_frame *f;
00754 
00755    /* Only apply it for the first packet, we just need the correct ip/port */
00756    if (pvt->options.nat) {
00757       ast_rtp_setnat(pvt->rtp, pvt->options.nat);
00758       pvt->options.nat = 0;
00759    }
00760 
00761    f = ast_rtp_read(pvt->rtp);
00762    /* Don't send RFC2833 if we're not supposed to */
00763    if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) {
00764       return &ast_null_frame;
00765    }
00766    if (pvt->owner) {
00767       /* We already hold the channel lock */
00768       if (f->frametype == AST_FRAME_VOICE) {
00769          if (f->subclass != pvt->owner->nativeformats) {
00770             /* Try to avoid deadlock */
00771             if (ast_channel_trylock(pvt->owner)) {
00772                ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n");
00773                return &ast_null_frame;
00774             }
00775             if (h323debug)
00776                ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
00777             pvt->owner->nativeformats = f->subclass;
00778             pvt->nativeformats = f->subclass;
00779             ast_set_read_format(pvt->owner, pvt->owner->readformat);
00780             ast_set_write_format(pvt->owner, pvt->owner->writeformat);
00781             ast_channel_unlock(pvt->owner);
00782          }
00783          /* Do in-band DTMF detection */
00784          if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) {
00785             if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) {
00786                if (!ast_channel_trylock(pvt->owner)) {
00787                   f = ast_dsp_process(pvt->owner, pvt->vad, f);
00788                   ast_channel_unlock(pvt->owner);
00789                }
00790                else
00791                   ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");
00792             } else if (pvt->nativeformats && !pvt->noInbandDtmf) {
00793                ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass));
00794                pvt->noInbandDtmf = 1;
00795             }
00796             if (f &&(f->frametype == AST_FRAME_DTMF)) {
00797                if (h323debug)
00798                   ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass);
00799             }
00800          }
00801       }
00802    }
00803    return f;
00804 }
00805 
00806 static struct ast_frame *oh323_read(struct ast_channel *c)
00807 {
00808    struct ast_frame *fr;
00809    struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
00810    ast_mutex_lock(&pvt->lock);
00811    __oh323_update_info(c, pvt);
00812    switch(c->fdno) {
00813    case 0:
00814       fr = oh323_rtp_read(pvt);
00815       break;
00816    case 1:
00817       if (pvt->rtp)
00818          fr = ast_rtcp_read(pvt->rtp);
00819       else
00820          fr = &ast_null_frame;
00821       break;
00822    default:
00823       ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name);
00824       fr = &ast_null_frame;
00825       break;
00826    }
00827    ast_mutex_unlock(&pvt->lock);
00828    return fr;
00829 }
00830 
00831 static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
00832 {
00833    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00834    int res = 0;
00835    if (frame->frametype != AST_FRAME_VOICE) {
00836       if (frame->frametype == AST_FRAME_IMAGE) {
00837          return 0;
00838       } else {
00839          ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
00840          return 0;
00841       }
00842    } else {
00843       if (!(frame->subclass & c->nativeformats)) {
00844          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
00845             frame->subclass, c->nativeformats, c->readformat, c->writeformat);
00846          return 0;
00847       }
00848    }
00849    if (pvt) {
00850       ast_mutex_lock(&pvt->lock);
00851       if (pvt->rtp && !pvt->recvonly)
00852          res = ast_rtp_write(pvt->rtp, frame);
00853       __oh323_update_info(c, pvt);
00854       ast_mutex_unlock(&pvt->lock);
00855    }
00856    return res;
00857 }
00858 
00859 static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen)
00860 {
00861 
00862    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00863    char *token = (char *)NULL;
00864    int res = -1;
00865    int got_progress;
00866 
00867    ast_mutex_lock(&pvt->lock);
00868    token = (pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL);
00869    got_progress = pvt->got_progress;
00870    if (condition == AST_CONTROL_PROGRESS)
00871       pvt->got_progress = 1;
00872    else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))
00873       pvt->alreadygone = 1;
00874    ast_mutex_unlock(&pvt->lock);
00875 
00876    if (h323debug)
00877       ast_debug(1, "OH323: Indicating %d on %s (%s)\n", condition, token, c->name);
00878 
00879    switch(condition) {
00880    case AST_CONTROL_RINGING:
00881       if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
00882          h323_send_alerting(token);
00883          res = (got_progress ? 0 : -1);   /* Do not simulate any audio tones if we got PROGRESS message */
00884       }
00885       break;
00886    case AST_CONTROL_PROGRESS:
00887       if (c->_state != AST_STATE_UP) {
00888          /* Do not send PROGRESS message more than once */
00889          if (!got_progress)
00890             h323_send_progress(token);
00891          res = 0;
00892       }
00893       break;
00894    case AST_CONTROL_BUSY:
00895       if (c->_state != AST_STATE_UP) {
00896          h323_answering_call(token, 1);
00897          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00898          res = 0;
00899       }
00900       break;
00901    case AST_CONTROL_CONGESTION:
00902       if (c->_state != AST_STATE_UP) {
00903          h323_answering_call(token, 1);
00904          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00905          res = 0;
00906       }
00907       break;
00908    case AST_CONTROL_HOLD:
00909       h323_hold_call(token, 1);
00910       /* We should start MOH only if remote party isn't provide audio for us */
00911       ast_moh_start(c, data, NULL);
00912       res = 0;
00913       break;
00914    case AST_CONTROL_UNHOLD:
00915       h323_hold_call(token, 0);
00916       ast_moh_stop(c);
00917       res = 0;
00918       break;
00919    case AST_CONTROL_SRCUPDATE:
00920       ast_rtp_new_source(pvt->rtp);
00921       res = 0;
00922       break;
00923    case AST_CONTROL_PROCEEDING:
00924    case -1:
00925       break;
00926    default:
00927       ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
00928       break;
00929    }
00930 
00931    if (h323debug)
00932       ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
00933    if (token)
00934       ast_free(token);
00935    oh323_update_info(c);
00936 
00937    return res;
00938 }
00939 
00940 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00941 {
00942    struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt;
00943 
00944    ast_mutex_lock(&pvt->lock);
00945    if (pvt->owner != oldchan) {
00946       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
00947       return -1;
00948    }
00949    pvt->owner = newchan;
00950    ast_mutex_unlock(&pvt->lock);
00951    return 0;
00952 }
00953 
00954 static int __oh323_rtp_create(struct oh323_pvt *pvt)
00955 {
00956    struct in_addr our_addr;
00957 
00958    if (pvt->rtp)
00959       return 0;
00960 
00961    if (ast_find_ourip(&our_addr, bindaddr)) {
00962       ast_mutex_unlock(&pvt->lock);
00963       ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00964       return -1;
00965    }
00966    pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr);
00967    if (!pvt->rtp) {
00968       ast_mutex_unlock(&pvt->lock);
00969       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00970       return -1;
00971    }
00972    if (h323debug)
00973       ast_debug(1, "Created RTP channel\n");
00974 
00975    ast_rtp_setqos(pvt->rtp, tos, cos, "H323 RTP");
00976 
00977    if (h323debug)
00978       ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
00979    ast_rtp_setnat(pvt->rtp, pvt->options.nat);
00980 
00981    if (pvt->dtmf_pt[0] > 0)
00982       ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
00983    if (pvt->dtmf_pt[1] > 0)
00984       ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
00985 
00986    if (pvt->peercapability)
00987       ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
00988 
00989    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
00990       ast_jb_configure(pvt->owner, &global_jbconf);
00991       ast_channel_set_fd(pvt->owner, 0, ast_rtp_fd(pvt->rtp));
00992       ast_channel_set_fd(pvt->owner, 1, ast_rtcp_fd(pvt->rtp));
00993       ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
00994       ast_channel_unlock(pvt->owner);
00995    } else
00996       pvt->update_rtp_info = 1;
00997 
00998    return 0;
00999 }
01000 
01001 /*! \brief Private structure should be locked on a call */
01002 static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host)
01003 {
01004    struct ast_channel *ch;
01005    char *cid_num, *cid_name;
01006    int fmt;
01007 
01008    if (!ast_strlen_zero(pvt->options.cid_num))
01009       cid_num = pvt->options.cid_num;
01010    else
01011       cid_num = pvt->cd.call_source_e164;
01012 
01013    if (!ast_strlen_zero(pvt->options.cid_name))
01014       cid_name = pvt->options.cid_name;
01015    else
01016       cid_name = pvt->cd.call_source_name;
01017    
01018    /* Don't hold a oh323_pvt lock while we allocate a chanel */
01019    ast_mutex_unlock(&pvt->lock);
01020    ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host);
01021    /* Update usage counter */
01022    ast_module_ref(ast_module_info->self);
01023    ast_mutex_lock(&pvt->lock);
01024    if (ch) {
01025       ch->tech = &oh323_tech;
01026       if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
01027          fmt = global_options.capability;
01028       ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
01029       pvt->nativeformats = ch->nativeformats;
01030       fmt = ast_best_codec(ch->nativeformats);
01031       ch->writeformat = fmt;
01032       ch->rawwriteformat = fmt;
01033       ch->readformat = fmt;
01034       ch->rawreadformat = fmt;
01035       if (!pvt->rtp)
01036          __oh323_rtp_create(pvt);
01037 #if 0
01038       ast_channel_set_fd(ch, 0, ast_rtp_fd(pvt->rtp));
01039       ast_channel_set_fd(ch, 1, ast_rtcp_fd(pvt->rtp));
01040 #endif
01041 #ifdef VIDEO_SUPPORT
01042       if (pvt->vrtp) {
01043          ast_channel_set_fd(ch, 2, ast_rtp_fd(pvt->vrtp));
01044          ast_channel_set_fd(ch, 3, ast_rtcp_fd(pvt->vrtp));
01045       }
01046 #endif
01047 #ifdef T38_SUPPORT
01048       if (pvt->udptl) {
01049          ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl));
01050       }
01051 #endif
01052       if (state == AST_STATE_RING) {
01053          ch->rings = 1;
01054       }
01055       /* Allocate dsp for in-band DTMF support */
01056       if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
01057          pvt->vad = ast_dsp_new();
01058          ast_dsp_set_features(pvt->vad, DSP_FEATURE_DTMF_DETECT);
01059       }
01060       /* Register channel functions. */
01061       ch->tech_pvt = pvt;
01062       /* Set the owner of this channel */
01063       pvt->owner = ch;
01064 
01065       ast_copy_string(ch->context, pvt->context, sizeof(ch->context));
01066       ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten));
01067       ch->priority = 1;
01068       if (!ast_strlen_zero(pvt->accountcode)) {
01069          ast_string_field_set(ch, accountcode, pvt->accountcode);
01070       }
01071       if (pvt->amaflags) {
01072          ch->amaflags = pvt->amaflags;
01073       }
01074 
01075       /* Don't use ast_set_callerid() here because it will
01076        * generate a needless NewCallerID event */
01077       ch->cid.cid_ani = ast_strdup(cid_num);
01078 
01079       if (pvt->cd.redirect_reason >= 0) {
01080          ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number);
01081          pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
01082       }
01083       ch->cid.cid_pres = pvt->cd.presentation;
01084       ch->cid.cid_ton = pvt->cd.type_of_number;
01085 
01086       if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
01087          ch->cid.cid_dnid = ast_strdup(pvt->exten);
01088       }
01089       if (pvt->cd.transfer_capability >= 0)
01090          ch->transfercapability = pvt->cd.transfer_capability;
01091       if (state != AST_STATE_DOWN) {
01092          if (ast_pbx_start(ch)) {
01093             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
01094             ast_hangup(ch);
01095             ch = NULL;
01096          }
01097       }
01098    } else {
01099       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01100    }
01101    return ch;
01102 }
01103 
01104 static struct oh323_pvt *oh323_alloc(int callid)
01105 {
01106    struct oh323_pvt *pvt;
01107 
01108    pvt = ast_calloc(1, sizeof(*pvt));
01109    if (!pvt) {
01110       ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
01111       return NULL;
01112    }
01113    pvt->cd.redirect_reason = -1;
01114    pvt->cd.transfer_capability = -1;
01115    /* Ensure the call token is allocated for outgoing call */
01116    if (!callid) {
01117       if ((pvt->cd).call_token == NULL) {
01118          (pvt->cd).call_token = ast_calloc(1, 128);
01119       }
01120       if (!pvt->cd.call_token) {
01121          ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
01122          ast_rtp_destroy(pvt->rtp);
01123          ast_free(pvt);
01124          return NULL;
01125       }
01126       memset((char *)(pvt->cd).call_token, 0, 128);
01127       pvt->cd.call_reference = callid;
01128    }
01129    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01130    pvt->jointcapability = pvt->options.capability;
01131    if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) {
01132       pvt->nonCodecCapability |= AST_RTP_DTMF;
01133    } else {
01134       pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01135    }
01136    ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
01137    pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
01138    ast_mutex_init(&pvt->lock);
01139    /* Add to interface list */
01140    ast_mutex_lock(&iflock);
01141    pvt->next = iflist;
01142    iflist = pvt;
01143    ast_mutex_unlock(&iflock);
01144    return pvt;
01145 }
01146 
01147 static struct oh323_pvt *find_call_locked(int call_reference, const char *token)
01148 {
01149    struct oh323_pvt *pvt;
01150 
01151    ast_mutex_lock(&iflock);
01152    pvt = iflist;
01153    while(pvt) {
01154       if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01155          /* Found the call */
01156          if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01157             ast_mutex_lock(&pvt->lock);
01158             ast_mutex_unlock(&iflock);
01159             return pvt;
01160          } else if (token == NULL) {
01161             ast_log(LOG_WARNING, "Call Token is NULL\n");
01162             ast_mutex_lock(&pvt->lock);
01163             ast_mutex_unlock(&iflock);
01164             return pvt;
01165          }
01166       }
01167       pvt = pvt->next;
01168    }
01169    ast_mutex_unlock(&iflock);
01170    return NULL;
01171 }
01172 
01173 static int update_state(struct oh323_pvt *pvt, int state, int signal)
01174 {
01175    if (!pvt)
01176       return 0;
01177    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01178       if (state >= 0)
01179          ast_setstate(pvt->owner, state);
01180       if (signal >= 0)
01181          ast_queue_control(pvt->owner, signal);
01182       ast_channel_unlock(pvt->owner);
01183       return 1;
01184    }
01185    else {
01186       if (state >= 0)
01187          pvt->newstate = state;
01188       if (signal >= 0)
01189          pvt->newcontrol = signal;
01190       return 0;
01191    }
01192 }
01193 
01194 static struct oh323_alias *build_alias(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01195 {
01196    struct oh323_alias *alias;
01197    int found = 0;
01198 
01199    alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
01200 
01201    if (alias)
01202       found++;
01203    else {
01204       if (!(alias = ast_calloc(1, sizeof(*alias))))
01205          return NULL;
01206       ASTOBJ_INIT(alias);
01207    }
01208    if (!found && name)
01209       ast_copy_string(alias->name, name, sizeof(alias->name));
01210    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01211       if (!strcasecmp(v->name, "e164")) {
01212          ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
01213       } else if (!strcasecmp(v->name, "prefix")) {
01214          ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
01215       } else if (!strcasecmp(v->name, "context")) {
01216          ast_copy_string(alias->context, v->value, sizeof(alias->context));
01217       } else if (!strcasecmp(v->name, "secret")) {
01218          ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
01219       } else {
01220          if (strcasecmp(v->value, "h323")) {
01221             ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
01222          }
01223       }
01224    }
01225    ASTOBJ_UNMARK(alias);
01226    return alias;
01227 }
01228 
01229 static struct oh323_alias *realtime_alias(const char *alias)
01230 {
01231    struct ast_variable *var, *tmp;
01232    struct oh323_alias *a;
01233 
01234    var = ast_load_realtime("h323", "name", alias, (char *)NULL);
01235 
01236    if (!var)
01237       return NULL;
01238 
01239    for (tmp = var; tmp; tmp = tmp->next) {
01240       if (!strcasecmp(tmp->name, "type") &&
01241       !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01242          ast_variables_destroy(var);
01243          return NULL;
01244       }
01245    }
01246 
01247    a = build_alias(alias, var, NULL, 1);
01248 
01249    ast_variables_destroy(var);
01250 
01251    return a;
01252 }
01253 
01254 static int update_common_options(struct ast_variable *v, struct call_options *options)
01255 {
01256    int tmp = 0;
01257    char *val, *opt;
01258 
01259    if (!strcasecmp(v->name, "allow")) {
01260       ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
01261    } else if (!strcasecmp(v->name, "autoframing")) {
01262       options->autoframing = ast_true(v->value);
01263    } else if (!strcasecmp(v->name, "disallow")) {
01264       ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
01265    } else if (!strcasecmp(v->name, "dtmfmode")) {
01266       val = ast_strdupa(v->value);
01267       if ((opt = strchr(val, ':')) != (char *)NULL) {
01268          *opt++ = '\0';
01269          tmp = atoi(opt);
01270       }
01271       if (!strcasecmp(v->value, "inband")) {
01272          options->dtmfmode |= H323_DTMF_INBAND;
01273       } else if (!strcasecmp(val, "rfc2833")) {
01274          options->dtmfmode |= H323_DTMF_RFC2833;
01275          if (!opt) {
01276             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01277          } else if ((tmp >= 96) && (tmp < 128)) {
01278             options->dtmfcodec[0] = tmp;
01279          } else {
01280             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01281             ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]);
01282          }
01283       } else if (!strcasecmp(val, "cisco")) {
01284          options->dtmfmode |= H323_DTMF_CISCO;
01285          if (!opt) {
01286             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01287          } else if ((tmp >= 96) && (tmp < 128)) {
01288             options->dtmfcodec[1] = tmp;
01289          } else {
01290             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01291             ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]);
01292          }
01293       } else if (!strcasecmp(v->value, "h245-signal")) {
01294          options->dtmfmode |= H323_DTMF_SIGNAL;
01295       } else {
01296          ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno);
01297       }
01298    } else if (!strcasecmp(v->name, "dtmfcodec")) {
01299       ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno);
01300       tmp = atoi(v->value);
01301       if (tmp < 96)
01302          ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
01303       else
01304          options->dtmfcodec[0] = tmp;
01305    } else if (!strcasecmp(v->name, "bridge")) {
01306       options->bridge = ast_true(v->value);
01307    } else if (!strcasecmp(v->name, "nat")) {
01308       options->nat = ast_true(v->value);
01309    } else if (!strcasecmp(v->name, "fastStart")) {
01310       options->fastStart = ast_true(v->value);
01311    } else if (!strcasecmp(v->name, "h245Tunneling")) {
01312       options->h245Tunneling = ast_true(v->value);
01313    } else if (!strcasecmp(v->name, "silenceSuppression")) {
01314       options->silenceSuppression = ast_true(v->value);
01315    } else if (!strcasecmp(v->name, "progress_setup")) {
01316       tmp = atoi(v->value);
01317       if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
01318          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01319          tmp = 0;
01320       }
01321       options->progress_setup = tmp;
01322    } else if (!strcasecmp(v->name, "progress_alert")) {
01323       tmp = atoi(v->value);
01324       if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
01325          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01326          tmp = 0;
01327       }
01328       options->progress_alert = tmp;
01329    } else if (!strcasecmp(v->name, "progress_audio")) {
01330       options->progress_audio = ast_true(v->value);
01331    } else if (!strcasecmp(v->name, "callerid")) {
01332       ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
01333    } else if (!strcasecmp(v->name, "fullname")) {
01334       ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
01335    } else if (!strcasecmp(v->name, "cid_number")) {
01336       ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
01337    } else if (!strcasecmp(v->name, "tunneling")) {
01338       if (!strcasecmp(v->value, "none"))
01339          options->tunnelOptions = 0;
01340       else if (!strcasecmp(v->value, "cisco"))
01341          options->tunnelOptions |= H323_TUNNEL_CISCO;
01342       else if (!strcasecmp(v->value, "qsig"))
01343          options->tunnelOptions |= H323_TUNNEL_QSIG;
01344       else
01345          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01346    } else if (!strcasecmp(v->name, "hold")) {
01347       if (!strcasecmp(v->value, "none"))
01348          options->holdHandling = ~0;
01349       else if (!strcasecmp(v->value, "notify"))
01350          options->holdHandling |= H323_HOLD_NOTIFY;
01351       else if (!strcasecmp(v->value, "q931only"))
01352          options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY;
01353       else if (!strcasecmp(v->value, "h450"))
01354          options->holdHandling |= H323_HOLD_H450;
01355       else
01356          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01357    } else
01358       return 1;
01359 
01360    return 0;
01361 }
01362 
01363 static struct oh323_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01364 {
01365    struct oh323_user *user;
01366    struct ast_ha *oldha;
01367    int found = 0;
01368    int format;
01369 
01370    user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
01371 
01372    if (user)
01373       found++;
01374    else {
01375       if (!(user = ast_calloc(1, sizeof(*user))))
01376          return NULL;
01377       ASTOBJ_INIT(user);
01378    }
01379    oldha = user->ha;
01380    user->ha = (struct ast_ha *)NULL;
01381    memcpy(&user->options, &global_options, sizeof(user->options));
01382    user->options.dtmfmode = 0;
01383    user->options.holdHandling = 0;
01384    /* Set default context */
01385    ast_copy_string(user->context, default_context, sizeof(user->context));
01386    if (user && !found)
01387       ast_copy_string(user->name, name, sizeof(user->name));
01388 
01389 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01390    if (user->chanvars) {
01391       ast_variables_destroy(user->chanvars);
01392       user->chanvars = NULL;
01393    }
01394 #endif
01395 
01396    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01397       if (!update_common_options(v, &user->options))
01398          continue;
01399       if (!strcasecmp(v->name, "context")) {
01400          ast_copy_string(user->context, v->value, sizeof(user->context));
01401       } else if (!strcasecmp(v->name, "secret")) {
01402          ast_copy_string(user->secret, v->value, sizeof(user->secret));
01403       } else if (!strcasecmp(v->name, "accountcode")) {
01404          ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
01405       } else if (!strcasecmp(v->name, "host")) {
01406          if (!strcasecmp(v->value, "dynamic")) {
01407             ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
01408             ASTOBJ_UNREF(user, oh323_destroy_user);
01409             return NULL;
01410          } else if (ast_get_ip(&user->addr, v->value)) {
01411             ASTOBJ_UNREF(user, oh323_destroy_user);
01412             return NULL;
01413          }
01414          /* Let us know we need to use ip authentication */
01415          user->host = 1;
01416       } else if (!strcasecmp(v->name, "amaflags")) {
01417          format = ast_cdr_amaflags2int(v->value);
01418          if (format < 0) {
01419             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
01420          } else {
01421             user->amaflags = format;
01422          }
01423       } else if (!strcasecmp(v->name, "permit") ||
01424                !strcasecmp(v->name, "deny")) {
01425          int ha_error = 0;
01426 
01427          user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error);
01428          if (ha_error)
01429             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01430       }
01431    }
01432    if (!user->options.dtmfmode)
01433       user->options.dtmfmode = global_options.dtmfmode;
01434    if (user->options.holdHandling == ~0)
01435       user->options.holdHandling = 0;
01436    else if (!user->options.holdHandling)
01437       user->options.holdHandling = global_options.holdHandling;
01438    ASTOBJ_UNMARK(user);
01439    ast_free_ha(oldha);
01440    return user;
01441 }
01442 
01443 static struct oh323_user *realtime_user(const call_details_t *cd)
01444 {
01445    struct ast_variable *var, *tmp;
01446    struct oh323_user *user;
01447    const char *username;
01448 
01449    if (userbyalias)
01450       var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, (char *)NULL);
01451    else {
01452       username = (char *)NULL;
01453       var = ast_load_realtime("h323", "host", cd->sourceIp, (char *)NULL);
01454    }
01455 
01456    if (!var)
01457       return NULL;
01458 
01459    for (tmp = var; tmp; tmp = tmp->next) {
01460       if (!strcasecmp(tmp->name, "type") &&
01461       !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01462          ast_variables_destroy(var);
01463          return NULL;
01464       } else if (!username && !strcasecmp(tmp->name, "name"))
01465          username = tmp->value;
01466    }
01467 
01468    if (!username) {
01469       ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01470       ast_variables_destroy(var);
01471       return NULL;
01472    }
01473 
01474    user = build_user(username, var, NULL, 1);
01475 
01476    ast_variables_destroy(var);
01477 
01478    return user;
01479 }
01480 
01481 static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01482 {
01483    struct oh323_peer *peer;
01484    struct ast_ha *oldha;
01485    int found = 0;
01486 
01487    peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01488 
01489    if (peer)
01490       found++;
01491    else {
01492       if (!(peer = ast_calloc(1, sizeof(*peer))))
01493          return NULL;
01494       ASTOBJ_INIT(peer);
01495    }
01496    oldha = peer->ha;
01497    peer->ha = NULL;
01498    memcpy(&peer->options, &global_options, sizeof(peer->options));
01499    peer->options.dtmfmode = 0;
01500    peer->options.holdHandling = 0;
01501    peer->addr.sin_port = htons(h323_signalling_port);
01502    peer->addr.sin_family = AF_INET;
01503    if (!found && name)
01504       ast_copy_string(peer->name, name, sizeof(peer->name));
01505 
01506 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01507    if (peer->chanvars) {
01508       ast_variables_destroy(peer->chanvars);
01509       peer->chanvars = NULL;
01510    }
01511 #endif
01512    /* Default settings for mailbox */
01513    peer->mailbox[0] = '\0';
01514 
01515    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01516       if (!update_common_options(v, &peer->options))
01517          continue;
01518       if (!strcasecmp(v->name, "host")) {
01519          if (!strcasecmp(v->value, "dynamic")) {
01520             ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01521             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01522             return NULL;
01523          }
01524          if (ast_get_ip(&peer->addr, v->value)) {
01525             ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01526             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01527             return NULL;
01528          }
01529       } else if (!strcasecmp(v->name, "port")) {
01530          peer->addr.sin_port = htons(atoi(v->value));
01531       } else if (!strcasecmp(v->name, "permit") ||
01532                !strcasecmp(v->name, "deny")) {
01533          int ha_error = 0;
01534 
01535          peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
01536          if (ha_error)
01537             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01538       } else if (!strcasecmp(v->name, "mailbox")) {
01539          ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01540       } else if (!strcasecmp(v->name, "hasvoicemail")) {
01541          if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01542             ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01543          }
01544       }
01545    }
01546    if (!peer->options.dtmfmode)
01547       peer->options.dtmfmode = global_options.dtmfmode;
01548    if (peer->options.holdHandling == ~0)
01549       peer->options.holdHandling = 0;
01550    else if (!peer->options.holdHandling)
01551       peer->options.holdHandling = global_options.holdHandling;
01552    ASTOBJ_UNMARK(peer);
01553    ast_free_ha(oldha);
01554    return peer;
01555 }
01556 
01557 static struct oh323_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
01558 {
01559    struct oh323_peer *peer;
01560    struct ast_variable *var;
01561    struct ast_variable *tmp;
01562    const char *addr = NULL;
01563 
01564    /* First check on peer name */
01565    if (peername)
01566       var = ast_load_realtime("h323", "name", peername, (char *)NULL);
01567    else if (sin) /* Then check on IP address for dynamic peers */
01568       var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), (char *)NULL);
01569    else
01570       return NULL;
01571 
01572    if (!var)
01573       return NULL;
01574 
01575    for (tmp = var; tmp; tmp = tmp->next) {
01576       /* If this is type=user, then skip this object. */
01577       if (!strcasecmp(tmp->name, "type") &&
01578             !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01579          ast_variables_destroy(var);
01580          return NULL;
01581       } else if (!peername && !strcasecmp(tmp->name, "name")) {
01582          peername = tmp->value;
01583       }
01584    }
01585 
01586    if (!peername) {  /* Did not find peer in realtime */
01587       ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01588       ast_variables_destroy(var);
01589       return NULL;
01590    }
01591 
01592    /* Peer found in realtime, now build it in memory */
01593    peer = build_peer(peername, var, NULL, 1);
01594 
01595    ast_variables_destroy(var);
01596 
01597    return peer;
01598 }
01599 
01600 static int oh323_addrcmp_str(struct in_addr inaddr, char *addr)
01601 {
01602    return strcmp(ast_inet_ntoa(inaddr), addr);
01603 }
01604 
01605 static struct oh323_user *find_user(const call_details_t *cd, int realtime)
01606 {
01607    struct oh323_user *u;
01608 
01609    if (userbyalias)
01610       u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01611    else
01612       u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01613 
01614    if (!u && realtime)
01615       u = realtime_user(cd);
01616 
01617    if (!u && h323debug)
01618       ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01619 
01620    return u;
01621 }
01622 
01623 static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin)
01624 {
01625    int res;
01626 
01627    if (!sin)
01628       res = -1;
01629    else
01630       res = inaddrcmp(&addr , sin);
01631 
01632    return res;
01633 }
01634 
01635 static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
01636 {
01637    struct oh323_peer *p;
01638 
01639    if (peer)
01640       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01641    else
01642       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01643 
01644    if (!p && realtime)
01645       p = realtime_peer(peer, sin);
01646 
01647    if (!p && h323debug)
01648       ast_debug(1, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
01649 
01650    return p;
01651 }
01652 
01653 static int create_addr(struct oh323_pvt *pvt, char *opeer)
01654 {
01655    struct hostent *hp;
01656    struct ast_hostent ahp;
01657    struct oh323_peer *p;
01658    int portno;
01659    int found = 0;
01660    char *port;
01661    char *hostn;
01662    char peer[256] = "";
01663 
01664    ast_copy_string(peer, opeer, sizeof(peer));
01665    port = strchr(peer, ':');
01666    if (port) {
01667       *port = '\0';
01668       port++;
01669    }
01670    pvt->sa.sin_family = AF_INET;
01671    p = find_peer(peer, NULL, 1);
01672    if (p) {
01673       found++;
01674       memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01675       pvt->jointcapability = pvt->options.capability;
01676       if (pvt->options.dtmfmode) {
01677          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01678             pvt->nonCodecCapability |= AST_RTP_DTMF;
01679          } else {
01680             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01681          }
01682       }
01683       if (p->addr.sin_addr.s_addr) {
01684          pvt->sa.sin_addr = p->addr.sin_addr;
01685          pvt->sa.sin_port = p->addr.sin_port;
01686       }
01687       ASTOBJ_UNREF(p, oh323_destroy_peer);
01688    }
01689    if (!p && !found) {
01690       hostn = peer;
01691       if (port) {
01692          portno = atoi(port);
01693       } else {
01694          portno = h323_signalling_port;
01695       }
01696       hp = ast_gethostbyname(hostn, &ahp);
01697       if (hp) {
01698          memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01699          pvt->sa.sin_port = htons(portno);
01700          /* Look peer by address */
01701          p = find_peer(NULL, &pvt->sa, 1);
01702          memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01703          pvt->jointcapability = pvt->options.capability;
01704          if (p) {
01705             ASTOBJ_UNREF(p, oh323_destroy_peer);
01706          }
01707          if (pvt->options.dtmfmode) {
01708             if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01709                pvt->nonCodecCapability |= AST_RTP_DTMF;
01710             } else {
01711                pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01712             }
01713          }
01714          return 0;
01715       } else {
01716          ast_log(LOG_WARNING, "No such host: %s\n", peer);
01717          return -1;
01718       }
01719    } else if (!found) {
01720       return -1;
01721    } else {
01722       return 0;
01723    }
01724 }
01725 static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause)
01726 {
01727    int oldformat;
01728    struct oh323_pvt *pvt;
01729    struct ast_channel *tmpc = NULL;
01730    char *dest = (char *)data;
01731    char *ext, *host;
01732    char *h323id = NULL;
01733    char tmp[256], tmp1[256];
01734 
01735    if (h323debug)
01736       ast_debug(1, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
01737 
01738    pvt = oh323_alloc(0);
01739    if (!pvt) {
01740       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
01741       return NULL;
01742    }
01743    oldformat = format;
01744    format &= AST_FORMAT_AUDIO_MASK;
01745    if (!format) {
01746       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
01747       oh323_destroy(pvt);
01748       if (cause)
01749          *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01750       return NULL;
01751    }
01752    ast_copy_string(tmp, dest, sizeof(tmp));
01753    host = strchr(tmp, '@');
01754    if (host) {
01755       *host = '\0';
01756       host++;
01757       ext = tmp;
01758    } else {
01759       ext = strrchr(tmp, '/');
01760       if (ext)
01761          *ext++ = '\0';
01762       host = tmp;
01763    }
01764    strtok_r(host, "/", &(h323id));
01765    if (!ast_strlen_zero(h323id)) {
01766       h323_set_id(h323id);
01767    }
01768    if (ext) {
01769       ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01770    }
01771    if (h323debug)
01772       ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
01773 
01774    if (gatekeeper_disable) {
01775       if (create_addr(pvt, host)) {
01776          oh323_destroy(pvt);
01777          if (cause)
01778             *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01779          return NULL;
01780       }
01781    }
01782    else {
01783       memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01784       pvt->jointcapability = pvt->options.capability;
01785       if (pvt->options.dtmfmode) {
01786          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01787             pvt->nonCodecCapability |= AST_RTP_DTMF;
01788          } else {
01789             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01790          }
01791       }
01792    }
01793 
01794    ast_mutex_lock(&caplock);
01795    /* Generate unique channel identifier */
01796    snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01797    tmp1[sizeof(tmp1)-1] = '\0';
01798    ast_mutex_unlock(&caplock);
01799 
01800    ast_mutex_lock(&pvt->lock);
01801    tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
01802    ast_mutex_unlock(&pvt->lock);
01803    if (!tmpc) {
01804       oh323_destroy(pvt);
01805       if (cause)
01806          *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01807    }
01808    ast_update_use_count();
01809    restart_monitor();
01810    return tmpc;
01811 }
01812 
01813 /*! \brief Find a call by alias */
01814 static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
01815 {
01816    struct oh323_alias *a;
01817 
01818    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01819 
01820    if (!a && realtime)
01821       a = realtime_alias(source_aliases);
01822 
01823    return a;
01824 }
01825 
01826 /*! \brief
01827   * Callback for sending digits from H.323 up to asterisk
01828   *
01829   */
01830 static int receive_digit(unsigned call_reference, char digit, const char *token, int duration)
01831 {
01832    struct oh323_pvt *pvt;
01833    int res;
01834 
01835    pvt = find_call_locked(call_reference, token);
01836    if (!pvt) {
01837       ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01838       return -1;
01839    }
01840    if (h323debug)
01841       ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01842 
01843    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01844       if (digit == '!')
01845          res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01846       else {
01847          struct ast_frame f = {
01848             .frametype = AST_FRAME_DTMF_END,
01849             .subclass = digit,
01850             .samples = duration * 8,
01851             .len = duration,
01852             .src = "SEND_DIGIT",
01853          };
01854          if (digit == ' ') {     /* signalUpdate message */
01855             f.subclass = pvt->curDTMF;
01856             AST_SCHED_DEL(sched, pvt->DTMFsched);
01857          } else {          /* Regular input or signal message */
01858             if (pvt->DTMFsched >= 0) {
01859                /* We still don't send DTMF END from previous event, send it now */
01860                AST_SCHED_DEL(sched, pvt->DTMFsched);
01861                f.subclass = pvt->curDTMF;
01862                f.samples = f.len = 0;
01863                ast_queue_frame(pvt->owner, &f);
01864                /* Restore values */
01865                f.subclass = digit;
01866                f.samples = duration * 8;
01867                f.len = duration;
01868             }
01869             if (duration) {      /* This is a signal, signalUpdate follows */
01870                f.frametype = AST_FRAME_DTMF_BEGIN;
01871                pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01872                if (h323debug)
01873                   ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01874             }
01875             pvt->curDTMF = digit;
01876          }
01877          res = ast_queue_frame(pvt->owner, &f);
01878       }
01879       ast_channel_unlock(pvt->owner);
01880    } else {
01881       if (digit == '!')
01882          pvt->newcontrol = AST_CONTROL_FLASH;
01883       else {
01884          pvt->newduration = duration;
01885          pvt->newdigit = digit;
01886       }
01887       res = 0;
01888    }
01889    ast_mutex_unlock(&pvt->lock);
01890    return res;
01891 }
01892 
01893 /*! \brief
01894   * Callback function used to inform the H.323 stack of the local rtp ip/port details
01895   *
01896   * \return Returns the local RTP information
01897   */
01898 static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
01899 {
01900    struct oh323_pvt *pvt;
01901    struct sockaddr_in us;
01902    struct rtp_info *info;
01903 
01904    info = ast_calloc(1, sizeof(*info));
01905    if (!info) {
01906       ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01907       return NULL;
01908    }
01909    pvt = find_call_locked(call_reference, token);
01910    if (!pvt) {
01911       ast_free(info);
01912       ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01913       return NULL;
01914    }
01915    if (!pvt->rtp)
01916       __oh323_rtp_create(pvt);
01917    if (!pvt->rtp) {
01918       ast_mutex_unlock(&pvt->lock);
01919       ast_free(info);
01920       ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01921       return NULL;
01922    }
01923    /* figure out our local RTP port and tell the H.323 stack about it */
01924    ast_rtp_get_us(pvt->rtp, &us);
01925    ast_mutex_unlock(&pvt->lock);
01926 
01927    ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01928    info->port = ntohs(us.sin_port);
01929    if (h323debug)
01930       ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01931    return info;
01932 }
01933 
01934 /* 
01935  * Definition taken from rtp.c for rtpPayloadType because we need it here.
01936  */
01937 
01938 struct rtpPayloadType {
01939    int isAstFormat;  /* whether the following code is an AST_FORMAT */
01940    int code;
01941 };
01942 
01943 /*! \brief
01944   * Call-back function passing remote ip/port information from H.323 to asterisk
01945   *
01946   * Returns nothing
01947   */
01948 static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
01949 {
01950    struct oh323_pvt *pvt;
01951    struct sockaddr_in them;
01952    struct rtpPayloadType rtptype;
01953    int nativeformats_changed;
01954    enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
01955 
01956    if (h323debug)
01957       ast_debug(1, "Setting up RTP connection for %s\n", token);
01958 
01959    /* Find the call or allocate a private structure if call not found */
01960    pvt = find_call_locked(call_reference, token);
01961    if (!pvt) {
01962       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
01963       return;
01964    }
01965    if (pvt->alreadygone) {
01966       ast_mutex_unlock(&pvt->lock);
01967       return;
01968    }
01969 
01970    if (!pvt->rtp)
01971       __oh323_rtp_create(pvt);
01972 
01973    if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
01974       ast_rtp_set_rtpmap_type(pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
01975    }
01976 
01977    them.sin_family = AF_INET;
01978    /* only works for IPv4 */
01979    them.sin_addr.s_addr = inet_addr(remoteIp);
01980    them.sin_port = htons(remotePort);
01981 
01982    if (them.sin_addr.s_addr) {
01983       ast_rtp_set_peer(pvt->rtp, &them);
01984       if (pvt->recvonly) {
01985          pvt->recvonly = 0;
01986          rtp_change = NEED_UNHOLD;
01987       }
01988    } else {
01989       ast_rtp_stop(pvt->rtp);
01990       if (!pvt->recvonly) {
01991          pvt->recvonly = 1;
01992          rtp_change = NEED_HOLD;
01993       }
01994    }
01995 
01996    /* Change native format to reflect information taken from OLC/OLCAck */
01997    nativeformats_changed = 0;
01998    if (pt != 128 && pvt->rtp) {  /* Payload type is invalid, so try to use previously decided */
01999       rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
02000       if (h323debug)
02001          ast_debug(1, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
02002       if (pvt->nativeformats != rtptype.code) {
02003          pvt->nativeformats = rtptype.code;
02004          nativeformats_changed = 1;
02005       }
02006    } else if (h323debug)
02007       ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
02008 
02009    /* Don't try to lock the channel if nothing changed */
02010    if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
02011       if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02012          /* Re-build translation path only if native format(s) has been changed */
02013          if (pvt->owner->nativeformats != pvt->nativeformats) {
02014             if (h323debug)
02015                ast_debug(1, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat);
02016             pvt->owner->nativeformats = pvt->nativeformats;
02017             ast_set_read_format(pvt->owner, pvt->owner->readformat);
02018             ast_set_write_format(pvt->owner, pvt->owner->writeformat);
02019          }
02020          if (pvt->options.progress_audio)
02021             ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
02022          switch (rtp_change) {
02023          case NEED_HOLD:
02024             ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02025             break;
02026          case NEED_UNHOLD:
02027             ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02028             break;
02029          default:
02030             break;
02031          }
02032          ast_channel_unlock(pvt->owner);
02033       }
02034       else {
02035          if (pvt->options.progress_audio)
02036             pvt->newcontrol = AST_CONTROL_PROGRESS;
02037          else if (rtp_change == NEED_HOLD)
02038             pvt->newcontrol = AST_CONTROL_HOLD;
02039          else if (rtp_change == NEED_UNHOLD)
02040             pvt->newcontrol = AST_CONTROL_UNHOLD;
02041          if (h323debug)
02042             ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
02043       }
02044    }
02045    ast_mutex_unlock(&pvt->lock);
02046 
02047    if (h323debug)
02048       ast_debug(1, "RTP connection prepared for %s\n", token);
02049 
02050    return;
02051 }
02052 
02053 /*! \brief
02054   *   Call-back function to signal asterisk that the channel has been answered
02055   * Returns nothing
02056   */
02057 static void connection_made(unsigned call_reference, const char *token)
02058 {
02059    struct oh323_pvt *pvt;
02060 
02061    if (h323debug)
02062       ast_debug(1, "Call %s answered\n", token);
02063 
02064    pvt = find_call_locked(call_reference, token);
02065    if (!pvt) {
02066       ast_log(LOG_ERROR, "Something is wrong: connection\n");
02067       return;
02068    }
02069 
02070    /* Inform asterisk about remote party connected only on outgoing calls */
02071    if (!pvt->outgoing) {
02072       ast_mutex_unlock(&pvt->lock);
02073       return;
02074    }
02075    /* Do not send ANSWER message more than once */
02076    if (!pvt->connection_established) {
02077       pvt->connection_established = 1;
02078       update_state(pvt, -1, AST_CONTROL_ANSWER);
02079    }
02080    ast_mutex_unlock(&pvt->lock);
02081    return;
02082 }
02083 
02084 static int progress(unsigned call_reference, const char *token, int inband)
02085 {
02086    struct oh323_pvt *pvt;
02087 
02088    if (h323debug)
02089       ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02090 
02091    pvt = find_call_locked(call_reference, token);
02092    if (!pvt) {
02093       ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02094       return -1;
02095    }
02096    if (!pvt->owner) {
02097       ast_mutex_unlock(&pvt->lock);
02098       ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02099       return -1;
02100    }
02101    update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02102    ast_mutex_unlock(&pvt->lock);
02103 
02104    return 0;
02105 }
02106 
02107 /*! \brief
02108  *  Call-back function for incoming calls
02109  *
02110  *  Returns 1 on success
02111  */
02112 static call_options_t *setup_incoming_call(call_details_t *cd)
02113 {
02114    struct oh323_pvt *pvt;
02115    struct oh323_user *user = NULL;
02116    struct oh323_alias *alias = NULL;
02117 
02118    if (h323debug)
02119       ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
02120 
02121    /* allocate the call*/
02122    pvt = oh323_alloc(cd->call_reference);
02123 
02124    if (!pvt) {
02125       ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02126       cleanup_call_details(cd);
02127       return NULL;
02128    }
02129 
02130    /* Populate the call details in the private structure */
02131    memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02132    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02133    pvt->jointcapability = pvt->options.capability;
02134 
02135    if (h323debug) {
02136       ast_verb(3, "Setting up Call\n");
02137       ast_verb(3, " \tCall token:  [%s]\n", pvt->cd.call_token);
02138       ast_verb(3, " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);
02139       ast_verb(3, " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
02140       ast_verb(3, " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
02141       ast_verb(3, " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
02142       if (pvt->cd.redirect_reason >= 0)
02143          ast_verb(3, " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02144       ast_verb(3, " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
02145    }
02146 
02147    /* Decide if we are allowing Gatekeeper routed calls*/
02148    if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02149       if (!ast_strlen_zero(cd->call_dest_e164)) {
02150          ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02151          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02152       } else {
02153          alias = find_alias(cd->call_dest_alias, 1);
02154          if (!alias) {
02155             ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02156             oh323_destroy(pvt);
02157             return NULL;
02158          }
02159          ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02160          ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02161       }
02162    } else {
02163       /* Either this call is not from the Gatekeeper
02164          or we are not allowing gk routed calls */
02165       user = find_user(cd, 1);
02166       if (!user) {
02167          if (!acceptAnonymous) {
02168             ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02169             oh323_destroy(pvt);
02170             return NULL;
02171          }
02172          if (ast_strlen_zero(default_context)) {
02173             ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02174             oh323_destroy(pvt);
02175             return NULL;
02176          }
02177          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02178          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02179             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02180          } else {
02181             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02182          }
02183          if (h323debug)
02184             ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02185       } else {
02186          if (user->host) {
02187             if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02188                if (ast_strlen_zero(user->context)) {
02189                   if (ast_strlen_zero(default_context)) {
02190                      ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02191                      oh323_destroy(pvt);
02192                      ASTOBJ_UNREF(user, oh323_destroy_user);
02193                      return NULL;
02194                   }
02195                   ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02196                } else {
02197                   ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02198                }
02199                pvt->exten[0] = 'i';
02200                pvt->exten[1] = '\0';
02201                ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02202                oh323_destroy(pvt);
02203                ASTOBJ_UNREF(user, oh323_destroy_user);
02204                return NULL;   /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
02205             }
02206          }
02207          ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02208          memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02209          pvt->jointcapability = pvt->options.capability;
02210          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02211             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02212          } else {
02213             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02214          }
02215          if (!ast_strlen_zero(user->accountcode)) {
02216             ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02217          }
02218          if (user->amaflags) {
02219             pvt->amaflags = user->amaflags;
02220          }
02221          ASTOBJ_UNREF(user, oh323_destroy_user);
02222       }
02223    }
02224    return &pvt->options;
02225 }
02226 
02227 /*! \brief
02228  * Call-back function to start PBX when OpenH323 ready to serve incoming call
02229  *
02230  * Returns 1 on success
02231  */
02232 static int answer_call(unsigned call_reference, const char *token)
02233 {
02234    struct oh323_pvt *pvt;
02235    struct ast_channel *c = NULL;
02236    enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02237    char tmp_exten[sizeof(pvt->exten)];
02238 
02239    if (h323debug)
02240       ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
02241 
02242    /* Find the call or allocate a private structure if call not found */
02243    pvt = find_call_locked(call_reference, token);
02244    if (!pvt) {
02245       ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02246       return 0;
02247    }
02248    /* Check if requested extension@context pair exists in the dialplan */
02249    ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02250 
02251    /* Try to find best extension in specified context */
02252    if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02253       if (tmp_exten[0] == 's')
02254          try_exten = ext_s;
02255       else if (tmp_exten[0] == 'i')
02256          try_exten = ext_i;
02257       else
02258          try_exten = ext_original;
02259    } else
02260       try_exten = ext_original;
02261    do {
02262       if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02263          break;
02264       switch (try_exten) {
02265       case ext_original:
02266          tmp_exten[0] = 's';
02267          tmp_exten[1] = '\0';
02268          try_exten = ext_s;
02269          break;
02270       case ext_s:
02271          tmp_exten[0] = 'i';
02272          try_exten = ext_i;
02273          break;
02274       case ext_i:
02275          try_exten = ext_notexists;
02276          break;
02277       default:
02278          break;
02279       }
02280    } while (try_exten != ext_notexists);
02281 
02282    /* Drop the call if we don't have <exten>, s and i extensions */
02283    if (try_exten == ext_notexists) {
02284       ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02285       ast_mutex_unlock(&pvt->lock);
02286       h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02287       return 0;
02288    } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02289       if (h323debug)
02290          ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02291       ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02292    }
02293 
02294    /* allocate a channel and tell asterisk about it */
02295    c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
02296 
02297    /* And release when done */
02298    ast_mutex_unlock(&pvt->lock);
02299    if (!c) {
02300       ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02301       return 0;
02302    }
02303    return 1;
02304 }
02305 
02306 /*! \brief
02307  * Call-back function to establish an outgoing H.323 call
02308  *
02309  * Returns 1 on success
02310  */
02311 static int setup_outgoing_call(call_details_t *cd)
02312 {
02313    /* Use argument here or free it immediately */
02314    cleanup_call_details(cd);
02315 
02316    return 1;
02317 }
02318 
02319 /*! \brief
02320   *  Call-back function to signal asterisk that the channel is ringing
02321   *  Returns nothing
02322   */
02323 static void chan_ringing(unsigned call_reference, const char *token)
02324 {
02325    struct oh323_pvt *pvt;
02326 
02327    if (h323debug)
02328       ast_debug(1, "Ringing on %s\n", token);
02329 
02330    pvt = find_call_locked(call_reference, token);
02331    if (!pvt) {
02332       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02333       return;
02334    }
02335    if (!pvt->owner) {
02336       ast_mutex_unlock(&pvt->lock);
02337       ast_log(LOG_ERROR, "Channel has no owner\n");
02338       return;
02339    }
02340    update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02341    ast_mutex_unlock(&pvt->lock);
02342    return;
02343 }
02344 
02345 /*! \brief
02346   * Call-back function to cleanup communication
02347   * Returns nothing,
02348   */
02349 static void cleanup_connection(unsigned call_reference, const char *call_token)
02350 {
02351    struct oh323_pvt *pvt;
02352 
02353    if (h323debug)
02354       ast_debug(1, "Cleaning connection to %s\n", call_token);
02355 
02356    while (1) {
02357       pvt = find_call_locked(call_reference, call_token);
02358       if (!pvt) {
02359          if (h323debug)
02360             ast_debug(1, "No connection for %s\n", call_token);
02361          return;
02362       }
02363       if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02364          break;
02365 #if 1
02366       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02367 #ifdef DEBUG_THREADS
02368       /* XXX to be completed
02369        * If we want to print more info on who is holding the lock,
02370        * implement the relevant code in lock.h and use the routines
02371        * supplied there.
02372        */
02373 #endif
02374 #endif
02375       ast_mutex_unlock(&pvt->lock);
02376       usleep(1);
02377    }
02378    if (pvt->rtp) {
02379       /* Immediately stop RTP */
02380       ast_rtp_destroy(pvt->rtp);
02381       pvt->rtp = NULL;
02382    }
02383    /* Free dsp used for in-band DTMF detection */
02384    if (pvt->vad) {
02385       ast_dsp_free(pvt->vad);
02386       pvt->vad = NULL;
02387    }
02388    cleanup_call_details(&pvt->cd);
02389    pvt->alreadygone = 1;
02390    /* Send hangup */
02391    if (pvt->owner) {
02392       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02393       ast_queue_hangup(pvt->owner);
02394       ast_channel_unlock(pvt->owner);
02395    }
02396    ast_mutex_unlock(&pvt->lock);
02397    if (h323debug)
02398       ast_debug(1, "Connection to %s cleaned\n", call_token);
02399    return;
02400 }
02401 
02402 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
02403 {
02404    struct oh323_pvt *pvt;
02405 
02406    if (h323debug)
02407       ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
02408 
02409    pvt = find_call_locked(call_reference, token);
02410    if (!pvt) {
02411       if (h323debug)
02412          ast_debug(1, "Connection to %s already cleared\n", token);
02413       return;
02414    }
02415    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02416       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02417       pvt->owner->hangupcause = pvt->hangupcause = cause;
02418       ast_queue_hangup(pvt->owner);
02419       ast_channel_unlock(pvt->owner);
02420    }
02421    else {
02422       pvt->needhangup = 1;
02423       pvt->hangupcause = cause;
02424       if (h323debug)
02425          ast_debug(1, "Hangup for %s is pending\n", token);
02426    }
02427    ast_mutex_unlock(&pvt->lock);
02428 }
02429 
02430 static void set_dtmf_payload(unsigned call_reference, const char *token, int payload, int is_cisco)
02431 {
02432    struct oh323_pvt *pvt;
02433 
02434    if (h323debug)
02435       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02436 
02437    pvt = find_call_locked(call_reference, token);
02438    if (!pvt) {
02439       return;
02440    }
02441    if (pvt->rtp) {
02442       ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
02443    }
02444    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02445    ast_mutex_unlock(&pvt->lock);
02446    if (h323debug)
02447       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02448 }
02449 
02450 static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
02451 {
02452    struct oh323_pvt *pvt;
02453 
02454    if (h323debug)
02455       ast_debug(1, "Got remote capabilities from connection %s\n", token);
02456 
02457    pvt = find_call_locked(call_reference, token);
02458    if (!pvt)
02459       return;
02460    pvt->peercapability = capabilities;
02461    pvt->jointcapability = pvt->options.capability & capabilities;
02462    if (prefs) {
02463       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02464       if (h323debug) {
02465          int i;
02466          for (i = 0; i < 32; ++i) {
02467             if (!prefs->order[i])
02468                break;
02469             ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02470          }
02471       }
02472       if (pvt->rtp) {
02473          if (pvt->options.autoframing) {
02474             ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02475             ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
02476          } else {
02477             ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02478             ast_rtp_codec_setpref(pvt->rtp, &pvt->options.prefs);
02479          }
02480       }
02481    }
02482    ast_mutex_unlock(&pvt->lock);
02483 }
02484 
02485 static void set_local_capabilities(unsigned call_reference, const char *token)
02486 {
02487    struct oh323_pvt *pvt;
02488    int capability, dtmfmode, pref_codec;
02489    struct ast_codec_pref prefs;
02490 
02491    if (h323debug)
02492       ast_debug(1, "Setting capabilities for connection %s\n", token);
02493 
02494    pvt = find_call_locked(call_reference, token);
02495    if (!pvt)
02496       return;
02497    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02498    dtmfmode = pvt->options.dtmfmode;
02499    prefs = pvt->options.prefs;
02500    pref_codec = pvt->pref_codec;
02501    ast_mutex_unlock(&pvt->lock);
02502    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02503 
02504    if (h323debug) {
02505       int i;
02506       for (i = 0; i < 32; i++) {
02507          if (!prefs.order[i])
02508             break;
02509          ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02510       }
02511       ast_debug(1, "Capabilities for connection %s is set\n", token);
02512    }
02513 }
02514 
02515 static void remote_hold(unsigned call_reference, const char *token, int is_hold)
02516 {
02517    struct oh323_pvt *pvt;
02518 
02519    if (h323debug)
02520       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02521 
02522    pvt = find_call_locked(call_reference, token);
02523    if (!pvt)
02524       return;
02525    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02526       if (is_hold)
02527          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02528       else
02529          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02530       ast_channel_unlock(pvt->owner);
02531    }
02532    else {
02533       if (is_hold)
02534          pvt->newcontrol = AST_CONTROL_HOLD;
02535       else
02536          pvt->newcontrol = AST_CONTROL_UNHOLD;
02537    }
02538    ast_mutex_unlock(&pvt->lock);
02539 }
02540 
02541 static void *do_monitor(void *data)
02542 {
02543    int res;
02544    int reloading;
02545    struct oh323_pvt *oh323 = NULL;
02546 
02547    for(;;) {
02548       /* Check for a reload request */
02549       ast_mutex_lock(&h323_reload_lock);
02550       reloading = h323_reloading;
02551       h323_reloading = 0;
02552       ast_mutex_unlock(&h323_reload_lock);
02553       if (reloading) {
02554          ast_verb(1, "Reloading H.323\n");
02555          h323_do_reload();
02556       }
02557       /* Check for interfaces needing to be killed */
02558       if (!ast_mutex_trylock(&iflock)) {
02559 #if 1
02560          do {
02561             for (oh323 = iflist; oh323; oh323 = oh323->next) {
02562                if (!ast_mutex_trylock(&oh323->lock)) {
02563                   if (oh323->needdestroy) {
02564                      __oh323_destroy(oh323);
02565                      break;
02566                   }
02567                   ast_mutex_unlock(&oh323->lock);
02568                }
02569             }
02570          } while (/*oh323*/ 0);
02571 #else
02572 restartsearch:
02573          oh323 = iflist;
02574          while(oh323) {
02575             if (!ast_mutex_trylock(&oh323->lock)) {
02576                if (oh323->needdestroy) {
02577                   __oh323_destroy(oh323);
02578                   goto restartsearch;
02579                }
02580                ast_mutex_unlock(&oh323->lock);
02581                oh323 = oh323->next;
02582             }
02583          }
02584 #endif
02585          ast_mutex_unlock(&iflock);
02586       } else
02587          oh323 = (struct oh323_pvt *)1;   /* Force fast loop */
02588       pthread_testcancel();
02589       /* Wait for sched or io */
02590       res = ast_sched_wait(sched);
02591       if ((res < 0) || (res > 1000)) {
02592          res = 1000;
02593       }
02594       /* Do not wait if some channel(s) is destroyed, probably, more available too */
02595       if (oh323)
02596          res = 1;
02597       res = ast_io_wait(io, res);
02598       pthread_testcancel();
02599       ast_mutex_lock(&monlock);
02600       if (res >= 0) {
02601          ast_sched_runq(sched);
02602       }
02603       ast_mutex_unlock(&monlock);
02604    }
02605    /* Never reached */
02606    return NULL;
02607 }
02608 
02609 static int restart_monitor(void)
02610 {
02611    /* If we're supposed to be stopped -- stay stopped */
02612    if (ast_mutex_lock(&monlock)) {
02613       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02614       return -1;
02615    }
02616    if (monitor_thread == AST_PTHREADT_STOP) {
02617       ast_mutex_unlock(&monlock);
02618       return 0;
02619    }
02620    if (monitor_thread == pthread_self()) {
02621       ast_mutex_unlock(&monlock);
02622       ast_log(LOG_WARNING, "Cannot kill myself\n");
02623       return -1;
02624    }
02625    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02626       /* Wake up the thread */
02627       pthread_kill(monitor_thread, SIGURG);
02628    } else {
02629       /* Start a new monitor */
02630       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02631          monitor_thread = AST_PTHREADT_NULL;
02632          ast_mutex_unlock(&monlock);
02633          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02634          return -1;
02635       }
02636    }
02637    ast_mutex_unlock(&monlock);
02638    return 0;
02639 }
02640 
02641 static char *handle_cli_h323_set_trace(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02642 {
02643    switch (cmd) {
02644    case CLI_INIT:
02645       e->command = "h323 set trace [off]";
02646       e->usage =
02647          "Usage: h323 set trace (off|<trace level>)\n"
02648          "       Enable/Disable H.323 stack tracing for debugging purposes\n";
02649       return NULL;
02650    case CLI_GENERATE:
02651       return NULL;
02652    }
02653 
02654    if (a->argc != 4)
02655       return CLI_SHOWUSAGE;
02656    if (!strcasecmp(a->argv[3], "off")) {
02657       h323_debug(0, 0);
02658       ast_cli(a->fd, "H.323 Trace Disabled\n");
02659    } else {
02660       int tracelevel = atoi(a->argv[3]);
02661       h323_debug(1, tracelevel);
02662       ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02663    }
02664    return CLI_SUCCESS;
02665 }
02666 
02667 static char *handle_cli_h323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02668 {
02669    switch (cmd) {
02670    case CLI_INIT:
02671       e->command = "h323 set debug [off]";
02672       e->usage =
02673          "Usage: h323 set debug [off]\n"
02674          "       Enable/Disable H.323 debugging output\n";
02675       return NULL;
02676    case CLI_GENERATE:
02677       return NULL;
02678    }
02679 
02680    if (a->argc < 3 || a->argc > 4)
02681       return CLI_SHOWUSAGE;
02682    if (a->argc == 4 && strcasecmp(a->argv[3], "off"))
02683       return CLI_SHOWUSAGE;
02684 
02685    h323debug = (a->argc == 3) ? 1 : 0;
02686    ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02687    return CLI_SUCCESS;
02688 }
02689 
02690 static char *handle_cli_h323_cycle_gk(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02691 {
02692    switch (cmd) {
02693    case CLI_INIT:
02694       e->command = "h323 cycle gk";
02695       e->usage =
02696          "Usage: h323 cycle gk\n"
02697          "       Manually re-register with the Gatekeper (Currently Disabled)\n";
02698       return NULL;
02699    case CLI_GENERATE:
02700       return NULL;
02701    }
02702 
02703    if (a->argc != 3)
02704       return CLI_SHOWUSAGE;
02705 
02706    h323_gk_urq();
02707 
02708    /* Possibly register with a GK */
02709    if (!gatekeeper_disable) {
02710       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02711          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02712       }
02713    }
02714    return CLI_SUCCESS;
02715 }
02716 
02717 static char *handle_cli_h323_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02718 {
02719    switch (cmd) {
02720    case CLI_INIT:
02721       e->command = "h323 hangup";
02722       e->usage =
02723          "Usage: h323 hangup <token>\n"
02724          "       Manually try to hang up the call identified by <token>\n";
02725       return NULL;
02726    case CLI_GENERATE:
02727       return NULL;
02728    }
02729 
02730    if (a->argc != 3)
02731       return CLI_SHOWUSAGE;
02732    if (h323_soft_hangup(a->argv[2])) {
02733       ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02734    } else {
02735       ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02736    }
02737    return CLI_SUCCESS;
02738 }
02739 
02740 static char *handle_cli_h323_show_tokens(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02741 {
02742    switch (cmd) {
02743    case CLI_INIT:
02744       e->command = "h323 show tokens";
02745       e->usage =
02746          "Usage: h323 show tokens\n"
02747          "       Print out all active call tokens\n";
02748       return NULL;
02749    case CLI_GENERATE:
02750       return NULL;
02751    }
02752 
02753    if (a->argc != 3)
02754       return CLI_SHOWUSAGE;
02755 
02756    h323_show_tokens();
02757 
02758    return CLI_SUCCESS;
02759 }
02760 
02761 static char *handle_cli_h323_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02762 {
02763    switch (cmd) {
02764    case CLI_INIT:
02765       e->command = "h323 show version";
02766       e->usage =
02767          "Usage: h323 show version\n"
02768          "     Show the version of the H.323 library in use\n";
02769       return NULL;
02770    case CLI_GENERATE:
02771       return NULL;
02772    }
02773 
02774    if (a->argc != 3)
02775       return CLI_SHOWUSAGE;
02776 
02777    h323_show_version();
02778    
02779    return CLI_SUCCESS;
02780 }
02781 
02782 static struct ast_cli_entry cli_h323[] = {
02783    AST_CLI_DEFINE(handle_cli_h323_set_trace,    "Enable/Disable H.323 Stack Tracing"),
02784    AST_CLI_DEFINE(handle_cli_h323_set_debug,    "Enable/Disable H.323 Debugging"),
02785    AST_CLI_DEFINE(handle_cli_h323_cycle_gk,     "Manually re-register with the Gatekeper"),
02786    AST_CLI_DEFINE(handle_cli_h323_hangup,       "Manually try to hang up a call"),
02787    AST_CLI_DEFINE(handle_cli_h323_show_tokens,  "Show all active call tokens"),
02788    AST_CLI_DEFINE(handle_cli_h323_show_version, "Show the version of the H.323 library in use"),
02789 };
02790 
02791 static void delete_users(void)
02792 {
02793    int pruned = 0;
02794 
02795    /* Delete all users */
02796    ASTOBJ_CONTAINER_WRLOCK(&userl);
02797    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02798       ASTOBJ_RDLOCK(iterator);
02799       ASTOBJ_MARK(iterator);
02800       ++pruned;
02801       ASTOBJ_UNLOCK(iterator);
02802    } while (0) );
02803    if (pruned) {
02804       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02805    }
02806    ASTOBJ_CONTAINER_UNLOCK(&userl);
02807 
02808    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02809    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02810       ASTOBJ_RDLOCK(iterator);
02811       ASTOBJ_MARK(iterator);
02812       ASTOBJ_UNLOCK(iterator);
02813    } while (0) );
02814    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02815 }
02816 
02817 static void delete_aliases(void)
02818 {
02819    int pruned = 0;
02820 
02821    /* Delete all aliases */
02822    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02823    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02824       ASTOBJ_RDLOCK(iterator);
02825       ASTOBJ_MARK(iterator);
02826       ++pruned;
02827       ASTOBJ_UNLOCK(iterator);
02828    } while (0) );
02829    if (pruned) {
02830       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02831    }
02832    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02833 }
02834 
02835 static void prune_peers(void)
02836 {
02837    /* Prune peers who still are supposed to be deleted */
02838    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02839 }
02840 
02841 static int reload_config(int is_reload)
02842 {
02843    struct ast_config *cfg, *ucfg;
02844    struct ast_variable *v;
02845    struct oh323_peer *peer = NULL;
02846    struct oh323_user *user = NULL;
02847    struct oh323_alias *alias = NULL;
02848    struct ast_hostent ahp; struct hostent *hp;
02849    char *cat;
02850    const char *utype;
02851    int is_user, is_peer, is_alias;
02852    char _gatekeeper[100];
02853    int gk_discover, gk_disable, gk_changed;
02854    struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02855 
02856    cfg = ast_config_load(config, config_flags);
02857 
02858    /* We *must* have a config file otherwise stop immediately */
02859    if (!cfg) {
02860       ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
02861       return 1;
02862    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02863       ucfg = ast_config_load("users.conf", config_flags);
02864       if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
02865          return 0;
02866       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02867       cfg = ast_config_load(config, config_flags);
02868    } else {
02869       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02870       ucfg = ast_config_load("users.conf", config_flags);
02871    }
02872 
02873    if (is_reload) {
02874       delete_users();
02875       delete_aliases();
02876       prune_peers();
02877    }
02878 
02879    /* fire up the H.323 Endpoint */
02880    if (!h323_end_point_exist()) {
02881       h323_end_point_create();
02882    }
02883    ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02884    gk_discover = gatekeeper_discover;
02885    gk_disable = gatekeeper_disable;
02886    memset(&bindaddr, 0, sizeof(bindaddr));
02887    memset(&global_options, 0, sizeof(global_options));
02888    global_options.fastStart = 1;
02889    global_options.h245Tunneling = 1;
02890    global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
02891    global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
02892    global_options.dtmfmode = 0;
02893    global_options.holdHandling = 0;
02894    global_options.capability = GLOBAL_CAPABILITY;
02895    global_options.bridge = 1;    /* Do native bridging by default */
02896    global_options.autoframing = 0;
02897    strcpy(default_context, "default");
02898    h323_signalling_port = 1720;
02899    gatekeeper_disable = 1;
02900    gatekeeper_discover = 0;
02901    gkroute = 0;
02902    userbyalias = 1;
02903    acceptAnonymous = 1;
02904    tos = 0;
02905    cos = 0;
02906 
02907    /* Copy the default jb config over global_jbconf */
02908    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02909 
02910    if (ucfg) {
02911       struct ast_variable *gen;
02912       int genhas_h323;
02913       const char *has_h323;
02914 
02915       genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
02916       gen = ast_variable_browse(ucfg, "general");
02917       for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
02918          if (strcasecmp(cat, "general")) {
02919             has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
02920             if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
02921                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
02922                if (user) {
02923                   ASTOBJ_CONTAINER_LINK(&userl, user);
02924                   ASTOBJ_UNREF(user, oh323_destroy_user);
02925                }
02926                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
02927                if (peer) {
02928                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
02929                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
02930                }
02931             }
02932          }
02933       }
02934       ast_config_destroy(ucfg);
02935    }
02936 
02937    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
02938       /* handle jb conf */
02939       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
02940          continue;
02941       /* Create the interface list */
02942       if (!strcasecmp(v->name, "port")) {
02943          h323_signalling_port = (int)strtol(v->value, NULL, 10);
02944       } else if (!strcasecmp(v->name, "bindaddr")) {
02945          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
02946             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
02947          } else {
02948             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
02949          }
02950       } else if (!strcasecmp(v->name, "tos")) { /* Needs to be removed in next release */
02951          ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n");
02952          if (ast_str2tos(v->value, &tos)) {
02953             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
02954          }
02955       } else if (!strcasecmp(v->name, "tos_audio")) {
02956          if (ast_str2tos(v->value, &tos)) {
02957             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
02958          }
02959       } else if (!strcasecmp(v->name, "cos")) {
02960          ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n");
02961          if (ast_str2cos(v->value, &cos)) {
02962             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
02963          }
02964       } else if (!strcasecmp(v->name, "cos_audio")) {
02965          if (ast_str2cos(v->value, &cos)) {
02966             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
02967          }
02968       } else if (!strcasecmp(v->name, "gatekeeper")) {
02969          if (!strcasecmp(v->value, "DISABLE")) {
02970             gatekeeper_disable = 1;
02971          } else if (!strcasecmp(v->value, "DISCOVER")) {
02972             gatekeeper_disable = 0;
02973             gatekeeper_discover = 1;
02974          } else {
02975             gatekeeper_disable = 0;
02976             ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
02977          }
02978       } else if (!strcasecmp(v->name, "secret")) {
02979          ast_copy_string(secret, v->value, sizeof(secret));
02980       } else if (!strcasecmp(v->name, "AllowGKRouted")) {
02981          gkroute = ast_true(v->value);
02982       } else if (!strcasecmp(v->name, "context")) {
02983          ast_copy_string(default_context, v->value, sizeof(default_context));
02984          ast_verb(2, "Setting default context to %s\n", default_context);
02985       } else if (!strcasecmp(v->name, "UserByAlias")) {
02986          userbyalias = ast_true(v->value);
02987       } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
02988          acceptAnonymous = ast_true(v->value);
02989       } else if (!update_common_options(v, &global_options)) {
02990          /* dummy */
02991       }
02992    }
02993    if (!global_options.dtmfmode)
02994       global_options.dtmfmode = H323_DTMF_RFC2833;
02995    if (global_options.holdHandling == ~0)
02996       global_options.holdHandling = 0;
02997    else if (!global_options.holdHandling)
02998       global_options.holdHandling = H323_HOLD_H450;
02999 
03000    for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
03001       if (strcasecmp(cat, "general")) {
03002          utype = ast_variable_retrieve(cfg, cat, "type");
03003          if (utype) {
03004             is_user = is_peer = is_alias = 0;
03005             if (!strcasecmp(utype, "user"))
03006                is_user = 1;
03007             else if (!strcasecmp(utype, "peer"))
03008                is_peer = 1;
03009             else if (!strcasecmp(utype, "friend"))
03010                is_user = is_peer = 1;
03011             else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
03012                is_alias = 1;
03013             else {
03014                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
03015                continue;
03016             }
03017             if (is_user) {
03018                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
03019                if (user) {
03020                   ASTOBJ_CONTAINER_LINK(&userl, user);
03021                   ASTOBJ_UNREF(user, oh323_destroy_user);
03022                }
03023             }
03024             if (is_peer) {
03025                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
03026                if (peer) {
03027                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
03028                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
03029                }
03030             }
03031             if (is_alias) {
03032                alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
03033                if (alias) {
03034                   ASTOBJ_CONTAINER_LINK(&aliasl, alias);
03035                   ASTOBJ_UNREF(alias, oh323_destroy_alias);
03036                }
03037             }
03038          } else {
03039             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
03040          }
03041       }
03042    }
03043    ast_config_destroy(cfg);
03044 
03045    /* Register our H.323 aliases if any*/
03046    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
03047    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
03048       ASTOBJ_RDLOCK(iterator);
03049       if (h323_set_alias(iterator)) {
03050          ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
03051          ASTOBJ_UNLOCK(iterator);
03052          continue;
03053       }
03054       ASTOBJ_UNLOCK(iterator);
03055    } while (0) );
03056    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
03057 
03058    /* Don't touch GK if nothing changed because URQ will drop all existing calls */
03059    gk_changed = 0;
03060    if (gatekeeper_disable != gk_disable)
03061       gk_changed = is_reload;
03062    else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
03063       gk_changed = is_reload;
03064    else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
03065       gk_changed = is_reload;
03066    if (gk_changed) {
03067       if(!gk_disable)
03068          h323_gk_urq();
03069       if (!gatekeeper_disable) {
03070          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03071             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03072             gatekeeper_disable = 1;
03073          }
03074       }
03075    }
03076    return 0;
03077 }
03078 
03079 static int h323_reload(void)
03080 {
03081    ast_mutex_lock(&h323_reload_lock);
03082    if (h323_reloading) {
03083       ast_verbose("Previous H.323 reload not yet done\n");
03084    } else {
03085       h323_reloading = 1;
03086    }
03087    ast_mutex_unlock(&h323_reload_lock);
03088    restart_monitor();
03089    return 0;
03090 }
03091 
03092 static char *handle_cli_h323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03093 {
03094    switch (cmd) {
03095    case CLI_INIT:
03096       e->command = "h323 reload";
03097       e->usage =
03098          "Usage: h323 reload\n"
03099          "       Reloads H.323 configuration from h323.conf\n";
03100       return NULL;
03101    case CLI_GENERATE:
03102       return NULL;
03103    }
03104 
03105    if (a->argc != 2)
03106       return CLI_SHOWUSAGE;
03107 
03108    h323_reload();
03109 
03110    return CLI_SUCCESS;
03111 }
03112 
03113 static int h323_do_reload(void)
03114 {
03115    reload_config(1);
03116    return 0;
03117 }
03118 
03119 static int reload(void)
03120 {
03121    if (!sched || !io) {
03122       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03123       return 0;
03124    }
03125    return h323_reload();
03126 }
03127 
03128 static struct ast_cli_entry cli_h323_reload =
03129    AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration");
03130 
03131 static enum ast_rtp_get_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
03132 {
03133    struct oh323_pvt *pvt;
03134    enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
03135 
03136    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03137       return AST_RTP_GET_FAILED;
03138 
03139    ast_mutex_lock(&pvt->lock);
03140    if (pvt->rtp && pvt->options.bridge) {
03141       *rtp = pvt->rtp;
03142       res = AST_RTP_TRY_NATIVE;
03143    }
03144    ast_mutex_unlock(&pvt->lock);
03145 
03146    return res;
03147 }
03148 
03149 static enum ast_rtp_get_result oh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
03150 {
03151    return AST_RTP_GET_FAILED;
03152 }
03153 
03154 static char *convertcap(int cap)
03155 {
03156    switch (cap) {
03157    case AST_FORMAT_G723_1:
03158       return "G.723";
03159    case AST_FORMAT_GSM:
03160       return "GSM";
03161    case AST_FORMAT_ULAW:
03162       return "ULAW";
03163    case AST_FORMAT_ALAW:
03164       return "ALAW";
03165    case AST_FORMAT_G722:
03166       return "G.722";
03167    case AST_FORMAT_ADPCM:
03168       return "G.728";
03169    case AST_FORMAT_G729A:
03170       return "G.729";
03171    case AST_FORMAT_SPEEX:
03172       return "SPEEX";
03173    case AST_FORMAT_ILBC:
03174       return "ILBC";
03175    default:
03176       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03177       return NULL;
03178    }
03179 }
03180 
03181 static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
03182 {
03183    /* XXX Deal with Video */
03184    struct oh323_pvt *pvt;
03185    struct sockaddr_in them;
03186    struct sockaddr_in us;
03187    char *mode;
03188 
03189    if (!rtp) {
03190       return 0;
03191    }
03192 
03193    mode = convertcap(chan->writeformat);
03194    pvt = (struct oh323_pvt *) chan->tech_pvt;
03195    if (!pvt) {
03196       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03197       return -1;
03198    }
03199    ast_rtp_get_peer(rtp, &them);
03200    ast_rtp_get_us(rtp, &us);
03201 #if 0 /* Native bridge still isn't ready */
03202    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03203 #endif
03204    return 0;
03205 }
03206 
03207 static struct ast_rtp_protocol oh323_rtp = {
03208    .type = "H323",
03209    .get_rtp_info = oh323_get_rtp_peer,
03210    .get_vrtp_info = oh323_get_vrtp_peer,
03211    .set_rtp_peer = oh323_set_rtp_peer,
03212 };
03213 
03214 static enum ast_module_load_result load_module(void)
03215 {
03216    int res;
03217 
03218    h323debug = 0;
03219    sched = sched_context_create();
03220    if (!sched) {
03221       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03222       return AST_MODULE_LOAD_FAILURE;
03223    }
03224    io = io_context_create();
03225    if (!io) {
03226       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03227       return AST_MODULE_LOAD_FAILURE;
03228    }
03229    ast_cli_register(&cli_h323_reload);
03230    ASTOBJ_CONTAINER_INIT(&userl);
03231    ASTOBJ_CONTAINER_INIT(&peerl);
03232    ASTOBJ_CONTAINER_INIT(&aliasl);
03233    res = reload_config(0);
03234    if (res) {
03235       /* No config entry */
03236       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03237       ast_cli_unregister(&cli_h323_reload);
03238       io_context_destroy(io);
03239       io = NULL;
03240       sched_context_destroy(sched);
03241       sched = NULL;
03242       ASTOBJ_CONTAINER_DESTROY(&userl);
03243       ASTOBJ_CONTAINER_DESTROY(&peerl);
03244       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03245       return AST_MODULE_LOAD_DECLINE;
03246    } else {
03247       /* Make sure we can register our channel type */
03248       if (ast_channel_register(&oh323_tech)) {
03249          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03250          ast_cli_unregister(&cli_h323_reload);
03251          h323_end_process();
03252          io_context_destroy(io);
03253          sched_context_destroy(sched);
03254 
03255          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03256          ASTOBJ_CONTAINER_DESTROY(&userl);
03257          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03258          ASTOBJ_CONTAINER_DESTROY(&peerl);
03259          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03260          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03261 
03262          return AST_MODULE_LOAD_FAILURE;
03263       }
03264       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03265 
03266       ast_rtp_proto_register(&oh323_rtp);
03267 
03268       /* Register our callback functions */
03269       h323_callback_register(setup_incoming_call,
03270                   setup_outgoing_call,
03271                   external_rtp_create,
03272                   setup_rtp_connection,
03273                   cleanup_connection,
03274                   chan_ringing,
03275                   connection_made,
03276                   receive_digit,
03277                   answer_call,
03278                   progress,
03279                   set_dtmf_payload,
03280                   hangup_connection,
03281                   set_local_capabilities,
03282                   set_peer_capabilities,
03283                   remote_hold);
03284       /* start the h.323 listener */
03285       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03286          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03287          ast_rtp_proto_unregister(&oh323_rtp);
03288          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03289          ast_cli_unregister(&cli_h323_reload);
03290          h323_end_process();
03291          io_context_destroy(io);
03292          sched_context_destroy(sched);
03293 
03294          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03295          ASTOBJ_CONTAINER_DESTROY(&userl);
03296          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03297          ASTOBJ_CONTAINER_DESTROY(&peerl);
03298          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03299          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03300 
03301          return AST_MODULE_LOAD_FAILURE;
03302       }
03303       /* Possibly register with a GK */
03304       if (!gatekeeper_disable) {
03305          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03306             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03307             gatekeeper_disable = 1;
03308             res = AST_MODULE_LOAD_SUCCESS;
03309          }
03310       }
03311       /* And start the monitor for the first time */
03312       restart_monitor();
03313    }
03314    return res;
03315 }
03316 
03317 static int unload_module(void)
03318 {
03319    struct oh323_pvt *p, *pl;
03320 
03321    /* unregister commands */
03322    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03323    ast_cli_unregister(&cli_h323_reload);
03324 
03325    ast_channel_unregister(&oh323_tech);
03326    ast_rtp_proto_unregister(&oh323_rtp);
03327 
03328    if (!ast_mutex_lock(&iflock)) {
03329       /* hangup all interfaces if they have an owner */
03330       p = iflist;
03331       while(p) {
03332          if (p->owner) {
03333             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03334          }
03335          p = p->next;
03336       }
03337       iflist = NULL;
03338       ast_mutex_unlock(&iflock);
03339    } else {
03340       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03341       return -1;
03342    }
03343    if (!ast_mutex_lock(&monlock)) {
03344       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03345          if (monitor_thread != pthread_self()) {
03346             pthread_cancel(monitor_thread);
03347          }
03348          pthread_kill(monitor_thread, SIGURG);
03349          pthread_join(monitor_thread, NULL);
03350       }
03351       monitor_thread = AST_PTHREADT_STOP;
03352       ast_mutex_unlock(&monlock);
03353    } else {
03354       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03355       return -1;
03356    }
03357    if (!ast_mutex_lock(&iflock)) {
03358       /* destroy all the interfaces and free their memory */
03359       p = iflist;
03360       while(p) {
03361          pl = p;
03362          p = p->next;
03363          /* free associated memory */
03364          ast_mutex_destroy(&pl->lock);
03365          ast_free(pl);
03366       }
03367       iflist = NULL;
03368       ast_mutex_unlock(&iflock);
03369    } else {
03370       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03371       return -1;
03372    }
03373    if (!gatekeeper_disable)
03374       h323_gk_urq();
03375    h323_end_process();
03376    if (io)
03377       io_context_destroy(io);
03378    if (sched)
03379       sched_context_destroy(sched);
03380 
03381    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03382    ASTOBJ_CONTAINER_DESTROY(&userl);
03383    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03384    ASTOBJ_CONTAINER_DESTROY(&peerl);
03385    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03386    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03387 
03388    return 0;
03389 }
03390 
03391 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "The NuFone Network's OpenH323 Channel Driver",
03392       .load = load_module,
03393       .unload = unload_module,
03394       .reload = reload,
03395 );

Generated on Thu Jul 9 13:40:26 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7