Wed Feb 11 12:00:11 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 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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, }
static int acceptAnonymous = 1
static struct ast_alias_list aliasl
static const struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_debug_deprecated
static struct ast_cli_entry cli_h323_gk_cycle_deprecated
static struct ast_cli_entry cli_h323_no_debug_deprecated
static struct ast_cli_entry cli_h323_no_trace_deprecated
static struct ast_cli_entry cli_h323_reload
static struct ast_cli_entry cli_h323_trace_deprecated
static const char config [] = "h323.conf"
static char debug_usage []
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
static char gatekeeper [100]
static int gatekeeper_disable = 1
static int gatekeeper_discover = 0
static int gkroute = 0
static struct ast_jb_conf global_jbconf
static call_options_t global_options
static ast_mutex_t h323_reload_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char h323_reload_usage []
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
oh323_pvtiflist
static ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char no_debug_usage []
static char no_trace_usage []
static struct ast_rtp_protocol oh323_rtp
static struct ast_channel_tech oh323_tech
answer_call_cb on_answer_call
chan_ringing_cb on_chan_ringing
clear_con_cb on_connection_cleared
con_established_cb on_connection_established
on_rtp_cb on_external_rtp_create
hangup_cb on_hangup
setup_incoming_cb on_incoming_call
setup_outbound_cb on_outgoing_call
progress_cb on_progress
receive_digit_cb on_receive_digit
rfc2833_cb on_set_rfc2833_payload
setcapabilities_cb on_setcapabilities
setpeercapabilities_cb on_setpeercapabilities
start_rtp_cb on_start_rtp_channel
static struct ast_peer_list peerl
static struct sched_contextsched
static char secret [50]
static char show_cycle_usage []
static char show_hangup_usage []
static char show_tokens_usage []
static 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 1250 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 141 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 450 of file chan_h323.c.

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

Referenced by do_monitor(), and oh323_destroy().

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

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

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

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

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

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

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

Definition at line 339 of file chan_h323.c.

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 3274 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 414 of file chan_h323.c.

References free.

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

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

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

Call-back function to cleanup communication Returns nothing,

Definition at line 2290 of file chan_h323.c.

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

Referenced by load_module().

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

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

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

static char* convertcap ( int  cap  )  [static]

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

03035 {
03036    switch (cap) {
03037    case AST_FORMAT_G723_1:
03038       return "G.723";
03039    case AST_FORMAT_GSM:
03040       return "GSM";
03041    case AST_FORMAT_ULAW:
03042       return "ULAW";
03043    case AST_FORMAT_ALAW:
03044       return "ALAW";
03045    case AST_FORMAT_G722:
03046       return "G.722";
03047    case AST_FORMAT_ADPCM:
03048       return "G.728";
03049    case AST_FORMAT_G729A:
03050       return "G.729";
03051    case AST_FORMAT_SPEEX:
03052       return "SPEEX";
03053    case AST_FORMAT_ILBC:
03054       return "ILBC";
03055    default:
03056       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03057       return NULL;
03058    }
03059 }

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

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

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

static void delete_aliases ( void   )  [static]

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

02735 {
02736    int pruned = 0;
02737 
02738    /* Delete all aliases */
02739    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02740    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02741       ASTOBJ_RDLOCK(iterator);
02742       ASTOBJ_MARK(iterator);
02743       ++pruned;
02744       ASTOBJ_UNLOCK(iterator);
02745    } while (0) );
02746    if (pruned) {
02747       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02748    }
02749    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02750 }

static void delete_users ( void   )  [static]

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

02709 {
02710    int pruned = 0;
02711 
02712    /* Delete all users */
02713    ASTOBJ_CONTAINER_WRLOCK(&userl);
02714    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02715       ASTOBJ_RDLOCK(iterator);
02716       ASTOBJ_MARK(iterator);
02717       ++pruned;
02718       ASTOBJ_UNLOCK(iterator);
02719    } while (0) );
02720    if (pruned) {
02721       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02722    }
02723    ASTOBJ_CONTAINER_UNLOCK(&userl);
02724 
02725    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02726    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02727       ASTOBJ_RDLOCK(iterator);
02728       ASTOBJ_MARK(iterator);
02729       ASTOBJ_UNLOCK(iterator);
02730    } while (0) );
02731    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02732 }

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

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

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

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

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

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

Find a call by alias

Definition at line 1760 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

01761 {
01762    struct oh323_alias *a;
01763 
01764    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01765 
01766    if (!a && realtime)
01767       a = realtime_alias(source_aliases);
01768 
01769    return a;
01770 }

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

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

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

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

Definition at line 1581 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(), 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(), set_config(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), update_call_counter(), and update_registry().

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

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

Definition at line 1551 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(), check_user_full(), forward_message(), leave_voicemail(), setup_incoming_call(), sip_show_user(), update_call_counter(), vm_authenticate(), vm_box_exists(), and vm_execmain().

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

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

Definition at line 2563 of file chan_h323.c.

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

02564 {
02565    if (argc < 2 || argc > 3) {
02566       return RESULT_SHOWUSAGE;
02567    }
02568    h323debug = 1;
02569    ast_cli(fd, "H.323 debug enabled\n");
02570    return RESULT_SUCCESS;
02571 }

static int h323_do_reload ( void   )  [static]

Definition at line 2990 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

02991 {
02992    reload_config(1);
02993    return 0;
02994 }

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

Definition at line 2543 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02544 {
02545    if (argc != 4) {
02546       return RESULT_SHOWUSAGE;
02547    }
02548    h323_debug(1, atoi(argv[3]));
02549    ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
02550    return RESULT_SUCCESS;
02551 }

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

Definition at line 2599 of file chan_h323.c.

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

02600 {
02601    if (argc != 3) {
02602       return RESULT_SHOWUSAGE;
02603    }
02604    if (h323_soft_hangup(argv[2])) {
02605       ast_verbose(VERBOSE_PREFIX_3 "Hangup succeeded on %s\n", argv[2]);
02606    } else {
02607       ast_verbose(VERBOSE_PREFIX_3 "Hangup failed for %s\n", argv[2]);
02608    }
02609    return RESULT_SUCCESS;
02610 }

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

Definition at line 2583 of file chan_h323.c.

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

02584 {
02585    if (argc != 3) {
02586       return RESULT_SHOWUSAGE;
02587    }
02588    h323_gk_urq();
02589 
02590    /* Possibly register with a GK */
02591    if (!gatekeeper_disable) {
02592       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02593          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02594       }
02595    }
02596    return RESULT_SUCCESS;
02597 }

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

Definition at line 2573 of file chan_h323.c.

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

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

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

Definition at line 2553 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02554 {
02555    if (argc < 3 || argc > 4) {
02556       return RESULT_SHOWUSAGE;
02557    }
02558    h323_debug(0,0);
02559    ast_cli(fd, "H.323 trace disabled\n");
02560    return RESULT_SUCCESS;
02561 }

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

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

02978 {
02979    ast_mutex_lock(&h323_reload_lock);
02980    if (h323_reloading) {
02981       ast_verbose("Previous H.323 reload not yet done\n");
02982    } else {
02983       h323_reloading = 1;
02984    }
02985    ast_mutex_unlock(&h323_reload_lock);
02986    restart_monitor();
02987    return 0;
02988 }

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

Definition at line 2612 of file chan_h323.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02613 {
02614    if (argc != 3) {
02615       return RESULT_SHOWUSAGE;
02616    }
02617    h323_show_tokens();
02618    return RESULT_SUCCESS;
02619 }

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

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

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

static enum ast_module_load_result load_module ( void   )  [static]

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

03095 {
03096    int res;
03097 
03098    h323debug = 0;
03099    sched = sched_context_create();
03100    if (!sched) {
03101       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03102       return AST_MODULE_LOAD_FAILURE;
03103    }
03104    io = io_context_create();
03105    if (!io) {
03106       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03107       return AST_MODULE_LOAD_FAILURE;
03108    }
03109    ast_cli_register(&cli_h323_reload);
03110    ASTOBJ_CONTAINER_INIT(&userl);
03111    ASTOBJ_CONTAINER_INIT(&peerl);
03112    ASTOBJ_CONTAINER_INIT(&aliasl);
03113    res = reload_config(0);
03114    if (res) {
03115       /* No config entry */
03116       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03117       ast_cli_unregister(&cli_h323_reload);
03118       io_context_destroy(io);
03119       io = NULL;
03120       sched_context_destroy(sched);
03121       sched = NULL;
03122       ASTOBJ_CONTAINER_DESTROY(&userl);
03123       ASTOBJ_CONTAINER_DESTROY(&peerl);
03124       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03125       return AST_MODULE_LOAD_DECLINE;
03126    } else {
03127       /* Make sure we can register our channel type */
03128       if (ast_channel_register(&oh323_tech)) {
03129          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03130          ast_cli_unregister(&cli_h323_reload);
03131          h323_end_process();
03132          io_context_destroy(io);
03133          sched_context_destroy(sched);
03134 
03135          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03136          ASTOBJ_CONTAINER_DESTROY(&userl);
03137          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03138          ASTOBJ_CONTAINER_DESTROY(&peerl);
03139          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03140          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03141 
03142          return AST_MODULE_LOAD_FAILURE;
03143       }
03144       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03145 
03146       ast_rtp_proto_register(&oh323_rtp);
03147 
03148       /* Register our callback functions */
03149       h323_callback_register(setup_incoming_call,
03150                   setup_outgoing_call,
03151                   external_rtp_create,
03152                   setup_rtp_connection,
03153                   cleanup_connection,
03154                   chan_ringing,
03155                   connection_made,
03156                   receive_digit,
03157                   answer_call,
03158                   progress,
03159                   set_dtmf_payload,
03160                   hangup_connection,
03161                   set_local_capabilities,
03162                   set_peer_capabilities);
03163       /* start the h.323 listener */
03164       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03165          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03166          ast_rtp_proto_unregister(&oh323_rtp);
03167          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03168          ast_cli_unregister(&cli_h323_reload);
03169          h323_end_process();
03170          io_context_destroy(io);
03171          sched_context_destroy(sched);
03172 
03173          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03174          ASTOBJ_CONTAINER_DESTROY(&userl);
03175          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03176          ASTOBJ_CONTAINER_DESTROY(&peerl);
03177          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03178          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03179 
03180          return AST_MODULE_LOAD_FAILURE;
03181       }
03182       /* Possibly register with a GK */
03183       if (!gatekeeper_disable) {
03184          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03185             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03186             gatekeeper_disable = 1;
03187             res = AST_MODULE_LOAD_SUCCESS;
03188          }
03189       }
03190       /* And start the monitor for the first time */
03191       restart_monitor();
03192    }
03193    return res;
03194 }

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

Definition at line 1569 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01570 {
01571    int res;
01572 
01573    if (!sin)
01574       res = -1;
01575    else
01576       res = inaddrcmp(&addr , sin);
01577 
01578    return res;
01579 }

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

Definition at line 1546 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01547 {
01548    return strcmp(ast_inet_ntoa(inaddr), addr);
01549 }

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

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

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

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 663 of file chan_h323.c.

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

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

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

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

Definition at line 584 of file chan_h323.c.

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

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 495 of file chan_h323.c.

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

Referenced by oh323_request(), and setup_incoming_call().

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

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

Definition at line 284 of file chan_h323.c.

References ast_log(), free, and LOG_DEBUG.

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

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

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

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

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

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

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

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

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

Definition at line 506 of file chan_h323.c.

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

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

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

Send (play) the specified digit to the channel.

Definition at line 545 of file chan_h323.c.

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

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

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

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

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

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

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

03012 {
03013    struct oh323_pvt *pvt;
03014    enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
03015 
03016    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03017       return res;
03018 
03019    ast_mutex_lock(&pvt->lock);
03020    if (pvt->rtp && pvt->options.bridge) {
03021       *rtp = pvt->rtp;
03022       res = AST_RTP_TRY_NATIVE;
03023    }
03024    ast_mutex_unlock(&pvt->lock);
03025 
03026    return res;
03027 }

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

Definition at line 3029 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03030 {
03031    return AST_RTP_GET_FAILED;
03032 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 686 of file chan_h323.c.

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

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

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

Definition at line 861 of file chan_h323.c.

References ast_channel::_state, oh323_pvt::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_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.

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

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

Definition at line 808 of file chan_h323.c.

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

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

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

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

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

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

Definition at line 752 of file chan_h323.c.

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

Referenced by oh323_read().

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

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

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

03062 {
03063    /* XXX Deal with Video */
03064    struct oh323_pvt *pvt;
03065    struct sockaddr_in them;
03066    struct sockaddr_in us;
03067    char *mode;
03068 
03069    if (!rtp) {
03070       return 0;
03071    }
03072 
03073    mode = convertcap(chan->writeformat);
03074    pvt = (struct oh323_pvt *) chan->tech_pvt;
03075    if (!pvt) {
03076       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03077       return -1;
03078    }
03079    ast_rtp_get_peer(rtp, &them);
03080    ast_rtp_get_us(rtp, &us);
03081 #if 0 /* Native bridge still isn't ready */
03082    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03083 #endif
03084    return 0;
03085 }

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

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

00308 {
00309    struct oh323_pvt *pvt = (struct oh323_pvt *)data;
00310 
00311    if (pvt) {
00312       ast_mutex_lock(&pvt->lock);
00313       /* Don't hold pvt lock while trying to lock the channel */
00314       while(pvt->owner && ast_channel_trylock(pvt->owner)) {
00315          ast_mutex_unlock(&pvt->lock);
00316          usleep(1);
00317          ast_mutex_lock(&pvt->lock);
00318       }
00319 
00320       if (pvt->owner) {
00321          struct ast_frame f = {
00322             .frametype = AST_FRAME_DTMF_END,
00323             .subclass = pvt->curDTMF,
00324             .samples = 0,
00325             .src = "SIMULATE_DTMF_END",
00326          };
00327          ast_queue_frame(pvt->owner, &f);
00328          ast_channel_unlock(pvt->owner);
00329       }
00330 
00331       pvt->DTMFsched = -1;
00332       ast_mutex_unlock(&pvt->lock);
00333    }
00334 
00335    return 0;
00336 }

static void oh323_update_info ( struct ast_channel c  )  [static]

Definition at line 403 of file chan_h323.c.

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

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

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

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

Definition at line 833 of file chan_h323.c.

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

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

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

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

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

static void prune_peers ( void   )  [static]

Definition at line 2752 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.

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

02753 {
02754    /* Prune peers who still are supposed to be deleted */
02755    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02756 }

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

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

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

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

Definition at line 1503 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(), find_peer(), and iax2_getpeername().

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

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

Definition at line 1401 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 check_access(), and find_user().

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

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

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

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

Definition at line 268 of file chan_h323.c.

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

static int reload ( void   )  [static]

Definition at line 2996 of file chan_h323.c.

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

02997 {
02998    if (!sched || !io) {
02999       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03000       return 0;
03001    }
03002    return h323_reload(0, 0, NULL);
03003 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2758 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_prune_realtime(), iax2_reload(), load_module(), mgcp_do_reload(), misdn_reload(), reload(), and sip_do_reload().

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

static int restart_monitor ( void   )  [static]

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

02512 {
02513    /* If we're supposed to be stopped -- stay stopped */
02514    if (ast_mutex_lock(&monlock)) {
02515       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02516       return -1;
02517    }
02518    if (monitor_thread == AST_PTHREADT_STOP) {
02519       ast_mutex_unlock(&monlock);
02520       return 0;
02521    }
02522    if (monitor_thread == pthread_self()) {
02523       ast_mutex_unlock(&monlock);
02524       ast_log(LOG_WARNING, "Cannot kill myself\n");
02525       return -1;
02526    }
02527    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02528       /* Wake up the thread */
02529       pthread_kill(monitor_thread, SIGURG);
02530    } else {
02531       /* Start a new monitor */
02532       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02533          monitor_thread = AST_PTHREADT_NULL;
02534          ast_mutex_unlock(&monlock);
02535          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02536          return -1;
02537       }
02538    }
02539    ast_mutex_unlock(&monlock);
02540    return 0;
02541 }

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

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

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

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

Definition at line 2418 of file chan_h323.c.

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

Referenced by load_module().

02419 {
02420    struct oh323_pvt *pvt;
02421    int capability, dtmfmode, pref_codec;
02422    struct ast_codec_pref prefs;
02423 
02424    if (h323debug)
02425       ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
02426 
02427    pvt = find_call_locked(call_reference, token);
02428    if (!pvt)
02429       return;
02430    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02431    dtmfmode = pvt->options.dtmfmode;
02432    prefs = pvt->options.prefs;
02433    pref_codec = pvt->pref_codec;
02434    ast_mutex_unlock(&pvt->lock);
02435    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02436 
02437    if (h323debug)
02438       ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
02439 }

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

Definition at line 2390 of file chan_h323.c.

References ast_getformatname(), ast_log(), ast_mutex_unlock(), ast_rtp_codec_setpref(), 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::peer_prefs, oh323_pvt::peercapability, prefs, and oh323_pvt::rtp.

Referenced by load_module().

02391 {
02392    struct oh323_pvt *pvt;
02393 
02394    if (h323debug)
02395       ast_log(LOG_DEBUG, "Got remote capabilities from connection %s\n", token);
02396 
02397    pvt = find_call_locked(call_reference, token);
02398    if (!pvt)
02399       return;
02400    pvt->peercapability = capabilities;
02401    pvt->jointcapability = pvt->options.capability & capabilities;
02402    if (prefs) {
02403       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02404       if (h323debug) {
02405          int i;
02406          for (i = 0; i < 32; ++i) {
02407             if (!prefs->order[i])
02408                break;
02409             ast_log(LOG_DEBUG, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02410          }
02411       }
02412       if (pvt->rtp)
02413          ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
02414    }
02415    ast_mutex_unlock(&pvt->lock);
02416 }

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

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

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

References cleanup_call_details().

Referenced by load_module().

02253 {
02254    /* Use argument here or free it immediately */
02255    cleanup_call_details(cd);
02256 
02257    return 1;
02258 }

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

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

static int unload_module ( void   )  [static]

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

03197 {
03198    struct oh323_pvt *p, *pl;
03199 
03200    /* unregister commands */
03201    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03202    ast_cli_unregister(&cli_h323_reload);
03203 
03204    ast_channel_unregister(&oh323_tech);
03205    ast_rtp_proto_unregister(&oh323_rtp);
03206 
03207    if (!ast_mutex_lock(&iflock)) {
03208       /* hangup all interfaces if they have an owner */
03209       p = iflist;
03210       while(p) {
03211          if (p->owner) {
03212             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03213          }
03214          p = p->next;
03215       }
03216       iflist = NULL;
03217       ast_mutex_unlock(&iflock);
03218    } else {
03219       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03220       return -1;
03221    }
03222    if (!ast_mutex_lock(&monlock)) {
03223       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03224          if (monitor_thread != pthread_self()) {
03225             pthread_cancel(monitor_thread);
03226          }
03227          pthread_kill(monitor_thread, SIGURG);
03228          pthread_join(monitor_thread, NULL);
03229       }
03230       monitor_thread = AST_PTHREADT_STOP;
03231       ast_mutex_unlock(&monlock);
03232    } else {
03233       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03234       return -1;
03235    }
03236    if (!ast_mutex_lock(&iflock)) {
03237       /* destroy all the interfaces and free their memory */
03238       p = iflist;
03239       while(p) {
03240          pl = p;
03241          p = p->next;
03242          /* free associated memory */
03243          ast_mutex_destroy(&pl->lock);
03244          free(pl);
03245       }
03246       iflist = NULL;
03247       ast_mutex_unlock(&iflock);
03248    } else {
03249       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03250       return -1;
03251    }
03252    if (!gatekeeper_disable)
03253       h323_gk_urq();
03254    h323_end_process();
03255    if (io)
03256       io_context_destroy(io);
03257    if (sched)
03258       sched_context_destroy(sched);
03259 
03260    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03261    ASTOBJ_CONTAINER_DESTROY(&userl);
03262    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03263    ASTOBJ_CONTAINER_DESTROY(&peerl);
03264    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03265    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03266 
03267    return 0;
03268 }

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

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

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

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

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

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


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

Definition at line 3274 of file chan_h323.c.

int acceptAnonymous = 1 [static]

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

struct sockaddr_in bindaddr [static]

Definition at line 139 of file chan_h323.c.

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

Definition at line 224 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2678 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 2663 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 2673 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 2658 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 2653 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 3005 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 2668 of file chan_h323.c.

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

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

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

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

char gatekeeper[100] [static]

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

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

int gkroute = 0 [static]

Definition at line 148 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct ast_jb_conf global_jbconf [static]

Definition at line 133 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 156 of file chan_h323.c.

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

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

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

int h323_reloading = 0 [static]

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

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

int h323debug

Definition at line 123 of file chan_h323.c.

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

struct oh323_pvt * iflist

Private structure of a OpenH323 channel

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

Protect the interface list (oh323_pvt)

Definition at line 217 of file chan_h323.c.

struct io_context* io [static]

Definition at line 214 of file chan_h323.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 232 of file chan_h323.c.

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

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

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3087 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech oh323_tech [static]

Definition at line 247 of file chan_h323.c.

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

answer_call_cb on_answer_call

Definition at line 115 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 112 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 114 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 113 of file chan_h323.c.

on_rtp_cb on_external_rtp_create

Definition at line 108 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 118 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 110 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 111 of file chan_h323.c.

progress_cb on_progress

Definition at line 116 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 107 of file chan_h323.c.

rfc2833_cb on_set_rfc2833_payload

Definition at line 117 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 119 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 120 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

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

char secret[50] [static]

Definition at line 153 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 2637 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 2641 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 2645 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 136 of file chan_h323.c.

int tos = 0 [static]

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

unsigned int unique = 0 [static]

Definition at line 154 of file chan_h323.c.

Referenced by oh323_request().

int userbyalias = 1 [static]

Definition at line 150 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 Wed Feb 11 12:00:11 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7