Thu Oct 11 06:33:38 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  * 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: 373330 $")
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(ast_channel_nativeformats(c));
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(ast_channel_nativeformats(c), 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       ast_channel_softhangup_internal_flag_add(c, AST_SOFTHANGUP_DEV);
00356       ast_channel_hangupcause_set(c, 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 = ast_channel_tech_pvt(c);
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       ast_channel_tech_pvt_set(pvt->owner, 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 *) ast_channel_tech_pvt(c);
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 *) ast_channel_tech_pvt(c);
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 *)ast_channel_tech_pvt(c);
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 ((ast_channel_state(c) != AST_STATE_DOWN) && (ast_channel_state(c) != 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 (ast_channel_connected(c)->id.number.valid && ast_channel_connected(c)->id.number.str) {
00624       ast_copy_string(pvt->options.cid_num, ast_channel_connected(c)->id.number.str, sizeof(pvt->options.cid_num));
00625    }
00626 
00627    if (ast_channel_connected(c)->id.name.valid && ast_channel_connected(c)->id.name.str) {
00628       ast_copy_string(pvt->options.cid_name, ast_channel_connected(c)->id.name.str, sizeof(pvt->options.cid_name));
00629    }
00630 
00631    if (ast_channel_redirecting(c)->from.number.valid && ast_channel_redirecting(c)->from.number.str) {
00632       ast_copy_string(pvt->options.cid_rdnis, ast_channel_redirecting(c)->from.number.str, sizeof(pvt->options.cid_rdnis));
00633    }
00634 
00635    pvt->options.presentation = ast_party_id_presentation(&ast_channel_connected(c)->id);
00636    pvt->options.type_of_number = ast_channel_connected(c)->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 = ast_channel_transfercapability(c);
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", ast_channel_transfercapability(c), ast_transfercapability2str(ast_channel_transfercapability(c)));
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 *) ast_channel_tech_pvt(c);
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 (ast_channel_state(c) != 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 *) ast_channel_tech_pvt(c);
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 (!ast_channel_tech_pvt(c)) {
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    ast_channel_tech_pvt_set(c, NULL);
00717 
00718    if (ast_channel_hangupcause(c)) {
00719       q931cause = ast_channel_hangupcause(c);
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(ast_channel_nativeformats(pvt->owner), &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(ast_channel_nativeformats(pvt->owner), &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 *)ast_channel_tech_pvt(c);
00821    ast_mutex_lock(&pvt->lock);
00822    __oh323_update_info(c, pvt);
00823    switch(ast_channel_fdno(c)) {
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", ast_channel_fdno(c), 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 *) ast_channel_tech_pvt(c);
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(ast_channel_nativeformats(c), &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), ast_channel_nativeformats(c)), 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 *) ast_channel_tech_pvt(c);
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 (ast_channel_state(c) == AST_STATE_RING || ast_channel_state(c) == 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 (ast_channel_state(c) != 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 (ast_channel_state(c) != 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 (ast_channel_state(c) != 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 AST_CONTROL_PVT_CAUSE_CODE:
00945    case -1:
00946       break;
00947    default:
00948       ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
00949       break;
00950    }
00951 
00952    if (h323debug)
00953       ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
00954    if (token)
00955       ast_free(token);
00956    oh323_update_info(c);
00957 
00958    return res;
00959 }
00960 
00961 static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00962 {
00963    struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(newchan);
00964 
00965    ast_mutex_lock(&pvt->lock);
00966    if (pvt->owner != oldchan) {
00967       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
00968       return -1;
00969    }
00970    pvt->owner = newchan;
00971    ast_mutex_unlock(&pvt->lock);
00972    return 0;
00973 }
00974 
00975 static int __oh323_rtp_create(struct oh323_pvt *pvt)
00976 {
00977    struct ast_sockaddr our_addr;
00978 
00979    if (pvt->rtp)
00980       return 0;
00981 
00982    {
00983       struct ast_sockaddr tmp;
00984 
00985       ast_sockaddr_from_sin(&tmp, &bindaddr);
00986       if (ast_find_ourip(&our_addr, &tmp, AF_INET)) {
00987          ast_mutex_unlock(&pvt->lock);
00988          ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00989          return -1;
00990       }
00991    }
00992    our_addr.ss.ss_family = AF_INET;
00993    pvt->rtp = ast_rtp_instance_new("asterisk", sched, &our_addr, NULL);
00994    if (!pvt->rtp) {
00995       ast_mutex_unlock(&pvt->lock);
00996       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00997       return -1;
00998    }
00999    if (h323debug)
01000       ast_debug(1, "Created RTP channel\n");
01001 
01002    ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP");
01003 
01004    if (h323debug)
01005       ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
01006    ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
01007 
01008    if (pvt->dtmf_pt[0] > 0)
01009       ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
01010    if (pvt->dtmf_pt[1] > 0)
01011       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);
01012 
01013    if (pvt->peercapability)
01014       ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
01015 
01016    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01017       ast_jb_configure(pvt->owner, &global_jbconf);
01018       ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
01019       ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
01020       ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
01021       ast_channel_unlock(pvt->owner);
01022    } else
01023       pvt->update_rtp_info = 1;
01024 
01025    return 0;
01026 }
01027 
01028 /*! \brief Private structure should be locked on a call */
01029 static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const char *host, const char *linkedid)
01030 {
01031    struct ast_channel *ch;
01032    char *cid_num, *cid_name;
01033    h323_format fmt;
01034    struct ast_format tmpfmt;
01035 
01036    if (!ast_strlen_zero(pvt->options.cid_num))
01037       cid_num = pvt->options.cid_num;
01038    else
01039       cid_num = pvt->cd.call_source_e164;
01040 
01041    if (!ast_strlen_zero(pvt->options.cid_name))
01042       cid_name = pvt->options.cid_name;
01043    else
01044       cid_name = pvt->cd.call_source_name;
01045    
01046    /* Don't hold a oh323_pvt lock while we allocate a chanel */
01047    ast_mutex_unlock(&pvt->lock);
01048    ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, linkedid, pvt->amaflags, "H323/%s", host);
01049    /* Update usage counter */
01050    ast_module_ref(ast_module_info->self);
01051    ast_mutex_lock(&pvt->lock);
01052    if (ch) {
01053       ast_channel_tech_set(ch, &oh323_tech);
01054       if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
01055          fmt = global_options.capability;
01056 
01057       ast_format_cap_from_old_bitfield(ast_channel_nativeformats(ch), fmt);
01058       ast_codec_choose(&pvt->options.prefs, ast_channel_nativeformats(ch), 1, &tmpfmt)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
01059 
01060       ast_format_cap_set(ast_channel_nativeformats(ch), &tmpfmt);
01061 
01062       pvt->nativeformats = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(ch));
01063       ast_best_codec(ast_channel_nativeformats(ch), &tmpfmt);
01064       ast_format_copy(&ch->writeformat, &tmpfmt);
01065       ast_format_copy(&ch->rawwriteformat, &tmpfmt);
01066       ast_format_copy(&ch->readformat, &tmpfmt);
01067       ast_format_copy(&ch->rawreadformat, &tmpfmt);
01068       if (!pvt->rtp)
01069          __oh323_rtp_create(pvt);
01070 #if 0
01071       ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(pvt->rtp, 0));
01072       ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(pvt->rtp, 1));
01073 #endif
01074 #ifdef VIDEO_SUPPORT
01075       if (pvt->vrtp) {
01076          ast_channel_set_fd(ch, 2, ast_rtp_instance_fd(pvt->vrtp, 0));
01077          ast_channel_set_fd(ch, 3, ast_rtp_instance_fd(pvt->vrtp, 1));
01078       }
01079 #endif
01080 #ifdef T38_SUPPORT
01081       if (pvt->udptl) {
01082          ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl));
01083       }
01084 #endif
01085       if (state == AST_STATE_RING) {
01086          ast_channel_rings_set(ch, 1);
01087       }
01088       /* Allocate dsp for in-band DTMF support */
01089       if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
01090          pvt->vad = ast_dsp_new();
01091          ast_dsp_set_features(pvt->vad, DSP_FEATURE_DIGIT_DETECT);
01092       }
01093       /* Register channel functions. */
01094       ast_channel_tech_pvt_set(ch, pvt);
01095       /* Set the owner of this channel */
01096       pvt->owner = ch;
01097 
01098       ast_channel_context_set(ch, pvt->context);
01099       ast_channel_exten_set(ch, pvt->exten);
01100       ast_channel_priority_set(ch, 1);
01101       if (!ast_strlen_zero(pvt->accountcode)) {
01102          ast_channel_accountcode_set(ch, pvt->accountcode);
01103       }
01104       if (pvt->amaflags) {
01105          ast_channel_amaflags_set(ch, pvt->amaflags);
01106       }
01107 
01108       /* Don't use ast_set_callerid() here because it will
01109        * generate a needless NewCallerID event */
01110       if (!ast_strlen_zero(cid_num)) {
01111          ast_channel_caller(ch)->ani.number.valid = 1;
01112          ast_channel_caller(ch)->ani.number.str = ast_strdup(cid_num);
01113       }
01114 
01115       if (pvt->cd.redirect_reason >= 0) {
01116          ast_channel_redirecting(ch)->from.number.valid = 1;
01117          ast_channel_redirecting(ch)->from.number.str = ast_strdup(pvt->cd.redirect_number);
01118          pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
01119       }
01120       ast_channel_caller(ch)->id.name.presentation = pvt->cd.presentation;
01121       ast_channel_caller(ch)->id.number.presentation = pvt->cd.presentation;
01122       ast_channel_caller(ch)->id.number.plan = pvt->cd.type_of_number;
01123 
01124       if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
01125          ast_channel_dialed(ch)->number.str = ast_strdup(pvt->exten);
01126       }
01127       if (pvt->cd.transfer_capability >= 0)
01128          ast_channel_transfercapability_set(ch, pvt->cd.transfer_capability);
01129       if (state != AST_STATE_DOWN) {
01130          if (ast_pbx_start(ch)) {
01131             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch));
01132             ast_hangup(ch);
01133             ch = NULL;
01134          }
01135       }
01136    } else {
01137       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01138    }
01139    return ch;
01140 }
01141 
01142 static struct oh323_pvt *oh323_alloc(int callid)
01143 {
01144    struct oh323_pvt *pvt;
01145 
01146    pvt = ast_calloc(1, sizeof(*pvt));
01147    if (!pvt) {
01148       ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
01149       return NULL;
01150    }
01151    pvt->cd.redirect_reason = -1;
01152    pvt->cd.transfer_capability = -1;
01153    /* Ensure the call token is allocated for outgoing call */
01154    if (!callid) {
01155       if ((pvt->cd).call_token == NULL) {
01156          (pvt->cd).call_token = ast_calloc(1, 128);
01157       }
01158       if (!pvt->cd.call_token) {
01159          ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
01160          ast_rtp_instance_destroy(pvt->rtp);
01161          ast_free(pvt);
01162          return NULL;
01163       }
01164       memset((char *)(pvt->cd).call_token, 0, 128);
01165       pvt->cd.call_reference = callid;
01166    }
01167    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01168    pvt->jointcapability = pvt->options.capability;
01169    if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) {
01170       pvt->nonCodecCapability |= AST_RTP_DTMF;
01171    } else {
01172       pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01173    }
01174    ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
01175    pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
01176    ast_mutex_init(&pvt->lock);
01177    /* Add to interface list */
01178    ast_mutex_lock(&iflock);
01179    pvt->next = iflist;
01180    iflist = pvt;
01181    ast_mutex_unlock(&iflock);
01182    return pvt;
01183 }
01184 
01185 static struct oh323_pvt *find_call_locked(int call_reference, const char *token)
01186 {
01187    struct oh323_pvt *pvt;
01188 
01189    ast_mutex_lock(&iflock);
01190    pvt = iflist;
01191    while(pvt) {
01192       if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01193          /* Found the call */
01194          if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01195             ast_mutex_lock(&pvt->lock);
01196             ast_mutex_unlock(&iflock);
01197             return pvt;
01198          } else if (token == NULL) {
01199             ast_log(LOG_WARNING, "Call Token is NULL\n");
01200             ast_mutex_lock(&pvt->lock);
01201             ast_mutex_unlock(&iflock);
01202             return pvt;
01203          }
01204       }
01205       pvt = pvt->next;
01206    }
01207    ast_mutex_unlock(&iflock);
01208    return NULL;
01209 }
01210 
01211 static int update_state(struct oh323_pvt *pvt, int state, int signal)
01212 {
01213    if (!pvt)
01214       return 0;
01215    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01216       if (state >= 0)
01217          ast_setstate(pvt->owner, state);
01218       if (signal >= 0)
01219          ast_queue_control(pvt->owner, signal);
01220       ast_channel_unlock(pvt->owner);
01221       return 1;
01222    }
01223    else {
01224       if (state >= 0)
01225          pvt->newstate = state;
01226       if (signal >= 0)
01227          pvt->newcontrol = signal;
01228       return 0;
01229    }
01230 }
01231 
01232 static struct oh323_alias *build_alias(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01233 {
01234    struct oh323_alias *alias;
01235    int found = 0;
01236 
01237    alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
01238 
01239    if (alias)
01240       found++;
01241    else {
01242       if (!(alias = ast_calloc(1, sizeof(*alias))))
01243          return NULL;
01244       ASTOBJ_INIT(alias);
01245    }
01246    if (!found && name)
01247       ast_copy_string(alias->name, name, sizeof(alias->name));
01248    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01249       if (!strcasecmp(v->name, "e164")) {
01250          ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
01251       } else if (!strcasecmp(v->name, "prefix")) {
01252          ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
01253       } else if (!strcasecmp(v->name, "context")) {
01254          ast_copy_string(alias->context, v->value, sizeof(alias->context));
01255       } else if (!strcasecmp(v->name, "secret")) {
01256          ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
01257       } else {
01258          if (strcasecmp(v->value, "h323")) {
01259             ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
01260          }
01261       }
01262    }
01263    ASTOBJ_UNMARK(alias);
01264    return alias;
01265 }
01266 
01267 static struct oh323_alias *realtime_alias(const char *alias)
01268 {
01269    struct ast_variable *var, *tmp;
01270    struct oh323_alias *a;
01271 
01272    var = ast_load_realtime("h323", "name", alias, SENTINEL);
01273 
01274    if (!var)
01275       return NULL;
01276 
01277    for (tmp = var; tmp; tmp = tmp->next) {
01278       if (!strcasecmp(tmp->name, "type") &&
01279       !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01280          ast_variables_destroy(var);
01281          return NULL;
01282       }
01283    }
01284 
01285    a = build_alias(alias, var, NULL, 1);
01286 
01287    ast_variables_destroy(var);
01288 
01289    return a;
01290 }
01291 
01292 static int h323_parse_allow_disallow(struct ast_codec_pref *pref, h323_format *formats, const char *list, int allowing)
01293 {
01294    int res;
01295    struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
01296    if (!cap) {
01297       return 1;
01298    }
01299 
01300    ast_format_cap_from_old_bitfield(cap, *formats);
01301    res = ast_parse_allow_disallow(pref, cap, list, allowing);
01302    *formats = ast_format_cap_to_old_bitfield(cap);
01303    cap = ast_format_cap_destroy(cap);
01304    return res;
01305 
01306 }
01307 
01308 static int update_common_options(struct ast_variable *v, struct call_options *options)
01309 {
01310    int tmp = 0;
01311    char *val, *opt;
01312 
01313    if (!strcasecmp(v->name, "allow")) {
01314       h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
01315    } else if (!strcasecmp(v->name, "autoframing")) {
01316       options->autoframing = ast_true(v->value);
01317    } else if (!strcasecmp(v->name, "disallow")) {
01318       h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
01319    } else if (!strcasecmp(v->name, "dtmfmode")) {
01320       val = ast_strdupa(v->value);
01321       if ((opt = strchr(val, ':')) != (char *)NULL) {
01322          *opt++ = '\0';
01323          tmp = atoi(opt);
01324       }
01325       if (!strcasecmp(v->value, "inband")) {
01326          options->dtmfmode |= H323_DTMF_INBAND;
01327       } else if (!strcasecmp(val, "rfc2833")) {
01328          options->dtmfmode |= H323_DTMF_RFC2833;
01329          if (!opt) {
01330             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01331          } else if ((tmp >= 96) && (tmp < 128)) {
01332             options->dtmfcodec[0] = tmp;
01333          } else {
01334             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01335             ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]);
01336          }
01337       } else if (!strcasecmp(val, "cisco")) {
01338          options->dtmfmode |= H323_DTMF_CISCO;
01339          if (!opt) {
01340             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01341          } else if ((tmp >= 96) && (tmp < 128)) {
01342             options->dtmfcodec[1] = tmp;
01343          } else {
01344             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01345             ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]);
01346          }
01347       } else if (!strcasecmp(v->value, "h245-signal")) {
01348          options->dtmfmode |= H323_DTMF_SIGNAL;
01349       } else {
01350          ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno);
01351       }
01352    } else if (!strcasecmp(v->name, "dtmfcodec")) {
01353       ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno);
01354       tmp = atoi(v->value);
01355       if (tmp < 96)
01356          ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
01357       else
01358          options->dtmfcodec[0] = tmp;
01359    } else if (!strcasecmp(v->name, "bridge")) {
01360       options->bridge = ast_true(v->value);
01361    } else if (!strcasecmp(v->name, "nat")) {
01362       options->nat = ast_true(v->value);
01363    } else if (!strcasecmp(v->name, "fastStart")) {
01364       options->fastStart = ast_true(v->value);
01365    } else if (!strcasecmp(v->name, "h245Tunneling")) {
01366       options->h245Tunneling = ast_true(v->value);
01367    } else if (!strcasecmp(v->name, "silenceSuppression")) {
01368       options->silenceSuppression = ast_true(v->value);
01369    } else if (!strcasecmp(v->name, "progress_setup")) {
01370       tmp = atoi(v->value);
01371       if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
01372          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01373          tmp = 0;
01374       }
01375       options->progress_setup = tmp;
01376    } else if (!strcasecmp(v->name, "progress_alert")) {
01377       tmp = atoi(v->value);
01378       if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
01379          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01380          tmp = 0;
01381       }
01382       options->progress_alert = tmp;
01383    } else if (!strcasecmp(v->name, "progress_audio")) {
01384       options->progress_audio = ast_true(v->value);
01385    } else if (!strcasecmp(v->name, "callerid")) {
01386       ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
01387    } else if (!strcasecmp(v->name, "fullname")) {
01388       ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
01389    } else if (!strcasecmp(v->name, "cid_number")) {
01390       ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
01391    } else if (!strcasecmp(v->name, "tunneling")) {
01392       if (!strcasecmp(v->value, "none"))
01393          options->tunnelOptions = 0;
01394       else if (!strcasecmp(v->value, "cisco"))
01395          options->tunnelOptions |= H323_TUNNEL_CISCO;
01396       else if (!strcasecmp(v->value, "qsig"))
01397          options->tunnelOptions |= H323_TUNNEL_QSIG;
01398       else
01399          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01400    } else if (!strcasecmp(v->name, "hold")) {
01401       if (!strcasecmp(v->value, "none"))
01402          options->holdHandling = ~0;
01403       else if (!strcasecmp(v->value, "notify"))
01404          options->holdHandling |= H323_HOLD_NOTIFY;
01405       else if (!strcasecmp(v->value, "q931only"))
01406          options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY;
01407       else if (!strcasecmp(v->value, "h450"))
01408          options->holdHandling |= H323_HOLD_H450;
01409       else
01410          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01411    } else
01412       return 1;
01413 
01414    return 0;
01415 }
01416 
01417 static struct oh323_user *build_user(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01418 {
01419    struct oh323_user *user;
01420    struct ast_ha *oldha;
01421    int found = 0;
01422    int format;
01423 
01424    user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
01425 
01426    if (user)
01427       found++;
01428    else {
01429       if (!(user = ast_calloc(1, sizeof(*user))))
01430          return NULL;
01431       ASTOBJ_INIT(user);
01432    }
01433    oldha = user->ha;
01434    user->ha = (struct ast_ha *)NULL;
01435    memcpy(&user->options, &global_options, sizeof(user->options));
01436    user->options.dtmfmode = 0;
01437    user->options.holdHandling = 0;
01438    /* Set default context */
01439    ast_copy_string(user->context, default_context, sizeof(user->context));
01440    if (!found) {
01441       ast_copy_string(user->name, name, sizeof(user->name));
01442    }
01443 
01444 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01445    if (user->chanvars) {
01446       ast_variables_destroy(user->chanvars);
01447       user->chanvars = NULL;
01448    }
01449 #endif
01450 
01451    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01452       if (!update_common_options(v, &user->options))
01453          continue;
01454       if (!strcasecmp(v->name, "context")) {
01455          ast_copy_string(user->context, v->value, sizeof(user->context));
01456       } else if (!strcasecmp(v->name, "secret")) {
01457          ast_copy_string(user->secret, v->value, sizeof(user->secret));
01458       } else if (!strcasecmp(v->name, "accountcode")) {
01459          ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
01460       } else if (!strcasecmp(v->name, "host")) {
01461          if (!strcasecmp(v->value, "dynamic")) {
01462             ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
01463             ASTOBJ_UNREF(user, oh323_destroy_user);
01464             return NULL;
01465          } else {
01466             struct ast_sockaddr tmp;
01467 
01468             tmp.ss.ss_family = AF_INET;
01469             if (ast_get_ip(&tmp, v->value)) {
01470                ASTOBJ_UNREF(user, oh323_destroy_user);
01471                return NULL;
01472             }
01473             ast_sockaddr_to_sin(&tmp, &user->addr);
01474          }
01475          /* Let us know we need to use ip authentication */
01476          user->host = 1;
01477       } else if (!strcasecmp(v->name, "amaflags")) {
01478          format = ast_cdr_amaflags2int(v->value);
01479          if (format < 0) {
01480             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
01481          } else {
01482             user->amaflags = format;
01483          }
01484       } else if (!strcasecmp(v->name, "permit") ||
01485                !strcasecmp(v->name, "deny")) {
01486          int ha_error = 0;
01487 
01488          user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error);
01489          if (ha_error)
01490             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01491       }
01492    }
01493    if (!user->options.dtmfmode)
01494       user->options.dtmfmode = global_options.dtmfmode;
01495    if (user->options.holdHandling == ~0)
01496       user->options.holdHandling = 0;
01497    else if (!user->options.holdHandling)
01498       user->options.holdHandling = global_options.holdHandling;
01499    ASTOBJ_UNMARK(user);
01500    ast_free_ha(oldha);
01501    return user;
01502 }
01503 
01504 static struct oh323_user *realtime_user(const call_details_t *cd)
01505 {
01506    struct ast_variable *var, *tmp;
01507    struct oh323_user *user;
01508    const char *username;
01509 
01510    if (userbyalias)
01511       var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL);
01512    else {
01513       username = (char *)NULL;
01514       var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL);
01515    }
01516 
01517    if (!var)
01518       return NULL;
01519 
01520    for (tmp = var; tmp; tmp = tmp->next) {
01521       if (!strcasecmp(tmp->name, "type") &&
01522       !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01523          ast_variables_destroy(var);
01524          return NULL;
01525       } else if (!username && !strcasecmp(tmp->name, "name"))
01526          username = tmp->value;
01527    }
01528 
01529    if (!username) {
01530       ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01531       ast_variables_destroy(var);
01532       return NULL;
01533    }
01534 
01535    user = build_user(username, var, NULL, 1);
01536 
01537    ast_variables_destroy(var);
01538 
01539    return user;
01540 }
01541 
01542 static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
01543 {
01544    struct oh323_peer *peer;
01545    struct ast_ha *oldha;
01546    int found = 0;
01547 
01548    peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01549 
01550    if (peer)
01551       found++;
01552    else {
01553       if (!(peer = ast_calloc(1, sizeof(*peer))))
01554          return NULL;
01555       ASTOBJ_INIT(peer);
01556    }
01557    oldha = peer->ha;
01558    peer->ha = NULL;
01559    memcpy(&peer->options, &global_options, sizeof(peer->options));
01560    peer->options.dtmfmode = 0;
01561    peer->options.holdHandling = 0;
01562    peer->addr.sin_port = htons(h323_signalling_port);
01563    peer->addr.sin_family = AF_INET;
01564    if (!found && name)
01565       ast_copy_string(peer->name, name, sizeof(peer->name));
01566 
01567 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01568    if (peer->chanvars) {
01569       ast_variables_destroy(peer->chanvars);
01570       peer->chanvars = NULL;
01571    }
01572 #endif
01573    /* Default settings for mailbox */
01574    peer->mailbox[0] = '\0';
01575 
01576    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01577       if (!update_common_options(v, &peer->options))
01578          continue;
01579       if (!strcasecmp(v->name, "host")) {
01580          if (!strcasecmp(v->value, "dynamic")) {
01581             ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01582             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01583             return NULL;
01584          }
01585          {
01586             struct ast_sockaddr tmp;
01587 
01588             tmp.ss.ss_family = AF_INET;
01589             if (ast_get_ip(&tmp, v->value)) {
01590                ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01591                ASTOBJ_UNREF(peer, oh323_destroy_peer);
01592                return NULL;
01593             }
01594             ast_sockaddr_to_sin(&tmp, &peer->addr);
01595          }
01596       } else if (!strcasecmp(v->name, "port")) {
01597          peer->addr.sin_port = htons(atoi(v->value));
01598       } else if (!strcasecmp(v->name, "permit") ||
01599                !strcasecmp(v->name, "deny")) {
01600          int ha_error = 0;
01601 
01602          peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
01603          if (ha_error)
01604             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01605       } else if (!strcasecmp(v->name, "mailbox")) {
01606          ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01607       } else if (!strcasecmp(v->name, "hasvoicemail")) {
01608          if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01609             ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01610          }
01611       }
01612    }
01613    if (!peer->options.dtmfmode)
01614       peer->options.dtmfmode = global_options.dtmfmode;
01615    if (peer->options.holdHandling == ~0)
01616       peer->options.holdHandling = 0;
01617    else if (!peer->options.holdHandling)
01618       peer->options.holdHandling = global_options.holdHandling;
01619    ASTOBJ_UNMARK(peer);
01620    ast_free_ha(oldha);
01621    return peer;
01622 }
01623 
01624 static struct oh323_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
01625 {
01626    struct oh323_peer *peer;
01627    struct ast_variable *var;
01628    struct ast_variable *tmp;
01629    const char *addr = NULL;
01630 
01631    /* First check on peer name */
01632    if (peername)
01633       var = ast_load_realtime("h323", "name", peername, SENTINEL);
01634    else if (sin) /* Then check on IP address for dynamic peers */
01635       var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL);
01636    else
01637       return NULL;
01638 
01639    if (!var)
01640       return NULL;
01641 
01642    for (tmp = var; tmp; tmp = tmp->next) {
01643       /* If this is type=user, then skip this object. */
01644       if (!strcasecmp(tmp->name, "type") &&
01645             !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01646          ast_variables_destroy(var);
01647          return NULL;
01648       } else if (!peername && !strcasecmp(tmp->name, "name")) {
01649          peername = tmp->value;
01650       }
01651    }
01652 
01653    if (!peername) {  /* Did not find peer in realtime */
01654       ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01655       ast_variables_destroy(var);
01656       return NULL;
01657    }
01658 
01659    /* Peer found in realtime, now build it in memory */
01660    peer = build_peer(peername, var, NULL, 1);
01661 
01662    ast_variables_destroy(var);
01663 
01664    return peer;
01665 }
01666 
01667 static int oh323_addrcmp_str(struct in_addr inaddr, char *addr)
01668 {
01669    return strcmp(ast_inet_ntoa(inaddr), addr);
01670 }
01671 
01672 static struct oh323_user *find_user(const call_details_t *cd, int realtime)
01673 {
01674    struct oh323_user *u;
01675 
01676    if (userbyalias)
01677       u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01678    else
01679       u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01680 
01681    if (!u && realtime)
01682       u = realtime_user(cd);
01683 
01684    if (!u && h323debug)
01685       ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01686 
01687    return u;
01688 }
01689 
01690 static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin)
01691 {
01692    int res;
01693 
01694    if (!sin)
01695       res = -1;
01696    else
01697       res = inaddrcmp(&addr , sin);
01698 
01699    return res;
01700 }
01701 
01702 static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
01703 {
01704    struct oh323_peer *p;
01705 
01706    if (peer)
01707       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01708    else
01709       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01710 
01711    if (!p && realtime)
01712       p = realtime_peer(peer, sin);
01713 
01714    if (!p && h323debug)
01715       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>"));
01716 
01717    return p;
01718 }
01719 
01720 static int create_addr(struct oh323_pvt *pvt, char *opeer)
01721 {
01722    struct hostent *hp;
01723    struct ast_hostent ahp;
01724    struct oh323_peer *p;
01725    int portno;
01726    int found = 0;
01727    char *port;
01728    char *hostn;
01729    char peer[256] = "";
01730 
01731    ast_copy_string(peer, opeer, sizeof(peer));
01732    port = strchr(peer, ':');
01733    if (port) {
01734       *port = '\0';
01735       port++;
01736    }
01737    pvt->sa.sin_family = AF_INET;
01738    p = find_peer(peer, NULL, 1);
01739    if (p) {
01740       found++;
01741       memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01742       pvt->jointcapability = pvt->options.capability;
01743       if (pvt->options.dtmfmode) {
01744          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01745             pvt->nonCodecCapability |= AST_RTP_DTMF;
01746          } else {
01747             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01748          }
01749       }
01750       if (p->addr.sin_addr.s_addr) {
01751          pvt->sa.sin_addr = p->addr.sin_addr;
01752          pvt->sa.sin_port = p->addr.sin_port;
01753       }
01754       ASTOBJ_UNREF(p, oh323_destroy_peer);
01755    }
01756    if (!p && !found) {
01757       hostn = peer;
01758       if (port) {
01759          portno = atoi(port);
01760       } else {
01761          portno = h323_signalling_port;
01762       }
01763       hp = ast_gethostbyname(hostn, &ahp);
01764       if (hp) {
01765          memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01766          pvt->sa.sin_port = htons(portno);
01767          /* Look peer by address */
01768          p = find_peer(NULL, &pvt->sa, 1);
01769          memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01770          pvt->jointcapability = pvt->options.capability;
01771          if (p) {
01772             ASTOBJ_UNREF(p, oh323_destroy_peer);
01773          }
01774          if (pvt->options.dtmfmode) {
01775             if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01776                pvt->nonCodecCapability |= AST_RTP_DTMF;
01777             } else {
01778                pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01779             }
01780          }
01781          return 0;
01782       } else {
01783          ast_log(LOG_WARNING, "No such host: %s\n", peer);
01784          return -1;
01785       }
01786    } else if (!found) {
01787       return -1;
01788    } else {
01789       return 0;
01790    }
01791 }
01792 static struct ast_channel *oh323_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause)
01793 {
01794    struct oh323_pvt *pvt;
01795    struct ast_channel *tmpc = NULL;
01796    char *ext, *host;
01797    char *h323id = NULL;
01798    char tmp[256], tmp1[256];
01799 
01800    if (h323debug)
01801       ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), cap), dest);
01802 
01803    pvt = oh323_alloc(0);
01804    if (!pvt) {
01805       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", dest);
01806       return NULL;
01807    }
01808    if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
01809       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
01810       oh323_destroy(pvt);
01811       if (cause)
01812          *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01813       return NULL;
01814    }
01815    ast_copy_string(tmp, dest, sizeof(tmp));
01816    host = strchr(tmp, '@');
01817    if (host) {
01818       *host = '\0';
01819       host++;
01820       ext = tmp;
01821    } else {
01822       ext = strrchr(tmp, '/');
01823       if (ext)
01824          *ext++ = '\0';
01825       host = tmp;
01826    }
01827    strtok_r(host, "/", &(h323id));
01828    if (!ast_strlen_zero(h323id)) {
01829       h323_set_id(h323id);
01830    }
01831    if (ext) {
01832       ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01833    }
01834    if (h323debug)
01835       ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
01836 
01837    if (gatekeeper_disable) {
01838       if (create_addr(pvt, host)) {
01839          oh323_destroy(pvt);
01840          if (cause)
01841             *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01842          return NULL;
01843       }
01844    }
01845    else {
01846       memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01847       pvt->jointcapability = pvt->options.capability;
01848       if (pvt->options.dtmfmode) {
01849          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01850             pvt->nonCodecCapability |= AST_RTP_DTMF;
01851          } else {
01852             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01853          }
01854       }
01855    }
01856 
01857    ast_mutex_lock(&caplock);
01858    /* Generate unique channel identifier */
01859    snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01860    tmp1[sizeof(tmp1)-1] = '\0';
01861    ast_mutex_unlock(&caplock);
01862 
01863    ast_mutex_lock(&pvt->lock);
01864    tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? ast_channel_linkedid(requestor) : NULL);
01865    ast_mutex_unlock(&pvt->lock);
01866    if (!tmpc) {
01867       oh323_destroy(pvt);
01868       if (cause)
01869          *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01870    }
01871    ast_update_use_count();
01872    restart_monitor();
01873    return tmpc;
01874 }
01875 
01876 /*! \brief Find a call by alias */
01877 static struct oh323_alias *find_alias(const char *source_aliases, int realtime)
01878 {
01879    struct oh323_alias *a;
01880 
01881    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01882 
01883    if (!a && realtime)
01884       a = realtime_alias(source_aliases);
01885 
01886    return a;
01887 }
01888 
01889 /*! \brief
01890   * Callback for sending digits from H.323 up to asterisk
01891   *
01892   */
01893 static int receive_digit(unsigned call_reference, char digit, const char *token, int duration)
01894 {
01895    struct oh323_pvt *pvt;
01896    int res;
01897 
01898    pvt = find_call_locked(call_reference, token);
01899    if (!pvt) {
01900       ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01901       return -1;
01902    }
01903    if (h323debug)
01904       ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01905 
01906    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01907       if (digit == '!')
01908          res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01909       else {
01910          struct ast_frame f = {
01911             .frametype = AST_FRAME_DTMF_END,
01912             .subclass.integer = digit,
01913             .samples = duration * 8,
01914             .len = duration,
01915             .src = "SEND_DIGIT",
01916          };
01917          if (digit == ' ') {     /* signalUpdate message */
01918             f.subclass.integer = pvt->curDTMF;
01919             AST_SCHED_DEL(sched, pvt->DTMFsched);
01920          } else {          /* Regular input or signal message */
01921             if (pvt->DTMFsched >= 0) {
01922                /* We still don't send DTMF END from previous event, send it now */
01923                AST_SCHED_DEL(sched, pvt->DTMFsched);
01924                f.subclass.integer = pvt->curDTMF;
01925                f.samples = f.len = 0;
01926                ast_queue_frame(pvt->owner, &f);
01927                /* Restore values */
01928                f.subclass.integer = digit;
01929                f.samples = duration * 8;
01930                f.len = duration;
01931             }
01932             if (duration) {      /* This is a signal, signalUpdate follows */
01933                f.frametype = AST_FRAME_DTMF_BEGIN;
01934                pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01935                if (h323debug)
01936                   ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01937             }
01938             pvt->curDTMF = digit;
01939          }
01940          res = ast_queue_frame(pvt->owner, &f);
01941       }
01942       ast_channel_unlock(pvt->owner);
01943    } else {
01944       if (digit == '!')
01945          pvt->newcontrol = AST_CONTROL_FLASH;
01946       else {
01947          pvt->newduration = duration;
01948          pvt->newdigit = digit;
01949       }
01950       res = 0;
01951    }
01952    ast_mutex_unlock(&pvt->lock);
01953    return res;
01954 }
01955 
01956 /*! \brief
01957   * Callback function used to inform the H.323 stack of the local rtp ip/port details
01958   *
01959   * \return Returns the local RTP information
01960   */
01961 static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
01962 {
01963    struct oh323_pvt *pvt;
01964    struct sockaddr_in us;
01965    struct rtp_info *info;
01966 
01967    info = ast_calloc(1, sizeof(*info));
01968    if (!info) {
01969       ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01970       return NULL;
01971    }
01972    pvt = find_call_locked(call_reference, token);
01973    if (!pvt) {
01974       ast_free(info);
01975       ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01976       return NULL;
01977    }
01978    if (!pvt->rtp)
01979       __oh323_rtp_create(pvt);
01980    if (!pvt->rtp) {
01981       ast_mutex_unlock(&pvt->lock);
01982       ast_free(info);
01983       ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01984       return NULL;
01985    }
01986    /* figure out our local RTP port and tell the H.323 stack about it */
01987    {
01988       struct ast_sockaddr tmp;
01989 
01990       ast_rtp_instance_get_local_address(pvt->rtp, &tmp);
01991       ast_sockaddr_to_sin(&tmp, &us);
01992    }
01993    ast_mutex_unlock(&pvt->lock);
01994 
01995    ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01996    info->port = ntohs(us.sin_port);
01997    if (h323debug)
01998       ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01999    return info;
02000 }
02001 
02002 /*! \brief
02003   * Call-back function passing remote ip/port information from H.323 to asterisk
02004   *
02005   * Returns nothing
02006   */
02007 static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
02008 {
02009    struct oh323_pvt *pvt;
02010    struct sockaddr_in them;
02011    int nativeformats_changed;
02012    enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
02013 
02014    if (h323debug)
02015       ast_debug(1, "Setting up RTP connection for %s\n", token);
02016 
02017    /* Find the call or allocate a private structure if call not found */
02018    pvt = find_call_locked(call_reference, token);
02019    if (!pvt) {
02020       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
02021       return;
02022    }
02023    if (pvt->alreadygone) {
02024       ast_mutex_unlock(&pvt->lock);
02025       return;
02026    }
02027 
02028    if (!pvt->rtp)
02029       __oh323_rtp_create(pvt);
02030 
02031    if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
02032       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);
02033    }
02034 
02035    them.sin_family = AF_INET;
02036    /* only works for IPv4 */
02037    them.sin_addr.s_addr = inet_addr(remoteIp);
02038    them.sin_port = htons(remotePort);
02039 
02040    if (them.sin_addr.s_addr) {
02041       {
02042          struct ast_sockaddr tmp;
02043 
02044          ast_sockaddr_from_sin(&tmp, &them);
02045          ast_rtp_instance_set_remote_address(pvt->rtp, &tmp);
02046       }
02047       if (pvt->recvonly) {
02048          pvt->recvonly = 0;
02049          rtp_change = NEED_UNHOLD;
02050       }
02051    } else {
02052       ast_rtp_instance_stop(pvt->rtp);
02053       if (!pvt->recvonly) {
02054          pvt->recvonly = 1;
02055          rtp_change = NEED_HOLD;
02056       }
02057    }
02058 
02059    /* Change native format to reflect information taken from OLC/OLCAck */
02060    nativeformats_changed = 0;
02061    if (pt != 128 && pvt->rtp) {  /* Payload type is invalid, so try to use previously decided */
02062       struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
02063       if (rtptype.asterisk_format) {
02064          if (pvt->nativeformats != ast_format_to_old_bitfield(&rtptype.format)) {
02065             pvt->nativeformats = ast_format_to_old_bitfield(&rtptype.format);
02066             nativeformats_changed = 1;
02067          }
02068       }
02069    } else if (h323debug)
02070       ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
02071 
02072    /* Don't try to lock the channel if nothing changed */
02073    if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
02074       if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02075          struct ast_format_cap *pvt_native = ast_format_cap_alloc_nolock();
02076          ast_format_cap_from_old_bitfield(pvt_native, pvt->nativeformats);
02077 
02078          /* Re-build translation path only if native format(s) has been changed */
02079          if (!(ast_format_cap_identical(ast_channel_nativeformats(pvt->owner), pvt_native))) {
02080             if (h323debug) {
02081                char tmp[256], tmp2[256];
02082                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), ast_channel_nativeformats(pvt->owner)), ast_getformatname(&pvt->owner->readformat), ast_getformatname(&pvt->owner->writeformat));
02083             }
02084             ast_format_cap_copy(ast_channel_nativeformats(pvt->owner), pvt_native);
02085             ast_set_read_format(pvt->owner, &pvt->owner->readformat);
02086             ast_set_write_format(pvt->owner, &pvt->owner->writeformat);
02087          }
02088          if (pvt->options.progress_audio)
02089             ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
02090          switch (rtp_change) {
02091          case NEED_HOLD:
02092             ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02093             break;
02094          case NEED_UNHOLD:
02095             ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02096             break;
02097          default:
02098             break;
02099          }
02100          ast_channel_unlock(pvt->owner);
02101          pvt_native = ast_format_cap_destroy(pvt_native);
02102       }
02103       else {
02104          if (pvt->options.progress_audio)
02105             pvt->newcontrol = AST_CONTROL_PROGRESS;
02106          else if (rtp_change == NEED_HOLD)
02107             pvt->newcontrol = AST_CONTROL_HOLD;
02108          else if (rtp_change == NEED_UNHOLD)
02109             pvt->newcontrol = AST_CONTROL_UNHOLD;
02110          if (h323debug)
02111             ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
02112       }
02113    }
02114    ast_mutex_unlock(&pvt->lock);
02115 
02116    if (h323debug)
02117       ast_debug(1, "RTP connection prepared for %s\n", token);
02118 
02119    return;
02120 }
02121 
02122 /*! \brief
02123   *   Call-back function to signal asterisk that the channel has been answered
02124   * Returns nothing
02125   */
02126 static void connection_made(unsigned call_reference, const char *token)
02127 {
02128    struct oh323_pvt *pvt;
02129 
02130    if (h323debug)
02131       ast_debug(1, "Call %s answered\n", token);
02132 
02133    pvt = find_call_locked(call_reference, token);
02134    if (!pvt) {
02135       ast_log(LOG_ERROR, "Something is wrong: connection\n");
02136       return;
02137    }
02138 
02139    /* Inform asterisk about remote party connected only on outgoing calls */
02140    if (!pvt->outgoing) {
02141       ast_mutex_unlock(&pvt->lock);
02142       return;
02143    }
02144    /* Do not send ANSWER message more than once */
02145    if (!pvt->connection_established) {
02146       pvt->connection_established = 1;
02147       update_state(pvt, -1, AST_CONTROL_ANSWER);
02148    }
02149    ast_mutex_unlock(&pvt->lock);
02150    return;
02151 }
02152 
02153 static int progress(unsigned call_reference, const char *token, int inband)
02154 {
02155    struct oh323_pvt *pvt;
02156 
02157    if (h323debug)
02158       ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02159 
02160    pvt = find_call_locked(call_reference, token);
02161    if (!pvt) {
02162       ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02163       return -1;
02164    }
02165    if (!pvt->owner) {
02166       ast_mutex_unlock(&pvt->lock);
02167       ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02168       return -1;
02169    }
02170    update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02171    ast_mutex_unlock(&pvt->lock);
02172 
02173    return 0;
02174 }
02175 
02176 /*! \brief
02177  *  Call-back function for incoming calls
02178  *
02179  *  Returns 1 on success
02180  */
02181 static call_options_t *setup_incoming_call(call_details_t *cd)
02182 {
02183    struct oh323_pvt *pvt;
02184    struct oh323_user *user = NULL;
02185    struct oh323_alias *alias = NULL;
02186 
02187    if (h323debug)
02188       ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
02189 
02190    /* allocate the call*/
02191    pvt = oh323_alloc(cd->call_reference);
02192 
02193    if (!pvt) {
02194       ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02195       cleanup_call_details(cd);
02196       return NULL;
02197    }
02198 
02199    /* Populate the call details in the private structure */
02200    memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02201    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02202    pvt->jointcapability = pvt->options.capability;
02203 
02204    if (h323debug) {
02205       ast_verb(3, "Setting up Call\n");
02206       ast_verb(3, " \tCall token:  [%s]\n", pvt->cd.call_token);
02207       ast_verb(3, " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);
02208       ast_verb(3, " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
02209       ast_verb(3, " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
02210       ast_verb(3, " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
02211       if (pvt->cd.redirect_reason >= 0)
02212          ast_verb(3, " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02213       ast_verb(3, " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
02214    }
02215 
02216    /* Decide if we are allowing Gatekeeper routed calls*/
02217    if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02218       if (!ast_strlen_zero(cd->call_dest_e164)) {
02219          ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02220          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02221       } else {
02222          alias = find_alias(cd->call_dest_alias, 1);
02223          if (!alias) {
02224             ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02225             oh323_destroy(pvt);
02226             return NULL;
02227          }
02228          ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02229          ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02230       }
02231    } else {
02232       /* Either this call is not from the Gatekeeper
02233          or we are not allowing gk routed calls */
02234       user = find_user(cd, 1);
02235       if (!user) {
02236          if (!acceptAnonymous) {
02237             ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02238             oh323_destroy(pvt);
02239             return NULL;
02240          }
02241          if (ast_strlen_zero(default_context)) {
02242             ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02243             oh323_destroy(pvt);
02244             return NULL;
02245          }
02246          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02247          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02248             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02249          } else {
02250             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02251          }
02252          if (h323debug)
02253             ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02254       } else {
02255          if (user->host) {
02256             if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02257                if (ast_strlen_zero(user->context)) {
02258                   if (ast_strlen_zero(default_context)) {
02259                      ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02260                      oh323_destroy(pvt);
02261                      ASTOBJ_UNREF(user, oh323_destroy_user);
02262                      return NULL;
02263                   }
02264                   ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02265                } else {
02266                   ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02267                }
02268                pvt->exten[0] = 'i';
02269                pvt->exten[1] = '\0';
02270                ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02271                oh323_destroy(pvt);
02272                ASTOBJ_UNREF(user, oh323_destroy_user);
02273                return NULL;   /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
02274             }
02275          }
02276          ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02277          memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02278          pvt->jointcapability = pvt->options.capability;
02279          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02280             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02281          } else {
02282             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02283          }
02284          if (!ast_strlen_zero(user->accountcode)) {
02285             ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02286          }
02287          if (user->amaflags) {
02288             pvt->amaflags = user->amaflags;
02289          }
02290          ASTOBJ_UNREF(user, oh323_destroy_user);
02291       }
02292    }
02293    return &pvt->options;
02294 }
02295 
02296 /*! \brief
02297  * Call-back function to start PBX when OpenH323 ready to serve incoming call
02298  *
02299  * Returns 1 on success
02300  */
02301 static int answer_call(unsigned call_reference, const char *token)
02302 {
02303    struct oh323_pvt *pvt;
02304    struct ast_channel *c = NULL;
02305    enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02306    char tmp_exten[sizeof(pvt->exten)];
02307 
02308    if (h323debug)
02309       ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
02310 
02311    /* Find the call or allocate a private structure if call not found */
02312    pvt = find_call_locked(call_reference, token);
02313    if (!pvt) {
02314       ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02315       return 0;
02316    }
02317    /* Check if requested extension@context pair exists in the dialplan */
02318    ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02319 
02320    /* Try to find best extension in specified context */
02321    if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02322       if (tmp_exten[0] == 's')
02323          try_exten = ext_s;
02324       else if (tmp_exten[0] == 'i')
02325          try_exten = ext_i;
02326       else
02327          try_exten = ext_original;
02328    } else
02329       try_exten = ext_original;
02330    do {
02331       if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02332          break;
02333       switch (try_exten) {
02334       case ext_original:
02335          tmp_exten[0] = 's';
02336          tmp_exten[1] = '\0';
02337          try_exten = ext_s;
02338          break;
02339       case ext_s:
02340          tmp_exten[0] = 'i';
02341          try_exten = ext_i;
02342          break;
02343       case ext_i:
02344          try_exten = ext_notexists;
02345          break;
02346       default:
02347          break;
02348       }
02349    } while (try_exten != ext_notexists);
02350 
02351    /* Drop the call if we don't have <exten>, s and i extensions */
02352    if (try_exten == ext_notexists) {
02353       ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02354       ast_mutex_unlock(&pvt->lock);
02355       h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02356       return 0;
02357    } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02358       if (h323debug)
02359          ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02360       ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02361    }
02362 
02363    /* allocate a channel and tell asterisk about it */
02364    c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL);
02365 
02366    /* And release when done */
02367    ast_mutex_unlock(&pvt->lock);
02368    if (!c) {
02369       ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02370       return 0;
02371    }
02372    return 1;
02373 }
02374 
02375 /*! \brief
02376  * Call-back function to establish an outgoing H.323 call
02377  *
02378  * Returns 1 on success
02379  */
02380 static int setup_outgoing_call(call_details_t *cd)
02381 {
02382    /* Use argument here or free it immediately */
02383    cleanup_call_details(cd);
02384 
02385    return 1;
02386 }
02387 
02388 /*! \brief
02389   *  Call-back function to signal asterisk that the channel is ringing
02390   *  Returns nothing
02391   */
02392 static void chan_ringing(unsigned call_reference, const char *token)
02393 {
02394    struct oh323_pvt *pvt;
02395 
02396    if (h323debug)
02397       ast_debug(1, "Ringing on %s\n", token);
02398 
02399    pvt = find_call_locked(call_reference, token);
02400    if (!pvt) {
02401       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02402       return;
02403    }
02404    if (!pvt->owner) {
02405       ast_mutex_unlock(&pvt->lock);
02406       ast_log(LOG_ERROR, "Channel has no owner\n");
02407       return;
02408    }
02409    update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02410    ast_mutex_unlock(&pvt->lock);
02411    return;
02412 }
02413 
02414 /*! \brief
02415   * Call-back function to cleanup communication
02416   * Returns nothing,
02417   */
02418 static void cleanup_connection(unsigned call_reference, const char *call_token)
02419 {
02420    struct oh323_pvt *pvt;
02421 
02422    if (h323debug)
02423       ast_debug(1, "Cleaning connection to %s\n", call_token);
02424 
02425    while (1) {
02426       pvt = find_call_locked(call_reference, call_token);
02427       if (!pvt) {
02428          if (h323debug)
02429             ast_debug(1, "No connection for %s\n", call_token);
02430          return;
02431       }
02432       if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02433          break;
02434 #if 1
02435       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02436 #ifdef DEBUG_THREADS
02437       /* XXX to be completed
02438        * If we want to print more info on who is holding the lock,
02439        * implement the relevant code in lock.h and use the routines
02440        * supplied there.
02441        */
02442 #endif
02443 #endif
02444       ast_mutex_unlock(&pvt->lock);
02445       usleep(1);
02446    }
02447    if (pvt->rtp) {
02448       /* Immediately stop RTP */
02449       ast_rtp_instance_destroy(pvt->rtp);
02450       pvt->rtp = NULL;
02451    }
02452    /* Free dsp used for in-band DTMF detection */
02453    if (pvt->vad) {
02454       ast_dsp_free(pvt->vad);
02455       pvt->vad = NULL;
02456    }
02457    cleanup_call_details(&pvt->cd);
02458    pvt->alreadygone = 1;
02459    /* Send hangup */
02460    if (pvt->owner) {
02461       ast_channel_softhangup_internal_flag_add(pvt->owner, AST_SOFTHANGUP_DEV);
02462       ast_queue_hangup(pvt->owner);
02463       ast_channel_unlock(pvt->owner);
02464    }
02465    ast_mutex_unlock(&pvt->lock);
02466    if (h323debug)
02467       ast_debug(1, "Connection to %s cleaned\n", call_token);
02468    return;
02469 }
02470 
02471 static void hangup_connection(unsigned int call_reference, const char *token, int cause)
02472 {
02473    struct oh323_pvt *pvt;
02474 
02475    if (h323debug)
02476       ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
02477 
02478    pvt = find_call_locked(call_reference, token);
02479    if (!pvt) {
02480       if (h323debug)
02481          ast_debug(1, "Connection to %s already cleared\n", token);
02482       return;
02483    }
02484    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02485       ast_channel_softhangup_internal_flag_add(pvt->owner, AST_SOFTHANGUP_DEV);
02486       ast_channel_hangupcause_set(pvt->owner, pvt->hangupcause = cause);
02487       ast_queue_hangup_with_cause(pvt->owner, cause);
02488       ast_channel_unlock(pvt->owner);
02489    }
02490    else {
02491       pvt->needhangup = 1;
02492       pvt->hangupcause = cause;
02493       if (h323debug)
02494          ast_debug(1, "Hangup for %s is pending\n", token);
02495    }
02496    ast_mutex_unlock(&pvt->lock);
02497 }
02498 
02499 static void set_dtmf_payload(unsigned call_reference, const char *token, int payload, int is_cisco)
02500 {
02501    struct oh323_pvt *pvt;
02502 
02503    if (h323debug)
02504       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02505 
02506    pvt = find_call_locked(call_reference, token);
02507    if (!pvt) {
02508       return;
02509    }
02510    if (pvt->rtp) {
02511       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);
02512    }
02513    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02514    ast_mutex_unlock(&pvt->lock);
02515    if (h323debug)
02516       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02517 }
02518 
02519 static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
02520 {
02521    struct oh323_pvt *pvt;
02522 
02523    if (h323debug)
02524       ast_debug(1, "Got remote capabilities from connection %s\n", token);
02525 
02526    pvt = find_call_locked(call_reference, token);
02527    if (!pvt)
02528       return;
02529    pvt->peercapability = capabilities;
02530    pvt->jointcapability = pvt->options.capability & capabilities;
02531    if (prefs) {
02532       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02533       if (h323debug) {
02534          int i;
02535          for (i = 0; i < 32; ++i) {
02536             if (!prefs->order[i])
02537                break;
02538             ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(&prefs->formats[i]) : "<none>"), prefs->framing[i]);
02539          }
02540       }
02541       if (pvt->rtp) {
02542          if (pvt->options.autoframing) {
02543             ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02544             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
02545          } else {
02546             ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02547             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
02548          }
02549       }
02550    }
02551    ast_mutex_unlock(&pvt->lock);
02552 }
02553 
02554 static void set_local_capabilities(unsigned call_reference, const char *token)
02555 {
02556    struct oh323_pvt *pvt;
02557    int capability, dtmfmode, pref_codec;
02558    struct ast_codec_pref prefs;
02559 
02560    if (h323debug)
02561       ast_debug(1, "Setting capabilities for connection %s\n", token);
02562 
02563    pvt = find_call_locked(call_reference, token);
02564    if (!pvt)
02565       return;
02566    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02567    dtmfmode = pvt->options.dtmfmode;
02568    prefs = pvt->options.prefs;
02569    pref_codec = pvt->pref_codec;
02570    ast_mutex_unlock(&pvt->lock);
02571    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02572 
02573    if (h323debug) {
02574       int i;
02575       for (i = 0; i < 32; i++) {
02576          if (!prefs.order[i])
02577             break;
02578          ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(&prefs.formats[i]) : "<none>"), prefs.framing[i]);
02579       }
02580       ast_debug(1, "Capabilities for connection %s is set\n", token);
02581    }
02582 }
02583 
02584 static void remote_hold(unsigned call_reference, const char *token, int is_hold)
02585 {
02586    struct oh323_pvt *pvt;
02587 
02588    if (h323debug)
02589       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02590 
02591    pvt = find_call_locked(call_reference, token);
02592    if (!pvt)
02593       return;
02594    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02595       if (is_hold)
02596          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02597       else
02598          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02599       ast_channel_unlock(pvt->owner);
02600    }
02601    else {
02602       if (is_hold)
02603          pvt->newcontrol = AST_CONTROL_HOLD;
02604       else
02605          pvt->newcontrol = AST_CONTROL_UNHOLD;
02606    }
02607    ast_mutex_unlock(&pvt->lock);
02608 }
02609 
02610 static void *do_monitor(void *data)
02611 {
02612    int res;
02613    int reloading;
02614    struct oh323_pvt *oh323 = NULL;
02615 
02616    for(;;) {
02617       /* Check for a reload request */
02618       ast_mutex_lock(&h323_reload_lock);
02619       reloading = h323_reloading;
02620       h323_reloading = 0;
02621       ast_mutex_unlock(&h323_reload_lock);
02622       if (reloading) {
02623          ast_verb(1, "Reloading H.323\n");
02624          h323_do_reload();
02625       }
02626       /* Check for interfaces needing to be killed */
02627       if (!ast_mutex_trylock(&iflock)) {
02628 #if 1
02629          do {
02630             for (oh323 = iflist; oh323; oh323 = oh323->next) {
02631                if (!ast_mutex_trylock(&oh323->lock)) {
02632                   if (oh323->needdestroy) {
02633                      __oh323_destroy(oh323);
02634                      break;
02635                   }
02636                   ast_mutex_unlock(&oh323->lock);
02637                }
02638             }
02639          } while (/*oh323*/ 0);
02640 #else
02641 restartsearch:
02642          oh323 = iflist;
02643          while(oh323) {
02644             if (!ast_mutex_trylock(&oh323->lock)) {
02645                if (oh323->needdestroy) {
02646                   __oh323_destroy(oh323);
02647                   goto restartsearch;
02648                }
02649                ast_mutex_unlock(&oh323->lock);
02650                oh323 = oh323->next;
02651             }
02652          }
02653 #endif
02654          ast_mutex_unlock(&iflock);
02655       } else
02656          oh323 = (struct oh323_pvt *)1;   /* Force fast loop */
02657       pthread_testcancel();
02658       /* Wait for sched or io */
02659       res = ast_sched_wait(sched);
02660       if ((res < 0) || (res > 1000)) {
02661          res = 1000;
02662       }
02663       /* Do not wait if some channel(s) is destroyed, probably, more available too */
02664       if (oh323)
02665          res = 1;
02666       res = ast_io_wait(io, res);
02667       pthread_testcancel();
02668       ast_mutex_lock(&monlock);
02669       if (res >= 0) {
02670          ast_sched_runq(sched);
02671       }
02672       ast_mutex_unlock(&monlock);
02673    }
02674    /* Never reached */
02675    return NULL;
02676 }
02677 
02678 static int restart_monitor(void)
02679 {
02680    /* If we're supposed to be stopped -- stay stopped */
02681    if (ast_mutex_lock(&monlock)) {
02682       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02683       return -1;
02684    }
02685    if (monitor_thread == AST_PTHREADT_STOP) {
02686       ast_mutex_unlock(&monlock);
02687       return 0;
02688    }
02689    if (monitor_thread == pthread_self()) {
02690       ast_mutex_unlock(&monlock);
02691       ast_log(LOG_WARNING, "Cannot kill myself\n");
02692       return -1;
02693    }
02694    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02695       /* Wake up the thread */
02696       pthread_kill(monitor_thread, SIGURG);
02697    } else {
02698       /* Start a new monitor */
02699       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02700          monitor_thread = AST_PTHREADT_NULL;
02701          ast_mutex_unlock(&monlock);
02702          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02703          return -1;
02704       }
02705    }
02706    ast_mutex_unlock(&monlock);
02707    return 0;
02708 }
02709 
02710 static char *handle_cli_h323_set_trace(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02711 {
02712    switch (cmd) {
02713    case CLI_INIT:
02714       e->command = "h323 set trace [on|off]";
02715       e->usage =
02716          "Usage: h323 set trace (on|off|<trace level>)\n"
02717          "       Enable/Disable H.323 stack tracing for debugging purposes\n";
02718       return NULL;
02719    case CLI_GENERATE:
02720       return NULL;
02721    }
02722 
02723    if (a->argc != e->args)
02724       return CLI_SHOWUSAGE;
02725    if (!strcasecmp(a->argv[3], "off")) {
02726       h323_debug(0, 0);
02727       ast_cli(a->fd, "H.323 Trace Disabled\n");
02728    } else if (!strcasecmp(a->argv[3], "on")) {
02729       h323_debug(1, 1);
02730       ast_cli(a->fd, "H.323 Trace Enabled\n");
02731    } else {
02732       int tracelevel = atoi(a->argv[3]);
02733       h323_debug(1, tracelevel);
02734       ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02735    }
02736    return CLI_SUCCESS;
02737 }
02738 
02739 static char *handle_cli_h323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02740 {
02741    switch (cmd) {
02742    case CLI_INIT:
02743       e->command = "h323 set debug [on|off]";
02744       e->usage =
02745          "Usage: h323 set debug [on|off]\n"
02746          "       Enable/Disable H.323 debugging output\n";
02747       return NULL;
02748    case CLI_GENERATE:
02749       return NULL;
02750    }
02751 
02752    if (a->argc != e->args)
02753       return CLI_SHOWUSAGE;
02754    if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off"))
02755       return CLI_SHOWUSAGE;
02756 
02757    h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1;
02758    ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02759    return CLI_SUCCESS;
02760 }
02761 
02762 static char *handle_cli_h323_cycle_gk(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02763 {
02764    switch (cmd) {
02765    case CLI_INIT:
02766       e->command = "h323 cycle gk";
02767       e->usage =
02768          "Usage: h323 cycle gk\n"
02769          "       Manually re-register with the Gatekeper (Currently Disabled)\n";
02770       return NULL;
02771    case CLI_GENERATE:
02772       return NULL;
02773    }
02774 
02775    if (a->argc != 3)
02776       return CLI_SHOWUSAGE;
02777 
02778    h323_gk_urq();
02779 
02780    /* Possibly register with a GK */
02781    if (!gatekeeper_disable) {
02782       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02783          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02784       }
02785    }
02786    return CLI_SUCCESS;
02787 }
02788 
02789 static char *handle_cli_h323_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02790 {
02791    switch (cmd) {
02792    case CLI_INIT:
02793       e->command = "h323 hangup";
02794       e->usage =
02795          "Usage: h323 hangup <token>\n"
02796          "       Manually try to hang up the call identified by <token>\n";
02797       return NULL;
02798    case CLI_GENERATE:
02799       return NULL;
02800    }
02801 
02802    if (a->argc != 3)
02803       return CLI_SHOWUSAGE;
02804    if (h323_soft_hangup(a->argv[2])) {
02805       ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02806    } else {
02807       ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02808    }
02809    return CLI_SUCCESS;
02810 }
02811 
02812 static char *handle_cli_h323_show_tokens(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02813 {
02814    switch (cmd) {
02815    case CLI_INIT:
02816       e->command = "h323 show tokens";
02817       e->usage =
02818          "Usage: h323 show tokens\n"
02819          "       Print out all active call tokens\n";
02820       return NULL;
02821    case CLI_GENERATE:
02822       return NULL;
02823    }
02824 
02825    if (a->argc != 3)
02826       return CLI_SHOWUSAGE;
02827 
02828    h323_show_tokens();
02829 
02830    return CLI_SUCCESS;
02831 }
02832 
02833 static char *handle_cli_h323_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02834 {
02835    switch (cmd) {
02836    case CLI_INIT:
02837       e->command = "h323 show version";
02838       e->usage =
02839          "Usage: h323 show version\n"
02840          "     Show the version of the H.323 library in use\n";
02841       return NULL;
02842    case CLI_GENERATE:
02843       return NULL;
02844    }
02845 
02846    if (a->argc != 3)
02847       return CLI_SHOWUSAGE;
02848 
02849    h323_show_version();
02850    
02851    return CLI_SUCCESS;
02852 }
02853 
02854 static struct ast_cli_entry cli_h323[] = {
02855    AST_CLI_DEFINE(handle_cli_h323_set_trace,    "Enable/Disable H.323 Stack Tracing"),
02856    AST_CLI_DEFINE(handle_cli_h323_set_debug,    "Enable/Disable H.323 Debugging"),
02857    AST_CLI_DEFINE(handle_cli_h323_cycle_gk,     "Manually re-register with the Gatekeper"),
02858    AST_CLI_DEFINE(handle_cli_h323_hangup,       "Manually try to hang up a call"),
02859    AST_CLI_DEFINE(handle_cli_h323_show_tokens,  "Show all active call tokens"),
02860    AST_CLI_DEFINE(handle_cli_h323_show_version, "Show the version of the H.323 library in use"),
02861 };
02862 
02863 static void delete_users(void)
02864 {
02865    int pruned = 0;
02866 
02867    /* Delete all users */
02868    ASTOBJ_CONTAINER_WRLOCK(&userl);
02869    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02870       ASTOBJ_RDLOCK(iterator);
02871       ASTOBJ_MARK(iterator);
02872       ++pruned;
02873       ASTOBJ_UNLOCK(iterator);
02874    } while (0) );
02875    if (pruned) {
02876       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02877    }
02878    ASTOBJ_CONTAINER_UNLOCK(&userl);
02879 
02880    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02881    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02882       ASTOBJ_RDLOCK(iterator);
02883       ASTOBJ_MARK(iterator);
02884       ASTOBJ_UNLOCK(iterator);
02885    } while (0) );
02886    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02887 }
02888 
02889 static void delete_aliases(void)
02890 {
02891    int pruned = 0;
02892 
02893    /* Delete all aliases */
02894    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02895    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02896       ASTOBJ_RDLOCK(iterator);
02897       ASTOBJ_MARK(iterator);
02898       ++pruned;
02899       ASTOBJ_UNLOCK(iterator);
02900    } while (0) );
02901    if (pruned) {
02902       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02903    }
02904    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02905 }
02906 
02907 static void prune_peers(void)
02908 {
02909    /* Prune peers who still are supposed to be deleted */
02910    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02911 }
02912 
02913 static int reload_config(int is_reload)
02914 {
02915    struct ast_config *cfg, *ucfg;
02916    struct ast_variable *v;
02917    struct oh323_peer *peer = NULL;
02918    struct oh323_user *user = NULL;
02919    struct oh323_alias *alias = NULL;
02920    struct ast_hostent ahp; struct hostent *hp;
02921    char *cat;
02922    const char *utype;
02923    int is_user, is_peer, is_alias;
02924    char _gatekeeper[100];
02925    int gk_discover, gk_disable, gk_changed;
02926    struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02927 
02928    cfg = ast_config_load(config, config_flags);
02929 
02930    /* We *must* have a config file otherwise stop immediately */
02931    if (!cfg) {
02932       ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
02933       return 1;
02934    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02935       ucfg = ast_config_load("users.conf", config_flags);
02936       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
02937          return 0;
02938       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
02939          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Aborting.\n");
02940          return 0;
02941       }
02942       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02943       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
02944          ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
02945          ast_config_destroy(ucfg);
02946          return 0;
02947       }
02948    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02949       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
02950       return 0;
02951    } else {
02952       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02953       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
02954          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Aborting.\n");
02955          ast_config_destroy(cfg);
02956          return 0;
02957       }
02958    }
02959 
02960    if (is_reload) {
02961       delete_users();
02962       delete_aliases();
02963       prune_peers();
02964    }
02965 
02966    /* fire up the H.323 Endpoint */
02967    if (!h323_end_point_exist()) {
02968       h323_end_point_create();
02969    }
02970    ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02971    gk_discover = gatekeeper_discover;
02972    gk_disable = gatekeeper_disable;
02973    memset(&bindaddr, 0, sizeof(bindaddr));
02974    memset(&global_options, 0, sizeof(global_options));
02975    global_options.fastStart = 1;
02976    global_options.h245Tunneling = 1;
02977    global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
02978    global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
02979    global_options.dtmfmode = 0;
02980    global_options.holdHandling = 0;
02981    global_options.capability = GLOBAL_CAPABILITY;
02982    global_options.bridge = 1;    /* Do native bridging by default */
02983    global_options.autoframing = 0;
02984    strcpy(default_context, "default");
02985    h323_signalling_port = 1720;
02986    gatekeeper_disable = 1;
02987    gatekeeper_discover = 0;
02988    gkroute = 0;
02989    userbyalias = 1;
02990    acceptAnonymous = 1;
02991    tos = 0;
02992    cos = 0;
02993 
02994    /* Copy the default jb config over global_jbconf */
02995    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02996 
02997    if (ucfg) {
02998       struct ast_variable *gen;
02999       int genhas_h323;
03000       const char *has_h323;
03001 
03002       genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
03003       gen = ast_variable_browse(ucfg, "general");
03004       for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
03005          if (strcasecmp(cat, "general")) {
03006             has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
03007             if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
03008                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
03009                if (user) {
03010                   ASTOBJ_CONTAINER_LINK(&userl, user);
03011                   ASTOBJ_UNREF(user, oh323_destroy_user);
03012                }
03013                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
03014                if (peer) {
03015                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
03016                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
03017                }
03018             }
03019          }
03020       }
03021       ast_config_destroy(ucfg);
03022    }
03023 
03024    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
03025       /* handle jb conf */
03026       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
03027          continue;
03028       /* Create the interface list */
03029       if (!strcasecmp(v->name, "port")) {
03030          h323_signalling_port = (int)strtol(v->value, NULL, 10);
03031       } else if (!strcasecmp(v->name, "bindaddr")) {
03032          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
03033             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
03034          } else {
03035             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
03036          }
03037       } else if (!strcasecmp(v->name, "tos")) { /* Needs to be removed in next release */
03038          ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n");
03039          if (ast_str2tos(v->value, &tos)) {
03040             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03041          }
03042       } else if (!strcasecmp(v->name, "tos_audio")) {
03043          if (ast_str2tos(v->value, &tos)) {
03044             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03045          }
03046       } else if (!strcasecmp(v->name, "cos")) {
03047          ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n");
03048          if (ast_str2cos(v->value, &cos)) {
03049             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03050          }
03051       } else if (!strcasecmp(v->name, "cos_audio")) {
03052          if (ast_str2cos(v->value, &cos)) {
03053             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03054          }
03055       } else if (!strcasecmp(v->name, "gatekeeper")) {
03056          if (!strcasecmp(v->value, "DISABLE")) {
03057             gatekeeper_disable = 1;
03058          } else if (!strcasecmp(v->value, "DISCOVER")) {
03059             gatekeeper_disable = 0;
03060             gatekeeper_discover = 1;
03061          } else {
03062             gatekeeper_disable = 0;
03063             ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
03064          }
03065       } else if (!strcasecmp(v->name, "secret")) {
03066          ast_copy_string(secret, v->value, sizeof(secret));
03067       } else if (!strcasecmp(v->name, "AllowGKRouted")) {
03068          gkroute = ast_true(v->value);
03069       } else if (!strcasecmp(v->name, "context")) {
03070          ast_copy_string(default_context, v->value, sizeof(default_context));
03071          ast_verb(2, "Setting default context to %s\n", default_context);
03072       } else if (!strcasecmp(v->name, "UserByAlias")) {
03073          userbyalias = ast_true(v->value);
03074       } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
03075          acceptAnonymous = ast_true(v->value);
03076       } else if (!update_common_options(v, &global_options)) {
03077          /* dummy */
03078       }
03079    }
03080    if (!global_options.dtmfmode)
03081       global_options.dtmfmode = H323_DTMF_RFC2833;
03082    if (global_options.holdHandling == ~0)
03083       global_options.holdHandling = 0;
03084    else if (!global_options.holdHandling)
03085       global_options.holdHandling = H323_HOLD_H450;
03086 
03087    for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
03088       if (strcasecmp(cat, "general")) {
03089          utype = ast_variable_retrieve(cfg, cat, "type");
03090          if (utype) {
03091             is_user = is_peer = is_alias = 0;
03092             if (!strcasecmp(utype, "user"))
03093                is_user = 1;
03094             else if (!strcasecmp(utype, "peer"))
03095                is_peer = 1;
03096             else if (!strcasecmp(utype, "friend"))
03097                is_user = is_peer = 1;
03098             else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
03099                is_alias = 1;
03100             else {
03101                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
03102                continue;
03103             }
03104             if (is_user) {
03105                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
03106                if (user) {
03107                   ASTOBJ_CONTAINER_LINK(&userl, user);
03108                   ASTOBJ_UNREF(user, oh323_destroy_user);
03109                }
03110             }
03111             if (is_peer) {
03112                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
03113                if (peer) {
03114                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
03115                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
03116                }
03117             }
03118             if (is_alias) {
03119                alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
03120                if (alias) {
03121                   ASTOBJ_CONTAINER_LINK(&aliasl, alias);
03122                   ASTOBJ_UNREF(alias, oh323_destroy_alias);
03123                }
03124             }
03125          } else {
03126             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
03127          }
03128       }
03129    }
03130    ast_config_destroy(cfg);
03131 
03132    /* Register our H.323 aliases if any*/
03133    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
03134    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
03135       ASTOBJ_RDLOCK(iterator);
03136       if (h323_set_alias(iterator)) {
03137          ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
03138          ASTOBJ_UNLOCK(iterator);
03139          continue;
03140       }
03141       ASTOBJ_UNLOCK(iterator);
03142    } while (0) );
03143    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
03144 
03145    /* Don't touch GK if nothing changed because URQ will drop all existing calls */
03146    gk_changed = 0;
03147    if (gatekeeper_disable != gk_disable)
03148       gk_changed = is_reload;
03149    else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
03150       gk_changed = is_reload;
03151    else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
03152       gk_changed = is_reload;
03153    if (gk_changed) {
03154       if(!gk_disable)
03155          h323_gk_urq();
03156       if (!gatekeeper_disable) {
03157          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03158             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03159             gatekeeper_disable = 1;
03160          }
03161       }
03162    }
03163    return 0;
03164 }
03165 
03166 static int h323_reload(void)
03167 {
03168    ast_mutex_lock(&h323_reload_lock);
03169    if (h323_reloading) {
03170       ast_verbose("Previous H.323 reload not yet done\n");
03171    } else {
03172       h323_reloading = 1;
03173    }
03174    ast_mutex_unlock(&h323_reload_lock);
03175    restart_monitor();
03176    return 0;
03177 }
03178 
03179 static char *handle_cli_h323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03180 {
03181    switch (cmd) {
03182    case CLI_INIT:
03183       e->command = "h323 reload";
03184       e->usage =
03185          "Usage: h323 reload\n"
03186          "       Reloads H.323 configuration from h323.conf\n";
03187       return NULL;
03188    case CLI_GENERATE:
03189       return NULL;
03190    }
03191 
03192    if (a->argc != 2)
03193       return CLI_SHOWUSAGE;
03194 
03195    h323_reload();
03196 
03197    return CLI_SUCCESS;
03198 }
03199 
03200 static int h323_do_reload(void)
03201 {
03202    reload_config(1);
03203    return 0;
03204 }
03205 
03206 static int reload(void)
03207 {
03208    if (!sched || !io) {
03209       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03210       return 0;
03211    }
03212    return h323_reload();
03213 }
03214 
03215 static struct ast_cli_entry cli_h323_reload =
03216    AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration");
03217 
03218 static enum ast_rtp_glue_result oh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
03219 {
03220    struct oh323_pvt *pvt;
03221    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
03222 
03223    if (!(pvt = (struct oh323_pvt *)ast_channel_tech_pvt(chan)))
03224       return AST_RTP_GLUE_RESULT_FORBID;
03225 
03226    ast_mutex_lock(&pvt->lock);
03227    *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
03228 #if 0
03229    if (pvt->options.bridge) {
03230       res = AST_RTP_GLUE_RESULT_REMOTE;
03231    }
03232 #endif
03233    ast_mutex_unlock(&pvt->lock);
03234 
03235    return res;
03236 }
03237 
03238 #if 0
03239 static char *convertcap(struct ast_format *format)
03240 {
03241    switch (format->id) {
03242    case AST_FORMAT_G723_1:
03243       return "G.723";
03244    case AST_FORMAT_GSM:
03245       return "GSM";
03246    case AST_FORMAT_ULAW:
03247       return "ULAW";
03248    case AST_FORMAT_ALAW:
03249       return "ALAW";
03250    case AST_FORMAT_G722:
03251       return "G.722";
03252    case AST_FORMAT_ADPCM:
03253       return "G.728";
03254    case AST_FORMAT_G729A:
03255       return "G.729";
03256    case AST_FORMAT_SPEEX:
03257       return "SPEEX";
03258    case AST_FORMAT_ILBC:
03259       return "ILBC";
03260    default:
03261       ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_getformatname(format));
03262       return NULL;
03263    }
03264 }
03265 #endif
03266 
03267 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)
03268 {
03269    /* XXX Deal with Video */
03270    struct oh323_pvt *pvt;
03271    struct sockaddr_in them = { 0, };
03272    struct sockaddr_in us = { 0, };
03273 #if 0 /* Native bridge still isn't ready */
03274    char *mode;
03275 #endif
03276 
03277    if (!rtp) {
03278       return 0;
03279    }
03280 
03281 #if 0 /* Native bridge still isn't ready */
03282    mode = convertcap(&chan->writeformat);
03283 #endif
03284 
03285    pvt = (struct oh323_pvt *) ast_channel_tech_pvt(chan);
03286    if (!pvt) {
03287       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03288       return -1;
03289    }
03290    {
03291       struct ast_sockaddr tmp;
03292 
03293       ast_rtp_instance_get_remote_address(rtp, &tmp);
03294       ast_sockaddr_to_sin(&tmp, &them);
03295       ast_rtp_instance_get_local_address(rtp, &tmp);
03296       ast_sockaddr_to_sin(&tmp, &us);
03297    }
03298 #if 0 /* Native bridge still isn't ready */
03299    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03300 #endif
03301    return 0;
03302 }
03303 
03304 static struct ast_rtp_glue oh323_rtp_glue = {
03305    .type = "H323",
03306    .get_rtp_info = oh323_get_rtp_peer,
03307    .update_peer = oh323_set_rtp_peer,
03308 };
03309 
03310 static enum ast_module_load_result load_module(void)
03311 {
03312    int res;
03313 
03314    if (!(oh323_tech.capabilities = ast_format_cap_alloc())) {
03315       return AST_MODULE_LOAD_FAILURE;
03316    }
03317    ast_format_cap_add_all_by_type(oh323_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
03318 
03319    h323debug = 0;
03320    sched = ast_sched_context_create();
03321    if (!sched) {
03322       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03323       return AST_MODULE_LOAD_FAILURE;
03324    }
03325    io = io_context_create();
03326    if (!io) {
03327       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03328       return AST_MODULE_LOAD_FAILURE;
03329    }
03330    ast_cli_register(&cli_h323_reload);
03331    ASTOBJ_CONTAINER_INIT(&userl);
03332    ASTOBJ_CONTAINER_INIT(&peerl);
03333    ASTOBJ_CONTAINER_INIT(&aliasl);
03334    res = reload_config(0);
03335    if (res) {
03336       /* No config entry */
03337       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03338       ast_cli_unregister(&cli_h323_reload);
03339       io_context_destroy(io);
03340       io = NULL;
03341       ast_sched_context_destroy(sched);
03342       sched = NULL;
03343       ASTOBJ_CONTAINER_DESTROY(&userl);
03344       ASTOBJ_CONTAINER_DESTROY(&peerl);
03345       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03346       return AST_MODULE_LOAD_DECLINE;
03347    } else {
03348       /* Make sure we can register our channel type */
03349       if (ast_channel_register(&oh323_tech)) {
03350          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03351          ast_cli_unregister(&cli_h323_reload);
03352          h323_end_process();
03353          io_context_destroy(io);
03354          ast_sched_context_destroy(sched);
03355 
03356          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03357          ASTOBJ_CONTAINER_DESTROY(&userl);
03358          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03359          ASTOBJ_CONTAINER_DESTROY(&peerl);
03360          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03361          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03362 
03363          return AST_MODULE_LOAD_FAILURE;
03364       }
03365       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03366 
03367       ast_rtp_glue_register(&oh323_rtp_glue);
03368 
03369       /* Register our callback functions */
03370       h323_callback_register(setup_incoming_call,
03371                   setup_outgoing_call,
03372                   external_rtp_create,
03373                   setup_rtp_connection,
03374                   cleanup_connection,
03375                   chan_ringing,
03376                   connection_made,
03377                   receive_digit,
03378                   answer_call,
03379                   progress,
03380                   set_dtmf_payload,
03381                   hangup_connection,
03382                   set_local_capabilities,
03383                   set_peer_capabilities,
03384                   remote_hold);
03385       /* start the h.323 listener */
03386       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03387          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03388          ast_rtp_glue_unregister(&oh323_rtp_glue);
03389          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03390          ast_cli_unregister(&cli_h323_reload);
03391          h323_end_process();
03392          io_context_destroy(io);
03393          ast_sched_context_destroy(sched);
03394 
03395          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03396          ASTOBJ_CONTAINER_DESTROY(&userl);
03397          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03398          ASTOBJ_CONTAINER_DESTROY(&peerl);
03399          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03400          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03401 
03402          return AST_MODULE_LOAD_DECLINE;
03403       }
03404       /* Possibly register with a GK */
03405       if (!gatekeeper_disable) {
03406          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03407             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03408             gatekeeper_disable = 1;
03409             res = AST_MODULE_LOAD_SUCCESS;
03410          }
03411       }
03412       /* And start the monitor for the first time */
03413       restart_monitor();
03414    }
03415    return res;
03416 }
03417 
03418 static int unload_module(void)
03419 {
03420    struct oh323_pvt *p, *pl;
03421 
03422    /* unregister commands */
03423    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03424    ast_cli_unregister(&cli_h323_reload);
03425 
03426    ast_channel_unregister(&oh323_tech);
03427    ast_rtp_glue_unregister(&oh323_rtp_glue);
03428 
03429    if (!ast_mutex_lock(&iflock)) {
03430       /* hangup all interfaces if they have an owner */
03431       p = iflist;
03432       while(p) {
03433          if (p->owner) {
03434             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03435          }
03436          p = p->next;
03437       }
03438       iflist = NULL;
03439       ast_mutex_unlock(&iflock);
03440    } else {
03441       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03442       return -1;
03443    }
03444    if (!ast_mutex_lock(&monlock)) {
03445       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03446          if (monitor_thread != pthread_self()) {
03447             pthread_cancel(monitor_thread);
03448          }
03449          pthread_kill(monitor_thread, SIGURG);
03450          pthread_join(monitor_thread, NULL);
03451       }
03452       monitor_thread = AST_PTHREADT_STOP;
03453       ast_mutex_unlock(&monlock);
03454    } else {
03455       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03456       return -1;
03457    }
03458    if (!ast_mutex_lock(&iflock)) {
03459       /* destroy all the interfaces and free their memory */
03460       p = iflist;
03461       while(p) {
03462          pl = p;
03463          p = p->next;
03464          /* free associated memory */
03465          ast_mutex_destroy(&pl->lock);
03466          ast_free(pl);
03467       }
03468       iflist = NULL;
03469       ast_mutex_unlock(&iflock);
03470    } else {
03471       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03472       return -1;
03473    }
03474    if (!gatekeeper_disable)
03475       h323_gk_urq();
03476    h323_end_process();
03477    if (io)
03478       io_context_destroy(io);
03479    if (sched)
03480       ast_sched_context_destroy(sched);
03481 
03482    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03483    ASTOBJ_CONTAINER_DESTROY(&userl);
03484    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03485    ASTOBJ_CONTAINER_DESTROY(&peerl);
03486    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03487    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03488 
03489    oh323_tech.capabilities = ast_format_cap_destroy(oh323_tech.capabilities);
03490    return 0;
03491 }
03492 
03493 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "The NuFone Network's OpenH323 Channel Driver",
03494       .load = load_module,
03495       .unload = unload_module,
03496       .reload = reload,
03497       .load_pri = AST_MODPRI_CHANNEL_DRIVER,
03498 );

Generated on Thu Oct 11 06:33:38 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6