Sat Aug 6 00:39:43 2011

Asterisk developer's documentation


chan_h323.c File Reference

This file is part of the chan_h323 driver for Asterisk. More...

#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "h323/chan_h323.h"

Go to the source code of this file.

Data Structures

struct  ast_alias_list
struct  ast_peer_list
 The peer list: Peers and Friends. More...
struct  ast_user_list
 The user list: Users and friends. More...
struct  oh323_pvt
struct  rtpPayloadType
 Structure representing a RTP session.The value of each payload format mapping:. More...

Defines

#define DEPRECATED(_v, _new_opt)   ast_log(LOG_WARNING, "Option %s found at line %d has beed deprecated. Use %s instead.\n", (_v)->name, (_v)->lineno, (_new_opt))
#define GLOBAL_CAPABILITY   (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261)

Functions

static void __oh323_destroy (struct oh323_pvt *pvt)
static struct ast_channel__oh323_new (struct oh323_pvt *pvt, int state, const char *host)
static int __oh323_rtp_create (struct oh323_pvt *pvt)
static void __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt)
static void __reg_module (void)
static void __unreg_module (void)
static int answer_call (unsigned call_reference, const char *token)
static struct oh323_alias * build_alias (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_peer * build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_user * build_user (char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static void chan_ringing (unsigned call_reference, const char *token)
static void cleanup_call_details (call_details_t *cd)
static void cleanup_connection (unsigned call_reference, const char *call_token)
static void connection_made (unsigned call_reference, const char *token)
static char * convertcap (int cap)
static int create_addr (struct oh323_pvt *pvt, char *opeer)
static void delete_aliases (void)
static void delete_users (void)
static void * do_monitor (void *data)
static struct rtp_info * external_rtp_create (unsigned call_reference, const char *token)
static struct oh323_alias * find_alias (const char *source_aliases, int realtime)
static struct oh323_pvtfind_call_locked (int call_reference, const char *token)
static struct oh323_peer * find_peer (const char *peer, struct sockaddr_in *sin, int realtime)
static struct oh323_user * find_user (const call_details_t *cd, int realtime)
static int h323_do_debug (int fd, int argc, char *argv[])
static int h323_do_reload (void)
static int h323_do_trace (int fd, int argc, char *argv[])
static int h323_ep_hangup (int fd, int argc, char *argv[])
static int h323_gk_cycle (int fd, int argc, char *argv[])
static int h323_no_debug (int fd, int argc, char *argv[])
static int h323_no_trace (int fd, int argc, char *argv[])
static int h323_reload (int fd, int argc, char *argv[])
static int h323_tokens_show (int fd, int argc, char *argv[])
static int h323_version_show (int fd, int argc, char *argv[])
static void hangup_connection (unsigned int call_reference, const char *token, int cause)
static enum ast_module_load_result load_module (void)
static int oh323_addrcmp (struct sockaddr_in addr, struct sockaddr_in *sin)
static int oh323_addrcmp_str (struct in_addr inaddr, char *addr)
static struct oh323_pvtoh323_alloc (int callid)
static int oh323_answer (struct ast_channel *c)
static int oh323_call (struct ast_channel *c, char *dest, int timeout)
static void oh323_destroy (struct oh323_pvt *pvt)
static void oh323_destroy_alias (struct oh323_alias *alias)
static void oh323_destroy_peer (struct oh323_peer *peer)
static void oh323_destroy_user (struct oh323_user *user)
static int oh323_digit_begin (struct ast_channel *c, char digit)
static int oh323_digit_end (struct ast_channel *c, char digit, unsigned int duration)
static int oh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_get_result oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static enum ast_rtp_get_result oh323_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static int oh323_hangup (struct ast_channel *c)
static int oh323_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen)
static struct ast_frameoh323_read (struct ast_channel *c)
static struct ast_channeloh323_request (const char *type, int format, void *data, int *cause)
static struct ast_frameoh323_rtp_read (struct oh323_pvt *pvt)
static int oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
static int oh323_simulate_dtmf_end (const void *data)
static void oh323_update_info (struct ast_channel *c)
static int oh323_write (struct ast_channel *c, struct ast_frame *frame)
static int progress (unsigned call_reference, const char *token, int inband)
static void prune_peers (void)
static struct oh323_alias * realtime_alias (const char *alias)
static struct oh323_peer * realtime_peer (const char *peername, struct sockaddr_in *sin)
static struct oh323_user * realtime_user (const call_details_t *cd)
static int receive_digit (unsigned call_reference, char digit, const char *token, int duration)
static const char * redirectingreason2str (int redirectingreason)
static int reload (void)
static int reload_config (int is_reload)
static int restart_monitor (void)
static void set_dtmf_payload (unsigned call_reference, const char *token, int payload)
static void set_local_capabilities (unsigned call_reference, const char *token)
static void set_peer_capabilities (unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
static call_options_t * setup_incoming_call (call_details_t *cd)
static int setup_outgoing_call (call_details_t *cd)
static void setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
static int unload_module (void)
static int update_common_options (struct ast_variable *v, struct call_options *options)
static int update_state (struct oh323_pvt *pvt, int state, int signal)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, }
static int acceptAnonymous = 1
static struct ast_alias_list aliasl
static const struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_debug_deprecated
static struct ast_cli_entry cli_h323_gk_cycle_deprecated
static struct ast_cli_entry cli_h323_no_debug_deprecated
static struct ast_cli_entry cli_h323_no_trace_deprecated
static struct ast_cli_entry cli_h323_reload
static struct ast_cli_entry cli_h323_trace_deprecated
static const char config [] = "h323.conf"
static char debug_usage []
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
static char gatekeeper [100]
static int gatekeeper_disable = 1
static int gatekeeper_discover = 0
static int gkroute = 0
static struct ast_jb_conf global_jbconf
static call_options_t global_options
static ast_mutex_t h323_reload_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char h323_reload_usage []
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
oh323_pvtiflist
static ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char no_debug_usage []
static char no_trace_usage []
static struct ast_rtp_protocol oh323_rtp
static struct ast_channel_tech oh323_tech
answer_call_cb on_answer_call
chan_ringing_cb on_chan_ringing
clear_con_cb on_connection_cleared
con_established_cb on_connection_established
on_rtp_cb on_external_rtp_create
hangup_cb on_hangup
setup_incoming_cb on_incoming_call
setup_outbound_cb on_outgoing_call
progress_cb on_progress
receive_digit_cb on_receive_digit
rfc2833_cb on_set_rfc2833_payload
setcapabilities_cb on_setcapabilities
setpeercapabilities_cb on_setpeercapabilities
start_rtp_cb on_start_rtp_channel
static struct ast_peer_list peerl
static struct sched_contextsched
static char secret [50]
static char show_cycle_usage []
static char show_hangup_usage []
static char show_tokens_usage []
static char show_version_usage []
static const char tdesc [] = "The NuFone Network's Open H.323 Channel Driver"
static int tos = 0
static char trace_usage []
static unsigned int unique = 0
static int userbyalias = 1
static struct ast_user_list userl


Detailed Description

This file is part of the chan_h323 driver for Asterisk.

Author:
Jeremy McNamara
See also

Definition in file chan_h323.c.


Define Documentation

#define DEPRECATED ( _v,
_new_opt   )     ast_log(LOG_WARNING, "Option %s found at line %d has beed deprecated. Use %s instead.\n", (_v)->name, (_v)->lineno, (_new_opt))

Definition at line 1254 of file chan_h323.c.

Referenced by update_common_options().

#define GLOBAL_CAPABILITY   (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261)

Definition at line 143 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 450 of file chan_h323.c.

References ast_channel_lock, ast_channel_unlock, ast_dsp_free(), ast_log(), ast_mutex_destroy(), ast_mutex_unlock(), ast_rtp_destroy(), AST_SCHED_DEL, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, free, iflist, oh323_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, oh323_pvt::next, dahdi_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, sched, ast_channel::tech_pvt, and oh323_pvt::vad.

Referenced by do_monitor(), and oh323_destroy().

00451 {
00452    struct oh323_pvt *cur, *prev = NULL;
00453 
00454    AST_SCHED_DEL(sched, pvt->DTMFsched);
00455 
00456    if (pvt->rtp) {
00457       ast_rtp_destroy(pvt->rtp);
00458    }
00459 
00460    /* Free dsp used for in-band DTMF detection */
00461    if (pvt->vad) {
00462       ast_dsp_free(pvt->vad);
00463    }
00464    cleanup_call_details(&pvt->cd);
00465 
00466    /* Unlink us from the owner if we have one */
00467    if (pvt->owner) {
00468       ast_channel_lock(pvt->owner);
00469       if (h323debug)
00470          ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name);
00471       pvt->owner->tech_pvt = NULL;
00472       ast_channel_unlock(pvt->owner);
00473    }
00474    cur = iflist;
00475    while(cur) {
00476       if (cur == pvt) {
00477          if (prev)
00478             prev->next = cur->next;
00479          else
00480             iflist = cur->next;
00481          break;
00482       }
00483       prev = cur;
00484       cur = cur->next;
00485    }
00486    if (!cur) {
00487       ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur);
00488    } else {
00489       ast_mutex_unlock(&pvt->lock);
00490       ast_mutex_destroy(&pvt->lock);
00491       free(pvt);
00492    }
00493 }

static struct ast_channel* __oh323_new ( struct oh323_pvt pvt,
int  state,
const char *  host 
) [static]

Definition at line 1003 of file chan_h323.c.

References accountcode, oh323_pvt::accountcode, ast_channel::amaflags, oh323_pvt::amaflags, ast_best_codec(), ast_channel_alloc(), ast_codec_choose(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_rtcp_fd(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_udptl_fd(), oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, cid_name, cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, ast_channel::context, oh323_pvt::context, DSP_FEATURE_DTMF_DETECT, ast_channel::exten, oh323_pvt::exten, ast_channel::fds, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_WARNING, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_tech, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, redirectingreason2str(), ast_channel::rings, oh323_pvt::rtp, strdup, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by answer_call(), and oh323_request().

01004 {
01005    struct ast_channel *ch;
01006    char *cid_num, *cid_name;
01007    int fmt;
01008 
01009    if (!ast_strlen_zero(pvt->options.cid_num))
01010       cid_num = pvt->options.cid_num;
01011    else
01012       cid_num = pvt->cd.call_source_e164;
01013 
01014    if (!ast_strlen_zero(pvt->options.cid_name))
01015       cid_name = pvt->options.cid_name;
01016    else
01017       cid_name = pvt->cd.call_source_name;
01018    
01019    /* Don't hold a oh323_pvt lock while we allocate a chanel */
01020    ast_mutex_unlock(&pvt->lock);
01021    ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host);
01022    /* Update usage counter */
01023    ast_module_ref(ast_module_info->self);
01024    ast_mutex_lock(&pvt->lock);
01025    if (ch) {
01026       ch->tech = &oh323_tech;
01027       if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
01028          fmt = global_options.capability;
01029       ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
01030       pvt->nativeformats = ch->nativeformats;
01031       fmt = ast_best_codec(ch->nativeformats);
01032       ch->writeformat = fmt;
01033       ch->rawwriteformat = fmt;
01034       ch->readformat = fmt;
01035       ch->rawreadformat = fmt;
01036 #if 0
01037       ch->fds[0] = ast_rtp_fd(pvt->rtp);
01038       ch->fds[1] = ast_rtcp_fd(pvt->rtp);
01039 #endif
01040 #ifdef VIDEO_SUPPORT
01041       if (pvt->vrtp) {
01042          ch->fds[2] = ast_rtp_fd(pvt->vrtp);
01043          ch->fds[3] = ast_rtcp_fd(pvt->vrtp);
01044       }
01045 #endif
01046 #ifdef T38_SUPPORT
01047       if (pvt->udptl) {
01048          ch->fds[4] = ast_udptl_fd(pvt->udptl);
01049       }
01050 #endif
01051       if (state == AST_STATE_RING) {
01052          ch->rings = 1;
01053       }
01054       /* Allocate dsp for in-band DTMF support */
01055       if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
01056          pvt->vad = ast_dsp_new();
01057          ast_dsp_set_features(pvt->vad, DSP_FEATURE_DTMF_DETECT);
01058       }
01059       /* Register channel functions. */
01060       ch->tech_pvt = pvt;
01061       /* Set the owner of this channel */
01062       pvt->owner = ch;
01063 
01064       ast_copy_string(ch->context, pvt->context, sizeof(ch->context));
01065       ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten));
01066       ch->priority = 1;
01067       if (!ast_strlen_zero(pvt->accountcode)) {
01068          ast_string_field_set(ch, accountcode, pvt->accountcode);
01069       }
01070       if (pvt->amaflags) {
01071          ch->amaflags = pvt->amaflags;
01072       }
01073 
01074       /* Don't use ast_set_callerid() here because it will
01075        * generate a needless NewCallerID event */
01076       ch->cid.cid_ani = ast_strdup(cid_num);
01077 
01078       if (pvt->cd.redirect_reason >= 0) {
01079          ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number);
01080          pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
01081       }
01082       ch->cid.cid_pres = pvt->cd.presentation;
01083       ch->cid.cid_ton = pvt->cd.type_of_number;
01084 
01085       if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
01086          ch->cid.cid_dnid = strdup(pvt->exten);
01087       }
01088       if (pvt->cd.transfer_capability >= 0)
01089          ch->transfercapability = pvt->cd.transfer_capability;
01090       if (state != AST_STATE_DOWN) {
01091          if (ast_pbx_start(ch)) {
01092             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
01093             ast_hangup(ch);
01094             ch = NULL;
01095          }
01096       }
01097    } else {
01098       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01099    }
01100    return ch;
01101 }

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 957 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, ast_find_ourip(), ast_jb_configure(), ast_log(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_rtpmap_type(), ast_rtp_setnat(), ast_rtp_settos(), oh323_pvt::dtmf_pt, errno, ast_channel::fds, global_jbconf, io, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, sched, and oh323_pvt::update_rtp_info.

Referenced by external_rtp_create(), and setup_rtp_connection().

00958 {
00959    struct in_addr our_addr;
00960 
00961    if (pvt->rtp)
00962       return 0;
00963 
00964    if (ast_find_ourip(&our_addr, bindaddr)) {
00965       ast_mutex_unlock(&pvt->lock);
00966       ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00967       return -1;
00968    }
00969    pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr);
00970    if (!pvt->rtp) {
00971       ast_mutex_unlock(&pvt->lock);
00972       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00973       return -1;
00974    }
00975    if (h323debug)
00976       ast_log(LOG_DEBUG, "Created RTP channel\n");
00977 
00978    ast_rtp_settos(pvt->rtp, tos);
00979 
00980    if (h323debug)
00981       ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
00982    ast_rtp_setnat(pvt->rtp, pvt->options.nat);
00983 
00984    if (pvt->dtmf_pt > 0)
00985       ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt, "audio", "telephone-event", 0);
00986 
00987    if (pvt->peercapability)
00988       ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
00989 
00990    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
00991       ast_jb_configure(pvt->owner, &global_jbconf);
00992       pvt->owner->fds[0] = ast_rtp_fd(pvt->rtp);
00993       pvt->owner->fds[1] = ast_rtcp_fd(pvt->rtp);
00994       ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
00995       ast_channel_unlock(pvt->owner);
00996    } else
00997       pvt->update_rtp_info = 1;
00998 
00999    return 0;
01000 }

static void __oh323_update_info ( struct ast_channel c,
struct oh323_pvt pvt 
) [static]

Definition at line 339 of file chan_h323.c.

References ast_channel::_softhangup, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_jb_configure(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hangup(), ast_rtcp_fd(), ast_rtp_fd(), ast_sched_add(), AST_SCHED_DEL, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_SOFTHANGUP_DEV, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, f, ast_channel::fds, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DEBUG, LOG_DTMF, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, sched, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

Referenced by oh323_read(), oh323_update_info(), and oh323_write().

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          .len = pvt->newduration,
00371          .src = "UPDATE_INFO",
00372       };
00373       if (pvt->newdigit == ' ') {      /* signalUpdate message */
00374          f.subclass = pvt->curDTMF;
00375          if (pvt->DTMFsched >= 0) {
00376             AST_SCHED_DEL(sched, pvt->DTMFsched);
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             AST_SCHED_DEL(sched, pvt->DTMFsched);
00382             pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt);
00383             if (h323debug)
00384                ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched);
00385          }
00386          pvt->curDTMF = pvt->newdigit;
00387       }
00388       ast_queue_frame(c, &f);
00389       pvt->newdigit = -1;
00390    }
00391    if (pvt->update_rtp_info > 0) {
00392       if (pvt->rtp) {
00393          ast_jb_configure(c, &global_jbconf);
00394          c->fds[0] = ast_rtp_fd(pvt->rtp);
00395          c->fds[1] = ast_rtcp_fd(pvt->rtp);
00396          ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
00397       }
00398       pvt->update_rtp_info = -1;
00399    }
00400 }

static void __reg_module ( void   )  [static]

Definition at line 3312 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

Definition at line 3312 of file chan_h323.c.

static int answer_call ( unsigned  call_reference,
const char *  token 
) [static]

Call-back function to start PBX when OpenH323 ready to serve incoming call

Returns 1 on success

Definition at line 2179 of file chan_h323.c.

References __oh323_new(), AST_CAUSE_UNALLOCATED, ast_copy_string(), ast_exists_extension(), ast_log(), ast_mutex_unlock(), AST_STATE_RINGING, oh323_pvt::cd, oh323_pvt::context, oh323_pvt::exten, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, and LOG_NOTICE.

Referenced by load_module().

02180 {
02181    struct oh323_pvt *pvt;
02182    struct ast_channel *c = NULL;
02183    enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02184    char tmp_exten[sizeof(pvt->exten)];
02185 
02186    if (h323debug)
02187       ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);
02188 
02189    /* Find the call or allocate a private structure if call not found */
02190    pvt = find_call_locked(call_reference, token);
02191    if (!pvt) {
02192       ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02193       return 0;
02194    }
02195    /* Check if requested extension@context pair exists in the dialplan */
02196    ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02197 
02198    /* Try to find best extension in specified context */
02199    if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02200       if (tmp_exten[0] == 's')
02201          try_exten = ext_s;
02202       else if (tmp_exten[0] == 'i')
02203          try_exten = ext_i;
02204       else
02205          try_exten = ext_original;
02206    } else
02207       try_exten = ext_original;
02208    do {
02209       if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02210          break;
02211       switch (try_exten) {
02212       case ext_original:
02213          tmp_exten[0] = 's';
02214          tmp_exten[1] = '\0';
02215          try_exten = ext_s;
02216          break;
02217       case ext_s:
02218          tmp_exten[0] = 'i';
02219          try_exten = ext_i;
02220          break;
02221       case ext_i:
02222          try_exten = ext_notexists;
02223          break;
02224       default:
02225          break;
02226       }
02227    } while (try_exten != ext_notexists);
02228 
02229    /* Drop the call if we don't have <exten>, s and i extensions */
02230    if (try_exten == ext_notexists) {
02231       ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02232       ast_mutex_unlock(&pvt->lock);
02233       h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02234       return 0;
02235    } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02236       if (h323debug)
02237          ast_log(LOG_DEBUG, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02238       ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02239    }
02240 
02241    /* allocate a channel and tell asterisk about it */
02242    c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token);
02243 
02244    /* And release when done */
02245    ast_mutex_unlock(&pvt->lock);
02246    if (!c) {
02247       ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02248       return 0;
02249    }
02250    return 1;
02251 }

static struct oh323_alias* build_alias ( const char *  name,
struct ast_variable v,
struct ast_variable alt,
int  realtime 
) [static]

Definition at line 1194 of file chan_h323.c.

References aliasl, ast_copy_string(), ast_log(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, calloc, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.

01195 {
01196    struct oh323_alias *alias;
01197    int found = 0;
01198 
01199    alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
01200 
01201    if (alias)
01202       found++;
01203    else {
01204       if (!(alias = (struct oh323_alias *)calloc(1, sizeof(*alias))))
01205          return NULL;
01206       ASTOBJ_INIT(alias);
01207    }
01208    if (!found && name)
01209       ast_copy_string(alias->name, name, sizeof(alias->name));
01210    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01211       if (!strcasecmp(v->name, "e164")) {
01212          ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
01213       } else if (!strcasecmp(v->name, "prefix")) {
01214          ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
01215       } else if (!strcasecmp(v->name, "context")) {
01216          ast_copy_string(alias->context, v->value, sizeof(alias->context));
01217       } else if (!strcasecmp(v->name, "secret")) {
01218          ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
01219       } else {
01220          if (strcasecmp(v->value, "h323")) {
01221             ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
01222          }
01223       }
01224    }
01225    ASTOBJ_UNMARK(alias);
01226    return alias;
01227 }

static struct oh323_peer* build_peer ( const char *  name,
struct ast_variable v,
struct ast_variable alt,
int  realtime 
) [static]

Definition at line 1445 of file chan_h323.c.

References ast_append_ha(), ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_strlen_zero(), ast_true(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, calloc, global_options, h323_signalling_port, LOG_ERROR, ast_variable::name, ast_variable::next, oh323_destroy_peer(), peerl, update_common_options(), and ast_variable::value.

Referenced by reload_config(), and set_config().

01446 {
01447    struct oh323_peer *peer;
01448    struct ast_ha *oldha;
01449    int found = 0;
01450 
01451    peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01452 
01453    if (peer)
01454       found++;
01455    else {
01456       if (!(peer = (struct oh323_peer*)calloc(1, sizeof(*peer))))
01457          return NULL;
01458       ASTOBJ_INIT(peer);
01459    }
01460    oldha = peer->ha;
01461    peer->ha = NULL;
01462    memcpy(&peer->options, &global_options, sizeof(peer->options));
01463    peer->addr.sin_port = htons(h323_signalling_port);
01464    peer->addr.sin_family = AF_INET;
01465    if (!found && name)
01466       ast_copy_string(peer->name, name, sizeof(peer->name));
01467 
01468 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01469    if (peer->chanvars) {
01470       ast_variables_destroy(peer->chanvars);
01471       peer->chanvars = NULL;
01472    }
01473 #endif
01474    /* Default settings for mailbox */
01475    peer->mailbox[0] = '\0';
01476 
01477    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01478       if (!update_common_options(v, &peer->options))
01479          continue;
01480       if (!strcasecmp(v->name, "host")) {
01481          if (!strcasecmp(v->value, "dynamic")) {
01482             ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01483             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01484             return NULL;
01485          }
01486          if (ast_get_ip(&peer->addr, v->value)) {
01487             ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01488             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01489             return NULL;
01490          }
01491       } else if (!strcasecmp(v->name, "port")) {
01492          peer->addr.sin_port = htons(atoi(v->value));
01493       } else if (!strcasecmp(v->name, "permit") ||
01494                !strcasecmp(v->name, "deny")) {
01495          peer->ha = ast_append_ha(v->name, v->value, peer->ha);
01496       } else if (!strcasecmp(v->name, "mailbox")) {
01497          ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01498       } else if (!strcasecmp(v->name, "hasvoicemail")) {
01499          if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01500             ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01501          }
01502       }
01503    }
01504    ASTOBJ_UNMARK(peer);
01505    ast_free_ha(oldha);
01506    return peer;
01507 }

static struct oh323_user* build_user ( char *  name,
struct ast_variable v,
struct ast_variable alt,
int  realtime 
) [static]

Definition at line 1339 of file chan_h323.c.

References ast_append_ha(), ast_cdr_amaflags2int(), ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, calloc, default_context, format, global_options, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_user(), update_common_options(), userl, and ast_variable::value.

Referenced by reload_config(), and set_config().

01340 {
01341    struct oh323_user *user;
01342    struct ast_ha *oldha;
01343    int found = 0;
01344    int format;
01345 
01346    user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
01347 
01348    if (user)
01349       found++;
01350    else {
01351       if (!(user = (struct oh323_user *)calloc(1, sizeof(*user))))
01352          return NULL;
01353       ASTOBJ_INIT(user);
01354    }
01355    oldha = user->ha;
01356    user->ha = (struct ast_ha *)NULL;
01357    memcpy(&user->options, &global_options, sizeof(user->options));
01358    /* Set default context */
01359    ast_copy_string(user->context, default_context, sizeof(user->context));
01360    if (user && !found)
01361       ast_copy_string(user->name, name, sizeof(user->name));
01362 
01363 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01364    if (user->chanvars) {
01365       ast_variables_destroy(user->chanvars);
01366       user->chanvars = NULL;
01367    }
01368 #endif
01369 
01370    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01371       if (!update_common_options(v, &user->options))
01372          continue;
01373       if (!strcasecmp(v->name, "context")) {
01374          ast_copy_string(user->context, v->value, sizeof(user->context));
01375       } else if (!strcasecmp(v->name, "secret")) {
01376          ast_copy_string(user->secret, v->value, sizeof(user->secret));
01377       } else if (!strcasecmp(v->name, "accountcode")) {
01378          ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
01379       } else if (!strcasecmp(v->name, "host")) {
01380          if (!strcasecmp(v->value, "dynamic")) {
01381             ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
01382             ASTOBJ_UNREF(user, oh323_destroy_user);
01383             return NULL;
01384          } else if (ast_get_ip(&user->addr, v->value)) {
01385             ASTOBJ_UNREF(user, oh323_destroy_user);
01386             return NULL;
01387          }
01388          /* Let us know we need to use ip authentication */
01389          user->host = 1;
01390       } else if (!strcasecmp(v->name, "amaflags")) {
01391          format = ast_cdr_amaflags2int(v->value);
01392          if (format < 0) {
01393             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
01394          } else {
01395             user->amaflags = format;
01396          }
01397       } else if (!strcasecmp(v->name, "permit") ||
01398                !strcasecmp(v->name, "deny")) {
01399          user->ha = ast_append_ha(v->name, v->value, user->ha);
01400       }
01401    }
01402    ASTOBJ_UNMARK(user);
01403    ast_free_ha(oldha);
01404    return user;
01405 }

static void chan_ringing ( unsigned  call_reference,
const char *  token 
) [static]

Call-back function to signal asterisk that the channel is ringing Returns nothing

Definition at line 2270 of file chan_h323.c.

References AST_CONTROL_RINGING, ast_log(), ast_mutex_unlock(), AST_STATE_RINGING, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, oh323_pvt::owner, and update_state().

Referenced by load_module().

02271 {
02272    struct oh323_pvt *pvt;
02273 
02274    if (h323debug)
02275       ast_log(LOG_DEBUG, "Ringing on %s\n", token);
02276 
02277    pvt = find_call_locked(call_reference, token);
02278    if (!pvt) {
02279       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02280       return;
02281    }
02282    if (!pvt->owner) {
02283       ast_mutex_unlock(&pvt->lock);
02284       ast_log(LOG_ERROR, "Channel has no owner\n");
02285       return;
02286    }
02287    update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02288    ast_mutex_unlock(&pvt->lock);
02289    return;
02290 }

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 414 of file chan_h323.c.

References free.

Referenced by __oh323_destroy(), cleanup_connection(), setup_incoming_call(), and setup_outgoing_call().

00415 {
00416    if (cd->call_token) {
00417       free(cd->call_token);
00418       cd->call_token = NULL;
00419    }
00420    if (cd->call_source_aliases) {
00421       free(cd->call_source_aliases);
00422       cd->call_source_aliases = NULL;
00423    }
00424    if (cd->call_dest_alias) {
00425       free(cd->call_dest_alias);
00426       cd->call_dest_alias = NULL;
00427    }
00428    if (cd->call_source_name) {
00429       free(cd->call_source_name);
00430       cd->call_source_name = NULL;
00431    }
00432    if (cd->call_source_e164) {
00433       free(cd->call_source_e164);
00434       cd->call_source_e164 = NULL;
00435    }
00436    if (cd->call_dest_e164) {
00437       free(cd->call_dest_e164);
00438       cd->call_dest_e164 = NULL;
00439    }
00440    if (cd->sourceIp) {
00441       free(cd->sourceIp);
00442       cd->sourceIp = NULL;
00443    }
00444    if (cd->redirect_number) {
00445       free(cd->redirect_number);
00446       cd->redirect_number = NULL;
00447    }
00448 }

static void cleanup_connection ( unsigned  call_reference,
const char *  call_token 
) [static]

Call-back function to cleanup communication Returns nothing,

Definition at line 2296 of file chan_h323.c.

References ast_channel::_softhangup, oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, ast_dsp_free(), ast_log(), ast_mutex_unlock(), ast_queue_hangup(), ast_rtp_destroy(), AST_SOFTHANGUP_DEV, oh323_pvt::cd, cleanup_call_details(), find_call_locked(), h323debug, oh323_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.

Referenced by load_module().

02297 {
02298    struct oh323_pvt *pvt;
02299 
02300    if (h323debug)
02301       ast_log(LOG_DEBUG, "Cleaning connection to %s\n", call_token);
02302 
02303    while (1) {
02304       pvt = find_call_locked(call_reference, call_token);
02305       if (!pvt) {
02306          if (h323debug)
02307             ast_log(LOG_DEBUG, "No connection for %s\n", call_token);
02308          return;
02309       }
02310       if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02311          break;
02312 #if 1
02313 #ifdef DEBUG_THREADS
02314       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]);
02315 #else
02316       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02317 #endif
02318 #endif
02319       ast_mutex_unlock(&pvt->lock);
02320       usleep(1);
02321    }
02322    if (pvt->rtp) {
02323       /* Immediately stop RTP */
02324       ast_rtp_destroy(pvt->rtp);
02325       pvt->rtp = NULL;
02326    }
02327    /* Free dsp used for in-band DTMF detection */
02328    if (pvt->vad) {
02329       ast_dsp_free(pvt->vad);
02330       pvt->vad = NULL;
02331    }
02332    cleanup_call_details(&pvt->cd);
02333    pvt->alreadygone = 1;
02334    /* Send hangup */
02335    if (pvt->owner) {
02336       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02337       ast_queue_hangup(pvt->owner);
02338       ast_channel_unlock(pvt->owner);
02339    }
02340    ast_mutex_unlock(&pvt->lock);
02341    if (h323debug)
02342       ast_log(LOG_DEBUG, "Connection to %s cleaned\n", call_token);
02343    return;
02344 }

static void connection_made ( unsigned  call_reference,
const char *  token 
) [static]

Call-back function to signal asterisk that the channel has been answered Returns nothing

Definition at line 2004 of file chan_h323.c.

References AST_CONTROL_ANSWER, ast_log(), ast_mutex_unlock(), oh323_pvt::connection_established, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, oh323_pvt::outgoing, and update_state().

Referenced by load_module().

02005 {
02006    struct oh323_pvt *pvt;
02007 
02008    if (h323debug)
02009       ast_log(LOG_DEBUG, "Call %s answered\n", token);
02010 
02011    pvt = find_call_locked(call_reference, token);
02012    if (!pvt) {
02013       ast_log(LOG_ERROR, "Something is wrong: connection\n");
02014       return;
02015    }
02016 
02017    /* Inform asterisk about remote party connected only on outgoing calls */
02018    if (!pvt->outgoing) {
02019       ast_mutex_unlock(&pvt->lock);
02020       return;
02021    }
02022    /* Do not send ANSWER message more than once */
02023    if (!pvt->connection_established) {
02024       pvt->connection_established = 1;
02025       update_state(pvt, -1, AST_CONTROL_ANSWER);
02026    }
02027    ast_mutex_unlock(&pvt->lock);
02028    return;
02029 }

static char* convertcap ( int  cap  )  [static]

Definition at line 3072 of file chan_h323.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, ast_log(), and LOG_NOTICE.

Referenced by oh323_set_rtp_peer().

03073 {
03074    switch (cap) {
03075    case AST_FORMAT_G723_1:
03076       return "G.723";
03077    case AST_FORMAT_GSM:
03078       return "GSM";
03079    case AST_FORMAT_ULAW:
03080       return "ULAW";
03081    case AST_FORMAT_ALAW:
03082       return "ALAW";
03083    case AST_FORMAT_G722:
03084       return "G.722";
03085    case AST_FORMAT_ADPCM:
03086       return "G.728";
03087    case AST_FORMAT_G729A:
03088       return "G.729";
03089    case AST_FORMAT_SPEEX:
03090       return "SPEEX";
03091    case AST_FORMAT_ILBC:
03092       return "ILBC";
03093    default:
03094       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03095       return NULL;
03096    }
03097 }

static int create_addr ( struct oh323_pvt pvt,
char *  opeer 
) [static]

Definition at line 1605 of file chan_h323.c.

References ahp, ast_copy_string(), ast_gethostbyname(), ast_log(), AST_RTP_DTMF, ASTOBJ_UNREF, find_peer(), global_options, h323_signalling_port, hp, oh323_pvt::jointcapability, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_destroy_peer(), oh323_pvt::options, portno, and oh323_pvt::sa.

Referenced by cache_get_callno_locked(), iax2_call(), iax2_provision(), iax2_request(), oh323_request(), sip_notify(), sip_request_call(), and transmit_register().

01606 {
01607    struct hostent *hp;
01608    struct ast_hostent ahp;
01609    struct oh323_peer *p;
01610    int portno;
01611    int found = 0;
01612    char *port;
01613    char *hostn;
01614    char peer[256] = "";
01615 
01616    ast_copy_string(peer, opeer, sizeof(peer));
01617    port = strchr(peer, ':');
01618    if (port) {
01619       *port = '\0';
01620       port++;
01621    }
01622    pvt->sa.sin_family = AF_INET;
01623    p = find_peer(peer, NULL, 1);
01624    if (p) {
01625       found++;
01626       memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01627       pvt->jointcapability = pvt->options.capability;
01628       if (pvt->options.dtmfmode) {
01629          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01630             pvt->nonCodecCapability |= AST_RTP_DTMF;
01631          } else {
01632             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01633          }
01634       }
01635       if (p->addr.sin_addr.s_addr) {
01636          pvt->sa.sin_addr = p->addr.sin_addr;
01637          pvt->sa.sin_port = p->addr.sin_port;
01638       }
01639       ASTOBJ_UNREF(p, oh323_destroy_peer);
01640    }
01641    if (!p && !found) {
01642       hostn = peer;
01643       if (port) {
01644          portno = atoi(port);
01645       } else {
01646          portno = h323_signalling_port;
01647       }
01648       hp = ast_gethostbyname(hostn, &ahp);
01649       if (hp) {
01650          memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01651          pvt->sa.sin_port = htons(portno);
01652          /* Look peer by address */
01653          p = find_peer(NULL, &pvt->sa, 1);
01654          memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01655          pvt->jointcapability = pvt->options.capability;
01656          if (p) {
01657             ASTOBJ_UNREF(p, oh323_destroy_peer);
01658          }
01659          if (pvt->options.dtmfmode) {
01660             if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01661                pvt->nonCodecCapability |= AST_RTP_DTMF;
01662             } else {
01663                pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01664             }
01665          }
01666          return 0;
01667       } else {
01668          ast_log(LOG_WARNING, "No such host: %s\n", peer);
01669          return -1;
01670       }
01671    } else if (!found) {
01672       return -1;
01673    } else {
01674       return 0;
01675    }
01676 }

static void delete_aliases ( void   )  [static]

Definition at line 2771 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and oh323_destroy_alias().

Referenced by reload_config().

02772 {
02773    int pruned = 0;
02774 
02775    /* Delete all aliases */
02776    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02777    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02778       ASTOBJ_RDLOCK(iterator);
02779       ASTOBJ_MARK(iterator);
02780       ++pruned;
02781       ASTOBJ_UNLOCK(iterator);
02782    } while (0) );
02783    if (pruned) {
02784       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02785    }
02786    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02787 }

static void delete_users ( void   )  [static]

Definition at line 2745 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, oh323_destroy_user(), peerl, and userl.

Referenced by __unload_module(), reload_config(), and set_config_destroy().

02746 {
02747    int pruned = 0;
02748 
02749    /* Delete all users */
02750    ASTOBJ_CONTAINER_WRLOCK(&userl);
02751    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02752       ASTOBJ_RDLOCK(iterator);
02753       ASTOBJ_MARK(iterator);
02754       ++pruned;
02755       ASTOBJ_UNLOCK(iterator);
02756    } while (0) );
02757    if (pruned) {
02758       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02759    }
02760    ASTOBJ_CONTAINER_UNLOCK(&userl);
02761 
02762    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02763    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02764       ASTOBJ_RDLOCK(iterator);
02765       ASTOBJ_MARK(iterator);
02766       ASTOBJ_UNLOCK(iterator);
02767    } while (0) );
02768    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02769 }

static void* do_monitor ( void *  data  )  [static]

Definition at line 2461 of file chan_h323.c.

References __oh323_destroy(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_verbose(), h323_do_reload(), h323_reload_lock, h323_reloading, iflist, iflock, oh323_pvt::lock, oh323_pvt::needdestroy, oh323_pvt::next, option_verbose, and VERBOSE_PREFIX_1.

02462 {
02463    int res;
02464    int reloading;
02465    struct oh323_pvt *oh323 = NULL;
02466 
02467    for(;;) {
02468       /* Check for a reload request */
02469       ast_mutex_lock(&h323_reload_lock);
02470       reloading = h323_reloading;
02471       h323_reloading = 0;
02472       ast_mutex_unlock(&h323_reload_lock);
02473       if (reloading) {
02474          if (option_verbose > 0) {
02475             ast_verbose(VERBOSE_PREFIX_1 "Reloading H.323\n");
02476          }
02477          h323_do_reload();
02478       }
02479       /* Check for interfaces needing to be killed */
02480       if (!ast_mutex_trylock(&iflock)) {
02481 #if 1
02482          do {
02483             for (oh323 = iflist; oh323; oh323 = oh323->next) {
02484                if (!ast_mutex_trylock(&oh323->lock)) {
02485                   if (oh323->needdestroy) {
02486                      __oh323_destroy(oh323);
02487                      break;
02488                   }
02489                   ast_mutex_unlock(&oh323->lock);
02490                }
02491             }
02492          } while (/*oh323*/ 0);
02493 #else
02494 restartsearch:
02495          oh323 = iflist;
02496          while(oh323) {
02497             if (!ast_mutex_trylock(&oh323->lock)) {
02498                if (oh323->needdestroy) {
02499                   __oh323_destroy(oh323);
02500                   goto restartsearch;
02501                }
02502                ast_mutex_unlock(&oh323->lock);
02503                oh323 = oh323->next;
02504             }
02505          }
02506 #endif
02507          ast_mutex_unlock(&iflock);
02508       } else
02509          oh323 = (struct oh323_pvt *)1;   /* Force fast loop */
02510       pthread_testcancel();
02511       /* Wait for sched or io */
02512       res = ast_sched_wait(sched);
02513       if ((res < 0) || (res > 1000)) {
02514          res = 1000;
02515       }
02516       /* Do not wait if some channel(s) is destroyed, probably, more available too */
02517       if (oh323)
02518          res = 1;
02519       res = ast_io_wait(io, res);
02520       pthread_testcancel();
02521       ast_mutex_lock(&monlock);
02522       if (res >= 0) {
02523          ast_sched_runq(sched);
02524       }
02525       ast_mutex_unlock(&monlock);
02526    }
02527    /* Never reached */
02528    return NULL;
02529 }

static struct rtp_info* external_rtp_create ( unsigned  call_reference,
const char *  token 
) [static]

Callback function used to inform the H.323 stack of the local rtp ip/port details

Returns the local RTP information

Definition at line 1850 of file chan_h323.c.

References __oh323_rtp_create(), ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_rtp_get_us(), find_call_locked(), free, h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, malloc, and oh323_pvt::rtp.

Referenced by load_module().

01851 {
01852    struct oh323_pvt *pvt;
01853    struct sockaddr_in us;
01854    struct rtp_info *info;
01855 
01856    info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
01857    if (!info) {
01858       ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01859       return NULL;
01860    }
01861    pvt = find_call_locked(call_reference, token);
01862    if (!pvt) {
01863       free(info);
01864       ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01865       return NULL;
01866    }
01867    if (!pvt->rtp)
01868       __oh323_rtp_create(pvt);
01869    if (!pvt->rtp) {
01870       ast_mutex_unlock(&pvt->lock);
01871       free(info);
01872       ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01873       return NULL;
01874    }
01875    /* figure out our local RTP port and tell the H.323 stack about it */
01876    ast_rtp_get_us(pvt->rtp, &us);
01877    ast_mutex_unlock(&pvt->lock);
01878 
01879    ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01880    info->port = ntohs(us.sin_port);
01881    if (h323debug)
01882       ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01883    return info;
01884 }

static struct oh323_alias* find_alias ( const char *  source_aliases,
int  realtime 
) [static]

Find a call by alias

Definition at line 1766 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

Referenced by __get_header(), add_header(), and setup_incoming_call().

01767 {
01768    struct oh323_alias *a;
01769 
01770    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01771 
01772    if (!a && realtime)
01773       a = realtime_alias(source_aliases);
01774 
01775    return a;
01776 }

static struct oh323_pvt* find_call_locked ( int  call_reference,
const char *  token 
) [static]

Definition at line 1147 of file chan_h323.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::cd, iflist, iflock, oh323_pvt::lock, LOG_WARNING, oh323_pvt::needdestroy, and oh323_pvt::next.

Referenced by answer_call(), chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), hangup_connection(), progress(), receive_digit(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), and setup_rtp_connection().

01148 {
01149    struct oh323_pvt *pvt;
01150 
01151    ast_mutex_lock(&iflock);
01152    pvt = iflist;
01153    while(pvt) {
01154       if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01155          /* Found the call */
01156          if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01157             ast_mutex_lock(&pvt->lock);
01158             ast_mutex_unlock(&iflock);
01159             return pvt;
01160          } else if (token == NULL) {
01161             ast_log(LOG_WARNING, "Call Token is NULL\n");
01162             ast_mutex_lock(&pvt->lock);
01163             ast_mutex_unlock(&iflock);
01164             return pvt;
01165          }
01166       }
01167       pvt = pvt->next;
01168    }
01169    ast_mutex_unlock(&iflock);
01170    return NULL;
01171 }

static struct oh323_peer* find_peer ( const char *  peer,
struct sockaddr_in *  sin,
int  realtime 
) [static]

Definition at line 1587 of file chan_h323.c.

References ast_inet_ntoa(), ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, h323debug, LOG_DEBUG, oh323_addrcmp(), peerl, and realtime_peer().

Referenced by _sip_show_peer(), calltoken_required(), check_user_full(), create_addr(), dundi_encrypt(), function_iaxpeer(), function_sippeer(), handle_command_response(), iax2_devicestate(), iax2_prune_realtime(), iax2_show_peer(), register_verify(), registry_authrequest(), requirecalltoken_mark_auto(), set_config(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), update_call_counter(), and update_registry().

01588 {
01589    struct oh323_peer *p;
01590 
01591    if (peer)
01592       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01593    else
01594       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01595 
01596    if (!p && realtime)
01597       p = realtime_peer(peer, sin);
01598 
01599    if (!p && h323debug)
01600       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>"));
01601 
01602    return p;
01603 }

static struct oh323_user* find_user ( const call_details_t *  cd,
int  realtime 
) [static]

Definition at line 1557 of file chan_h323.c.

References ast_log(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, h323debug, LOG_DEBUG, oh323_addrcmp_str(), realtime_user(), userbyalias, and userl.

Referenced by admin_exec(), advanced_options(), calltoken_required(), check_user_full(), forward_message(), iax2_prune_realtime(), leave_voicemail(), requirecalltoken_mark_auto(), setup_incoming_call(), sip_show_user(), update_call_counter(), vm_authenticate(), vm_box_exists(), and vm_execmain().

01558 {
01559    struct oh323_user *u;
01560 
01561    if (userbyalias)
01562       u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01563    else
01564       u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01565 
01566    if (!u && realtime)
01567       u = realtime_user(cd);
01568 
01569    if (!u && h323debug)
01570       ast_log(LOG_DEBUG, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01571 
01572    return u;
01573 }

static int h323_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2583 of file chan_h323.c.

References ast_cli(), h323debug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02584 {
02585    if (argc < 2 || argc > 3) {
02586       return RESULT_SHOWUSAGE;
02587    }
02588    h323debug = 1;
02589    ast_cli(fd, "H.323 debug enabled\n");
02590    return RESULT_SUCCESS;
02591 }

static int h323_do_reload ( void   )  [static]

Definition at line 3028 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03029 {
03030    reload_config(1);
03031    return 0;
03032 }

static int h323_do_trace ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2563 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02564 {
02565    if (argc != 4) {
02566       return RESULT_SHOWUSAGE;
02567    }
02568    h323_debug(1, atoi(argv[3]));
02569    ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
02570    return RESULT_SUCCESS;
02571 }

static int h323_ep_hangup ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2619 of file chan_h323.c.

References ast_verbose(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and VERBOSE_PREFIX_3.

02620 {
02621    if (argc != 3) {
02622       return RESULT_SHOWUSAGE;
02623    }
02624    if (h323_soft_hangup(argv[2])) {
02625       ast_verbose(VERBOSE_PREFIX_3 "Hangup succeeded on %s\n", argv[2]);
02626    } else {
02627       ast_verbose(VERBOSE_PREFIX_3 "Hangup failed for %s\n", argv[2]);
02628    }
02629    return RESULT_SUCCESS;
02630 }

static int h323_gk_cycle ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2603 of file chan_h323.c.

References ast_log(), gatekeeper, gatekeeper_disable, gatekeeper_discover, LOG_ERROR, RESULT_SHOWUSAGE, RESULT_SUCCESS, and secret.

02604 {
02605    if (argc != 3) {
02606       return RESULT_SHOWUSAGE;
02607    }
02608    h323_gk_urq();
02609 
02610    /* Possibly register with a GK */
02611    if (!gatekeeper_disable) {
02612       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02613          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02614       }
02615    }
02616    return RESULT_SUCCESS;
02617 }

static int h323_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2593 of file chan_h323.c.

References ast_cli(), h323debug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02594 {
02595    if (argc < 3 || argc > 4) {
02596       return RESULT_SHOWUSAGE;
02597    }
02598    h323debug = 0;
02599    ast_cli(fd, "H.323 debug disabled\n");
02600    return RESULT_SUCCESS;
02601 }

static int h323_no_trace ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2573 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02574 {
02575    if (argc < 3 || argc > 4) {
02576       return RESULT_SHOWUSAGE;
02577    }
02578    h323_debug(0,0);
02579    ast_cli(fd, "H.323 trace disabled\n");
02580    return RESULT_SUCCESS;
02581 }

static int h323_reload ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 3015 of file chan_h323.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), h323_reload_lock, h323_reloading, and restart_monitor().

Referenced by reload().

03016 {
03017    ast_mutex_lock(&h323_reload_lock);
03018    if (h323_reloading) {
03019       ast_verbose("Previous H.323 reload not yet done\n");
03020    } else {
03021       h323_reloading = 1;
03022    }
03023    ast_mutex_unlock(&h323_reload_lock);
03024    restart_monitor();
03025    return 0;
03026 }

static int h323_tokens_show ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2632 of file chan_h323.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02633 {
02634    if (argc != 3) {
02635       return RESULT_SHOWUSAGE;
02636    }
02637    h323_show_tokens();
02638    return RESULT_SUCCESS;
02639 }

static int h323_version_show ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2641 of file chan_h323.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02642 {
02643    if (argc != 3) {
02644       return RESULT_SHOWUSAGE;
02645    }
02646    h323_show_version();
02647    return RESULT_SUCCESS;
02648 }

static void hangup_connection ( unsigned int  call_reference,
const char *  token,
int  cause 
) [static]

Definition at line 2346 of file chan_h323.c.

References ast_channel::_softhangup, ast_channel_trylock, ast_channel_unlock, ast_log(), ast_mutex_unlock(), ast_queue_hangup(), AST_SOFTHANGUP_DEV, find_call_locked(), h323debug, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_DEBUG, oh323_pvt::needhangup, and oh323_pvt::owner.

Referenced by load_module().

02347 {
02348    struct oh323_pvt *pvt;
02349 
02350    if (h323debug) {
02351       ast_log(LOG_DEBUG, "Hanging up connection to %s with cause %d\n", token, cause);
02352    }
02353 
02354    pvt = find_call_locked(call_reference, token);
02355    if (!pvt) {
02356       if (h323debug) {
02357          ast_log(LOG_DEBUG, "Connection to %s already cleared\n", token);
02358       }
02359       return;
02360    }
02361    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02362       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02363       pvt->owner->hangupcause = pvt->hangupcause = cause;
02364       ast_queue_hangup(pvt->owner);
02365       ast_channel_unlock(pvt->owner);
02366    }
02367    else {
02368       pvt->needhangup = 1;
02369       pvt->hangupcause = cause;
02370       if (h323debug)
02371          ast_log(LOG_DEBUG, "Hangup for %s is pending\n", token);
02372    }
02373    ast_mutex_unlock(&pvt->lock);
02374 }

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3132 of file chan_h323.c.

References aliasl, answer_call(), ast_channel_register(), ast_cli_register(), ast_cli_register_multiple(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), ast_rtp_proto_unregister(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, chan_ringing(), cleanup_connection(), cli_h323, cli_h323_reload, connection_made(), external_rtp_create(), gatekeeper, gatekeeper_disable, gatekeeper_discover, h323_signalling_port, h323debug, hangup_connection(), io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, peerl, receive_digit(), reload_config(), restart_monitor(), sched_context_create(), sched_context_destroy(), secret, set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.

03133 {
03134    int res;
03135 
03136    h323debug = 0;
03137    sched = sched_context_create();
03138    if (!sched) {
03139       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03140       return AST_MODULE_LOAD_FAILURE;
03141    }
03142    io = io_context_create();
03143    if (!io) {
03144       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03145       return AST_MODULE_LOAD_FAILURE;
03146    }
03147    ast_cli_register(&cli_h323_reload);
03148    ASTOBJ_CONTAINER_INIT(&userl);
03149    ASTOBJ_CONTAINER_INIT(&peerl);
03150    ASTOBJ_CONTAINER_INIT(&aliasl);
03151    res = reload_config(0);
03152    if (res) {
03153       /* No config entry */
03154       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03155       ast_cli_unregister(&cli_h323_reload);
03156       io_context_destroy(io);
03157       io = NULL;
03158       sched_context_destroy(sched);
03159       sched = NULL;
03160       ASTOBJ_CONTAINER_DESTROY(&userl);
03161       ASTOBJ_CONTAINER_DESTROY(&peerl);
03162       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03163       return AST_MODULE_LOAD_DECLINE;
03164    } else {
03165       /* Make sure we can register our channel type */
03166       if (ast_channel_register(&oh323_tech)) {
03167          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03168          ast_cli_unregister(&cli_h323_reload);
03169          h323_end_process();
03170          io_context_destroy(io);
03171          sched_context_destroy(sched);
03172 
03173          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03174          ASTOBJ_CONTAINER_DESTROY(&userl);
03175          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03176          ASTOBJ_CONTAINER_DESTROY(&peerl);
03177          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03178          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03179 
03180          return AST_MODULE_LOAD_FAILURE;
03181       }
03182       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03183 
03184       ast_rtp_proto_register(&oh323_rtp);
03185 
03186       /* Register our callback functions */
03187       h323_callback_register(setup_incoming_call,
03188                   setup_outgoing_call,
03189                   external_rtp_create,
03190                   setup_rtp_connection,
03191                   cleanup_connection,
03192                   chan_ringing,
03193                   connection_made,
03194                   receive_digit,
03195                   answer_call,
03196                   progress,
03197                   set_dtmf_payload,
03198                   hangup_connection,
03199                   set_local_capabilities,
03200                   set_peer_capabilities);
03201       /* start the h.323 listener */
03202       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03203          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03204          ast_rtp_proto_unregister(&oh323_rtp);
03205          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03206          ast_cli_unregister(&cli_h323_reload);
03207          h323_end_process();
03208          io_context_destroy(io);
03209          sched_context_destroy(sched);
03210 
03211          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03212          ASTOBJ_CONTAINER_DESTROY(&userl);
03213          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03214          ASTOBJ_CONTAINER_DESTROY(&peerl);
03215          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03216          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03217 
03218          return AST_MODULE_LOAD_DECLINE;
03219       }
03220       /* Possibly register with a GK */
03221       if (!gatekeeper_disable) {
03222          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03223             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03224             gatekeeper_disable = 1;
03225             res = AST_MODULE_LOAD_SUCCESS;
03226          }
03227       }
03228       /* And start the monitor for the first time */
03229       restart_monitor();
03230    }
03231    return res;
03232 }

static int oh323_addrcmp ( struct sockaddr_in  addr,
struct sockaddr_in *  sin 
) [static]

Definition at line 1575 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01576 {
01577    int res;
01578 
01579    if (!sin)
01580       res = -1;
01581    else
01582       res = inaddrcmp(&addr , sin);
01583 
01584    return res;
01585 }

static int oh323_addrcmp_str ( struct in_addr  inaddr,
char *  addr 
) [static]

Definition at line 1552 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01553 {
01554    return strcmp(ast_inet_ntoa(inaddr), addr);
01555 }

static struct oh323_pvt* oh323_alloc ( int  callid  )  [static]

Definition at line 1103 of file chan_h323.c.

References ast_copy_string(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), AST_RTP_DTMF, oh323_pvt::cd, oh323_pvt::context, oh323_pvt::DTMFsched, free, iflist, iflock, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, malloc, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newstate, oh323_pvt::next, oh323_pvt::nonCodecCapability, oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::update_rtp_info.

Referenced by oh323_request(), and setup_incoming_call().

01104 {
01105    struct oh323_pvt *pvt;
01106 
01107    pvt = (struct oh323_pvt *) malloc(sizeof(struct oh323_pvt));
01108    if (!pvt) {
01109       ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
01110       return NULL;
01111    }
01112    memset(pvt, 0, sizeof(struct oh323_pvt));
01113    pvt->cd.redirect_reason = -1;
01114    pvt->cd.transfer_capability = -1;
01115    /* Ensure the call token is allocated for outgoing call */
01116    if (!callid) {
01117       if ((pvt->cd).call_token == NULL) {
01118          (pvt->cd).call_token = (char *)malloc(128);
01119       }
01120       if (!pvt->cd.call_token) {
01121          ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
01122          ast_rtp_destroy(pvt->rtp);
01123          free(pvt);
01124          return NULL;
01125       }
01126       memset((char *)(pvt->cd).call_token, 0, 128);
01127       pvt->cd.call_reference = callid;
01128    }
01129    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01130    pvt->jointcapability = pvt->options.capability;
01131    if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01132       pvt->nonCodecCapability |= AST_RTP_DTMF;
01133    } else {
01134       pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01135    }
01136    ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
01137    pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
01138    ast_mutex_init(&pvt->lock);
01139    /* Add to interface list */
01140    ast_mutex_lock(&iflock);
01141    pvt->next = iflist;
01142    iflist = pvt;
01143    ast_mutex_unlock(&iflock);
01144    return pvt;
01145 }

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 663 of file chan_h323.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, oh323_pvt::cd, free, oh323_pvt::lock, LOG_DEBUG, ast_channel::name, oh323_update_info(), strdup, and ast_channel::tech_pvt.

00664 {
00665    int res;
00666    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00667    char *token;
00668 
00669    if (h323debug)
00670       ast_log(LOG_DEBUG, "Answering on %s\n", c->name);
00671 
00672    ast_mutex_lock(&pvt->lock);
00673    token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00674    ast_mutex_unlock(&pvt->lock);
00675    res = h323_answering_call(token, 0);
00676    if (token)
00677       free(token);
00678 
00679    oh323_update_info(c);
00680    if (c->_state != AST_STATE_UP) {
00681       ast_setstate(c, AST_STATE_UP);
00682    }
00683    return res;
00684 }

static int oh323_call ( struct ast_channel c,
char *  dest,
int  timeout 
) [static]

Make a call over the specified channel to the specified destination. Returns -1 on error, 0 on success.

Definition at line 584 of file chan_h323.c.

References ast_channel::_state, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, oh323_pvt::exten, oh323_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::name, oh323_update_info(), option_verbose, oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), oh323_pvt::sa, ast_channel::tech_pvt, ast_channel::transfercapability, and VERBOSE_PREFIX_3.

00585 {
00586    int res = 0;
00587    struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
00588    const char *addr;
00589    char called_addr[1024];
00590 
00591    if (h323debug) {
00592       ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);
00593    }
00594    if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {
00595       ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);
00596       return -1;
00597    }
00598    ast_mutex_lock(&pvt->lock);
00599    if (!gatekeeper_disable) {
00600       if (ast_strlen_zero(pvt->exten)) {
00601          ast_copy_string(called_addr, dest, sizeof(called_addr));
00602       } else {
00603          snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
00604       }
00605    } else {
00606       res = htons(pvt->sa.sin_port);
00607       addr = ast_inet_ntoa(pvt->sa.sin_addr);
00608       if (ast_strlen_zero(pvt->exten)) {
00609          snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);
00610       } else {
00611          snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);
00612       }
00613    }
00614    /* make sure null terminated */
00615    called_addr[sizeof(called_addr) - 1] = '\0';
00616 
00617    if (c->cid.cid_num)
00618       ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));
00619 
00620    if (c->cid.cid_name)
00621       ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));
00622 
00623    if (c->cid.cid_rdnis) {
00624       ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));
00625    }
00626 
00627    pvt->options.presentation = c->cid.cid_pres;
00628    pvt->options.type_of_number = c->cid.cid_ton;
00629 
00630    if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
00631       if (!strcasecmp(addr, "UNKNOWN"))
00632          pvt->options.redirect_reason = 0;
00633       else if (!strcasecmp(addr, "BUSY"))
00634          pvt->options.redirect_reason = 1;
00635       else if (!strcasecmp(addr, "NO_REPLY"))
00636          pvt->options.redirect_reason = 2;
00637       else if (!strcasecmp(addr, "UNCONDITIONAL"))
00638          pvt->options.redirect_reason = 15;
00639       else
00640          pvt->options.redirect_reason = -1;
00641    } else
00642       pvt->options.redirect_reason = -1;
00643 
00644    pvt->options.transfer_capability = c->transfercapability;
00645 
00646    /* indicate that this is an outgoing call */
00647    pvt->outgoing = 1;
00648 
00649    if (option_verbose > 2)
00650       ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability));
00651    if (h323debug)
00652       ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d\n", called_addr, pvt->options.dtmfcodec);
00653    ast_mutex_unlock(&pvt->lock);
00654    res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
00655    if (res) {
00656       ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
00657       return -1;
00658    }
00659    oh323_update_info(c);
00660    return 0;
00661 }

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 495 of file chan_h323.c.

References __oh323_destroy(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), iflock, oh323_pvt::lock, LOG_DEBUG, ast_channel::name, and oh323_pvt::owner.

Referenced by oh323_request(), and setup_incoming_call().

00496 {
00497    if (h323debug) {
00498       ast_log(LOG_DEBUG, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
00499    }
00500    ast_mutex_lock(&iflock);
00501    ast_mutex_lock(&pvt->lock);
00502    __oh323_destroy(pvt);
00503    ast_mutex_unlock(&iflock);
00504 }

static void oh323_destroy_alias ( struct oh323_alias *  alias  )  [static]

Definition at line 286 of file chan_h323.c.

References ast_log(), free, and LOG_DEBUG.

Referenced by delete_aliases(), load_module(), and unload_module().

00287 {
00288    if (h323debug)
00289       ast_log(LOG_DEBUG, "Destroying alias '%s'\n", alias->name);
00290    free(alias);
00291 }

static void oh323_destroy_peer ( struct oh323_peer *  peer  )  [static]

Definition at line 301 of file chan_h323.c.

References ast_free_ha(), ast_log(), free, and LOG_DEBUG.

Referenced by build_peer(), create_addr(), load_module(), prune_peers(), reload_config(), and unload_module().

00302 {
00303    if (h323debug)
00304       ast_log(LOG_DEBUG, "Destroying peer '%s'\n", peer->name);
00305    ast_free_ha(peer->ha);
00306    free(peer);
00307 }

static void oh323_destroy_user ( struct oh323_user *  user  )  [static]

Definition at line 293 of file chan_h323.c.

References ast_free_ha(), ast_log(), free, and LOG_DEBUG.

Referenced by build_user(), delete_users(), load_module(), reload_config(), setup_incoming_call(), and unload_module().

00294 {
00295    if (h323debug)
00296       ast_log(LOG_DEBUG, "Destroying user '%s'\n", user->name);
00297    ast_free_ha(user->ha);
00298    free(user);
00299 }

static int oh323_digit_begin ( struct ast_channel c,
char  digit 
) [static]

Definition at line 506 of file chan_h323.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_begin(), oh323_pvt::cd, oh323_pvt::dtmf_pt, free, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, strdup, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.

00507 {
00508    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00509    char *token;
00510 
00511    if (!pvt) {
00512       ast_log(LOG_ERROR, "No private structure?! This is bad\n");
00513       return -1;
00514    }
00515    ast_mutex_lock(&pvt->lock);
00516    if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {
00517       /* out-of-band DTMF */
00518       if (h323debug) {
00519          ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name);
00520       }
00521       ast_rtp_senddigit_begin(pvt->rtp, digit);
00522       ast_mutex_unlock(&pvt->lock);
00523    } else if (pvt->txDtmfDigit != digit) {
00524       /* in-band DTMF */
00525       if (h323debug) {
00526          ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, c->name);
00527       }
00528       pvt->txDtmfDigit = digit;
00529       token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00530       ast_mutex_unlock(&pvt->lock);
00531       h323_send_tone(token, digit);
00532       if (token) {
00533          free(token);
00534       }
00535    } else
00536       ast_mutex_unlock(&pvt->lock);
00537    oh323_update_info(c);
00538    return 0;
00539 }

static int oh323_digit_end ( struct ast_channel c,
char  digit,
unsigned int  duration 
) [static]

Send (play) the specified digit to the channel.

Definition at line 545 of file chan_h323.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_end(), oh323_pvt::cd, oh323_pvt::dtmf_pt, free, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, strdup, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.

00546 {
00547    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00548    char *token;
00549 
00550    if (!pvt) {
00551       ast_log(LOG_ERROR, "No private structure?! This is bad\n");
00552       return -1;
00553    }
00554    ast_mutex_lock(&pvt->lock);
00555    if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {
00556       /* out-of-band DTMF */
00557       if (h323debug) {
00558          ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);
00559       }
00560       ast_rtp_senddigit_end(pvt->rtp, digit);
00561       ast_mutex_unlock(&pvt->lock);
00562    } else {
00563       /* in-band DTMF */
00564       if (h323debug) {
00565          ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, c->name, duration);
00566       }
00567       pvt->txDtmfDigit = ' ';
00568       token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00569       ast_mutex_unlock(&pvt->lock);
00570       h323_send_tone(token, ' ');
00571       if (token) {
00572          free(token);
00573       }
00574    }
00575    oh323_update_info(c);
00576    return 0;
00577 }

static int oh323_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 943 of file chan_h323.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::lock, LOG_WARNING, oh323_pvt::owner, and ast_channel::tech_pvt.

00944 {
00945    struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt;
00946 
00947    ast_mutex_lock(&pvt->lock);
00948    if (pvt->owner != oldchan) {
00949       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
00950       return -1;
00951    }
00952    pvt->owner = newchan;
00953    ast_mutex_unlock(&pvt->lock);
00954    return 0;
00955 }

static enum ast_rtp_get_result oh323_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp **  rtp 
) [static]

Definition at line 3049 of file chan_h323.c.

References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, oh323_pvt::lock, oh323_pvt::options, oh323_pvt::rtp, and ast_channel::tech_pvt.

03050 {
03051    struct oh323_pvt *pvt;
03052    enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
03053 
03054    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03055       return res;
03056 
03057    ast_mutex_lock(&pvt->lock);
03058    if (pvt->rtp && pvt->options.bridge) {
03059       *rtp = pvt->rtp;
03060       res = AST_RTP_TRY_NATIVE;
03061    }
03062    ast_mutex_unlock(&pvt->lock);
03063 
03064    return res;
03065 }

static enum ast_rtp_get_result oh323_get_vrtp_peer ( struct ast_channel chan,
struct ast_rtp **  rtp 
) [static]

Definition at line 3067 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03068 {
03069    return AST_RTP_GET_FAILED;
03070 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 686 of file chan_h323.c.

References oh323_pvt::alreadygone, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_REQUESTED_CHAN_UNAVAIL, AST_CAUSE_USER_BUSY, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::cd, free, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), strdup, and ast_channel::tech_pvt.

00687 {
00688    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00689    int q931cause = AST_CAUSE_NORMAL_CLEARING;
00690    char *call_token;
00691 
00692 
00693    if (h323debug)
00694       ast_log(LOG_DEBUG, "Hanging up and scheduling destroy of call %s\n", c->name);
00695 
00696    if (!c->tech_pvt) {
00697       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00698       return 0;
00699    }
00700    ast_mutex_lock(&pvt->lock);
00701    /* Determine how to disconnect */
00702    if (pvt->owner != c) {
00703       ast_log(LOG_WARNING, "Huh?  We aren't the owner?\n");
00704       ast_mutex_unlock(&pvt->lock);
00705       return 0;
00706    }
00707 
00708    pvt->owner = NULL;
00709    c->tech_pvt = NULL;
00710 
00711    if (c->hangupcause) {
00712       q931cause = c->hangupcause;
00713    } else {
00714       const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
00715       if (cause) {
00716          if (!strcmp(cause, "CONGESTION")) {
00717             q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
00718          } else if (!strcmp(cause, "BUSY")) {
00719             q931cause = AST_CAUSE_USER_BUSY;
00720          } else if (!strcmp(cause, "CHANISUNVAIL")) {
00721             q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
00722          } else if (!strcmp(cause, "NOANSWER")) {
00723             q931cause = AST_CAUSE_NO_ANSWER;
00724          } else if (!strcmp(cause, "CANCEL")) {
00725             q931cause = AST_CAUSE_CALL_REJECTED;
00726          }
00727       }
00728    }
00729 
00730    /* Start the process if it's not already started */
00731    if (!pvt->alreadygone && !pvt->hangupcause) {
00732       call_token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00733       if (call_token) {
00734          /* Release lock to eliminate deadlock */
00735          ast_mutex_unlock(&pvt->lock);
00736          if (h323_clear_call(call_token, q931cause)) {
00737             ast_log(LOG_WARNING, "ClearCall failed.\n");
00738          }
00739          free(call_token);
00740          ast_mutex_lock(&pvt->lock);
00741       }
00742    }
00743    pvt->needdestroy = 1;
00744    ast_mutex_unlock(&pvt->lock);
00745 
00746    /* Update usage counter */
00747    ast_module_unref(ast_module_info->self);
00748 
00749    return 0;
00750 }

static int oh323_indicate ( struct ast_channel c,
int  condition,
const void *  data,
size_t  datalen 
) [static]

Definition at line 861 of file chan_h323.c.

References ast_channel::_state, oh323_pvt::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_change_source(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, oh323_pvt::cd, free, oh323_pvt::got_progress, oh323_pvt::lock, LOG_DEBUG, LOG_WARNING, oh323_update_info(), oh323_pvt::rtp, strdup, and ast_channel::tech_pvt.

00862 {
00863 
00864    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00865    char *token = (char *)NULL;
00866    int res = -1;
00867    int got_progress;
00868 
00869    ast_mutex_lock(&pvt->lock);
00870    token = (pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL);
00871    got_progress = pvt->got_progress;
00872    if (condition == AST_CONTROL_PROGRESS)
00873       pvt->got_progress = 1;
00874    else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))
00875       pvt->alreadygone = 1;
00876    ast_mutex_unlock(&pvt->lock);
00877 
00878    if (h323debug)
00879       ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, token);
00880 
00881    switch(condition) {
00882    case AST_CONTROL_RINGING:
00883       if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
00884          h323_send_alerting(token);
00885          res = (got_progress ? 0 : -1);   /* Do not simulate any audio tones if we got PROGRESS message */
00886       }
00887       break;
00888    case AST_CONTROL_PROGRESS:
00889       if (c->_state != AST_STATE_UP) {
00890          /* Do not send PROGRESS message more than once */
00891          if (!got_progress)
00892             h323_send_progress(token);
00893          res = 0;
00894       }
00895       break;
00896    case AST_CONTROL_BUSY:
00897       if (c->_state != AST_STATE_UP) {
00898          h323_answering_call(token, 1);
00899          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00900          res = 0;
00901       }
00902       break;
00903    case AST_CONTROL_CONGESTION:
00904       if (c->_state != AST_STATE_UP) {
00905          h323_answering_call(token, 1);
00906          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00907          res = 0;
00908       }
00909       break;
00910    case AST_CONTROL_HOLD:
00911       ast_moh_start(c, data, NULL);
00912       res = 0;
00913       break;
00914    case AST_CONTROL_UNHOLD:
00915       ast_moh_stop(c);
00916       res = 0;
00917       break;
00918    case AST_CONTROL_SRCUPDATE:
00919       ast_rtp_new_source(pvt->rtp);
00920       res = 0;
00921       break;
00922    case AST_CONTROL_SRCCHANGE:
00923       ast_rtp_change_source(pvt->rtp);
00924       res = 0;
00925       break;
00926    case AST_CONTROL_PROCEEDING:
00927    case -1:
00928       break;
00929    default:
00930       ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
00931       break;
00932    }
00933 
00934    if (h323debug)
00935       ast_log(LOG_DEBUG, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
00936    if (token)
00937       free(token);
00938    oh323_update_info(c);
00939 
00940    return res;
00941 }

static struct ast_frame * oh323_read ( struct ast_channel c  )  [static]

Definition at line 808 of file chan_h323.c.

References __oh323_update_info(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_rtcp_read(), ast_channel::fdno, oh323_pvt::lock, LOG_ERROR, ast_channel::name, oh323_rtp_read(), oh323_pvt::rtp, and ast_channel::tech_pvt.

00809 {
00810    struct ast_frame *fr;
00811    struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
00812    ast_mutex_lock(&pvt->lock);
00813    __oh323_update_info(c, pvt);
00814    switch(c->fdno) {
00815    case 0:
00816       fr = oh323_rtp_read(pvt);
00817       break;
00818    case 1:
00819       if (pvt->rtp)
00820          fr = ast_rtcp_read(pvt->rtp);
00821       else
00822          fr = &ast_null_frame;
00823       break;
00824    default:
00825       ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name);
00826       fr = &ast_null_frame;
00827       break;
00828    }
00829    ast_mutex_unlock(&pvt->lock);
00830    return fr;
00831 }

static struct ast_channel * oh323_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 1677 of file chan_h323.c.

References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_copy_string(), AST_FORMAT_MAX_AUDIO, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_DTMF, AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), caplock, create_addr(), ext, oh323_pvt::exten, gatekeeper_disable, global_options, h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, restart_monitor(), and unique.

01678 {
01679    int oldformat;
01680    struct oh323_pvt *pvt;
01681    struct ast_channel *tmpc = NULL;
01682    char *dest = (char *)data;
01683    char *ext, *host;
01684    char *h323id = NULL;
01685    char tmp[256], tmp1[256];
01686 
01687    if (h323debug)
01688       ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
01689 
01690    pvt = oh323_alloc(0);
01691    if (!pvt) {
01692       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
01693       return NULL;
01694    }
01695    oldformat = format;
01696    format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1);
01697    if (!format) {
01698       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
01699       oh323_destroy(pvt);
01700       if (cause)
01701          *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01702       return NULL;
01703    }
01704    ast_copy_string(tmp, dest, sizeof(tmp));
01705    host = strchr(tmp, '@');
01706    if (host) {
01707       *host = '\0';
01708       host++;
01709       ext = tmp;
01710    } else {
01711       ext = strrchr(tmp, '/');
01712       if (ext)
01713          *ext++ = '\0';
01714       host = tmp;
01715    }
01716    strtok_r(host, "/", &(h323id));
01717    if (!ast_strlen_zero(h323id)) {
01718       h323_set_id(h323id);
01719    }
01720    if (ext) {
01721       ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01722    }
01723    if (h323debug)
01724       ast_log(LOG_DEBUG, "Extension: %s Host: %s\n", pvt->exten, host);
01725 
01726    if (gatekeeper_disable) {
01727       if (create_addr(pvt, host)) {
01728          oh323_destroy(pvt);
01729          if (cause)
01730             *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01731          return NULL;
01732       }
01733    }
01734    else {
01735       memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01736       pvt->jointcapability = pvt->options.capability;
01737       if (pvt->options.dtmfmode) {
01738          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01739             pvt->nonCodecCapability |= AST_RTP_DTMF;
01740          } else {
01741             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01742          }
01743       }
01744    }
01745 
01746    ast_mutex_lock(&caplock);
01747    /* Generate unique channel identifier */
01748    snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01749    tmp1[sizeof(tmp1)-1] = '\0';
01750    ast_mutex_unlock(&caplock);
01751 
01752    ast_mutex_lock(&pvt->lock);
01753    tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
01754    ast_mutex_unlock(&pvt->lock);
01755    if (!tmpc) {
01756       oh323_destroy(pvt);
01757       if (cause)
01758          *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01759    }
01760    ast_update_use_count();
01761    restart_monitor();
01762    return tmpc;
01763 }

static struct ast_frame* oh323_rtp_read ( struct oh323_pvt pvt  )  [static]

Definition at line 752 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, ast_dsp_process(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_read(), ast_rtp_setnat(), ast_set_read_format(), ast_set_write_format(), f, LOG_DEBUG, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by oh323_read().

00753 {
00754    /* Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
00755    struct ast_frame *f;
00756 
00757    /* Only apply it for the first packet, we just need the correct ip/port */
00758    if (pvt->options.nat) {
00759       ast_rtp_setnat(pvt->rtp, pvt->options.nat);
00760       pvt->options.nat = 0;
00761    }
00762 
00763    f = ast_rtp_read(pvt->rtp);
00764    /* Don't send RFC2833 if we're not supposed to */
00765    if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & H323_DTMF_RFC2833)) {
00766       return &ast_null_frame;
00767    }
00768    if (pvt->owner) {
00769       /* We already hold the channel lock */
00770       if (f->frametype == AST_FRAME_VOICE) {
00771          if (f->subclass != pvt->owner->nativeformats) {
00772             /* Try to avoid deadlock */
00773             if (ast_channel_trylock(pvt->owner)) {
00774                ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n");
00775                return &ast_null_frame;
00776             }
00777             if (h323debug)
00778                ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
00779             pvt->owner->nativeformats = f->subclass;
00780             pvt->nativeformats = f->subclass;
00781             ast_set_read_format(pvt->owner, pvt->owner->readformat);
00782             ast_set_write_format(pvt->owner, pvt->owner->writeformat);
00783             ast_channel_unlock(pvt->owner);
00784          }
00785          /* Do in-band DTMF detection */
00786          if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) {
00787             if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) {
00788                if (!ast_channel_trylock(pvt->owner)) {
00789                   f = ast_dsp_process(pvt->owner, pvt->vad, f);
00790                   ast_channel_unlock(pvt->owner);
00791                }
00792                else
00793                   ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");
00794             } else if (pvt->nativeformats && !pvt->noInbandDtmf) {
00795                ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass));
00796                pvt->noInbandDtmf = 1;
00797             }
00798             if (f &&(f->frametype == AST_FRAME_DTMF)) {
00799                if (h323debug)
00800                   ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass);
00801             }
00802          }
00803       }
00804    }
00805    return f;
00806 }

static int oh323_set_rtp_peer ( struct ast_channel chan,
struct ast_rtp rtp,
struct ast_rtp vrtp,
int  codecs,
int  nat_active 
) [static]

Definition at line 3099 of file chan_h323.c.

References ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_us(), oh323_pvt::cd, convertcap(), LOG_ERROR, oh323_pvt::rtp, ast_channel::tech_pvt, and ast_channel::writeformat.

03100 {
03101    /* XXX Deal with Video */
03102    struct oh323_pvt *pvt;
03103    struct sockaddr_in them;
03104    struct sockaddr_in us;
03105    char *mode;
03106 
03107    if (!rtp) {
03108       return 0;
03109    }
03110 
03111    mode = convertcap(chan->writeformat);
03112    pvt = (struct oh323_pvt *) chan->tech_pvt;
03113    if (!pvt) {
03114       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03115       return -1;
03116    }
03117    ast_rtp_get_peer(rtp, &them);
03118    ast_rtp_get_us(rtp, &us);
03119 #if 0 /* Native bridge still isn't ready */
03120    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03121 #endif
03122    return 0;
03123 }

static int oh323_simulate_dtmf_end ( const void *  data  )  [static]

Definition at line 309 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, AST_FRAME_DTMF_END, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.

Referenced by __oh323_update_info(), and receive_digit().

00310 {
00311    struct oh323_pvt *pvt = (struct oh323_pvt *)data;
00312 
00313    if (pvt) {
00314       ast_mutex_lock(&pvt->lock);
00315       /* Don't hold pvt lock while trying to lock the channel */
00316       while (pvt->owner && ast_channel_trylock(pvt->owner)) {
00317          DEADLOCK_AVOIDANCE(&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 }

static void oh323_update_info ( struct ast_channel c  )  [static]

Definition at line 403 of file chan_h323.c.

References __oh323_update_info(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::lock, and ast_channel::tech_pvt.

Referenced by oh323_answer(), oh323_call(), oh323_digit_begin(), oh323_digit_end(), and oh323_indicate().

00404 {
00405    struct oh323_pvt *pvt = c->tech_pvt;
00406 
00407    if (pvt) {
00408       ast_mutex_lock(&pvt->lock);
00409       __oh323_update_info(c, pvt);
00410       ast_mutex_unlock(&pvt->lock);
00411    }
00412 }

static int oh323_write ( struct ast_channel c,
struct ast_frame frame 
) [static]

Definition at line 833 of file chan_h323.c.

References __oh323_update_info(), AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, oh323_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.

00834 {
00835    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00836    int res = 0;
00837    if (frame->frametype != AST_FRAME_VOICE) {
00838       if (frame->frametype == AST_FRAME_IMAGE) {
00839          return 0;
00840       } else {
00841          ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
00842          return 0;
00843       }
00844    } else {
00845       if (!(frame->subclass & c->nativeformats)) {
00846          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
00847             frame->subclass, c->nativeformats, c->readformat, c->writeformat);
00848          return 0;
00849       }
00850    }
00851    if (pvt) {
00852       ast_mutex_lock(&pvt->lock);
00853       if (pvt->rtp && !pvt->recvonly)
00854          res = ast_rtp_write(pvt->rtp, frame);
00855       __oh323_update_info(c, pvt);
00856       ast_mutex_unlock(&pvt->lock);
00857    }
00858    return res;
00859 }

static int progress ( unsigned  call_reference,
const char *  token,
int  inband 
) [static]

Definition at line 2031 of file chan_h323.c.

References AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_log(), ast_mutex_unlock(), find_call_locked(), h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, oh323_pvt::owner, and update_state().

02032 {
02033    struct oh323_pvt *pvt;
02034 
02035    if (h323debug)
02036       ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02037 
02038    pvt = find_call_locked(call_reference, token);
02039    if (!pvt) {
02040       ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02041       return -1;
02042    }
02043    if (!pvt->owner) {
02044       ast_mutex_unlock(&pvt->lock);
02045       ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02046       return -1;
02047    }
02048    update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02049    ast_mutex_unlock(&pvt->lock);
02050 
02051    return 0;
02052 }

static void prune_peers ( void   )  [static]

Definition at line 2789 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.

Referenced by iax2_prune_realtime(), reload_config(), set_config(), and unload_module().

02790 {
02791    /* Prune peers who still are supposed to be deleted */
02792    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02793 }

static struct oh323_alias* realtime_alias ( const char *  alias  )  [static]

Definition at line 1229 of file chan_h323.c.

References ast_load_realtime(), ast_variables_destroy(), ast_variable::name, ast_variable::next, ast_variable::value, and var.

Referenced by find_alias().

01230 {
01231    struct ast_variable *var, *tmp;
01232    struct oh323_alias *a;
01233 
01234    var = ast_load_realtime("h323", "name", alias, NULL);
01235 
01236    if (!var)
01237       return NULL;
01238 
01239    for (tmp = var; tmp; tmp = tmp->next) {
01240       if (!strcasecmp(tmp->name, "type") &&
01241       !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01242          ast_variables_destroy(var);
01243          return NULL;
01244       }
01245    }
01246 
01247    a = build_alias(alias, var, NULL, 1);
01248 
01249    ast_variables_destroy(var);
01250 
01251    return a;
01252 }

static struct oh323_peer* realtime_peer ( const char *  peername,
struct sockaddr_in *  sin 
) [static]

Definition at line 1509 of file chan_h323.c.

References ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), ast_variable::name, ast_variable::next, ast_variable::value, and var.

Referenced by authenticate_reply(), calltoken_required(), find_peer(), and iax2_getpeername().

01510 {
01511    struct oh323_peer *peer;
01512    struct ast_variable *var;
01513    struct ast_variable *tmp;
01514    const char *addr;
01515 
01516    /* First check on peer name */
01517    if (peername)
01518       var = ast_load_realtime("h323", "name", peername, addr = NULL);
01519    else if (sin) /* Then check on IP address for dynamic peers */
01520       var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), NULL);
01521    else
01522       return NULL;
01523 
01524    if (!var)
01525       return NULL;
01526 
01527    for (tmp = var; tmp; tmp = tmp->next) {
01528       /* If this is type=user, then skip this object. */
01529       if (!strcasecmp(tmp->name, "type") &&
01530             !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01531          ast_variables_destroy(var);
01532          return NULL;
01533       } else if (!peername && !strcasecmp(tmp->name, "name")) {
01534          peername = tmp->value;
01535       }
01536    }
01537 
01538    if (!peername) {  /* Did not find peer in realtime */
01539       ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01540       ast_variables_destroy(var);
01541       return NULL;
01542    }
01543 
01544    /* Peer found in realtime, now build it in memory */
01545    peer = build_peer(peername, var, NULL, 1);
01546 
01547    ast_variables_destroy(var);
01548 
01549    return peer;
01550 }

static struct oh323_user* realtime_user ( const call_details_t *  cd  )  [static]

Definition at line 1407 of file chan_h323.c.

References ast_load_realtime(), ast_variables_destroy(), ast_variable::name, ast_variable::next, userbyalias, username, ast_variable::value, and var.

Referenced by calltoken_required(), check_access(), and find_user().

01408 {
01409    struct ast_variable *var, *tmp;
01410    struct oh323_user *user;
01411    char *username;
01412 
01413    if (userbyalias)
01414       var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, NULL);
01415    else {
01416       username = (char *)NULL;
01417       var = ast_load_realtime("h323", "host", cd->sourceIp, NULL);
01418    }
01419 
01420    if (!var)
01421       return NULL;
01422 
01423    for (tmp = var; tmp; tmp = tmp->next) {
01424       if (!strcasecmp(tmp->name, "type") &&
01425       !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01426          ast_variables_destroy(var);
01427          return NULL;
01428       } else if (!username && !strcasecmp(tmp->name, "name"))
01429          username = tmp->value;
01430    }
01431 
01432    if (!username) {
01433       ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01434       ast_variables_destroy(var);
01435       return NULL;
01436    }
01437 
01438    user = build_user(username, var, NULL, 1);
01439 
01440    ast_variables_destroy(var);
01441 
01442    return user;
01443 }

static int receive_digit ( unsigned  call_reference,
char  digit,
const char *  token,
int  duration 
) [static]

Callback for sending digits from H.323 up to asterisk

Definition at line 1782 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, AST_CONTROL_FLASH, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_unlock(), ast_queue_control(), ast_queue_frame(), ast_sched_add(), AST_SCHED_DEL, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, f, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_simulate_dtmf_end(), and oh323_pvt::owner.

Referenced by load_module().

01783 {
01784    struct oh323_pvt *pvt;
01785    int res;
01786 
01787    pvt = find_call_locked(call_reference, token);
01788    if (!pvt) {
01789       ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01790       return -1;
01791    }
01792    if (h323debug)
01793       ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01794 
01795    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01796       if (digit == '!')
01797          res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01798       else {
01799          struct ast_frame f = {
01800             .frametype = AST_FRAME_DTMF_END,
01801             .subclass = digit,
01802             .samples = duration * 8,
01803             .len = duration,
01804             .src = "SEND_DIGIT",
01805          };
01806          if (digit == ' ') {     /* signalUpdate message */
01807             f.subclass = pvt->curDTMF;
01808             AST_SCHED_DEL(sched, pvt->DTMFsched);
01809          } else {          /* Regular input or signal message */
01810             if (pvt->DTMFsched >= 0) {
01811                /* We still don't send DTMF END from previous event, send it now */
01812                AST_SCHED_DEL(sched, pvt->DTMFsched);
01813                f.subclass = pvt->curDTMF;
01814                f.samples = f.len = 0;
01815                ast_queue_frame(pvt->owner, &f);
01816                /* Restore values */
01817                f.subclass = digit;
01818                f.samples = duration * 8;
01819                f.len = duration;
01820             }
01821             if (duration) {      /* This is a signal, signalUpdate follows */
01822                f.frametype = AST_FRAME_DTMF_BEGIN;
01823                pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01824                if (h323debug)
01825                   ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01826             }
01827             pvt->curDTMF = digit;
01828          }
01829          res = ast_queue_frame(pvt->owner, &f);
01830       }
01831       ast_channel_unlock(pvt->owner);
01832    } else {
01833       if (digit == '!')
01834          pvt->newcontrol = AST_CONTROL_FLASH;
01835       else {
01836          pvt->newduration = duration;
01837          pvt->newdigit = digit;
01838       }
01839       res = 0;
01840    }
01841    ast_mutex_unlock(&pvt->lock);
01842    return res;
01843 }

static const char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 270 of file chan_h323.c.

00271 {
00272    switch (redirectingreason) {
00273    case 0:
00274       return "UNKNOWN";
00275    case 1:
00276       return "BUSY";
00277    case 2:
00278       return "NO_REPLY";
00279    case 0xF:
00280       return "UNCONDITIONAL";
00281    default:
00282       return "NOREDIRECT";
00283    }
00284 }

static int reload ( void   )  [static]

Definition at line 3034 of file chan_h323.c.

References ast_log(), h323_reload(), io, and LOG_NOTICE.

03035 {
03036    if (!sched || !io) {
03037       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03038       return 0;
03039    }
03040    return h323_reload(0, 0, NULL);
03041 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2795 of file chan_h323.c.

References acceptAnonymous, ahp, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTOBJ_CONTAINER_LINK, ASTOBJ_UNREF, bindaddr, build_peer(), build_user(), config, default_context, default_jbconf, delete_aliases(), delete_users(), format, gatekeeper, gatekeeper_disable, gatekeeper_discover, gen, gkroute, GLOBAL_CAPABILITY, global_jbconf, global_options, h323_signalling_port, hp, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_peer(), oh323_destroy_user(), peerl, prune_peers(), tos, userbyalias, userl, and ast_variable::value.

Referenced by h323_do_reload(), iax2_reload(), load_module(), mgcp_do_reload(), misdn_reload(), reload(), and sip_do_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    if (is_reload) {
02819       delete_users();
02820       delete_aliases();
02821       prune_peers();
02822    }
02823 
02824    /* fire up the H.323 Endpoint */
02825    if (!h323_end_point_exist()) {
02826       h323_end_point_create();
02827    }
02828    ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02829    gk_discover = gatekeeper_discover;
02830    gk_disable = gatekeeper_disable;
02831    memset(&bindaddr, 0, sizeof(bindaddr));
02832    memset(&global_options, 0, sizeof(global_options));
02833    global_options.fastStart = 1;
02834    global_options.h245Tunneling = 1;
02835    global_options.dtmfcodec = 101;
02836    global_options.dtmfmode = H323_DTMF_RFC2833;
02837    global_options.capability = GLOBAL_CAPABILITY;
02838    global_options.bridge = 1;    /* Do native bridging by default */
02839    global_options.autoframing = 0;
02840    strcpy(default_context, "default");
02841    h323_signalling_port = 1720;
02842    gatekeeper_disable = 1;
02843    gatekeeper_discover = 0;
02844    gkroute = 0;
02845    userbyalias = 1;
02846    acceptAnonymous = 1;
02847    tos = 0;
02848 
02849    /* Copy the default jb config over global_jbconf */
02850    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02851 
02852    /* Load configuration from users.conf */
02853    ucfg = ast_config_load("users.conf");
02854    if (ucfg) {
02855       struct ast_variable *gen;
02856       int genhas_h323;
02857       const char *has_h323;
02858 
02859       genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
02860       gen = ast_variable_browse(ucfg, "general");
02861       for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
02862          if (strcasecmp(cat, "general")) {
02863             has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
02864             if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
02865                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
02866                if (user) {
02867                   ASTOBJ_CONTAINER_LINK(&userl, user);
02868                   ASTOBJ_UNREF(user, oh323_destroy_user);
02869                }
02870                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
02871                if (peer) {
02872                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
02873                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
02874                }
02875             }
02876          }
02877       }
02878       ast_config_destroy(ucfg);
02879    }
02880 
02881    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
02882       /* handle jb conf */
02883       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
02884          continue;
02885       /* Create the interface list */
02886       if (!strcasecmp(v->name, "port")) {
02887          h323_signalling_port = (int)strtol(v->value, NULL, 10);
02888       } else if (!strcasecmp(v->name, "bindaddr")) {
02889          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
02890             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
02891          } else {
02892             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
02893          }
02894       } else if (!strcasecmp(v->name, "tos")) {
02895          if (sscanf(v->value, "%30d", &format)) {
02896             tos = format & 0xff;
02897          } else if (!strcasecmp(v->value, "lowdelay")) {
02898             tos = IPTOS_LOWDELAY;
02899          } else if (!strcasecmp(v->value, "throughput")) {
02900             tos = IPTOS_THROUGHPUT;
02901          } else if (!strcasecmp(v->value, "reliability")) {
02902             tos = IPTOS_RELIABILITY;
02903          } else if (!strcasecmp(v->value, "mincost")) {
02904             tos = IPTOS_MINCOST;
02905          } else if (!strcasecmp(v->value, "none")) {
02906             tos = 0;
02907          } else {
02908             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
02909          }
02910       } else if (!strcasecmp(v->name, "gatekeeper")) {
02911          if (!strcasecmp(v->value, "DISABLE")) {
02912             gatekeeper_disable = 1;
02913          } else if (!strcasecmp(v->value, "DISCOVER")) {
02914             gatekeeper_disable = 0;
02915             gatekeeper_discover = 1;
02916          } else {
02917             gatekeeper_disable = 0;
02918             ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
02919          }
02920       } else if (!strcasecmp(v->name, "secret")) {
02921          ast_copy_string(secret, v->value, sizeof(secret));
02922       } else if (!strcasecmp(v->name, "AllowGKRouted")) {
02923          gkroute = ast_true(v->value);
02924       } else if (!strcasecmp(v->name, "context")) {
02925          ast_copy_string(default_context, v->value, sizeof(default_context));
02926          ast_verbose(VERBOSE_PREFIX_2 "Setting default context to %s\n", default_context);
02927       } else if (!strcasecmp(v->name, "UserByAlias")) {
02928          userbyalias = ast_true(v->value);
02929       } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
02930          acceptAnonymous = ast_true(v->value);
02931       } else if (!update_common_options(v, &global_options)) {
02932          /* dummy */
02933       }
02934    }
02935 
02936    for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
02937       if (strcasecmp(cat, "general")) {
02938          utype = ast_variable_retrieve(cfg, cat, "type");
02939          if (utype) {
02940             is_user = is_peer = is_alias = 0;
02941             if (!strcasecmp(utype, "user"))
02942                is_user = 1;
02943             else if (!strcasecmp(utype, "peer"))
02944                is_peer = 1;
02945             else if (!strcasecmp(utype, "friend"))
02946                is_user = is_peer = 1;
02947             else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
02948                is_alias = 1;
02949             else {
02950                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
02951                continue;
02952             }
02953             if (is_user) {
02954                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
02955                if (user) {
02956                   ASTOBJ_CONTAINER_LINK(&userl, user);
02957                   ASTOBJ_UNREF(user, oh323_destroy_user);
02958                }
02959             }
02960             if (is_peer) {
02961                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
02962                if (peer) {
02963                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
02964                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
02965                }
02966             }
02967             if (is_alias) {
02968                alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
02969                if (alias) {
02970                   ASTOBJ_CONTAINER_LINK(&aliasl, alias);
02971                   ASTOBJ_UNREF(alias, oh323_destroy_alias);
02972                }
02973             }
02974          } else {
02975             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
02976          }
02977       }
02978    }
02979    ast_config_destroy(cfg);
02980 
02981    /* Register our H.323 aliases if any*/
02982    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02983    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02984       ASTOBJ_RDLOCK(iterator);
02985       if (h323_set_alias(iterator)) {
02986          ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
02987          ASTOBJ_UNLOCK(iterator);
02988          continue;
02989       }
02990       ASTOBJ_UNLOCK(iterator);
02991    } while (0) );
02992    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02993 
02994    /* Don't touch GK if nothing changed because URQ will drop all existing calls */
02995    gk_changed = 0;
02996    if (gatekeeper_disable != gk_disable)
02997       gk_changed = is_reload;
02998    else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
02999       gk_changed = is_reload;
03000    else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
03001       gk_changed = is_reload;
03002    if (gk_changed) {
03003       if(!gk_disable)
03004          h323_gk_urq();
03005       if (!gatekeeper_disable) {
03006          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03007             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03008             gatekeeper_disable = 1;
03009          }
03010       }
03011    }
03012    return 0;
03013 }

static int restart_monitor ( void   )  [static]

Definition at line 2531 of file chan_h323.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, monitor_thread, and monlock.

02532 {
02533    /* If we're supposed to be stopped -- stay stopped */
02534    if (ast_mutex_lock(&monlock)) {
02535       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02536       return -1;
02537    }
02538    if (monitor_thread == AST_PTHREADT_STOP) {
02539       ast_mutex_unlock(&monlock);
02540       return 0;
02541    }
02542    if (monitor_thread == pthread_self()) {
02543       ast_mutex_unlock(&monlock);
02544       ast_log(LOG_WARNING, "Cannot kill myself\n");
02545       return -1;
02546    }
02547    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02548       /* Wake up the thread */
02549       pthread_kill(monitor_thread, SIGURG);
02550    } else {
02551       /* Start a new monitor */
02552       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02553          monitor_thread = AST_PTHREADT_NULL;
02554          ast_mutex_unlock(&monlock);
02555          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02556          return -1;
02557       }
02558    }
02559    ast_mutex_unlock(&monlock);
02560    return 0;
02561 }

static void set_dtmf_payload ( unsigned  call_reference,
const char *  token,
int  payload 
) [static]

Definition at line 2376 of file chan_h323.c.

References ast_log(), ast_mutex_unlock(), ast_rtp_set_rtpmap_type(), oh323_pvt::dtmf_pt, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DEBUG, and oh323_pvt::rtp.

Referenced by load_module().

02377 {
02378    struct oh323_pvt *pvt;
02379 
02380    if (h323debug)
02381       ast_log(LOG_DEBUG, "Setting DTMF payload to %d on %s\n", payload, token);
02382 
02383    pvt = find_call_locked(call_reference, token);
02384    if (!pvt) {
02385       return;
02386    }
02387    if (pvt->rtp) {
02388       ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", "telephone-event", 0);
02389    }
02390    pvt->dtmf_pt = payload;
02391    ast_mutex_unlock(&pvt->lock);
02392    if (h323debug)
02393       ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
02394 }

static void set_local_capabilities ( unsigned  call_reference,
const char *  token 
) [static]

Definition at line 2431 of file chan_h323.c.

References ast_getformatname(), ast_log(), ast_mutex_unlock(), capability, dtmfmode, find_call_locked(), ast_codec_pref::framing, h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_DEBUG, oh323_pvt::options, ast_codec_pref::order, oh323_pvt::pref_codec, and prefs.

Referenced by load_module().

02432 {
02433    struct oh323_pvt *pvt;
02434    int capability, dtmfmode, pref_codec;
02435    struct ast_codec_pref prefs;
02436 
02437    if (h323debug)
02438       ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
02439 
02440    pvt = find_call_locked(call_reference, token);
02441    if (!pvt)
02442       return;
02443    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02444    dtmfmode = pvt->options.dtmfmode;
02445    prefs = pvt->options.prefs;
02446    pref_codec = pvt->pref_codec;
02447    ast_mutex_unlock(&pvt->lock);
02448    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02449 
02450    if (h323debug) {
02451       int i;
02452       for (i = 0; i < 32; i++) {
02453          if (!prefs.order[i])
02454             break;
02455          ast_log(LOG_DEBUG, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02456       }
02457       ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
02458    }
02459 }

static void set_peer_capabilities ( unsigned  call_reference,
const char *  token,
int  capabilities,
struct ast_codec_pref prefs 
) [static]

Definition at line 2396 of file chan_h323.c.

References ast_getformatname(), ast_log(), ast_rtp_codec_setpref(), find_call_locked(), ast_codec_pref::framing, h323debug, oh323_pvt::jointcapability, LOG_DEBUG, oh323_pvt::options, ast_codec_pref::order, oh323_pvt::peer_prefs, oh323_pvt::peercapability, prefs, and oh323_pvt::rtp.

Referenced by load_module().

02397 {
02398    struct oh323_pvt *pvt;
02399 
02400    if (h323debug)
02401       ast_log(LOG_DEBUG, "Got remote capabilities from connection %s\n", token);
02402 
02403    pvt = find_call_locked(call_reference, token);
02404    if (!pvt)
02405       return;
02406    pvt->peercapability = capabilities;
02407    pvt->jointcapability = pvt->options.capability & capabilities;
02408    if (prefs) {
02409       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02410       if (h323debug) {
02411          int i;
02412          for (i = 0; i < 32; ++i) {
02413             if (!prefs->order[i])
02414                break;
02415             ast_log(LOG_DEBUG, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02416          }
02417       }
02418       if (pvt->rtp) {
02419          if (pvt->options.autoframing) {
02420             ast_log(LOG_DEBUG, "Autoframing option set, using peer's packetization settings\n");
02421             ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
02422          } else {
02423             ast_log(LOG_DEBUG, "Autoframing option not set, using ignoring peer's packetization settings\n");
02424             ast_rtp_codec_setpref(pvt->rtp, &pvt->options.prefs);
02425          }
02426       }
02427    }
02428    ast_mutex_unlock(&pvt->lock);
02429 }

static call_options_t* setup_incoming_call ( call_details_t *  cd  )  [static]

Call-back function for incoming calls

Returns 1 on success

Definition at line 2059 of file chan_h323.c.

References acceptAnonymous, oh323_pvt::accountcode, oh323_pvt::amaflags, ast_copy_string(), ast_inet_ntoa(), ast_log(), ast_strlen_zero(), ast_verbose(), ASTOBJ_UNREF, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::context, default_context, oh323_pvt::exten, find_alias(), find_user(), gatekeeper, gatekeeper_disable, gkroute, global_options, h323debug, oh323_pvt::jointcapability, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, oh323_alloc(), oh323_destroy(), oh323_destroy_user(), oh323_pvt::options, and VERBOSE_PREFIX_3.

Referenced by load_module().

02060 {
02061    struct oh323_pvt *pvt;
02062    struct oh323_user *user = NULL;
02063    struct oh323_alias *alias = NULL;
02064 
02065    if (h323debug)
02066       ast_log(LOG_DEBUG, "Setting up incoming call for %s\n", cd->call_token);
02067 
02068    /* allocate the call*/
02069    pvt = oh323_alloc(cd->call_reference);
02070 
02071    if (!pvt) {
02072       ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02073       cleanup_call_details(cd);
02074       return NULL;
02075    }
02076 
02077    /* Populate the call details in the private structure */
02078    memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02079    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02080    pvt->jointcapability = pvt->options.capability;
02081 
02082    if (h323debug) {
02083       ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
02084       ast_verbose(VERBOSE_PREFIX_3 " \tCall token:  [%s]\n", pvt->cd.call_token);
02085       ast_verbose(VERBOSE_PREFIX_3 " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);
02086       ast_verbose(VERBOSE_PREFIX_3 " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
02087       ast_verbose(VERBOSE_PREFIX_3 " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
02088       ast_verbose(VERBOSE_PREFIX_3 " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
02089       if (pvt->cd.redirect_reason >= 0)
02090          ast_verbose(VERBOSE_PREFIX_3 " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02091       ast_verbose(VERBOSE_PREFIX_3 " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
02092    }
02093 
02094    /* Decide if we are allowing Gatekeeper routed calls*/
02095    if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02096       if (!ast_strlen_zero(cd->call_dest_e164)) {
02097          ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02098          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02099       } else {
02100          alias = find_alias(cd->call_dest_alias, 1);
02101          if (!alias) {
02102             ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02103             oh323_destroy(pvt);
02104             return NULL;
02105          }
02106          ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02107          ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02108       }
02109    } else {
02110       /* Either this call is not from the Gatekeeper
02111          or we are not allowing gk routed calls */
02112       user = find_user(cd, 1);
02113       if (!user) {
02114          if (!acceptAnonymous) {
02115             ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02116             oh323_destroy(pvt);
02117             return NULL;
02118          }
02119          if (ast_strlen_zero(default_context)) {
02120             ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02121             oh323_destroy(pvt);
02122             return NULL;
02123          }
02124          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02125          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02126             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02127          } else {
02128             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02129          }
02130          if (h323debug)
02131             ast_log(LOG_DEBUG, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02132       } else {
02133          if (user->host) {
02134             if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02135                if (ast_strlen_zero(user->context)) {
02136                   if (ast_strlen_zero(default_context)) {
02137                      ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02138                      oh323_destroy(pvt);
02139                      ASTOBJ_UNREF(user, oh323_destroy_user);
02140                      return NULL;
02141                   }
02142                   ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02143                } else {
02144                   ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02145                }
02146                pvt->exten[0] = 'i';
02147                pvt->exten[1] = '\0';
02148                ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02149                oh323_destroy(pvt);
02150                ASTOBJ_UNREF(user, oh323_destroy_user);
02151                return NULL;   /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
02152             }
02153          }
02154          ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02155          memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02156          pvt->jointcapability = pvt->options.capability;
02157          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02158             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02159          } else {
02160             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02161          }
02162          if (!ast_strlen_zero(user->accountcode)) {
02163             ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02164          }
02165          if (user->amaflags) {
02166             pvt->amaflags = user->amaflags;
02167          }
02168          ASTOBJ_UNREF(user, oh323_destroy_user);
02169       }
02170    }
02171    return &pvt->options;
02172 }

static int setup_outgoing_call ( call_details_t *  cd  )  [static]

Call-back function to establish an outgoing H.323 call

Returns 1 on success

Definition at line 2258 of file chan_h323.c.

References cleanup_call_details().

Referenced by load_module().

02259 {
02260    /* Use argument here or free it immediately */
02261    cleanup_call_details(cd);
02262 
02263    return 1;
02264 }

static void setup_rtp_connection ( unsigned  call_reference,
const char *  remoteIp,
int  remotePort,
const char *  token,
int  pt 
) [static]

Call-back function passing remote ip/port information from H.323 to asterisk

Returns nothing

Definition at line 1899 of file chan_h323.c.

References __oh323_rtp_create(), oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_log(), ast_mutex_unlock(), ast_queue_control(), ast_rtp_lookup_pt(), ast_rtp_set_peer(), ast_rtp_stop(), ast_set_read_format(), ast_set_write_format(), rtpPayloadType::code, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, ast_channel::nativeformats, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_channel::writeformat.

Referenced by load_module().

01900 {
01901    struct oh323_pvt *pvt;
01902    struct sockaddr_in them;
01903    struct rtpPayloadType rtptype;
01904    int nativeformats_changed;
01905    enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
01906 
01907    if (h323debug)
01908       ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
01909 
01910    /* Find the call or allocate a private structure if call not found */
01911    pvt = find_call_locked(call_reference, token);
01912    if (!pvt) {
01913       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
01914       return;
01915    }
01916    if (pvt->alreadygone) {
01917       ast_mutex_unlock(&pvt->lock);
01918       return;
01919    }
01920 
01921    if (!pvt->rtp)
01922       __oh323_rtp_create(pvt);
01923 
01924    them.sin_family = AF_INET;
01925    /* only works for IPv4 */
01926    them.sin_addr.s_addr = inet_addr(remoteIp);
01927    them.sin_port = htons(remotePort);
01928 
01929    if (them.sin_addr.s_addr) {
01930       ast_rtp_set_peer(pvt->rtp, &them);
01931       if (pvt->recvonly) {
01932          pvt->recvonly = 0;
01933          rtp_change = NEED_UNHOLD;
01934       }
01935    } else {
01936       ast_rtp_stop(pvt->rtp);
01937       if (!pvt->recvonly) {
01938          pvt->recvonly = 1;
01939          rtp_change = NEED_HOLD;
01940       }
01941    }
01942 
01943    /* Change native format to reflect information taken from OLC/OLCAck */
01944    nativeformats_changed = 0;
01945    if (pt != 128 && pvt->rtp) {  /* Payload type is invalid, so try to use previously decided */
01946       rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
01947       if (h323debug)
01948          ast_log(LOG_DEBUG, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
01949       if (pvt->nativeformats != rtptype.code) {
01950          pvt->nativeformats = rtptype.code;
01951          nativeformats_changed = 1;
01952       }
01953    } else if (h323debug)
01954       ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
01955 
01956    /* Don't try to lock the channel if nothing changed */
01957    if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
01958       if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01959          /* Re-build translation path only if native format(s) has been changed */
01960          if (pvt->owner->nativeformats != pvt->nativeformats) {
01961             if (h323debug)
01962                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);
01963             pvt->owner->nativeformats = pvt->nativeformats;
01964             ast_set_read_format(pvt->owner, pvt->owner->readformat);
01965             ast_set_write_format(pvt->owner, pvt->owner->writeformat);
01966          }
01967          if (pvt->options.progress_audio)
01968             ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
01969          switch (rtp_change) {
01970          case NEED_HOLD:
01971             ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
01972             break;
01973          case NEED_UNHOLD:
01974             ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
01975             break;
01976          default:
01977             break;
01978          }
01979          ast_channel_unlock(pvt->owner);
01980       }
01981       else {
01982          if (pvt->options.progress_audio)
01983             pvt->newcontrol = AST_CONTROL_PROGRESS;
01984          else if (rtp_change == NEED_HOLD)
01985             pvt->newcontrol = AST_CONTROL_HOLD;
01986          else if (rtp_change == NEED_UNHOLD)
01987             pvt->newcontrol = AST_CONTROL_UNHOLD;
01988          if (h323debug)
01989             ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
01990       }
01991    }
01992    ast_mutex_unlock(&pvt->lock);
01993 
01994    if (h323debug)
01995       ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);
01996 
01997    return;
01998 }

static int unload_module ( void   )  [static]

Definition at line 3234 of file chan_h323.c.

References aliasl, ast_channel_unregister(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, cli_h323, cli_h323_reload, free, gatekeeper_disable, iflist, iflock, io, io_context_destroy(), oh323_pvt::lock, LOG_WARNING, monitor_thread, monlock, oh323_pvt::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, oh323_pvt::owner, peerl, sched_context_destroy(), and userl.

03235 {
03236    struct oh323_pvt *p, *pl;
03237 
03238    /* unregister commands */
03239    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03240    ast_cli_unregister(&cli_h323_reload);
03241 
03242    ast_channel_unregister(&oh323_tech);
03243    ast_rtp_proto_unregister(&oh323_rtp);
03244 
03245    if (!ast_mutex_lock(&iflock)) {
03246       /* hangup all interfaces if they have an owner */
03247       p = iflist;
03248       while(p) {
03249          if (p->owner) {
03250             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03251          }
03252          p = p->next;
03253       }
03254       iflist = NULL;
03255       ast_mutex_unlock(&iflock);
03256    } else {
03257       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03258       return -1;
03259    }
03260    if (!ast_mutex_lock(&monlock)) {
03261       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03262          if (monitor_thread != pthread_self()) {
03263             pthread_cancel(monitor_thread);
03264          }
03265          pthread_kill(monitor_thread, SIGURG);
03266          pthread_join(monitor_thread, NULL);
03267       }
03268       monitor_thread = AST_PTHREADT_STOP;
03269       ast_mutex_unlock(&monlock);
03270    } else {
03271       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03272       return -1;
03273    }
03274    if (!ast_mutex_lock(&iflock)) {
03275       /* destroy all the interfaces and free their memory */
03276       p = iflist;
03277       while(p) {
03278          pl = p;
03279          p = p->next;
03280          /* free associated memory */
03281          ast_mutex_destroy(&pl->lock);
03282          free(pl);
03283       }
03284       iflist = NULL;
03285       ast_mutex_unlock(&iflock);
03286    } else {
03287       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03288       return -1;
03289    }
03290    if (!gatekeeper_disable)
03291       h323_gk_urq();
03292    h323_end_process();
03293    if (io)
03294       io_context_destroy(io);
03295    if (sched)
03296       sched_context_destroy(sched);
03297 
03298    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03299    ASTOBJ_CONTAINER_DESTROY(&userl);
03300    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03301    ASTOBJ_CONTAINER_DESTROY(&peerl);
03302    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03303    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03304 
03305    return 0;
03306 }

static int update_common_options ( struct ast_variable v,
struct call_options *  options 
) [static]

Definition at line 1257 of file chan_h323.c.

References ast_callerid_split(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ast_true(), DEPRECATED, ast_variable::lineno, LOG_WARNING, ast_variable::name, and ast_variable::value.

Referenced by build_peer(), and build_user().

01258 {
01259    int tmp;
01260 
01261    if (!strcasecmp(v->name, "allow")) {
01262       ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
01263    } else if (!strcasecmp(v->name, "autoframing")) {
01264       options->autoframing = ast_true(v->value);
01265    } else if (!strcasecmp(v->name, "disallow")) {
01266       ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
01267    } else if (!strcasecmp(v->name, "dtmfmode")) {
01268       if (!strcasecmp(v->value, "inband")) {
01269          options->dtmfmode = H323_DTMF_INBAND;
01270       } else if (!strcasecmp(v->value, "rfc2833")) {
01271          options->dtmfmode = H323_DTMF_RFC2833;
01272       } else {
01273          ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
01274          options->dtmfmode = H323_DTMF_RFC2833;
01275       }
01276    } else if (!strcasecmp(v->name, "dtmfcodec")) {
01277       tmp = atoi(v->value);
01278       if (tmp < 96)
01279          ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
01280       else
01281          options->dtmfcodec = tmp;
01282    } else if (!strcasecmp(v->name, "bridge")) {
01283       options->bridge = ast_true(v->value);
01284    } else if (!strcasecmp(v->name, "nat")) {
01285       options->nat = ast_true(v->value);
01286    } else if (!strcasecmp(v->name, "noFastStart")) {
01287       DEPRECATED(v, "fastStart");
01288       options->fastStart = !ast_true(v->value);
01289    } else if (!strcasecmp(v->name, "fastStart")) {
01290       options->fastStart = ast_true(v->value);
01291    } else if (!strcasecmp(v->name, "noH245Tunneling")) {
01292       DEPRECATED(v, "h245Tunneling");
01293       options->h245Tunneling = !ast_true(v->value);
01294    } else if (!strcasecmp(v->name, "h245Tunneling")) {
01295       options->h245Tunneling = ast_true(v->value);
01296    } else if (!strcasecmp(v->name, "noSilenceSuppression")) {
01297       DEPRECATED(v, "silenceSuppression");
01298       options->silenceSuppression = !ast_true(v->value);
01299    } else if (!strcasecmp(v->name, "silenceSuppression")) {
01300       options->silenceSuppression = ast_true(v->value);
01301    } else if (!strcasecmp(v->name, "progress_setup")) {
01302       tmp = atoi(v->value);
01303       if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
01304          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01305          tmp = 0;
01306       }
01307       options->progress_setup = tmp;
01308    } else if (!strcasecmp(v->name, "progress_alert")) {
01309       tmp = atoi(v->value);
01310       if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
01311          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01312          tmp = 0;
01313       }
01314       options->progress_alert = tmp;
01315    } else if (!strcasecmp(v->name, "progress_audio")) {
01316       options->progress_audio = ast_true(v->value);
01317    } else if (!strcasecmp(v->name, "callerid")) {
01318       ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
01319    } else if (!strcasecmp(v->name, "fullname")) {
01320       ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
01321    } else if (!strcasecmp(v->name, "cid_number")) {
01322       ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
01323    } else if (!strcasecmp(v->name, "tunneling")) {
01324       if (!strcasecmp(v->value, "none"))
01325          options->tunnelOptions = 0;
01326       else if (!strcasecmp(v->value, "cisco"))
01327          options->tunnelOptions |= H323_TUNNEL_CISCO;
01328       else if (!strcasecmp(v->value, "qsig"))
01329          options->tunnelOptions |= H323_TUNNEL_QSIG;
01330       else
01331          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01332    } else
01333       return 1;
01334 
01335    return 0;
01336 }

static int update_state ( struct oh323_pvt pvt,
int  state,
int  signal 
) [static]

Definition at line 1173 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, ast_queue_control(), ast_setstate(), oh323_pvt::newcontrol, oh323_pvt::newstate, and oh323_pvt::owner.

Referenced by chan_ringing(), connection_made(), and progress().

01174 {
01175    if (!pvt)
01176       return 0;
01177    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01178       if (state >= 0)
01179          ast_setstate(pvt->owner, state);
01180       if (signal >= 0)
01181          ast_queue_control(pvt->owner, signal);
01182       ast_channel_unlock(pvt->owner);
01183       return 1;
01184    }
01185    else {
01186       if (state >= 0)
01187          pvt->newstate = state;
01188       if (signal >= 0)
01189          pvt->newcontrol = signal;
01190       return 0;
01191    }
01192 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 3312 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 153 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct ast_alias_list aliasl [static]

Referenced by build_alias(), delete_aliases(), find_alias(), load_module(), and unload_module().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3312 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 141 of file chan_h323.c.

ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 226 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2711 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_h323_debug_deprecated [static]

Initial value:

 {
   { "h.323", "debug", NULL },
   h323_do_debug, "Enable H.323 debug",
   debug_usage }

Definition at line 2696 of file chan_h323.c.

struct ast_cli_entry cli_h323_gk_cycle_deprecated [static]

Initial value:

 {
   { "h.323", "gk", "cycle", NULL },
   h323_gk_cycle, "Manually re-register with the Gatekeper",
   show_cycle_usage }

Definition at line 2706 of file chan_h323.c.

struct ast_cli_entry cli_h323_no_debug_deprecated [static]

Initial value:

 {
   { "h.323", "no", "debug", NULL },
   h323_no_debug, "Disable H.323 debug",
   no_debug_usage }

Definition at line 2691 of file chan_h323.c.

struct ast_cli_entry cli_h323_no_trace_deprecated [static]

Initial value:

 {
   { "h.323", "no", "trace", NULL },
   h323_no_trace, "Disable H.323 Stack Tracing",
   no_trace_usage }

Definition at line 2686 of file chan_h323.c.

struct ast_cli_entry cli_h323_reload [static]

Initial value:

   { { "h.323", "reload", NULL },
   h323_reload, "Reload H.323 configuration",
   h323_reload_usage
}

Definition at line 3043 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_h323_trace_deprecated [static]

Initial value:

 {
   { "h.323", "trace", NULL },
   h323_do_trace, "Enable H.323 Stack Tracing",
   trace_usage }

Definition at line 2701 of file chan_h323.c.

const char config[] = "h323.conf" [static]

Definition at line 139 of file chan_h323.c.

char debug_usage[] [static]

Initial value:

"Usage: h.323 debug\n"
"       Enables H.323 debug output\n"

Definition at line 2658 of file chan_h323.c.

char default_context[AST_MAX_CONTEXT] = "default" [static]

Definition at line 140 of file chan_h323.c.

Referenced by build_user(), reload_config(), and setup_incoming_call().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 128 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 147 of file chan_h323.c.

Referenced by h323_gk_cycle(), load_module(), reload_config(), and setup_incoming_call().

int gatekeeper_disable = 1 [static]

Definition at line 148 of file chan_h323.c.

Referenced by h323_gk_cycle(), load_module(), oh323_request(), reload_config(), setup_incoming_call(), and unload_module().

int gatekeeper_discover = 0 [static]

Definition at line 149 of file chan_h323.c.

Referenced by h323_gk_cycle(), load_module(), and reload_config().

int gkroute = 0 [static]

Definition at line 150 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct ast_jb_conf global_jbconf [static]

Definition at line 135 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 158 of file chan_h323.c.

Referenced by build_peer(), build_user(), create_addr(), oh323_request(), reload_config(), and setup_incoming_call().

ast_mutex_t h323_reload_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 229 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

char h323_reload_usage[] [static]

Initial value:

"Usage: h323 reload\n"
"       Reloads H.323 configuration from h323.conf\n"

Definition at line 2682 of file chan_h323.c.

int h323_reloading = 0 [static]

Definition at line 230 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 146 of file chan_h323.c.

Referenced by build_peer(), create_addr(), load_module(), and reload_config().

int h323debug

Definition at line 125 of file chan_h323.c.

Referenced by answer_call(), chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), find_peer(), find_user(), h323_do_debug(), h323_no_debug(), hangup_connection(), load_module(), oh323_request(), progress(), receive_digit(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), and setup_rtp_connection().

struct oh323_pvt * iflist

Private structure of a OpenH323 channel

ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Protect the interface list (oh323_pvt)

Definition at line 219 of file chan_h323.c.

struct io_context* io [static]

Definition at line 216 of file chan_h323.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 234 of file chan_h323.c.

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 223 of file chan_h323.c.

char no_debug_usage[] [static]

Initial value:

"Usage: h.323 debug off\n"
"       Disables H.323 debug output\n"

Definition at line 2662 of file chan_h323.c.

char no_trace_usage[] [static]

Initial value:

"Usage: h.323 trace off\n"
"       Disables H.323 stack tracing for debugging purposes\n"

Definition at line 2654 of file chan_h323.c.

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3125 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech oh323_tech [static]

Definition at line 249 of file chan_h323.c.

Referenced by __oh323_new(), load_module(), and unload_module().

answer_call_cb on_answer_call

Definition at line 117 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 114 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 116 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 115 of file chan_h323.c.

on_rtp_cb on_external_rtp_create

Definition at line 110 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 120 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 112 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 113 of file chan_h323.c.

progress_cb on_progress

Definition at line 118 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 109 of file chan_h323.c.

rfc2833_cb on_set_rfc2833_payload

Definition at line 119 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 121 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 122 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 111 of file chan_h323.c.

struct ast_peer_list peerl [static]

Referenced by _sip_show_peers(), build_peer(), complete_sip_peer(), delete_users(), do_monitor(), expire_register(), find_peer(), load_module(), prune_peers(), register_verify(), reload_config(), sip_do_reload(), sip_poke_all_peers(), sip_poke_peer_s(), sip_prune_realtime(), sip_show_inuse(), sip_show_objects(), and unload_module().

struct sched_context* sched [static]

Asterisk RTP stuff

Definition at line 215 of file chan_h323.c.

char secret[50] [static]

Definition at line 155 of file chan_h323.c.

Referenced by add_realm_authentication(), aji_act_hook(), authenticate_verify(), build_peer(), build_reply_digest(), build_user(), cache_get_callno_locked(), check_access(), decrypt_frame(), h323_gk_cycle(), iax2_call(), iax2_register(), load_module(), read_agent_config(), register_verify(), set_config(), and sip_register().

char show_cycle_usage[] [static]

Initial value:

"Usage: h.323 gk cycle\n"
"       Manually re-register with the Gatekeper (Currently Disabled)\n"

Definition at line 2666 of file chan_h323.c.

char show_hangup_usage[] [static]

Initial value:

"Usage: h.323 hangup <token>\n"
"       Manually try to hang up call identified by <token>\n"

Definition at line 2670 of file chan_h323.c.

char show_tokens_usage[] [static]

Initial value:

"Usage: h.323 show tokens\n"
"       Print out all active call tokens\n"

Definition at line 2674 of file chan_h323.c.

char show_version_usage[] [static]

Initial value:

"Usage: h.323 show version\n"
"     Print the version of the H.323 library in use\n"

Definition at line 2678 of file chan_h323.c.

const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver" [static]

Variables required by Asterisk

Definition at line 138 of file chan_h323.c.

int tos = 0 [static]

Definition at line 154 of file chan_h323.c.

Referenced by reload_config().

char trace_usage[] [static]

Initial value:

"Usage: h.323 trace <level num>\n"
"       Enables H.323 stack tracing for debugging purposes\n"

Definition at line 2650 of file chan_h323.c.

unsigned int unique = 0 [static]

Definition at line 156 of file chan_h323.c.

Referenced by oh323_request().

int userbyalias = 1 [static]

Definition at line 152 of file chan_h323.c.

Referenced by find_user(), realtime_user(), and reload_config().

struct ast_user_list userl [static]

Referenced by build_user(), complete_sip_user(), delete_users(), find_user(), load_module(), reload_config(), sip_show_inuse(), sip_show_objects(), sip_show_users(), and unload_module().


Generated on Sat Aug 6 00:39:43 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7