Thu Dec 17 23:51:36 2009

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 = "6989f2ec67f8497e38c12890500c525b" , .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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 1252 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 452 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().

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

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

Definition at line 1001 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().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 955 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().

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

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

Definition at line 341 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().

00342 {
00343    if (c->nativeformats != pvt->nativeformats) {
00344       if (h323debug)
00345          ast_log(LOG_DEBUG, "Preparing %s for new native format\n", c->name);
00346       c->nativeformats = pvt->nativeformats;
00347       ast_set_read_format(c, c->readformat);
00348       ast_set_write_format(c, c->writeformat);
00349    }
00350    if (pvt->needhangup) {
00351       if (h323debug)
00352          ast_log(LOG_DEBUG, "Process pending hangup for %s\n", c->name);
00353       c->_softhangup |= AST_SOFTHANGUP_DEV;
00354       c->hangupcause = pvt->hangupcause;
00355       ast_queue_hangup(c);
00356       pvt->needhangup = 0;
00357       pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->DTMFsched = -1;
00358    }
00359    if (pvt->newstate >= 0) {
00360       ast_setstate(c, pvt->newstate);
00361       pvt->newstate = -1;
00362    }
00363    if (pvt->newcontrol >= 0) {
00364       ast_queue_control(c, pvt->newcontrol);
00365       pvt->newcontrol = -1;
00366    }
00367    if (pvt->newdigit >= 0) {
00368       struct ast_frame f = {
00369          .frametype = AST_FRAME_DTMF_END,
00370          .subclass = pvt->newdigit,
00371          .samples = pvt->newduration * 8,
00372          .len = pvt->newduration,
00373          .src = "UPDATE_INFO",
00374       };
00375       if (pvt->newdigit == ' ') {      /* signalUpdate message */
00376          f.subclass = pvt->curDTMF;
00377          if (pvt->DTMFsched >= 0) {
00378             AST_SCHED_DEL(sched, pvt->DTMFsched);
00379          }
00380       } else {                /* Regular input or signal message */
00381          if (pvt->newduration) {    /* This is a signal, signalUpdate follows */
00382             f.frametype = AST_FRAME_DTMF_BEGIN;
00383             AST_SCHED_DEL(sched, pvt->DTMFsched);
00384             pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt);
00385             if (h323debug)
00386                ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched);
00387          }
00388          pvt->curDTMF = pvt->newdigit;
00389       }
00390       ast_queue_frame(c, &f);
00391       pvt->newdigit = -1;
00392    }
00393    if (pvt->update_rtp_info > 0) {
00394       if (pvt->rtp) {
00395          ast_jb_configure(c, &global_jbconf);
00396          c->fds[0] = ast_rtp_fd(pvt->rtp);
00397          c->fds[1] = ast_rtcp_fd(pvt->rtp);
00398          ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
00399       }
00400       pvt->update_rtp_info = -1;
00401    }
00402 }

static void __reg_module ( void   )  [static]

Definition at line 3310 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

Definition at line 3310 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 2177 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().

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

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

Definition at line 1192 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.

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

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

Definition at line 1443 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().

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

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

Definition at line 1337 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().

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

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 2268 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().

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

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 416 of file chan_h323.c.

References free.

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

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

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

Call-back function to cleanup communication Returns nothing,

Definition at line 2294 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(), ast_mutex_info::file, find_call_locked(), ast_mutex_info::func, h323debug, ast_mutex_info::lineno, oh323_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, oh323_pvt::owner, ast_mutex_info::reentrancy, oh323_pvt::rtp, ast_mutex_info::thread, and oh323_pvt::vad.

Referenced by load_module().

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

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 2002 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().

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

static char* convertcap ( int  cap  )  [static]

Definition at line 3070 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().

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

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

Definition at line 1603 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().

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

static void delete_aliases ( void   )  [static]

Definition at line 2769 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().

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

static void delete_users ( void   )  [static]

Definition at line 2743 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().

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

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

Definition at line 2459 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.

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

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 1848 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().

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

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

Find a call by alias

Definition at line 1764 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

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

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

Definition at line 1145 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().

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

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

Definition at line 1585 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().

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

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

Definition at line 1555 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().

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

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

Definition at line 2581 of file chan_h323.c.

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

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

static int h323_do_reload ( void   )  [static]

Definition at line 3026 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03027 {
03028    reload_config(1);
03029    return 0;
03030 }

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

Definition at line 2561 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 2617 of file chan_h323.c.

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

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

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

Definition at line 2601 of file chan_h323.c.

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

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

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

Definition at line 2591 of file chan_h323.c.

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

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

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

Definition at line 2571 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 3013 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().

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

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

Definition at line 2630 of file chan_h323.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 2639 of file chan_h323.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

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

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

Definition at line 2344 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().

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

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3130 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.

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

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

Definition at line 1573 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

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

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

Definition at line 1550 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01551 {
01552    return strcmp(ast_inet_ntoa(inaddr), addr);
01553 }

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

Definition at line 1101 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().

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

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 665 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.

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

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 586 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.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 497 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().

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

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 508 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.

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

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 547 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.

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

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

Definition at line 941 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.

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

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

Definition at line 3047 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.

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

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

Definition at line 3065 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03066 {
03067    return AST_RTP_GET_FAILED;
03068 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 688 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.

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

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

Definition at line 863 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_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, 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.

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

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

Definition at line 810 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.

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

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

Definition at line 1675 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.

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

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

Definition at line 754 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().

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

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 3097 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.

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

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(), 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          ast_mutex_unlock(&pvt->lock);
00318          usleep(1);
00319          ast_mutex_lock(&pvt->lock);
00320       }
00321 
00322       if (pvt->owner) {
00323          struct ast_frame f = {
00324             .frametype = AST_FRAME_DTMF_END,
00325             .subclass = pvt->curDTMF,
00326             .samples = 0,
00327             .src = "SIMULATE_DTMF_END",
00328          };
00329          ast_queue_frame(pvt->owner, &f);
00330          ast_channel_unlock(pvt->owner);
00331       }
00332 
00333       pvt->DTMFsched = -1;
00334       ast_mutex_unlock(&pvt->lock);
00335    }
00336 
00337    return 0;
00338 }

static void oh323_update_info ( struct ast_channel c  )  [static]

Definition at line 405 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().

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

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

Definition at line 835 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.

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

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

Definition at line 2029 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().

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

static void prune_peers ( void   )  [static]

Definition at line 2787 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().

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

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

Definition at line 1227 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().

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

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

Definition at line 1507 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().

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

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

Definition at line 1405 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().

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

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 1780 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().

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

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 3032 of file chan_h323.c.

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

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

static int reload_config ( int  is_reload  )  [static]

Definition at line 2793 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().

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

static int restart_monitor ( void   )  [static]

Definition at line 2529 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.

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

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

Definition at line 2374 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().

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

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

Definition at line 2429 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().

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

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

Definition at line 2394 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().

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

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 2057 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().

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

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 2256 of file chan_h323.c.

References cleanup_call_details().

Referenced by load_module().

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

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 1897 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().

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

static int unload_module ( void   )  [static]

Definition at line 3232 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.

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

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

Definition at line 1255 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().

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

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

Definition at line 1171 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().

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


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 = "6989f2ec67f8497e38c12890500c525b" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 3310 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 3310 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 141 of file chan_h323.c.

ast_mutex_t caplock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 2709 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 2694 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 2704 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 2689 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 2684 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 3041 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 2699 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 2656 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 2680 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 2660 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 2652 of file chan_h323.c.

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3123 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(), expire_register(), find_peer(), load_module(), prune_peers(), register_verify(), reload_config(), sip_do_reload(), sip_poke_all_peers(), 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 2664 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 2668 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 2672 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 2676 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 2648 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 Thu Dec 17 23:51:36 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7