Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:33 2007

Asterisk developer's documentation :: Codename Pineapple


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

Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen