Sat Feb 11 06:33:07 2012

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

Generated on Sat Feb 11 06:33:07 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6