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