Thu Oct 11 06:35:04 2012

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 <netdb.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.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 "asterisk/format.h"
#include "asterisk/format_cap.h"
#include "h323/chan_h323.h"

Include dependency graph for chan_h323.c:

Go to the source code of this file.

Data Structures

struct  h323_alias_list
 H323 alias list. More...
struct  h323_peer_list
 H323 peer list. More...
struct  h323_user_list
 H323 User list. More...
struct  oh323_pvt
 Private structure of a OpenH323 channel. More...

Defines

#define GLOBAL_CAPABILITY

Functions

static void __oh323_destroy (struct oh323_pvt *pvt)
static struct ast_channel__oh323_new (struct oh323_pvt *pvt, int state, const char *host, const char *linkedid)
 Private structure should be locked on a call.
static int __oh323_rtp_create (struct oh323_pvt *pvt)
static void __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt)
 Channel and private structures should be already locked.
static void __reg_module (void)
static void __unreg_module (void)
static int answer_call (unsigned call_reference, const char *token)
 Call-back function to start PBX when OpenH323 ready to serve incoming call.
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 (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static void chan_ringing (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel is ringing Returns nothing.
static void cleanup_call_details (call_details_t *cd)
static void cleanup_connection (unsigned call_reference, const char *call_token)
 Call-back function to cleanup communication Returns nothing,.
static void connection_made (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel has been answered Returns nothing.
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)
 Callback function used to inform the H.323 stack of the local rtp ip/port details.
static struct oh323_alias * find_alias (const char *source_aliases, int realtime)
 Find a call by alias.
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_reload (void)
static int h323_parse_allow_disallow (struct ast_codec_pref *pref, h323_format *formats, const char *list, int allowing)
static int h323_reload (void)
static char * handle_cli_h323_cycle_gk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_set_trace (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_show_tokens (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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, const char *dest, int timeout)
 Make a call over the specified channel to the specified destination. Returns -1 on error, 0 on success.
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)
 Send (play) the specified digit to the channel.
static int oh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_glue_result oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
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, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause)
static struct ast_frameoh323_rtp_read (struct oh323_pvt *pvt)
 Retrieve audio/etc from channel. Assumes pvt->lock is already held.
static int oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active)
static int oh323_simulate_dtmf_end (const void *data)
static void oh323_update_info (struct ast_channel *c)
 Only channel structure should be locked.
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)
 Callback for sending digits from H.323 up to asterisk.
static const char * redirectingreason2str (int redirectingreason)
static int reload (void)
static int reload_config (int is_reload)
static void remote_hold (unsigned call_reference, const char *token, int is_hold)
static int restart_monitor (void)
static void set_dtmf_payload (unsigned call_reference, const char *token, int payload, int is_cisco)
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)
 Call-back function for incoming calls.
static int setup_outgoing_call (call_details_t *cd)
 Call-back function to establish an outgoing H.323 call.
static void setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
 Call-back function passing remote ip/port information from H.323 to asterisk.
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_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static int acceptAnonymous = 1
static struct h323_alias_list aliasl
 H323 alias list.
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static ast_mutex_t caplock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_reload
static const char config [] = "h323.conf"
static unsigned int cos = 0
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration - by default, jb is disabled.
static char gatekeeper [100]
static int gatekeeper_disable = 1
static int gatekeeper_discover = 0
static int gkroute = 0
static struct ast_jb_conf global_jbconf
static call_options_t global_options
static ast_mutex_t h323_reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the reload process.
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
static struct oh323_pvtiflist
 Private structure of a OpenH323 channel.
static ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static struct ast_rtp_glue oh323_rtp_glue
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
onhold_cb on_hold
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 h323_peer_list peerl
 H323 peer list.
static struct ast_sched_contextsched
static char secret [50]
static const char tdesc [] = "The NuFone Network's Open H.323 Channel Driver"
static unsigned int tos = 0
static unsigned int unique = 0
static int userbyalias = 1
static struct h323_user_list userl
 H323 User list.


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 GLOBAL_CAPABILITY

Definition at line 137 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 454 of file chan_h323.c.

References ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt_set(), ast_channel_unlock, ast_debug, ast_dsp_free(), ast_free, ast_log(), ast_mutex_destroy, ast_mutex_unlock, ast_rtp_instance_destroy(), AST_SCHED_DEL, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, iflist, oh323_pvt::lock, LOG_WARNING, oh323_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.

Referenced by do_monitor(), and oh323_destroy().

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

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

Private structure should be locked on a call.

Definition at line 1029 of file chan_h323.c.

References __oh323_rtp_create(), oh323_pvt::accountcode, oh323_pvt::amaflags, ast_party_caller::ani, ast_best_codec(), ast_channel_alloc, ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_context_set(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_priority_set(), ast_channel_redirecting(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_transfercapability_set(), ast_codec_choose(), ast_dsp_new(), ast_dsp_set_features(), ast_format_cap_from_old_bitfield(), ast_format_cap_set(), ast_format_cap_to_old_bitfield(), ast_format_copy(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), ast_rtp_instance_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_udptl_fd(), oh323_pvt::cd, cid_name, cid_num, oh323_pvt::context, DSP_FEATURE_DIGIT_DETECT, oh323_pvt::exten, ast_party_redirecting::from, ast_party_caller::id, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_WARNING, ast_party_id::name, oh323_pvt::nativeformats, ast_party_dialed::number, ast_party_id::number, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, redirectingreason2str(), oh323_pvt::rtp, ast_party_dialed::str, ast_party_number::str, oh323_pvt::vad, ast_party_number::valid, and ast_channel::writeformat.

Referenced by answer_call(), and oh323_request().

01030 {
01031    struct ast_channel *ch;
01032    char *cid_num, *cid_name;
01033    h323_format fmt;
01034    struct ast_format tmpfmt;
01035 
01036    if (!ast_strlen_zero(pvt->options.cid_num))
01037       cid_num = pvt->options.cid_num;
01038    else
01039       cid_num = pvt->cd.call_source_e164;
01040 
01041    if (!ast_strlen_zero(pvt->options.cid_name))
01042       cid_name = pvt->options.cid_name;
01043    else
01044       cid_name = pvt->cd.call_source_name;
01045    
01046    /* Don't hold a oh323_pvt lock while we allocate a chanel */
01047    ast_mutex_unlock(&pvt->lock);
01048    ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, linkedid, pvt->amaflags, "H323/%s", host);
01049    /* Update usage counter */
01050    ast_module_ref(ast_module_info->self);
01051    ast_mutex_lock(&pvt->lock);
01052    if (ch) {
01053       ast_channel_tech_set(ch, &oh323_tech);
01054       if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
01055          fmt = global_options.capability;
01056 
01057       ast_format_cap_from_old_bitfield(ast_channel_nativeformats(ch), fmt);
01058       ast_codec_choose(&pvt->options.prefs, ast_channel_nativeformats(ch), 1, &tmpfmt)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
01059 
01060       ast_format_cap_set(ast_channel_nativeformats(ch), &tmpfmt);
01061 
01062       pvt->nativeformats = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(ch));
01063       ast_best_codec(ast_channel_nativeformats(ch), &tmpfmt);
01064       ast_format_copy(&ch->writeformat, &tmpfmt);
01065       ast_format_copy(&ch->rawwriteformat, &tmpfmt);
01066       ast_format_copy(&ch->readformat, &tmpfmt);
01067       ast_format_copy(&ch->rawreadformat, &tmpfmt);
01068       if (!pvt->rtp)
01069          __oh323_rtp_create(pvt);
01070 #if 0
01071       ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(pvt->rtp, 0));
01072       ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(pvt->rtp, 1));
01073 #endif
01074 #ifdef VIDEO_SUPPORT
01075       if (pvt->vrtp) {
01076          ast_channel_set_fd(ch, 2, ast_rtp_instance_fd(pvt->vrtp, 0));
01077          ast_channel_set_fd(ch, 3, ast_rtp_instance_fd(pvt->vrtp, 1));
01078       }
01079 #endif
01080 #ifdef T38_SUPPORT
01081       if (pvt->udptl) {
01082          ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl));
01083       }
01084 #endif
01085       if (state == AST_STATE_RING) {
01086          ast_channel_rings_set(ch, 1);
01087       }
01088       /* Allocate dsp for in-band DTMF support */
01089       if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
01090          pvt->vad = ast_dsp_new();
01091          ast_dsp_set_features(pvt->vad, DSP_FEATURE_DIGIT_DETECT);
01092       }
01093       /* Register channel functions. */
01094       ast_channel_tech_pvt_set(ch, pvt);
01095       /* Set the owner of this channel */
01096       pvt->owner = ch;
01097 
01098       ast_channel_context_set(ch, pvt->context);
01099       ast_channel_exten_set(ch, pvt->exten);
01100       ast_channel_priority_set(ch, 1);
01101       if (!ast_strlen_zero(pvt->accountcode)) {
01102          ast_channel_accountcode_set(ch, pvt->accountcode);
01103       }
01104       if (pvt->amaflags) {
01105          ast_channel_amaflags_set(ch, pvt->amaflags);
01106       }
01107 
01108       /* Don't use ast_set_callerid() here because it will
01109        * generate a needless NewCallerID event */
01110       if (!ast_strlen_zero(cid_num)) {
01111          ast_channel_caller(ch)->ani.number.valid = 1;
01112          ast_channel_caller(ch)->ani.number.str = ast_strdup(cid_num);
01113       }
01114 
01115       if (pvt->cd.redirect_reason >= 0) {
01116          ast_channel_redirecting(ch)->from.number.valid = 1;
01117          ast_channel_redirecting(ch)->from.number.str = ast_strdup(pvt->cd.redirect_number);
01118          pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
01119       }
01120       ast_channel_caller(ch)->id.name.presentation = pvt->cd.presentation;
01121       ast_channel_caller(ch)->id.number.presentation = pvt->cd.presentation;
01122       ast_channel_caller(ch)->id.number.plan = pvt->cd.type_of_number;
01123 
01124       if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
01125          ast_channel_dialed(ch)->number.str = ast_strdup(pvt->exten);
01126       }
01127       if (pvt->cd.transfer_capability >= 0)
01128          ast_channel_transfercapability_set(ch, pvt->cd.transfer_capability);
01129       if (state != AST_STATE_DOWN) {
01130          if (ast_pbx_start(ch)) {
01131             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch));
01132             ast_hangup(ch);
01133             ch = NULL;
01134          }
01135       }
01136    } else {
01137       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
01138    }
01139    return ch;
01140 }

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 975 of file chan_h323.c.

References ast_channel_set_fd(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_find_ourip(), ast_jb_configure(), ast_log(), ast_mutex_unlock, ast_null_frame, ast_queue_frame(), ast_rtp_codecs_packetization_set(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, ast_sockaddr_from_sin, bindaddr, oh323_pvt::dtmf_pt, errno, global_jbconf, oh323_pvt::lock, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, ast_sockaddr::ss, and oh323_pvt::update_rtp_info.

Referenced by __oh323_new(), external_rtp_create(), and setup_rtp_connection().

00976 {
00977    struct ast_sockaddr our_addr;
00978 
00979    if (pvt->rtp)
00980       return 0;
00981 
00982    {
00983       struct ast_sockaddr tmp;
00984 
00985       ast_sockaddr_from_sin(&tmp, &bindaddr);
00986       if (ast_find_ourip(&our_addr, &tmp, AF_INET)) {
00987          ast_mutex_unlock(&pvt->lock);
00988          ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00989          return -1;
00990       }
00991    }
00992    our_addr.ss.ss_family = AF_INET;
00993    pvt->rtp = ast_rtp_instance_new("asterisk", sched, &our_addr, NULL);
00994    if (!pvt->rtp) {
00995       ast_mutex_unlock(&pvt->lock);
00996       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00997       return -1;
00998    }
00999    if (h323debug)
01000       ast_debug(1, "Created RTP channel\n");
01001 
01002    ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP");
01003 
01004    if (h323debug)
01005       ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
01006    ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
01007 
01008    if (pvt->dtmf_pt[0] > 0)
01009       ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
01010    if (pvt->dtmf_pt[1] > 0)
01011       ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
01012 
01013    if (pvt->peercapability)
01014       ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
01015 
01016    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01017       ast_jb_configure(pvt->owner, &global_jbconf);
01018       ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
01019       ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
01020       ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
01021       ast_channel_unlock(pvt->owner);
01022    } else
01023       pvt->update_rtp_info = 1;
01024 
01025    return 0;
01026 }

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

Channel and private structures should be already locked.

Definition at line 342 of file chan_h323.c.

References ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_set_fd(), ast_channel_softhangup_internal_flag_add(), ast_debug, ast_format_cap_from_old_bitfield(), ast_format_cap_to_old_bitfield(), 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_with_cause(), ast_rtp_instance_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, ast_frame::frametype, global_jbconf, oh323_pvt::hangupcause, ast_frame_subclass::integer, LOG_DTMF, oh323_pvt::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, ast_frame::subclass, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

static void __reg_module ( void   )  [static]

Definition at line 3498 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_module().

02302 {
02303    struct oh323_pvt *pvt;
02304    struct ast_channel *c = NULL;
02305    enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02306    char tmp_exten[sizeof(pvt->exten)];
02307 
02308    if (h323debug)
02309       ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
02310 
02311    /* Find the call or allocate a private structure if call not found */
02312    pvt = find_call_locked(call_reference, token);
02313    if (!pvt) {
02314       ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02315       return 0;
02316    }
02317    /* Check if requested extension@context pair exists in the dialplan */
02318    ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02319 
02320    /* Try to find best extension in specified context */
02321    if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02322       if (tmp_exten[0] == 's')
02323          try_exten = ext_s;
02324       else if (tmp_exten[0] == 'i')
02325          try_exten = ext_i;
02326       else
02327          try_exten = ext_original;
02328    } else
02329       try_exten = ext_original;
02330    do {
02331       if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02332          break;
02333       switch (try_exten) {
02334       case ext_original:
02335          tmp_exten[0] = 's';
02336          tmp_exten[1] = '\0';
02337          try_exten = ext_s;
02338          break;
02339       case ext_s:
02340          tmp_exten[0] = 'i';
02341          try_exten = ext_i;
02342          break;
02343       case ext_i:
02344          try_exten = ext_notexists;
02345          break;
02346       default:
02347          break;
02348       }
02349    } while (try_exten != ext_notexists);
02350 
02351    /* Drop the call if we don't have <exten>, s and i extensions */
02352    if (try_exten == ext_notexists) {
02353       ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02354       ast_mutex_unlock(&pvt->lock);
02355       h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02356       return 0;
02357    } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02358       if (h323debug)
02359          ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02360       ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02361    }
02362 
02363    /* allocate a channel and tell asterisk about it */
02364    c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL);
02365 
02366    /* And release when done */
02367    ast_mutex_unlock(&pvt->lock);
02368    if (!c) {
02369       ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02370       return 0;
02371    }
02372    return 1;
02373 }

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

Definition at line 1232 of file chan_h323.c.

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

Referenced by realtime_alias(), and reload_config().

01233 {
01234    struct oh323_alias *alias;
01235    int found = 0;
01236 
01237    alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
01238 
01239    if (alias)
01240       found++;
01241    else {
01242       if (!(alias = ast_calloc(1, sizeof(*alias))))
01243          return NULL;
01244       ASTOBJ_INIT(alias);
01245    }
01246    if (!found && name)
01247       ast_copy_string(alias->name, name, sizeof(alias->name));
01248    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01249       if (!strcasecmp(v->name, "e164")) {
01250          ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
01251       } else if (!strcasecmp(v->name, "prefix")) {
01252          ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
01253       } else if (!strcasecmp(v->name, "context")) {
01254          ast_copy_string(alias->context, v->value, sizeof(alias->context));
01255       } else if (!strcasecmp(v->name, "secret")) {
01256          ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
01257       } else {
01258          if (strcasecmp(v->value, "h323")) {
01259             ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
01260          }
01261       }
01262    }
01263    ASTOBJ_UNMARK(alias);
01264    return alias;
01265 }

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

Definition at line 1542 of file chan_h323.c.

References ast_append_ha(), ast_calloc, ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_sockaddr_to_sin, ast_strlen_zero(), ast_true(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, oh323_destroy_peer(), peerl, ast_sockaddr::ss, update_common_options(), and ast_variable::value.

Referenced by realtime_peer(), register_realtime_peers_with_callbackextens(), reload_config(), and set_config().

01543 {
01544    struct oh323_peer *peer;
01545    struct ast_ha *oldha;
01546    int found = 0;
01547 
01548    peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01549 
01550    if (peer)
01551       found++;
01552    else {
01553       if (!(peer = ast_calloc(1, sizeof(*peer))))
01554          return NULL;
01555       ASTOBJ_INIT(peer);
01556    }
01557    oldha = peer->ha;
01558    peer->ha = NULL;
01559    memcpy(&peer->options, &global_options, sizeof(peer->options));
01560    peer->options.dtmfmode = 0;
01561    peer->options.holdHandling = 0;
01562    peer->addr.sin_port = htons(h323_signalling_port);
01563    peer->addr.sin_family = AF_INET;
01564    if (!found && name)
01565       ast_copy_string(peer->name, name, sizeof(peer->name));
01566 
01567 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01568    if (peer->chanvars) {
01569       ast_variables_destroy(peer->chanvars);
01570       peer->chanvars = NULL;
01571    }
01572 #endif
01573    /* Default settings for mailbox */
01574    peer->mailbox[0] = '\0';
01575 
01576    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01577       if (!update_common_options(v, &peer->options))
01578          continue;
01579       if (!strcasecmp(v->name, "host")) {
01580          if (!strcasecmp(v->value, "dynamic")) {
01581             ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01582             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01583             return NULL;
01584          }
01585          {
01586             struct ast_sockaddr tmp;
01587 
01588             tmp.ss.ss_family = AF_INET;
01589             if (ast_get_ip(&tmp, v->value)) {
01590                ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01591                ASTOBJ_UNREF(peer, oh323_destroy_peer);
01592                return NULL;
01593             }
01594             ast_sockaddr_to_sin(&tmp, &peer->addr);
01595          }
01596       } else if (!strcasecmp(v->name, "port")) {
01597          peer->addr.sin_port = htons(atoi(v->value));
01598       } else if (!strcasecmp(v->name, "permit") ||
01599                !strcasecmp(v->name, "deny")) {
01600          int ha_error = 0;
01601 
01602          peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
01603          if (ha_error)
01604             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01605       } else if (!strcasecmp(v->name, "mailbox")) {
01606          ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01607       } else if (!strcasecmp(v->name, "hasvoicemail")) {
01608          if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01609             ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01610          }
01611       }
01612    }
01613    if (!peer->options.dtmfmode)
01614       peer->options.dtmfmode = global_options.dtmfmode;
01615    if (peer->options.holdHandling == ~0)
01616       peer->options.holdHandling = 0;
01617    else if (!peer->options.holdHandling)
01618       peer->options.holdHandling = global_options.holdHandling;
01619    ASTOBJ_UNMARK(peer);
01620    ast_free_ha(oldha);
01621    return peer;
01622 }

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

Definition at line 1417 of file chan_h323.c.

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

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

01418 {
01419    struct oh323_user *user;
01420    struct ast_ha *oldha;
01421    int found = 0;
01422    int format;
01423 
01424    user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
01425 
01426    if (user)
01427       found++;
01428    else {
01429       if (!(user = ast_calloc(1, sizeof(*user))))
01430          return NULL;
01431       ASTOBJ_INIT(user);
01432    }
01433    oldha = user->ha;
01434    user->ha = (struct ast_ha *)NULL;
01435    memcpy(&user->options, &global_options, sizeof(user->options));
01436    user->options.dtmfmode = 0;
01437    user->options.holdHandling = 0;
01438    /* Set default context */
01439    ast_copy_string(user->context, default_context, sizeof(user->context));
01440    if (!found) {
01441       ast_copy_string(user->name, name, sizeof(user->name));
01442    }
01443 
01444 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01445    if (user->chanvars) {
01446       ast_variables_destroy(user->chanvars);
01447       user->chanvars = NULL;
01448    }
01449 #endif
01450 
01451    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01452       if (!update_common_options(v, &user->options))
01453          continue;
01454       if (!strcasecmp(v->name, "context")) {
01455          ast_copy_string(user->context, v->value, sizeof(user->context));
01456       } else if (!strcasecmp(v->name, "secret")) {
01457          ast_copy_string(user->secret, v->value, sizeof(user->secret));
01458       } else if (!strcasecmp(v->name, "accountcode")) {
01459          ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
01460       } else if (!strcasecmp(v->name, "host")) {
01461          if (!strcasecmp(v->value, "dynamic")) {
01462             ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
01463             ASTOBJ_UNREF(user, oh323_destroy_user);
01464             return NULL;
01465          } else {
01466             struct ast_sockaddr tmp;
01467 
01468             tmp.ss.ss_family = AF_INET;
01469             if (ast_get_ip(&tmp, v->value)) {
01470                ASTOBJ_UNREF(user, oh323_destroy_user);
01471                return NULL;
01472             }
01473             ast_sockaddr_to_sin(&tmp, &user->addr);
01474          }
01475          /* Let us know we need to use ip authentication */
01476          user->host = 1;
01477       } else if (!strcasecmp(v->name, "amaflags")) {
01478          format = ast_cdr_amaflags2int(v->value);
01479          if (format < 0) {
01480             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
01481          } else {
01482             user->amaflags = format;
01483          }
01484       } else if (!strcasecmp(v->name, "permit") ||
01485                !strcasecmp(v->name, "deny")) {
01486          int ha_error = 0;
01487 
01488          user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error);
01489          if (ha_error)
01490             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01491       }
01492    }
01493    if (!user->options.dtmfmode)
01494       user->options.dtmfmode = global_options.dtmfmode;
01495    if (user->options.holdHandling == ~0)
01496       user->options.holdHandling = 0;
01497    else if (!user->options.holdHandling)
01498       user->options.holdHandling = global_options.holdHandling;
01499    ASTOBJ_UNMARK(user);
01500    ast_free_ha(oldha);
01501    return user;
01502 }

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

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

Referenced by load_module().

02393 {
02394    struct oh323_pvt *pvt;
02395 
02396    if (h323debug)
02397       ast_debug(1, "Ringing on %s\n", token);
02398 
02399    pvt = find_call_locked(call_reference, token);
02400    if (!pvt) {
02401       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02402       return;
02403    }
02404    if (!pvt->owner) {
02405       ast_mutex_unlock(&pvt->lock);
02406       ast_log(LOG_ERROR, "Channel has no owner\n");
02407       return;
02408    }
02409    update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02410    ast_mutex_unlock(&pvt->lock);
02411    return;
02412 }

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 418 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

Definition at line 2418 of file chan_h323.c.

References oh323_pvt::alreadygone, ast_channel_softhangup_internal_flag_add(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_dsp_free(), ast_log(), ast_mutex_unlock, ast_queue_hangup(), ast_rtp_instance_destroy(), AST_SOFTHANGUP_DEV, oh323_pvt::cd, cleanup_call_details(), find_call_locked(), oh323_pvt::lock, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.

Referenced by load_module().

02419 {
02420    struct oh323_pvt *pvt;
02421 
02422    if (h323debug)
02423       ast_debug(1, "Cleaning connection to %s\n", call_token);
02424 
02425    while (1) {
02426       pvt = find_call_locked(call_reference, call_token);
02427       if (!pvt) {
02428          if (h323debug)
02429             ast_debug(1, "No connection for %s\n", call_token);
02430          return;
02431       }
02432       if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02433          break;
02434 #if 1
02435       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02436 #ifdef DEBUG_THREADS
02437       /* XXX to be completed
02438        * If we want to print more info on who is holding the lock,
02439        * implement the relevant code in lock.h and use the routines
02440        * supplied there.
02441        */
02442 #endif
02443 #endif
02444       ast_mutex_unlock(&pvt->lock);
02445       usleep(1);
02446    }
02447    if (pvt->rtp) {
02448       /* Immediately stop RTP */
02449       ast_rtp_instance_destroy(pvt->rtp);
02450       pvt->rtp = NULL;
02451    }
02452    /* Free dsp used for in-band DTMF detection */
02453    if (pvt->vad) {
02454       ast_dsp_free(pvt->vad);
02455       pvt->vad = NULL;
02456    }
02457    cleanup_call_details(&pvt->cd);
02458    pvt->alreadygone = 1;
02459    /* Send hangup */
02460    if (pvt->owner) {
02461       ast_channel_softhangup_internal_flag_add(pvt->owner, AST_SOFTHANGUP_DEV);
02462       ast_queue_hangup(pvt->owner);
02463       ast_channel_unlock(pvt->owner);
02464    }
02465    ast_mutex_unlock(&pvt->lock);
02466    if (h323debug)
02467       ast_debug(1, "Connection to %s cleaned\n", call_token);
02468    return;
02469 }

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

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

Referenced by load_module().

02127 {
02128    struct oh323_pvt *pvt;
02129 
02130    if (h323debug)
02131       ast_debug(1, "Call %s answered\n", token);
02132 
02133    pvt = find_call_locked(call_reference, token);
02134    if (!pvt) {
02135       ast_log(LOG_ERROR, "Something is wrong: connection\n");
02136       return;
02137    }
02138 
02139    /* Inform asterisk about remote party connected only on outgoing calls */
02140    if (!pvt->outgoing) {
02141       ast_mutex_unlock(&pvt->lock);
02142       return;
02143    }
02144    /* Do not send ANSWER message more than once */
02145    if (!pvt->connection_established) {
02146       pvt->connection_established = 1;
02147       update_state(pvt, -1, AST_CONTROL_ANSWER);
02148    }
02149    ast_mutex_unlock(&pvt->lock);
02150    return;
02151 }

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

Definition at line 1720 of file chan_h323.c.

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

Referenced by __sip_subscribe_mwi_do(), cache_get_callno_locked(), iax2_call(), iax2_provision(), iax2_request(), manager_sipnotify(), oh323_request(), sip_cc_monitor_request_cc(), sip_cli_notify(), sip_msg_send(), sip_request_call(), transmit_publish(), and transmit_register().

01721 {
01722    struct hostent *hp;
01723    struct ast_hostent ahp;
01724    struct oh323_peer *p;
01725    int portno;
01726    int found = 0;
01727    char *port;
01728    char *hostn;
01729    char peer[256] = "";
01730 
01731    ast_copy_string(peer, opeer, sizeof(peer));
01732    port = strchr(peer, ':');
01733    if (port) {
01734       *port = '\0';
01735       port++;
01736    }
01737    pvt->sa.sin_family = AF_INET;
01738    p = find_peer(peer, NULL, 1);
01739    if (p) {
01740       found++;
01741       memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01742       pvt->jointcapability = pvt->options.capability;
01743       if (pvt->options.dtmfmode) {
01744          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01745             pvt->nonCodecCapability |= AST_RTP_DTMF;
01746          } else {
01747             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01748          }
01749       }
01750       if (p->addr.sin_addr.s_addr) {
01751          pvt->sa.sin_addr = p->addr.sin_addr;
01752          pvt->sa.sin_port = p->addr.sin_port;
01753       }
01754       ASTOBJ_UNREF(p, oh323_destroy_peer);
01755    }
01756    if (!p && !found) {
01757       hostn = peer;
01758       if (port) {
01759          portno = atoi(port);
01760       } else {
01761          portno = h323_signalling_port;
01762       }
01763       hp = ast_gethostbyname(hostn, &ahp);
01764       if (hp) {
01765          memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01766          pvt->sa.sin_port = htons(portno);
01767          /* Look peer by address */
01768          p = find_peer(NULL, &pvt->sa, 1);
01769          memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01770          pvt->jointcapability = pvt->options.capability;
01771          if (p) {
01772             ASTOBJ_UNREF(p, oh323_destroy_peer);
01773          }
01774          if (pvt->options.dtmfmode) {
01775             if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01776                pvt->nonCodecCapability |= AST_RTP_DTMF;
01777             } else {
01778                pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01779             }
01780          }
01781          return 0;
01782       } else {
01783          ast_log(LOG_WARNING, "No such host: %s\n", peer);
01784          return -1;
01785       }
01786    } else if (!found) {
01787       return -1;
01788    } else {
01789       return 0;
01790    }
01791 }

static void delete_aliases ( void   )  [static]

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

02890 {
02891    int pruned = 0;
02892 
02893    /* Delete all aliases */
02894    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02895    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02896       ASTOBJ_RDLOCK(iterator);
02897       ASTOBJ_MARK(iterator);
02898       ++pruned;
02899       ASTOBJ_UNLOCK(iterator);
02900    } while (0) );
02901    if (pruned) {
02902       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02903    }
02904    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02905 }

static void delete_users ( void   )  [static]

Definition at line 2863 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(), reload_config(), set_config_destroy(), and unload_module().

02864 {
02865    int pruned = 0;
02866 
02867    /* Delete all users */
02868    ASTOBJ_CONTAINER_WRLOCK(&userl);
02869    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02870       ASTOBJ_RDLOCK(iterator);
02871       ASTOBJ_MARK(iterator);
02872       ++pruned;
02873       ASTOBJ_UNLOCK(iterator);
02874    } while (0) );
02875    if (pruned) {
02876       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02877    }
02878    ASTOBJ_CONTAINER_UNLOCK(&userl);
02879 
02880    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02881    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02882       ASTOBJ_RDLOCK(iterator);
02883       ASTOBJ_MARK(iterator);
02884       ASTOBJ_UNLOCK(iterator);
02885    } while (0) );
02886    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02887 }

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

Definition at line 2610 of file chan_h323.c.

References __oh323_destroy(), ast_io_wait(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_verb, h323_do_reload(), h323_reload_lock, iflist, iflock, oh323_pvt::lock, monlock, oh323_pvt::needdestroy, and oh323_pvt::next.

02611 {
02612    int res;
02613    int reloading;
02614    struct oh323_pvt *oh323 = NULL;
02615 
02616    for(;;) {
02617       /* Check for a reload request */
02618       ast_mutex_lock(&h323_reload_lock);
02619       reloading = h323_reloading;
02620       h323_reloading = 0;
02621       ast_mutex_unlock(&h323_reload_lock);
02622       if (reloading) {
02623          ast_verb(1, "Reloading H.323\n");
02624          h323_do_reload();
02625       }
02626       /* Check for interfaces needing to be killed */
02627       if (!ast_mutex_trylock(&iflock)) {
02628 #if 1
02629          do {
02630             for (oh323 = iflist; oh323; oh323 = oh323->next) {
02631                if (!ast_mutex_trylock(&oh323->lock)) {
02632                   if (oh323->needdestroy) {
02633                      __oh323_destroy(oh323);
02634                      break;
02635                   }
02636                   ast_mutex_unlock(&oh323->lock);
02637                }
02638             }
02639          } while (/*oh323*/ 0);
02640 #else
02641 restartsearch:
02642          oh323 = iflist;
02643          while(oh323) {
02644             if (!ast_mutex_trylock(&oh323->lock)) {
02645                if (oh323->needdestroy) {
02646                   __oh323_destroy(oh323);
02647                   goto restartsearch;
02648                }
02649                ast_mutex_unlock(&oh323->lock);
02650                oh323 = oh323->next;
02651             }
02652          }
02653 #endif
02654          ast_mutex_unlock(&iflock);
02655       } else
02656          oh323 = (struct oh323_pvt *)1;   /* Force fast loop */
02657       pthread_testcancel();
02658       /* Wait for sched or io */
02659       res = ast_sched_wait(sched);
02660       if ((res < 0) || (res > 1000)) {
02661          res = 1000;
02662       }
02663       /* Do not wait if some channel(s) is destroyed, probably, more available too */
02664       if (oh323)
02665          res = 1;
02666       res = ast_io_wait(io, res);
02667       pthread_testcancel();
02668       ast_mutex_lock(&monlock);
02669       if (res >= 0) {
02670          ast_sched_runq(sched);
02671       }
02672       ast_mutex_unlock(&monlock);
02673    }
02674    /* Never reached */
02675    return NULL;
02676 }

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

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

Returns:
Returns the local RTP information

Definition at line 1961 of file chan_h323.c.

References __oh323_rtp_create(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_unlock, ast_rtp_instance_get_local_address(), ast_sockaddr_to_sin, find_call_locked(), oh323_pvt::lock, LOG_ERROR, and oh323_pvt::rtp.

Referenced by load_module().

01962 {
01963    struct oh323_pvt *pvt;
01964    struct sockaddr_in us;
01965    struct rtp_info *info;
01966 
01967    info = ast_calloc(1, sizeof(*info));
01968    if (!info) {
01969       ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01970       return NULL;
01971    }
01972    pvt = find_call_locked(call_reference, token);
01973    if (!pvt) {
01974       ast_free(info);
01975       ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01976       return NULL;
01977    }
01978    if (!pvt->rtp)
01979       __oh323_rtp_create(pvt);
01980    if (!pvt->rtp) {
01981       ast_mutex_unlock(&pvt->lock);
01982       ast_free(info);
01983       ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01984       return NULL;
01985    }
01986    /* figure out our local RTP port and tell the H.323 stack about it */
01987    {
01988       struct ast_sockaddr tmp;
01989 
01990       ast_rtp_instance_get_local_address(pvt->rtp, &tmp);
01991       ast_sockaddr_to_sin(&tmp, &us);
01992    }
01993    ast_mutex_unlock(&pvt->lock);
01994 
01995    ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01996    info->port = ntohs(us.sin_port);
01997    if (h323debug)
01998       ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01999    return info;
02000 }

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

Find a call by alias.

Definition at line 1877 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

01878 {
01879    struct oh323_alias *a;
01880 
01881    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01882 
01883    if (!a && realtime)
01884       a = realtime_alias(source_aliases);
01885 
01886    return a;
01887 }

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

Definition at line 1185 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(), remote_hold(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), and setup_rtp_connection().

01186 {
01187    struct oh323_pvt *pvt;
01188 
01189    ast_mutex_lock(&iflock);
01190    pvt = iflist;
01191    while(pvt) {
01192       if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01193          /* Found the call */
01194          if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01195             ast_mutex_lock(&pvt->lock);
01196             ast_mutex_unlock(&iflock);
01197             return pvt;
01198          } else if (token == NULL) {
01199             ast_log(LOG_WARNING, "Call Token is NULL\n");
01200             ast_mutex_lock(&pvt->lock);
01201             ast_mutex_unlock(&iflock);
01202             return pvt;
01203          }
01204       }
01205       pvt = pvt->next;
01206    }
01207    ast_mutex_unlock(&iflock);
01208    return NULL;
01209 }

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

Definition at line 1702 of file chan_h323.c.

References ast_debug, ast_inet_ntoa(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, oh323_addrcmp(), peerl, and realtime_peer().

Referenced by calltoken_required(), create_addr(), dundi_encrypt(), function_iaxpeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), handle_command_response(), iax2_devicestate(), register_verify(), registry_authrequest(), requirecalltoken_mark_auto(), set_config(), and update_registry().

01703 {
01704    struct oh323_peer *p;
01705 
01706    if (peer)
01707       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01708    else
01709       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01710 
01711    if (!p && realtime)
01712       p = realtime_peer(peer, sin);
01713 
01714    if (!p && h323debug)
01715       ast_debug(1, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
01716 
01717    return p;
01718 }

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

Definition at line 1672 of file chan_h323.c.

References ast_debug, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, oh323_addrcmp_str(), realtime_user(), and userl.

01673 {
01674    struct oh323_user *u;
01675 
01676    if (userbyalias)
01677       u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01678    else
01679       u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01680 
01681    if (!u && realtime)
01682       u = realtime_user(cd);
01683 
01684    if (!u && h323debug)
01685       ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01686 
01687    return u;
01688 }

static int h323_do_reload ( void   )  [static]

Definition at line 3200 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03201 {
03202    reload_config(1);
03203    return 0;
03204 }

static int h323_parse_allow_disallow ( struct ast_codec_pref pref,
h323_format *  formats,
const char *  list,
int  allowing 
) [static]

Definition at line 1292 of file chan_h323.c.

References ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_from_old_bitfield(), ast_format_cap_to_old_bitfield(), and ast_parse_allow_disallow().

Referenced by update_common_options().

01293 {
01294    int res;
01295    struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
01296    if (!cap) {
01297       return 1;
01298    }
01299 
01300    ast_format_cap_from_old_bitfield(cap, *formats);
01301    res = ast_parse_allow_disallow(pref, cap, list, allowing);
01302    *formats = ast_format_cap_to_old_bitfield(cap);
01303    cap = ast_format_cap_destroy(cap);
01304    return res;
01305 
01306 }

static int h323_reload ( void   )  [static]

Definition at line 3166 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

03167 {
03168    ast_mutex_lock(&h323_reload_lock);
03169    if (h323_reloading) {
03170       ast_verbose("Previous H.323 reload not yet done\n");
03171    } else {
03172       h323_reloading = 1;
03173    }
03174    ast_mutex_unlock(&h323_reload_lock);
03175    restart_monitor();
03176    return 0;
03177 }

static char* handle_cli_h323_cycle_gk ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2762 of file chan_h323.c.

References ast_cli_args::argc, ast_log(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, LOG_ERROR, and ast_cli_entry::usage.

02763 {
02764    switch (cmd) {
02765    case CLI_INIT:
02766       e->command = "h323 cycle gk";
02767       e->usage =
02768          "Usage: h323 cycle gk\n"
02769          "       Manually re-register with the Gatekeper (Currently Disabled)\n";
02770       return NULL;
02771    case CLI_GENERATE:
02772       return NULL;
02773    }
02774 
02775    if (a->argc != 3)
02776       return CLI_SHOWUSAGE;
02777 
02778    h323_gk_urq();
02779 
02780    /* Possibly register with a GK */
02781    if (!gatekeeper_disable) {
02782       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02783          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02784       }
02785    }
02786    return CLI_SUCCESS;
02787 }

static char* handle_cli_h323_hangup ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2789 of file chan_h323.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_verb, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

02790 {
02791    switch (cmd) {
02792    case CLI_INIT:
02793       e->command = "h323 hangup";
02794       e->usage =
02795          "Usage: h323 hangup <token>\n"
02796          "       Manually try to hang up the call identified by <token>\n";
02797       return NULL;
02798    case CLI_GENERATE:
02799       return NULL;
02800    }
02801 
02802    if (a->argc != 3)
02803       return CLI_SHOWUSAGE;
02804    if (h323_soft_hangup(a->argv[2])) {
02805       ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02806    } else {
02807       ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02808    }
02809    return CLI_SUCCESS;
02810 }

static char* handle_cli_h323_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3179 of file chan_h323.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, h323_reload(), and ast_cli_entry::usage.

03180 {
03181    switch (cmd) {
03182    case CLI_INIT:
03183       e->command = "h323 reload";
03184       e->usage =
03185          "Usage: h323 reload\n"
03186          "       Reloads H.323 configuration from h323.conf\n";
03187       return NULL;
03188    case CLI_GENERATE:
03189       return NULL;
03190    }
03191 
03192    if (a->argc != 2)
03193       return CLI_SHOWUSAGE;
03194 
03195    h323_reload();
03196 
03197    return CLI_SUCCESS;
03198 }

static char* handle_cli_h323_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2739 of file chan_h323.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

02740 {
02741    switch (cmd) {
02742    case CLI_INIT:
02743       e->command = "h323 set debug [on|off]";
02744       e->usage =
02745          "Usage: h323 set debug [on|off]\n"
02746          "       Enable/Disable H.323 debugging output\n";
02747       return NULL;
02748    case CLI_GENERATE:
02749       return NULL;
02750    }
02751 
02752    if (a->argc != e->args)
02753       return CLI_SHOWUSAGE;
02754    if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off"))
02755       return CLI_SHOWUSAGE;
02756 
02757    h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1;
02758    ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02759    return CLI_SUCCESS;
02760 }

static char* handle_cli_h323_set_trace ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2710 of file chan_h323.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

02711 {
02712    switch (cmd) {
02713    case CLI_INIT:
02714       e->command = "h323 set trace [on|off]";
02715       e->usage =
02716          "Usage: h323 set trace (on|off|<trace level>)\n"
02717          "       Enable/Disable H.323 stack tracing for debugging purposes\n";
02718       return NULL;
02719    case CLI_GENERATE:
02720       return NULL;
02721    }
02722 
02723    if (a->argc != e->args)
02724       return CLI_SHOWUSAGE;
02725    if (!strcasecmp(a->argv[3], "off")) {
02726       h323_debug(0, 0);
02727       ast_cli(a->fd, "H.323 Trace Disabled\n");
02728    } else if (!strcasecmp(a->argv[3], "on")) {
02729       h323_debug(1, 1);
02730       ast_cli(a->fd, "H.323 Trace Enabled\n");
02731    } else {
02732       int tracelevel = atoi(a->argv[3]);
02733       h323_debug(1, tracelevel);
02734       ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02735    }
02736    return CLI_SUCCESS;
02737 }

static char* handle_cli_h323_show_tokens ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2812 of file chan_h323.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

02813 {
02814    switch (cmd) {
02815    case CLI_INIT:
02816       e->command = "h323 show tokens";
02817       e->usage =
02818          "Usage: h323 show tokens\n"
02819          "       Print out all active call tokens\n";
02820       return NULL;
02821    case CLI_GENERATE:
02822       return NULL;
02823    }
02824 
02825    if (a->argc != 3)
02826       return CLI_SHOWUSAGE;
02827 
02828    h323_show_tokens();
02829 
02830    return CLI_SUCCESS;
02831 }

static char* handle_cli_h323_show_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2833 of file chan_h323.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

02834 {
02835    switch (cmd) {
02836    case CLI_INIT:
02837       e->command = "h323 show version";
02838       e->usage =
02839          "Usage: h323 show version\n"
02840          "     Show the version of the H.323 library in use\n";
02841       return NULL;
02842    case CLI_GENERATE:
02843       return NULL;
02844    }
02845 
02846    if (a->argc != 3)
02847       return CLI_SHOWUSAGE;
02848 
02849    h323_show_version();
02850    
02851    return CLI_SUCCESS;
02852 }

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

Definition at line 2471 of file chan_h323.c.

References ast_channel_hangupcause_set(), ast_channel_softhangup_internal_flag_add(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_mutex_unlock, ast_queue_hangup_with_cause(), AST_SOFTHANGUP_DEV, find_call_locked(), oh323_pvt::hangupcause, oh323_pvt::lock, oh323_pvt::needhangup, and oh323_pvt::owner.

Referenced by load_module().

02472 {
02473    struct oh323_pvt *pvt;
02474 
02475    if (h323debug)
02476       ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
02477 
02478    pvt = find_call_locked(call_reference, token);
02479    if (!pvt) {
02480       if (h323debug)
02481          ast_debug(1, "Connection to %s already cleared\n", token);
02482       return;
02483    }
02484    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02485       ast_channel_softhangup_internal_flag_add(pvt->owner, AST_SOFTHANGUP_DEV);
02486       ast_channel_hangupcause_set(pvt->owner, pvt->hangupcause = cause);
02487       ast_queue_hangup_with_cause(pvt->owner, cause);
02488       ast_channel_unlock(pvt->owner);
02489    }
02490    else {
02491       pvt->needhangup = 1;
02492       pvt->hangupcause = cause;
02493       if (h323debug)
02494          ast_debug(1, "Hangup for %s is pending\n", token);
02495    }
02496    ast_mutex_unlock(&pvt->lock);
02497 }

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3310 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_format_cap_add_all_by_type(), ast_format_cap_alloc(), AST_FORMAT_TYPE_AUDIO, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_rtp_glue_unregister(), ast_sched_context_create(), ast_sched_context_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, ast_channel_tech::capabilities, chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), hangup_connection(), io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.

03311 {
03312    int res;
03313 
03314    if (!(oh323_tech.capabilities = ast_format_cap_alloc())) {
03315       return AST_MODULE_LOAD_FAILURE;
03316    }
03317    ast_format_cap_add_all_by_type(oh323_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
03318 
03319    h323debug = 0;
03320    sched = ast_sched_context_create();
03321    if (!sched) {
03322       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03323       return AST_MODULE_LOAD_FAILURE;
03324    }
03325    io = io_context_create();
03326    if (!io) {
03327       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03328       return AST_MODULE_LOAD_FAILURE;
03329    }
03330    ast_cli_register(&cli_h323_reload);
03331    ASTOBJ_CONTAINER_INIT(&userl);
03332    ASTOBJ_CONTAINER_INIT(&peerl);
03333    ASTOBJ_CONTAINER_INIT(&aliasl);
03334    res = reload_config(0);
03335    if (res) {
03336       /* No config entry */
03337       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03338       ast_cli_unregister(&cli_h323_reload);
03339       io_context_destroy(io);
03340       io = NULL;
03341       ast_sched_context_destroy(sched);
03342       sched = NULL;
03343       ASTOBJ_CONTAINER_DESTROY(&userl);
03344       ASTOBJ_CONTAINER_DESTROY(&peerl);
03345       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03346       return AST_MODULE_LOAD_DECLINE;
03347    } else {
03348       /* Make sure we can register our channel type */
03349       if (ast_channel_register(&oh323_tech)) {
03350          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03351          ast_cli_unregister(&cli_h323_reload);
03352          h323_end_process();
03353          io_context_destroy(io);
03354          ast_sched_context_destroy(sched);
03355 
03356          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03357          ASTOBJ_CONTAINER_DESTROY(&userl);
03358          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03359          ASTOBJ_CONTAINER_DESTROY(&peerl);
03360          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03361          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03362 
03363          return AST_MODULE_LOAD_FAILURE;
03364       }
03365       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03366 
03367       ast_rtp_glue_register(&oh323_rtp_glue);
03368 
03369       /* Register our callback functions */
03370       h323_callback_register(setup_incoming_call,
03371                   setup_outgoing_call,
03372                   external_rtp_create,
03373                   setup_rtp_connection,
03374                   cleanup_connection,
03375                   chan_ringing,
03376                   connection_made,
03377                   receive_digit,
03378                   answer_call,
03379                   progress,
03380                   set_dtmf_payload,
03381                   hangup_connection,
03382                   set_local_capabilities,
03383                   set_peer_capabilities,
03384                   remote_hold);
03385       /* start the h.323 listener */
03386       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03387          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03388          ast_rtp_glue_unregister(&oh323_rtp_glue);
03389          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03390          ast_cli_unregister(&cli_h323_reload);
03391          h323_end_process();
03392          io_context_destroy(io);
03393          ast_sched_context_destroy(sched);
03394 
03395          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03396          ASTOBJ_CONTAINER_DESTROY(&userl);
03397          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03398          ASTOBJ_CONTAINER_DESTROY(&peerl);
03399          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03400          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03401 
03402          return AST_MODULE_LOAD_DECLINE;
03403       }
03404       /* Possibly register with a GK */
03405       if (!gatekeeper_disable) {
03406          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03407             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03408             gatekeeper_disable = 1;
03409             res = AST_MODULE_LOAD_SUCCESS;
03410          }
03411       }
03412       /* And start the monitor for the first time */
03413       restart_monitor();
03414    }
03415    return res;
03416 }

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

Definition at line 1690 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01691 {
01692    int res;
01693 
01694    if (!sin)
01695       res = -1;
01696    else
01697       res = inaddrcmp(&addr , sin);
01698 
01699    return res;
01700 }

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

Definition at line 1667 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01668 {
01669    return strcmp(ast_inet_ntoa(inaddr), addr);
01670 }

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

Definition at line 1142 of file chan_h323.c.

References ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, AST_RTP_DTMF, ast_rtp_instance_destroy(), oh323_pvt::cd, oh323_pvt::context, oh323_pvt::DTMFsched, iflist, iflock, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, 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().

01143 {
01144    struct oh323_pvt *pvt;
01145 
01146    pvt = ast_calloc(1, sizeof(*pvt));
01147    if (!pvt) {
01148       ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
01149       return NULL;
01150    }
01151    pvt->cd.redirect_reason = -1;
01152    pvt->cd.transfer_capability = -1;
01153    /* Ensure the call token is allocated for outgoing call */
01154    if (!callid) {
01155       if ((pvt->cd).call_token == NULL) {
01156          (pvt->cd).call_token = ast_calloc(1, 128);
01157       }
01158       if (!pvt->cd.call_token) {
01159          ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
01160          ast_rtp_instance_destroy(pvt->rtp);
01161          ast_free(pvt);
01162          return NULL;
01163       }
01164       memset((char *)(pvt->cd).call_token, 0, 128);
01165       pvt->cd.call_reference = callid;
01166    }
01167    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01168    pvt->jointcapability = pvt->options.capability;
01169    if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) {
01170       pvt->nonCodecCapability |= AST_RTP_DTMF;
01171    } else {
01172       pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01173    }
01174    ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
01175    pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
01176    ast_mutex_init(&pvt->lock);
01177    /* Add to interface list */
01178    ast_mutex_lock(&iflock);
01179    pvt->next = iflist;
01180    iflist = pvt;
01181    ast_mutex_unlock(&iflock);
01182    return pvt;
01183 }

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 670 of file chan_h323.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_free, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::lock, and oh323_update_info().

00671 {
00672    int res;
00673    struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
00674    char *token;
00675 
00676    if (h323debug)
00677       ast_debug(1, "Answering on %s\n", ast_channel_name(c));
00678 
00679    ast_mutex_lock(&pvt->lock);
00680    token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
00681    ast_mutex_unlock(&pvt->lock);
00682    res = h323_answering_call(token, 0);
00683    if (token)
00684       ast_free(token);
00685 
00686    oh323_update_info(c);
00687    if (ast_channel_state(c) != AST_STATE_UP) {
00688       ast_setstate(c, AST_STATE_UP);
00689    }
00690    return res;
00691 }

static int oh323_call ( struct ast_channel c,
const 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 590 of file chan_h323.c.

References ast_channel_connected(), ast_channel_name(), ast_channel_redirecting(), ast_channel_tech_pvt(), ast_channel_transfercapability(), ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_party_id_presentation(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verb, oh323_pvt::cd, oh323_pvt::exten, ast_party_connected_line::id, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, name, ast_party_id::number, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), ast_party_number::plan, oh323_pvt::sa, ast_party_number::str, and ast_party_number::valid.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 499 of file chan_h323.c.

References __oh323_destroy(), ast_channel_name(), ast_debug, ast_mutex_lock, ast_mutex_unlock, iflock, oh323_pvt::lock, and oh323_pvt::owner.

Referenced by oh323_request(), and setup_incoming_call().

00500 {
00501    if (h323debug) {
00502       ast_debug(1, "Destroying channel %s\n", (pvt->owner ? ast_channel_name(pvt->owner) : "<unknown>"));
00503    }
00504    ast_mutex_lock(&iflock);
00505    ast_mutex_lock(&pvt->lock);
00506    __oh323_destroy(pvt);
00507    ast_mutex_unlock(&iflock);
00508 }

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

Definition at line 289 of file chan_h323.c.

References ast_debug, and ast_free.

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

00290 {
00291    if (h323debug)
00292       ast_debug(1, "Destroying alias '%s'\n", alias->name);
00293    ast_free(alias);
00294 }

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

Definition at line 304 of file chan_h323.c.

References ast_debug, ast_free, and ast_free_ha().

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

00305 {
00306    if (h323debug)
00307       ast_debug(1, "Destroying peer '%s'\n", peer->name);
00308    ast_free_ha(peer->ha);
00309    ast_free(peer);
00310 }

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

Definition at line 296 of file chan_h323.c.

References ast_debug, ast_free, and ast_free_ha().

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

00297 {
00298    if (h323debug)
00299       ast_debug(1, "Destroying user '%s'\n", user->name);
00300    ast_free_ha(user->ha);
00301    ast_free(user);
00302 }

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

Definition at line 510 of file chan_h323.c.

References ast_channel_name(), ast_channel_tech_pvt(), ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_begin(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::txDtmfDigit.

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

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

References ast_channel_name(), ast_channel_tech_pvt(), ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_end(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::txDtmfDigit.

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

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

Definition at line 961 of file chan_h323.c.

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

00962 {
00963    struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(newchan);
00964 
00965    ast_mutex_lock(&pvt->lock);
00966    if (pvt->owner != oldchan) {
00967       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
00968       return -1;
00969    }
00970    pvt->owner = newchan;
00971    ast_mutex_unlock(&pvt->lock);
00972    return 0;
00973 }

static enum ast_rtp_glue_result oh323_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance **  instance 
) [static]

Definition at line 3218 of file chan_h323.c.

References ao2_ref, ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, oh323_pvt::lock, oh323_pvt::options, and oh323_pvt::rtp.

03219 {
03220    struct oh323_pvt *pvt;
03221    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
03222 
03223    if (!(pvt = (struct oh323_pvt *)ast_channel_tech_pvt(chan)))
03224       return AST_RTP_GLUE_RESULT_FORBID;
03225 
03226    ast_mutex_lock(&pvt->lock);
03227    *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
03228 #if 0
03229    if (pvt->options.bridge) {
03230       res = AST_RTP_GLUE_RESULT_REMOTE;
03231    }
03232 #endif
03233    ast_mutex_unlock(&pvt->lock);
03234 
03235    return res;
03236 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 693 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_channel_hangupcause(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), ast_debug, ast_free, ast_log(), ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, cause, oh323_pvt::cd, oh323_pvt::hangupcause, oh323_pvt::lock, LOG_WARNING, oh323_pvt::needdestroy, oh323_pvt::owner, and pbx_builtin_getvar_helper().

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

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

Definition at line 871 of file chan_h323.c.

References oh323_pvt::alreadygone, ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_free, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::got_progress, oh323_pvt::lock, LOG_WARNING, oh323_update_info(), and oh323_pvt::rtp.

00872 {
00873 
00874    struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
00875    char *token = (char *)NULL;
00876    int res = -1;
00877    int got_progress;
00878 
00879    ast_mutex_lock(&pvt->lock);
00880    token = (pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL);
00881    got_progress = pvt->got_progress;
00882    if (condition == AST_CONTROL_PROGRESS)
00883       pvt->got_progress = 1;
00884    else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))
00885       pvt->alreadygone = 1;
00886    ast_mutex_unlock(&pvt->lock);
00887 
00888    if (h323debug)
00889       ast_debug(1, "OH323: Indicating %d on %s (%s)\n", condition, token, ast_channel_name(c));
00890 
00891    switch(condition) {
00892    case AST_CONTROL_RINGING:
00893       if (ast_channel_state(c) == AST_STATE_RING || ast_channel_state(c) == AST_STATE_RINGING) {
00894          h323_send_alerting(token);
00895          res = (got_progress ? 0 : -1);   /* Do not simulate any audio tones if we got PROGRESS message */
00896       }
00897       break;
00898    case AST_CONTROL_PROGRESS:
00899       if (ast_channel_state(c) != AST_STATE_UP) {
00900          /* Do not send PROGRESS message more than once */
00901          if (!got_progress)
00902             h323_send_progress(token);
00903          res = 0;
00904       }
00905       break;
00906    case AST_CONTROL_BUSY:
00907       if (ast_channel_state(c) != AST_STATE_UP) {
00908          h323_answering_call(token, 1);
00909          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00910          res = 0;
00911       }
00912       break;
00913    case AST_CONTROL_INCOMPLETE:
00914       /* While h323 does support overlapped dialing, this channel driver does not
00915        * at this time.  Treat a response of Incomplete as if it were congestion.
00916        */
00917    case AST_CONTROL_CONGESTION:
00918       if (ast_channel_state(c) != AST_STATE_UP) {
00919          h323_answering_call(token, 1);
00920          ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
00921          res = 0;
00922       }
00923       break;
00924    case AST_CONTROL_HOLD:
00925       h323_hold_call(token, 1);
00926       /* We should start MOH only if remote party isn't provide audio for us */
00927       ast_moh_start(c, data, NULL);
00928       res = 0;
00929       break;
00930    case AST_CONTROL_UNHOLD:
00931       h323_hold_call(token, 0);
00932       ast_moh_stop(c);
00933       res = 0;
00934       break;
00935    case AST_CONTROL_SRCUPDATE:
00936       ast_rtp_instance_update_source(pvt->rtp);
00937       res = 0;
00938       break;
00939    case AST_CONTROL_SRCCHANGE:
00940       ast_rtp_instance_change_source(pvt->rtp);
00941       res = 0;
00942       break;
00943    case AST_CONTROL_PROCEEDING:
00944    case AST_CONTROL_PVT_CAUSE_CODE:
00945    case -1:
00946       break;
00947    default:
00948       ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
00949       break;
00950    }
00951 
00952    if (h323debug)
00953       ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
00954    if (token)
00955       ast_free(token);
00956    oh323_update_info(c);
00957 
00958    return res;
00959 }

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

Definition at line 817 of file chan_h323.c.

References __oh323_update_info(), ast_channel_fdno(), ast_channel_name(), ast_channel_tech_pvt(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_null_frame, ast_rtp_instance_read(), oh323_pvt::lock, LOG_ERROR, oh323_rtp_read(), and oh323_pvt::rtp.

00818 {
00819    struct ast_frame *fr;
00820    struct oh323_pvt *pvt = (struct oh323_pvt *)ast_channel_tech_pvt(c);
00821    ast_mutex_lock(&pvt->lock);
00822    __oh323_update_info(c, pvt);
00823    switch(ast_channel_fdno(c)) {
00824    case 0:
00825       fr = oh323_rtp_read(pvt);
00826       break;
00827    case 1:
00828       if (pvt->rtp)
00829          fr = ast_rtp_instance_read(pvt->rtp, 1);
00830       else
00831          fr = &ast_null_frame;
00832       break;
00833    default:
00834       ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", ast_channel_fdno(c), ast_channel_name(c));
00835       fr = &ast_null_frame;
00836       break;
00837    }
00838    ast_mutex_unlock(&pvt->lock);
00839    return fr;
00840 }

static struct ast_channel * oh323_request ( const char *  type,
struct ast_format_cap cap,
const struct ast_channel requestor,
const char *  dest,
int *  cause 
) [static, read]

Definition at line 1792 of file chan_h323.c.

References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_channel_linkedid(), ast_copy_string(), ast_debug, ast_format_cap_has_type(), AST_FORMAT_TYPE_AUDIO, ast_getformatname_multiple(), 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, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, and restart_monitor().

01793 {
01794    struct oh323_pvt *pvt;
01795    struct ast_channel *tmpc = NULL;
01796    char *ext, *host;
01797    char *h323id = NULL;
01798    char tmp[256], tmp1[256];
01799 
01800    if (h323debug)
01801       ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), cap), dest);
01802 
01803    pvt = oh323_alloc(0);
01804    if (!pvt) {
01805       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", dest);
01806       return NULL;
01807    }
01808    if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
01809       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
01810       oh323_destroy(pvt);
01811       if (cause)
01812          *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01813       return NULL;
01814    }
01815    ast_copy_string(tmp, dest, sizeof(tmp));
01816    host = strchr(tmp, '@');
01817    if (host) {
01818       *host = '\0';
01819       host++;
01820       ext = tmp;
01821    } else {
01822       ext = strrchr(tmp, '/');
01823       if (ext)
01824          *ext++ = '\0';
01825       host = tmp;
01826    }
01827    strtok_r(host, "/", &(h323id));
01828    if (!ast_strlen_zero(h323id)) {
01829       h323_set_id(h323id);
01830    }
01831    if (ext) {
01832       ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01833    }
01834    if (h323debug)
01835       ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
01836 
01837    if (gatekeeper_disable) {
01838       if (create_addr(pvt, host)) {
01839          oh323_destroy(pvt);
01840          if (cause)
01841             *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01842          return NULL;
01843       }
01844    }
01845    else {
01846       memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01847       pvt->jointcapability = pvt->options.capability;
01848       if (pvt->options.dtmfmode) {
01849          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01850             pvt->nonCodecCapability |= AST_RTP_DTMF;
01851          } else {
01852             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01853          }
01854       }
01855    }
01856 
01857    ast_mutex_lock(&caplock);
01858    /* Generate unique channel identifier */
01859    snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01860    tmp1[sizeof(tmp1)-1] = '\0';
01861    ast_mutex_unlock(&caplock);
01862 
01863    ast_mutex_lock(&pvt->lock);
01864    tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? ast_channel_linkedid(requestor) : NULL);
01865    ast_mutex_unlock(&pvt->lock);
01866    if (!tmpc) {
01867       oh323_destroy(pvt);
01868       if (cause)
01869          *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01870    }
01871    ast_update_use_count();
01872    restart_monitor();
01873    return tmpc;
01874 }

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

Retrieve audio/etc from channel. Assumes pvt->lock is already held.

Definition at line 760 of file chan_h323.c.

References ast_channel_nativeformats(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_dsp_process(), AST_FORMAT_ALAW, ast_format_cap_iscompatible(), ast_format_cap_set(), AST_FORMAT_SLINEAR, ast_format_to_old_bitfield(), AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_instance_read(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_NAT, ast_set_read_format(), ast_set_write_format(), f, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, ast_frame::subclass, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by oh323_read().

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

static int oh323_set_rtp_peer ( struct ast_channel chan,
struct ast_rtp_instance rtp,
struct ast_rtp_instance vrtp,
struct ast_rtp_instance trtp,
const struct ast_format_cap codecs,
int  nat_active 
) [static]

Definition at line 3267 of file chan_h323.c.

References ast_channel_tech_pvt(), ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_sockaddr_to_sin, oh323_pvt::cd, LOG_ERROR, and ast_channel::writeformat.

03268 {
03269    /* XXX Deal with Video */
03270    struct oh323_pvt *pvt;
03271    struct sockaddr_in them = { 0, };
03272    struct sockaddr_in us = { 0, };
03273 #if 0 /* Native bridge still isn't ready */
03274    char *mode;
03275 #endif
03276 
03277    if (!rtp) {
03278       return 0;
03279    }
03280 
03281 #if 0 /* Native bridge still isn't ready */
03282    mode = convertcap(&chan->writeformat);
03283 #endif
03284 
03285    pvt = (struct oh323_pvt *) ast_channel_tech_pvt(chan);
03286    if (!pvt) {
03287       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03288       return -1;
03289    }
03290    {
03291       struct ast_sockaddr tmp;
03292 
03293       ast_rtp_instance_get_remote_address(rtp, &tmp);
03294       ast_sockaddr_to_sin(&tmp, &them);
03295       ast_rtp_instance_get_local_address(rtp, &tmp);
03296       ast_sockaddr_to_sin(&tmp, &us);
03297    }
03298 #if 0 /* Native bridge still isn't ready */
03299    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03300 #endif
03301    return 0;
03302 }

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

Definition at line 312 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(), oh323_pvt::curDTMF, DEADLOCK_AVOIDANCE, oh323_pvt::DTMFsched, ast_frame::frametype, oh323_pvt::lock, and oh323_pvt::owner.

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

Definition at line 407 of file chan_h323.c.

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

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

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

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

Definition at line 842 of file chan_h323.c.

References __oh323_update_info(), ast_channel_nativeformats(), ast_channel_tech_pvt(), ast_format_cap_iscompatible(), AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::format, ast_frame::frametype, oh323_pvt::lock, LOG_WARNING, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, ast_frame::subclass, and ast_channel::writeformat.

00843 {
00844    struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
00845    int res = 0;
00846    if (frame->frametype != AST_FRAME_VOICE) {
00847       if (frame->frametype == AST_FRAME_IMAGE) {
00848          return 0;
00849       } else {
00850          ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
00851          return 0;
00852       }
00853    } else {
00854       if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(c), &frame->subclass.format))) {
00855          char tmp[256];
00856          ast_log(LOG_WARNING, "Asked to transmit frame type '%s', while native formats is '%s' (read/write = %s/%s)\n",
00857             ast_getformatname(&frame->subclass.format), ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(c)), ast_getformatname(&c->readformat), ast_getformatname(&c->writeformat));
00858          return 0;
00859       }
00860    }
00861    if (pvt) {
00862       ast_mutex_lock(&pvt->lock);
00863       if (pvt->rtp && !pvt->recvonly)
00864          res = ast_rtp_instance_write(pvt->rtp, frame);
00865       __oh323_update_info(c, pvt);
00866       ast_mutex_unlock(&pvt->lock);
00867    }
00868    return res;
00869 }

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

Definition at line 2153 of file chan_h323.c.

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

02154 {
02155    struct oh323_pvt *pvt;
02156 
02157    if (h323debug)
02158       ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02159 
02160    pvt = find_call_locked(call_reference, token);
02161    if (!pvt) {
02162       ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02163       return -1;
02164    }
02165    if (!pvt->owner) {
02166       ast_mutex_unlock(&pvt->lock);
02167       ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02168       return -1;
02169    }
02170    update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02171    ast_mutex_unlock(&pvt->lock);
02172 
02173    return 0;
02174 }

static void prune_peers ( void   )  [static]

Definition at line 2907 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.

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

02908 {
02909    /* Prune peers who still are supposed to be deleted */
02910    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02911 }

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

Definition at line 1267 of file chan_h323.c.

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

Referenced by find_alias().

01268 {
01269    struct ast_variable *var, *tmp;
01270    struct oh323_alias *a;
01271 
01272    var = ast_load_realtime("h323", "name", alias, SENTINEL);
01273 
01274    if (!var)
01275       return NULL;
01276 
01277    for (tmp = var; tmp; tmp = tmp->next) {
01278       if (!strcasecmp(tmp->name, "type") &&
01279       !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01280          ast_variables_destroy(var);
01281          return NULL;
01282       }
01283    }
01284 
01285    a = build_alias(alias, var, NULL, 1);
01286 
01287    ast_variables_destroy(var);
01288 
01289    return a;
01290 }

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

Definition at line 1624 of file chan_h323.c.

References ast_inet_ntoa(), ast_load_realtime(), ast_log(), ast_variables_destroy(), build_peer(), LOG_WARNING, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.

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

01625 {
01626    struct oh323_peer *peer;
01627    struct ast_variable *var;
01628    struct ast_variable *tmp;
01629    const char *addr = NULL;
01630 
01631    /* First check on peer name */
01632    if (peername)
01633       var = ast_load_realtime("h323", "name", peername, SENTINEL);
01634    else if (sin) /* Then check on IP address for dynamic peers */
01635       var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL);
01636    else
01637       return NULL;
01638 
01639    if (!var)
01640       return NULL;
01641 
01642    for (tmp = var; tmp; tmp = tmp->next) {
01643       /* If this is type=user, then skip this object. */
01644       if (!strcasecmp(tmp->name, "type") &&
01645             !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01646          ast_variables_destroy(var);
01647          return NULL;
01648       } else if (!peername && !strcasecmp(tmp->name, "name")) {
01649          peername = tmp->value;
01650       }
01651    }
01652 
01653    if (!peername) {  /* Did not find peer in realtime */
01654       ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01655       ast_variables_destroy(var);
01656       return NULL;
01657    }
01658 
01659    /* Peer found in realtime, now build it in memory */
01660    peer = build_peer(peername, var, NULL, 1);
01661 
01662    ast_variables_destroy(var);
01663 
01664    return peer;
01665 }

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

Definition at line 1504 of file chan_h323.c.

References ast_load_realtime(), ast_log(), ast_variables_destroy(), build_user(), LOG_WARNING, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.

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

01505 {
01506    struct ast_variable *var, *tmp;
01507    struct oh323_user *user;
01508    const char *username;
01509 
01510    if (userbyalias)
01511       var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL);
01512    else {
01513       username = (char *)NULL;
01514       var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL);
01515    }
01516 
01517    if (!var)
01518       return NULL;
01519 
01520    for (tmp = var; tmp; tmp = tmp->next) {
01521       if (!strcasecmp(tmp->name, "type") &&
01522       !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01523          ast_variables_destroy(var);
01524          return NULL;
01525       } else if (!username && !strcasecmp(tmp->name, "name"))
01526          username = tmp->value;
01527    }
01528 
01529    if (!username) {
01530       ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01531       ast_variables_destroy(var);
01532       return NULL;
01533    }
01534 
01535    user = build_user(username, var, NULL, 1);
01536 
01537    ast_variables_destroy(var);
01538 
01539    return user;
01540 }

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 1893 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, find_call_locked(), ast_frame::frametype, ast_frame_subclass::integer, ast_frame::len, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_frame::samples, and ast_frame::subclass.

Referenced by load_module().

01894 {
01895    struct oh323_pvt *pvt;
01896    int res;
01897 
01898    pvt = find_call_locked(call_reference, token);
01899    if (!pvt) {
01900       ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01901       return -1;
01902    }
01903    if (h323debug)
01904       ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01905 
01906    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01907       if (digit == '!')
01908          res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01909       else {
01910          struct ast_frame f = {
01911             .frametype = AST_FRAME_DTMF_END,
01912             .subclass.integer = digit,
01913             .samples = duration * 8,
01914             .len = duration,
01915             .src = "SEND_DIGIT",
01916          };
01917          if (digit == ' ') {     /* signalUpdate message */
01918             f.subclass.integer = pvt->curDTMF;
01919             AST_SCHED_DEL(sched, pvt->DTMFsched);
01920          } else {          /* Regular input or signal message */
01921             if (pvt->DTMFsched >= 0) {
01922                /* We still don't send DTMF END from previous event, send it now */
01923                AST_SCHED_DEL(sched, pvt->DTMFsched);
01924                f.subclass.integer = pvt->curDTMF;
01925                f.samples = f.len = 0;
01926                ast_queue_frame(pvt->owner, &f);
01927                /* Restore values */
01928                f.subclass.integer = digit;
01929                f.samples = duration * 8;
01930                f.len = duration;
01931             }
01932             if (duration) {      /* This is a signal, signalUpdate follows */
01933                f.frametype = AST_FRAME_DTMF_BEGIN;
01934                pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01935                if (h323debug)
01936                   ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01937             }
01938             pvt->curDTMF = digit;
01939          }
01940          res = ast_queue_frame(pvt->owner, &f);
01941       }
01942       ast_channel_unlock(pvt->owner);
01943    } else {
01944       if (digit == '!')
01945          pvt->newcontrol = AST_CONTROL_FLASH;
01946       else {
01947          pvt->newduration = duration;
01948          pvt->newdigit = digit;
01949       }
01950       res = 0;
01951    }
01952    ast_mutex_unlock(&pvt->lock);
01953    return res;
01954 }

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

Definition at line 273 of file chan_h323.c.

Referenced by __oh323_new().

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

static int reload ( void   )  [static]

Definition at line 3206 of file chan_h323.c.

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

03207 {
03208    if (!sched || !io) {
03209       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03210       return 0;
03211    }
03212    return h323_reload();
03213 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2913 of file chan_h323.c.

References aliasl, ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_str2cos(), ast_str2tos(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, ASTOBJ_UNREF, bindaddr, build_alias(), build_peer(), build_user(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, delete_aliases(), delete_users(), gen, GLOBAL_CAPABILITY, global_jbconf, hp, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, prune_peers(), update_common_options(), userl, and ast_variable::value.

Referenced by acl_change_event_cb(), do_monitor(), h323_do_reload(), handle_cli_iax2_reload(), handle_cli_misdn_reload(), load_module(), reload(), and sip_do_reload().

02914 {
02915    struct ast_config *cfg, *ucfg;
02916    struct ast_variable *v;
02917    struct oh323_peer *peer = NULL;
02918    struct oh323_user *user = NULL;
02919    struct oh323_alias *alias = NULL;
02920    struct ast_hostent ahp; struct hostent *hp;
02921    char *cat;
02922    const char *utype;
02923    int is_user, is_peer, is_alias;
02924    char _gatekeeper[100];
02925    int gk_discover, gk_disable, gk_changed;
02926    struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02927 
02928    cfg = ast_config_load(config, config_flags);
02929 
02930    /* We *must* have a config file otherwise stop immediately */
02931    if (!cfg) {
02932       ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
02933       return 1;
02934    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02935       ucfg = ast_config_load("users.conf", config_flags);
02936       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
02937          return 0;
02938       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
02939          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Aborting.\n");
02940          return 0;
02941       }
02942       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02943       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
02944          ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
02945          ast_config_destroy(ucfg);
02946          return 0;
02947       }
02948    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02949       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", config);
02950       return 0;
02951    } else {
02952       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
02953       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
02954          ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Aborting.\n");
02955          ast_config_destroy(cfg);
02956          return 0;
02957       }
02958    }
02959 
02960    if (is_reload) {
02961       delete_users();
02962       delete_aliases();
02963       prune_peers();
02964    }
02965 
02966    /* fire up the H.323 Endpoint */
02967    if (!h323_end_point_exist()) {
02968       h323_end_point_create();
02969    }
02970    ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02971    gk_discover = gatekeeper_discover;
02972    gk_disable = gatekeeper_disable;
02973    memset(&bindaddr, 0, sizeof(bindaddr));
02974    memset(&global_options, 0, sizeof(global_options));
02975    global_options.fastStart = 1;
02976    global_options.h245Tunneling = 1;
02977    global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
02978    global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
02979    global_options.dtmfmode = 0;
02980    global_options.holdHandling = 0;
02981    global_options.capability = GLOBAL_CAPABILITY;
02982    global_options.bridge = 1;    /* Do native bridging by default */
02983    global_options.autoframing = 0;
02984    strcpy(default_context, "default");
02985    h323_signalling_port = 1720;
02986    gatekeeper_disable = 1;
02987    gatekeeper_discover = 0;
02988    gkroute = 0;
02989    userbyalias = 1;
02990    acceptAnonymous = 1;
02991    tos = 0;
02992    cos = 0;
02993 
02994    /* Copy the default jb config over global_jbconf */
02995    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02996 
02997    if (ucfg) {
02998       struct ast_variable *gen;
02999       int genhas_h323;
03000       const char *has_h323;
03001 
03002       genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
03003       gen = ast_variable_browse(ucfg, "general");
03004       for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
03005          if (strcasecmp(cat, "general")) {
03006             has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
03007             if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
03008                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
03009                if (user) {
03010                   ASTOBJ_CONTAINER_LINK(&userl, user);
03011                   ASTOBJ_UNREF(user, oh323_destroy_user);
03012                }
03013                peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
03014                if (peer) {
03015                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
03016                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
03017                }
03018             }
03019          }
03020       }
03021       ast_config_destroy(ucfg);
03022    }
03023 
03024    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
03025       /* handle jb conf */
03026       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
03027          continue;
03028       /* Create the interface list */
03029       if (!strcasecmp(v->name, "port")) {
03030          h323_signalling_port = (int)strtol(v->value, NULL, 10);
03031       } else if (!strcasecmp(v->name, "bindaddr")) {
03032          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
03033             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
03034          } else {
03035             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
03036          }
03037       } else if (!strcasecmp(v->name, "tos")) { /* Needs to be removed in next release */
03038          ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n");
03039          if (ast_str2tos(v->value, &tos)) {
03040             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03041          }
03042       } else if (!strcasecmp(v->name, "tos_audio")) {
03043          if (ast_str2tos(v->value, &tos)) {
03044             ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03045          }
03046       } else if (!strcasecmp(v->name, "cos")) {
03047          ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n");
03048          if (ast_str2cos(v->value, &cos)) {
03049             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03050          }
03051       } else if (!strcasecmp(v->name, "cos_audio")) {
03052          if (ast_str2cos(v->value, &cos)) {
03053             ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);        
03054          }
03055       } else if (!strcasecmp(v->name, "gatekeeper")) {
03056          if (!strcasecmp(v->value, "DISABLE")) {
03057             gatekeeper_disable = 1;
03058          } else if (!strcasecmp(v->value, "DISCOVER")) {
03059             gatekeeper_disable = 0;
03060             gatekeeper_discover = 1;
03061          } else {
03062             gatekeeper_disable = 0;
03063             ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
03064          }
03065       } else if (!strcasecmp(v->name, "secret")) {
03066          ast_copy_string(secret, v->value, sizeof(secret));
03067       } else if (!strcasecmp(v->name, "AllowGKRouted")) {
03068          gkroute = ast_true(v->value);
03069       } else if (!strcasecmp(v->name, "context")) {
03070          ast_copy_string(default_context, v->value, sizeof(default_context));
03071          ast_verb(2, "Setting default context to %s\n", default_context);
03072       } else if (!strcasecmp(v->name, "UserByAlias")) {
03073          userbyalias = ast_true(v->value);
03074       } else if (!strcasecmp(v->name, "AcceptAnonymous")) {
03075          acceptAnonymous = ast_true(v->value);
03076       } else if (!update_common_options(v, &global_options)) {
03077          /* dummy */
03078       }
03079    }
03080    if (!global_options.dtmfmode)
03081       global_options.dtmfmode = H323_DTMF_RFC2833;
03082    if (global_options.holdHandling == ~0)
03083       global_options.holdHandling = 0;
03084    else if (!global_options.holdHandling)
03085       global_options.holdHandling = H323_HOLD_H450;
03086 
03087    for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
03088       if (strcasecmp(cat, "general")) {
03089          utype = ast_variable_retrieve(cfg, cat, "type");
03090          if (utype) {
03091             is_user = is_peer = is_alias = 0;
03092             if (!strcasecmp(utype, "user"))
03093                is_user = 1;
03094             else if (!strcasecmp(utype, "peer"))
03095                is_peer = 1;
03096             else if (!strcasecmp(utype, "friend"))
03097                is_user = is_peer = 1;
03098             else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
03099                is_alias = 1;
03100             else {
03101                ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
03102                continue;
03103             }
03104             if (is_user) {
03105                user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
03106                if (user) {
03107                   ASTOBJ_CONTAINER_LINK(&userl, user);
03108                   ASTOBJ_UNREF(user, oh323_destroy_user);
03109                }
03110             }
03111             if (is_peer) {
03112                peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
03113                if (peer) {
03114                   ASTOBJ_CONTAINER_LINK(&peerl, peer);
03115                   ASTOBJ_UNREF(peer, oh323_destroy_peer);
03116                }
03117             }
03118             if (is_alias) {
03119                alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
03120                if (alias) {
03121                   ASTOBJ_CONTAINER_LINK(&aliasl, alias);
03122                   ASTOBJ_UNREF(alias, oh323_destroy_alias);
03123                }
03124             }
03125          } else {
03126             ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
03127          }
03128       }
03129    }
03130    ast_config_destroy(cfg);
03131 
03132    /* Register our H.323 aliases if any*/
03133    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
03134    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
03135       ASTOBJ_RDLOCK(iterator);
03136       if (h323_set_alias(iterator)) {
03137          ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
03138          ASTOBJ_UNLOCK(iterator);
03139          continue;
03140       }
03141       ASTOBJ_UNLOCK(iterator);
03142    } while (0) );
03143    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
03144 
03145    /* Don't touch GK if nothing changed because URQ will drop all existing calls */
03146    gk_changed = 0;
03147    if (gatekeeper_disable != gk_disable)
03148       gk_changed = is_reload;
03149    else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
03150       gk_changed = is_reload;
03151    else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
03152       gk_changed = is_reload;
03153    if (gk_changed) {
03154       if(!gk_disable)
03155          h323_gk_urq();
03156       if (!gatekeeper_disable) {
03157          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03158             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03159             gatekeeper_disable = 1;
03160          }
03161       }
03162    }
03163    return 0;
03164 }

static void remote_hold ( unsigned  call_reference,
const char *  token,
int  is_hold 
) [static]

Definition at line 2584 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, ast_mutex_unlock, ast_queue_control(), find_call_locked(), oh323_pvt::lock, oh323_pvt::newcontrol, and oh323_pvt::owner.

Referenced by load_module().

02585 {
02586    struct oh323_pvt *pvt;
02587 
02588    if (h323debug)
02589       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02590 
02591    pvt = find_call_locked(call_reference, token);
02592    if (!pvt)
02593       return;
02594    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02595       if (is_hold)
02596          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02597       else
02598          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02599       ast_channel_unlock(pvt->owner);
02600    }
02601    else {
02602       if (is_hold)
02603          pvt->newcontrol = AST_CONTROL_HOLD;
02604       else
02605          pvt->newcontrol = AST_CONTROL_UNHOLD;
02606    }
02607    ast_mutex_unlock(&pvt->lock);
02608 }

static int restart_monitor ( void   )  [static]

Definition at line 2678 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, and monlock.

02679 {
02680    /* If we're supposed to be stopped -- stay stopped */
02681    if (ast_mutex_lock(&monlock)) {
02682       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02683       return -1;
02684    }
02685    if (monitor_thread == AST_PTHREADT_STOP) {
02686       ast_mutex_unlock(&monlock);
02687       return 0;
02688    }
02689    if (monitor_thread == pthread_self()) {
02690       ast_mutex_unlock(&monlock);
02691       ast_log(LOG_WARNING, "Cannot kill myself\n");
02692       return -1;
02693    }
02694    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02695       /* Wake up the thread */
02696       pthread_kill(monitor_thread, SIGURG);
02697    } else {
02698       /* Start a new monitor */
02699       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02700          monitor_thread = AST_PTHREADT_NULL;
02701          ast_mutex_unlock(&monlock);
02702          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02703          return -1;
02704       }
02705    }
02706    ast_mutex_unlock(&monlock);
02707    return 0;
02708 }

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

Definition at line 2499 of file chan_h323.c.

References ast_debug, ast_mutex_unlock, ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), oh323_pvt::dtmf_pt, find_call_locked(), oh323_pvt::lock, and oh323_pvt::rtp.

Referenced by load_module().

02500 {
02501    struct oh323_pvt *pvt;
02502 
02503    if (h323debug)
02504       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02505 
02506    pvt = find_call_locked(call_reference, token);
02507    if (!pvt) {
02508       return;
02509    }
02510    if (pvt->rtp) {
02511       ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
02512    }
02513    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02514    ast_mutex_unlock(&pvt->lock);
02515    if (h323debug)
02516       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02517 }

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

Definition at line 2554 of file chan_h323.c.

References ast_debug, ast_getformatname(), ast_mutex_unlock, dtmfmode, find_call_locked(), ast_codec_pref::formats, ast_codec_pref::framing, oh323_pvt::jointcapability, oh323_pvt::lock, oh323_pvt::options, ast_codec_pref::order, and oh323_pvt::pref_codec.

Referenced by load_module().

02555 {
02556    struct oh323_pvt *pvt;
02557    int capability, dtmfmode, pref_codec;
02558    struct ast_codec_pref prefs;
02559 
02560    if (h323debug)
02561       ast_debug(1, "Setting capabilities for connection %s\n", token);
02562 
02563    pvt = find_call_locked(call_reference, token);
02564    if (!pvt)
02565       return;
02566    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02567    dtmfmode = pvt->options.dtmfmode;
02568    prefs = pvt->options.prefs;
02569    pref_codec = pvt->pref_codec;
02570    ast_mutex_unlock(&pvt->lock);
02571    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02572 
02573    if (h323debug) {
02574       int i;
02575       for (i = 0; i < 32; i++) {
02576          if (!prefs.order[i])
02577             break;
02578          ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(&prefs.formats[i]) : "<none>"), prefs.framing[i]);
02579       }
02580       ast_debug(1, "Capabilities for connection %s is set\n", token);
02581    }
02582 }

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

Definition at line 2519 of file chan_h323.c.

References ast_debug, ast_getformatname(), ast_mutex_unlock, ast_rtp_codecs_packetization_set(), ast_rtp_instance_get_codecs(), find_call_locked(), ast_codec_pref::formats, ast_codec_pref::framing, oh323_pvt::jointcapability, oh323_pvt::lock, oh323_pvt::options, ast_codec_pref::order, oh323_pvt::peer_prefs, oh323_pvt::peercapability, and oh323_pvt::rtp.

Referenced by load_module().

02520 {
02521    struct oh323_pvt *pvt;
02522 
02523    if (h323debug)
02524       ast_debug(1, "Got remote capabilities from connection %s\n", token);
02525 
02526    pvt = find_call_locked(call_reference, token);
02527    if (!pvt)
02528       return;
02529    pvt->peercapability = capabilities;
02530    pvt->jointcapability = pvt->options.capability & capabilities;
02531    if (prefs) {
02532       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02533       if (h323debug) {
02534          int i;
02535          for (i = 0; i < 32; ++i) {
02536             if (!prefs->order[i])
02537                break;
02538             ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(&prefs->formats[i]) : "<none>"), prefs->framing[i]);
02539          }
02540       }
02541       if (pvt->rtp) {
02542          if (pvt->options.autoframing) {
02543             ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02544             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
02545          } else {
02546             ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02547             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
02548          }
02549       }
02550    }
02551    ast_mutex_unlock(&pvt->lock);
02552 }

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

References oh323_pvt::accountcode, oh323_pvt::amaflags, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), ast_verb, ASTOBJ_UNREF, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::context, oh323_pvt::exten, find_alias(), find_user(), oh323_pvt::jointcapability, LOG_ERROR, LOG_NOTICE, oh323_alloc(), oh323_destroy(), oh323_destroy_user(), and oh323_pvt::options.

Referenced by load_module().

02182 {
02183    struct oh323_pvt *pvt;
02184    struct oh323_user *user = NULL;
02185    struct oh323_alias *alias = NULL;
02186 
02187    if (h323debug)
02188       ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
02189 
02190    /* allocate the call*/
02191    pvt = oh323_alloc(cd->call_reference);
02192 
02193    if (!pvt) {
02194       ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02195       cleanup_call_details(cd);
02196       return NULL;
02197    }
02198 
02199    /* Populate the call details in the private structure */
02200    memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02201    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02202    pvt->jointcapability = pvt->options.capability;
02203 
02204    if (h323debug) {
02205       ast_verb(3, "Setting up Call\n");
02206       ast_verb(3, " \tCall token:  [%s]\n", pvt->cd.call_token);
02207       ast_verb(3, " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);
02208       ast_verb(3, " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
02209       ast_verb(3, " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
02210       ast_verb(3, " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
02211       if (pvt->cd.redirect_reason >= 0)
02212          ast_verb(3, " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02213       ast_verb(3, " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
02214    }
02215 
02216    /* Decide if we are allowing Gatekeeper routed calls*/
02217    if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02218       if (!ast_strlen_zero(cd->call_dest_e164)) {
02219          ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02220          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02221       } else {
02222          alias = find_alias(cd->call_dest_alias, 1);
02223          if (!alias) {
02224             ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02225             oh323_destroy(pvt);
02226             return NULL;
02227          }
02228          ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02229          ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02230       }
02231    } else {
02232       /* Either this call is not from the Gatekeeper
02233          or we are not allowing gk routed calls */
02234       user = find_user(cd, 1);
02235       if (!user) {
02236          if (!acceptAnonymous) {
02237             ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02238             oh323_destroy(pvt);
02239             return NULL;
02240          }
02241          if (ast_strlen_zero(default_context)) {
02242             ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02243             oh323_destroy(pvt);
02244             return NULL;
02245          }
02246          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02247          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02248             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02249          } else {
02250             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02251          }
02252          if (h323debug)
02253             ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02254       } else {
02255          if (user->host) {
02256             if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02257                if (ast_strlen_zero(user->context)) {
02258                   if (ast_strlen_zero(default_context)) {
02259                      ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02260                      oh323_destroy(pvt);
02261                      ASTOBJ_UNREF(user, oh323_destroy_user);
02262                      return NULL;
02263                   }
02264                   ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02265                } else {
02266                   ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02267                }
02268                pvt->exten[0] = 'i';
02269                pvt->exten[1] = '\0';
02270                ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02271                oh323_destroy(pvt);
02272                ASTOBJ_UNREF(user, oh323_destroy_user);
02273                return NULL;   /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
02274             }
02275          }
02276          ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02277          memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02278          pvt->jointcapability = pvt->options.capability;
02279          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02280             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02281          } else {
02282             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02283          }
02284          if (!ast_strlen_zero(user->accountcode)) {
02285             ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02286          }
02287          if (user->amaflags) {
02288             pvt->amaflags = user->amaflags;
02289          }
02290          ASTOBJ_UNREF(user, oh323_destroy_user);
02291       }
02292    }
02293    return &pvt->options;
02294 }

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

References cleanup_call_details().

Referenced by load_module().

02381 {
02382    /* Use argument here or free it immediately */
02383    cleanup_call_details(cd);
02384 
02385    return 1;
02386 }

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

References __oh323_rtp_create(), oh323_pvt::alreadygone, ast_channel_nativeformats(), ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_debug, ast_format_cap_alloc_nolock(), ast_format_cap_copy(), ast_format_cap_destroy(), ast_format_cap_from_old_bitfield(), ast_format_cap_identical(), AST_FORMAT_G726_AAL2, ast_format_to_old_bitfield(), ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_unlock, ast_queue_control(), ast_rtp_codecs_payload_lookup(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_rtp_instance_stop(), AST_RTP_OPT_G726_NONSTANDARD, ast_set_read_format(), ast_set_write_format(), ast_sockaddr_from_sin, ast_rtp_payload_type::asterisk_format, find_call_locked(), ast_rtp_payload_type::format, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, 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().

02008 {
02009    struct oh323_pvt *pvt;
02010    struct sockaddr_in them;
02011    int nativeformats_changed;
02012    enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
02013 
02014    if (h323debug)
02015       ast_debug(1, "Setting up RTP connection for %s\n", token);
02016 
02017    /* Find the call or allocate a private structure if call not found */
02018    pvt = find_call_locked(call_reference, token);
02019    if (!pvt) {
02020       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
02021       return;
02022    }
02023    if (pvt->alreadygone) {
02024       ast_mutex_unlock(&pvt->lock);
02025       return;
02026    }
02027 
02028    if (!pvt->rtp)
02029       __oh323_rtp_create(pvt);
02030 
02031    if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
02032       ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
02033    }
02034 
02035    them.sin_family = AF_INET;
02036    /* only works for IPv4 */
02037    them.sin_addr.s_addr = inet_addr(remoteIp);
02038    them.sin_port = htons(remotePort);
02039 
02040    if (them.sin_addr.s_addr) {
02041       {
02042          struct ast_sockaddr tmp;
02043 
02044          ast_sockaddr_from_sin(&tmp, &them);
02045          ast_rtp_instance_set_remote_address(pvt->rtp, &tmp);
02046       }
02047       if (pvt->recvonly) {
02048          pvt->recvonly = 0;
02049          rtp_change = NEED_UNHOLD;
02050       }
02051    } else {
02052       ast_rtp_instance_stop(pvt->rtp);
02053       if (!pvt->recvonly) {
02054          pvt->recvonly = 1;
02055          rtp_change = NEED_HOLD;
02056       }
02057    }
02058 
02059    /* Change native format to reflect information taken from OLC/OLCAck */
02060    nativeformats_changed = 0;
02061    if (pt != 128 && pvt->rtp) {  /* Payload type is invalid, so try to use previously decided */
02062       struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
02063       if (rtptype.asterisk_format) {
02064          if (pvt->nativeformats != ast_format_to_old_bitfield(&rtptype.format)) {
02065             pvt->nativeformats = ast_format_to_old_bitfield(&rtptype.format);
02066             nativeformats_changed = 1;
02067          }
02068       }
02069    } else if (h323debug)
02070       ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
02071 
02072    /* Don't try to lock the channel if nothing changed */
02073    if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
02074       if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02075          struct ast_format_cap *pvt_native = ast_format_cap_alloc_nolock();
02076          ast_format_cap_from_old_bitfield(pvt_native, pvt->nativeformats);
02077 
02078          /* Re-build translation path only if native format(s) has been changed */
02079          if (!(ast_format_cap_identical(ast_channel_nativeformats(pvt->owner), pvt_native))) {
02080             if (h323debug) {
02081                char tmp[256], tmp2[256];
02082                ast_debug(1, "Native format changed to '%s' from '%s', read format is %s, write format is %s\n", ast_getformatname_multiple(tmp, sizeof(tmp), pvt_native), ast_getformatname_multiple(tmp2, sizeof(tmp2), ast_channel_nativeformats(pvt->owner)), ast_getformatname(&pvt->owner->readformat), ast_getformatname(&pvt->owner->writeformat));
02083             }
02084             ast_format_cap_copy(ast_channel_nativeformats(pvt->owner), pvt_native);
02085             ast_set_read_format(pvt->owner, &pvt->owner->readformat);
02086             ast_set_write_format(pvt->owner, &pvt->owner->writeformat);
02087          }
02088          if (pvt->options.progress_audio)
02089             ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
02090          switch (rtp_change) {
02091          case NEED_HOLD:
02092             ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02093             break;
02094          case NEED_UNHOLD:
02095             ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02096             break;
02097          default:
02098             break;
02099          }
02100          ast_channel_unlock(pvt->owner);
02101          pvt_native = ast_format_cap_destroy(pvt_native);
02102       }
02103       else {
02104          if (pvt->options.progress_audio)
02105             pvt->newcontrol = AST_CONTROL_PROGRESS;
02106          else if (rtp_change == NEED_HOLD)
02107             pvt->newcontrol = AST_CONTROL_HOLD;
02108          else if (rtp_change == NEED_UNHOLD)
02109             pvt->newcontrol = AST_CONTROL_UNHOLD;
02110          if (h323debug)
02111             ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
02112       }
02113    }
02114    ast_mutex_unlock(&pvt->lock);
02115 
02116    if (h323debug)
02117       ast_debug(1, "RTP connection prepared for %s\n", token);
02118 
02119    return;
02120 }

static int unload_module ( void   )  [static]

Definition at line 3418 of file chan_h323.c.

References aliasl, ast_channel_unregister(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_format_cap_destroy(), ast_free, ast_log(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_glue_unregister(), ast_sched_context_destroy(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ast_channel_tech::capabilities, iflist, iflock, io_context_destroy(), oh323_pvt::lock, LOG_WARNING, monlock, oh323_pvt::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_pvt::owner, peerl, and userl.

03419 {
03420    struct oh323_pvt *p, *pl;
03421 
03422    /* unregister commands */
03423    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03424    ast_cli_unregister(&cli_h323_reload);
03425 
03426    ast_channel_unregister(&oh323_tech);
03427    ast_rtp_glue_unregister(&oh323_rtp_glue);
03428 
03429    if (!ast_mutex_lock(&iflock)) {
03430       /* hangup all interfaces if they have an owner */
03431       p = iflist;
03432       while(p) {
03433          if (p->owner) {
03434             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03435          }
03436          p = p->next;
03437       }
03438       iflist = NULL;
03439       ast_mutex_unlock(&iflock);
03440    } else {
03441       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03442       return -1;
03443    }
03444    if (!ast_mutex_lock(&monlock)) {
03445       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03446          if (monitor_thread != pthread_self()) {
03447             pthread_cancel(monitor_thread);
03448          }
03449          pthread_kill(monitor_thread, SIGURG);
03450          pthread_join(monitor_thread, NULL);
03451       }
03452       monitor_thread = AST_PTHREADT_STOP;
03453       ast_mutex_unlock(&monlock);
03454    } else {
03455       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03456       return -1;
03457    }
03458    if (!ast_mutex_lock(&iflock)) {
03459       /* destroy all the interfaces and free their memory */
03460       p = iflist;
03461       while(p) {
03462          pl = p;
03463          p = p->next;
03464          /* free associated memory */
03465          ast_mutex_destroy(&pl->lock);
03466          ast_free(pl);
03467       }
03468       iflist = NULL;
03469       ast_mutex_unlock(&iflock);
03470    } else {
03471       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03472       return -1;
03473    }
03474    if (!gatekeeper_disable)
03475       h323_gk_urq();
03476    h323_end_process();
03477    if (io)
03478       io_context_destroy(io);
03479    if (sched)
03480       ast_sched_context_destroy(sched);
03481 
03482    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03483    ASTOBJ_CONTAINER_DESTROY(&userl);
03484    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03485    ASTOBJ_CONTAINER_DESTROY(&peerl);
03486    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03487    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03488 
03489    oh323_tech.capabilities = ast_format_cap_destroy(oh323_tech.capabilities);
03490    return 0;
03491 }

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

Definition at line 1308 of file chan_h323.c.

References ast_callerid_split(), ast_copy_string(), ast_log(), ast_strdupa, ast_true(), h323_parse_allow_disallow(), ast_variable::lineno, LOG_NOTICE, LOG_WARNING, ast_variable::name, and ast_variable::value.

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

01309 {
01310    int tmp = 0;
01311    char *val, *opt;
01312 
01313    if (!strcasecmp(v->name, "allow")) {
01314       h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
01315    } else if (!strcasecmp(v->name, "autoframing")) {
01316       options->autoframing = ast_true(v->value);
01317    } else if (!strcasecmp(v->name, "disallow")) {
01318       h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
01319    } else if (!strcasecmp(v->name, "dtmfmode")) {
01320       val = ast_strdupa(v->value);
01321       if ((opt = strchr(val, ':')) != (char *)NULL) {
01322          *opt++ = '\0';
01323          tmp = atoi(opt);
01324       }
01325       if (!strcasecmp(v->value, "inband")) {
01326          options->dtmfmode |= H323_DTMF_INBAND;
01327       } else if (!strcasecmp(val, "rfc2833")) {
01328          options->dtmfmode |= H323_DTMF_RFC2833;
01329          if (!opt) {
01330             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01331          } else if ((tmp >= 96) && (tmp < 128)) {
01332             options->dtmfcodec[0] = tmp;
01333          } else {
01334             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01335             ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]);
01336          }
01337       } else if (!strcasecmp(val, "cisco")) {
01338          options->dtmfmode |= H323_DTMF_CISCO;
01339          if (!opt) {
01340             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01341          } else if ((tmp >= 96) && (tmp < 128)) {
01342             options->dtmfcodec[1] = tmp;
01343          } else {
01344             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01345             ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]);
01346          }
01347       } else if (!strcasecmp(v->value, "h245-signal")) {
01348          options->dtmfmode |= H323_DTMF_SIGNAL;
01349       } else {
01350          ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno);
01351       }
01352    } else if (!strcasecmp(v->name, "dtmfcodec")) {
01353       ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno);
01354       tmp = atoi(v->value);
01355       if (tmp < 96)
01356          ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
01357       else
01358          options->dtmfcodec[0] = tmp;
01359    } else if (!strcasecmp(v->name, "bridge")) {
01360       options->bridge = ast_true(v->value);
01361    } else if (!strcasecmp(v->name, "nat")) {
01362       options->nat = ast_true(v->value);
01363    } else if (!strcasecmp(v->name, "fastStart")) {
01364       options->fastStart = ast_true(v->value);
01365    } else if (!strcasecmp(v->name, "h245Tunneling")) {
01366       options->h245Tunneling = ast_true(v->value);
01367    } else if (!strcasecmp(v->name, "silenceSuppression")) {
01368       options->silenceSuppression = ast_true(v->value);
01369    } else if (!strcasecmp(v->name, "progress_setup")) {
01370       tmp = atoi(v->value);
01371       if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
01372          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01373          tmp = 0;
01374       }
01375       options->progress_setup = tmp;
01376    } else if (!strcasecmp(v->name, "progress_alert")) {
01377       tmp = atoi(v->value);
01378       if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
01379          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01380          tmp = 0;
01381       }
01382       options->progress_alert = tmp;
01383    } else if (!strcasecmp(v->name, "progress_audio")) {
01384       options->progress_audio = ast_true(v->value);
01385    } else if (!strcasecmp(v->name, "callerid")) {
01386       ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
01387    } else if (!strcasecmp(v->name, "fullname")) {
01388       ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
01389    } else if (!strcasecmp(v->name, "cid_number")) {
01390       ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
01391    } else if (!strcasecmp(v->name, "tunneling")) {
01392       if (!strcasecmp(v->value, "none"))
01393          options->tunnelOptions = 0;
01394       else if (!strcasecmp(v->value, "cisco"))
01395          options->tunnelOptions |= H323_TUNNEL_CISCO;
01396       else if (!strcasecmp(v->value, "qsig"))
01397          options->tunnelOptions |= H323_TUNNEL_QSIG;
01398       else
01399          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01400    } else if (!strcasecmp(v->name, "hold")) {
01401       if (!strcasecmp(v->value, "none"))
01402          options->holdHandling = ~0;
01403       else if (!strcasecmp(v->value, "notify"))
01404          options->holdHandling |= H323_HOLD_NOTIFY;
01405       else if (!strcasecmp(v->value, "q931only"))
01406          options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY;
01407       else if (!strcasecmp(v->value, "h450"))
01408          options->holdHandling |= H323_HOLD_H450;
01409       else
01410          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01411    } else
01412       return 1;
01413 
01414    return 0;
01415 }

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

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

01212 {
01213    if (!pvt)
01214       return 0;
01215    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01216       if (state >= 0)
01217          ast_setstate(pvt->owner, state);
01218       if (signal >= 0)
01219          ast_queue_control(pvt->owner, signal);
01220       ast_channel_unlock(pvt->owner);
01221       return 1;
01222    }
01223    else {
01224       if (state >= 0)
01225          pvt->newstate = state;
01226       if (signal >= 0)
01227          pvt->newcontrol = signal;
01228       return 0;
01229    }
01230 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 3498 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 153 of file chan_h323.c.

struct h323_alias_list aliasl [static]

Definition at line 3498 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 135 of file chan_h323.c.

ast_mutex_t caplock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.

Definition at line 229 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2854 of file chan_h323.c.

struct ast_cli_entry cli_h323_reload [static]

Initial value:

   AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration")

Definition at line 3215 of file chan_h323.c.

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

Definition at line 133 of file chan_h323.c.

unsigned int cos = 0 [static]

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

Definition at line 134 of file chan_h323.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

Note:
Values shown here match the defaults shown in h323.conf.sample

Definition at line 121 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 147 of file chan_h323.c.

int gatekeeper_disable = 1 [static]

Definition at line 148 of file chan_h323.c.

int gatekeeper_discover = 0 [static]

Definition at line 149 of file chan_h323.c.

int gkroute = 0 [static]

Definition at line 150 of file chan_h323.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 129 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 159 of file chan_h323.c.

ast_mutex_t h323_reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Protect the reload process.

Definition at line 232 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 233 of file chan_h323.c.

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 146 of file chan_h323.c.

int h323debug

global debug flag

Definition at line 117 of file chan_h323.c.

struct oh323_pvt * iflist [static]

Private structure of a OpenH323 channel.

ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Protect the interface list (oh323_pvt)

Definition at line 222 of file chan_h323.c.

struct io_context* io [static]

Definition at line 220 of file chan_h323.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 237 of file chan_h323.c.

ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.

Definition at line 226 of file chan_h323.c.

struct ast_rtp_glue oh323_rtp_glue [static]

Initial value:

 {
   .type = "H323",
   .get_rtp_info = oh323_get_rtp_peer,
   .update_peer = oh323_set_rtp_peer,
}

Definition at line 3304 of file chan_h323.c.

struct ast_channel_tech oh323_tech [static]

Definition at line 256 of file chan_h323.c.

answer_call_cb on_answer_call

Definition at line 109 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 106 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 108 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 107 of file chan_h323.c.

Definition at line 102 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 112 of file chan_h323.c.

onhold_cb on_hold

Definition at line 115 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 104 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 105 of file chan_h323.c.

progress_cb on_progress

Definition at line 110 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 101 of file chan_h323.c.

Definition at line 111 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 113 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 114 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 103 of file chan_h323.c.

struct h323_peer_list peerl [static]

struct ast_sched_context* sched [static]

Definition at line 219 of file chan_h323.c.

char secret[50] [static]

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

Variables required by Asterisk

Definition at line 132 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 154 of file chan_h323.c.

unsigned int unique = 0 [static]

Definition at line 157 of file chan_h323.c.

int userbyalias = 1 [static]

Definition at line 152 of file chan_h323.c.

struct h323_user_list userl [static]


Generated on Thu Oct 11 06:35:05 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6