Sat Apr 26 2014 22:01:30

Asterisk developer's documentation


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