Wed Apr 6 11:29:56 2011

Asterisk developer's documentation


chan_h323.c File Reference

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

#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <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 "h323/chan_h323.h"

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   (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261)

Functions

static void __oh323_destroy (struct oh323_pvt *pvt)
static struct ast_channel__oh323_new (struct oh323_pvt *pvt, int state, const char *host, 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 char * convertcap (format_t cap)
static int create_addr (struct oh323_pvt *pvt, char *opeer)
static void delete_aliases (void)
static void delete_users (void)
static void * do_monitor (void *data)
static struct rtp_info * external_rtp_create (unsigned call_reference, const char *token)
 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_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, 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, format_t format, const struct ast_channel *requestor, void *data, 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, format_t 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
 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 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
ExtRef:
OpenH323 http://www.voxgratia.org/

Definition in file chan_h323.c.


Define Documentation

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

Definition at line 132 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 443 of file chan_h323.c.

References ast_channel_lock, 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, ast_channel::name, oh323_pvt::next, dahdi_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, sched, ast_channel::tech_pvt, and oh323_pvt::vad.

Referenced by do_monitor(), and oh323_destroy().

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

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

Private structure should be locked on a call.

Definition at line 1010 of file chan_h323.c.

References __oh323_rtp_create(), accountcode, oh323_pvt::accountcode, ast_channel::amaflags, oh323_pvt::amaflags, ast_party_caller::ani, ast_best_codec(), ast_channel_alloc, ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), ast_rtp_instance_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_udptl_fd(), ast_channel::caller, oh323_pvt::cd, cid_name, cid_num, ast_channel::context, oh323_pvt::context, ast_channel::dialed, DSP_FEATURE_DIGIT_DETECT, ast_channel::exten, 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_channel::nativeformats, ast_party_dialed::number, ast_party_id::number, oh323_tech, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_party_number::plan, ast_party_number::presentation, ast_party_name::presentation, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::redirecting, redirectingreason2str(), ast_channel::rings, oh323_pvt::rtp, ast_party_dialed::str, ast_party_number::str, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, ast_party_number::valid, and ast_channel::writeformat.

Referenced by answer_call(), and oh323_request().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 957 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, 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, sched, and oh323_pvt::update_rtp_info.

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

00958 {
00959    struct ast_sockaddr our_addr;
00960 
00961    if (pvt->rtp)
00962       return 0;
00963 
00964    {
00965       struct ast_sockaddr tmp;
00966 
00967       ast_sockaddr_from_sin(&tmp, &bindaddr);
00968       if (ast_find_ourip(&our_addr, &tmp, AF_INET)) {
00969          ast_mutex_unlock(&pvt->lock);
00970          ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00971          return -1;
00972       }
00973    }
00974    pvt->rtp = ast_rtp_instance_new("asterisk", sched, &our_addr, NULL);
00975    if (!pvt->rtp) {
00976       ast_mutex_unlock(&pvt->lock);
00977       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00978       return -1;
00979    }
00980    if (h323debug)
00981       ast_debug(1, "Created RTP channel\n");
00982 
00983    ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP");
00984 
00985    if (h323debug)
00986       ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
00987    ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
00988 
00989    if (pvt->dtmf_pt[0] > 0)
00990       ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
00991    if (pvt->dtmf_pt[1] > 0)
00992       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);
00993 
00994    if (pvt->peercapability)
00995       ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
00996 
00997    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
00998       ast_jb_configure(pvt->owner, &global_jbconf);
00999       ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
01000       ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
01001       ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
01002       ast_channel_unlock(pvt->owner);
01003    } else
01004       pvt->update_rtp_info = 1;
01005 
01006    return 0;
01007 }

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

References ast_channel::_softhangup, ast_channel_set_fd(), ast_debug, 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, f, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DTMF, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, sched, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

static void __reg_module ( void   )  [static]

Definition at line 3441 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

Definition at line 3441 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 2257 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(), h323debug, oh323_pvt::lock, LOG_ERROR, and LOG_NOTICE.

Referenced by load_module().

02258 {
02259    struct oh323_pvt *pvt;
02260    struct ast_channel *c = NULL;
02261    enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02262    char tmp_exten[sizeof(pvt->exten)];
02263 
02264    if (h323debug)
02265       ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
02266 
02267    /* Find the call or allocate a private structure if call not found */
02268    pvt = find_call_locked(call_reference, token);
02269    if (!pvt) {
02270       ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02271       return 0;
02272    }
02273    /* Check if requested extension@context pair exists in the dialplan */
02274    ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02275 
02276    /* Try to find best extension in specified context */
02277    if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02278       if (tmp_exten[0] == 's')
02279          try_exten = ext_s;
02280       else if (tmp_exten[0] == 'i')
02281          try_exten = ext_i;
02282       else
02283          try_exten = ext_original;
02284    } else
02285       try_exten = ext_original;
02286    do {
02287       if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02288          break;
02289       switch (try_exten) {
02290       case ext_original:
02291          tmp_exten[0] = 's';
02292          tmp_exten[1] = '\0';
02293          try_exten = ext_s;
02294          break;
02295       case ext_s:
02296          tmp_exten[0] = 'i';
02297          try_exten = ext_i;
02298          break;
02299       case ext_i:
02300          try_exten = ext_notexists;
02301          break;
02302       default:
02303          break;
02304       }
02305    } while (try_exten != ext_notexists);
02306 
02307    /* Drop the call if we don't have <exten>, s and i extensions */
02308    if (try_exten == ext_notexists) {
02309       ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02310       ast_mutex_unlock(&pvt->lock);
02311       h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02312       return 0;
02313    } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02314       if (h323debug)
02315          ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02316       ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02317    }
02318 
02319    /* allocate a channel and tell asterisk about it */
02320    c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL);
02321 
02322    /* And release when done */
02323    ast_mutex_unlock(&pvt->lock);
02324    if (!c) {
02325       ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02326       return 0;
02327    }
02328    return 1;
02329 }

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

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

01208 {
01209    struct oh323_alias *alias;
01210    int found = 0;
01211 
01212    alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
01213 
01214    if (alias)
01215       found++;
01216    else {
01217       if (!(alias = ast_calloc(1, sizeof(*alias))))
01218          return NULL;
01219       ASTOBJ_INIT(alias);
01220    }
01221    if (!found && name)
01222       ast_copy_string(alias->name, name, sizeof(alias->name));
01223    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01224       if (!strcasecmp(v->name, "e164")) {
01225          ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
01226       } else if (!strcasecmp(v->name, "prefix")) {
01227          ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
01228       } else if (!strcasecmp(v->name, "context")) {
01229          ast_copy_string(alias->context, v->value, sizeof(alias->context));
01230       } else if (!strcasecmp(v->name, "secret")) {
01231          ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
01232       } else {
01233          if (strcasecmp(v->value, "h323")) {
01234             ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
01235          }
01236       }
01237    }
01238    ASTOBJ_UNMARK(alias);
01239    return alias;
01240 }

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

Definition at line 1499 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, global_options, h323_signalling_port, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, oh323_destroy_peer(), peerl, update_common_options(), and ast_variable::value.

Referenced by reload_config(), and set_config().

01500 {
01501    struct oh323_peer *peer;
01502    struct ast_ha *oldha;
01503    int found = 0;
01504 
01505    peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01506 
01507    if (peer)
01508       found++;
01509    else {
01510       if (!(peer = ast_calloc(1, sizeof(*peer))))
01511          return NULL;
01512       ASTOBJ_INIT(peer);
01513    }
01514    oldha = peer->ha;
01515    peer->ha = NULL;
01516    memcpy(&peer->options, &global_options, sizeof(peer->options));
01517    peer->options.dtmfmode = 0;
01518    peer->options.holdHandling = 0;
01519    peer->addr.sin_port = htons(h323_signalling_port);
01520    peer->addr.sin_family = AF_INET;
01521    if (!found && name)
01522       ast_copy_string(peer->name, name, sizeof(peer->name));
01523 
01524 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01525    if (peer->chanvars) {
01526       ast_variables_destroy(peer->chanvars);
01527       peer->chanvars = NULL;
01528    }
01529 #endif
01530    /* Default settings for mailbox */
01531    peer->mailbox[0] = '\0';
01532 
01533    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01534       if (!update_common_options(v, &peer->options))
01535          continue;
01536       if (!strcasecmp(v->name, "host")) {
01537          if (!strcasecmp(v->value, "dynamic")) {
01538             ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01539             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01540             return NULL;
01541          }
01542          {
01543             struct ast_sockaddr tmp;
01544 
01545             if (ast_get_ip(&tmp, v->value)) {
01546                ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01547                ASTOBJ_UNREF(peer, oh323_destroy_peer);
01548                return NULL;
01549             }
01550             ast_sockaddr_to_sin(&tmp, &peer->addr);
01551          }
01552       } else if (!strcasecmp(v->name, "port")) {
01553          peer->addr.sin_port = htons(atoi(v->value));
01554       } else if (!strcasecmp(v->name, "permit") ||
01555                !strcasecmp(v->name, "deny")) {
01556          int ha_error = 0;
01557 
01558          peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
01559          if (ha_error)
01560             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01561       } else if (!strcasecmp(v->name, "mailbox")) {
01562          ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01563       } else if (!strcasecmp(v->name, "hasvoicemail")) {
01564          if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01565             ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01566          }
01567       }
01568    }
01569    if (!peer->options.dtmfmode)
01570       peer->options.dtmfmode = global_options.dtmfmode;
01571    if (peer->options.holdHandling == ~0)
01572       peer->options.holdHandling = 0;
01573    else if (!peer->options.holdHandling)
01574       peer->options.holdHandling = global_options.holdHandling;
01575    ASTOBJ_UNMARK(peer);
01576    ast_free_ha(oldha);
01577    return peer;
01578 }

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

Definition at line 1376 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, default_context, format, global_options, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_user(), update_common_options(), userl, and ast_variable::value.

Referenced by reload_config(), and set_config().

01377 {
01378    struct oh323_user *user;
01379    struct ast_ha *oldha;
01380    int found = 0;
01381    int format;
01382 
01383    user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
01384 
01385    if (user)
01386       found++;
01387    else {
01388       if (!(user = ast_calloc(1, sizeof(*user))))
01389          return NULL;
01390       ASTOBJ_INIT(user);
01391    }
01392    oldha = user->ha;
01393    user->ha = (struct ast_ha *)NULL;
01394    memcpy(&user->options, &global_options, sizeof(user->options));
01395    user->options.dtmfmode = 0;
01396    user->options.holdHandling = 0;
01397    /* Set default context */
01398    ast_copy_string(user->context, default_context, sizeof(user->context));
01399    if (user && !found)
01400       ast_copy_string(user->name, name, sizeof(user->name));
01401 
01402 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01403    if (user->chanvars) {
01404       ast_variables_destroy(user->chanvars);
01405       user->chanvars = NULL;
01406    }
01407 #endif
01408 
01409    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01410       if (!update_common_options(v, &user->options))
01411          continue;
01412       if (!strcasecmp(v->name, "context")) {
01413          ast_copy_string(user->context, v->value, sizeof(user->context));
01414       } else if (!strcasecmp(v->name, "secret")) {
01415          ast_copy_string(user->secret, v->value, sizeof(user->secret));
01416       } else if (!strcasecmp(v->name, "accountcode")) {
01417          ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
01418       } else if (!strcasecmp(v->name, "host")) {
01419          if (!strcasecmp(v->value, "dynamic")) {
01420             ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
01421             ASTOBJ_UNREF(user, oh323_destroy_user);
01422             return NULL;
01423          } else {
01424             struct ast_sockaddr tmp;
01425 
01426             if (ast_get_ip(&tmp, v->value)) {
01427                ASTOBJ_UNREF(user, oh323_destroy_user);
01428                return NULL;
01429             }
01430             ast_sockaddr_to_sin(&tmp, &user->addr);
01431          }
01432          /* Let us know we need to use ip authentication */
01433          user->host = 1;
01434       } else if (!strcasecmp(v->name, "amaflags")) {
01435          format = ast_cdr_amaflags2int(v->value);
01436          if (format < 0) {
01437             ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
01438          } else {
01439             user->amaflags = format;
01440          }
01441       } else if (!strcasecmp(v->name, "permit") ||
01442                !strcasecmp(v->name, "deny")) {
01443          int ha_error = 0;
01444 
01445          user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error);
01446          if (ha_error)
01447             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01448       }
01449    }
01450    if (!user->options.dtmfmode)
01451       user->options.dtmfmode = global_options.dtmfmode;
01452    if (user->options.holdHandling == ~0)
01453       user->options.holdHandling = 0;
01454    else if (!user->options.holdHandling)
01455       user->options.holdHandling = global_options.holdHandling;
01456    ASTOBJ_UNMARK(user);
01457    ast_free_ha(oldha);
01458    return user;
01459 }

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

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

Referenced by load_module().

02349 {
02350    struct oh323_pvt *pvt;
02351 
02352    if (h323debug)
02353       ast_debug(1, "Ringing on %s\n", token);
02354 
02355    pvt = find_call_locked(call_reference, token);
02356    if (!pvt) {
02357       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02358       return;
02359    }
02360    if (!pvt->owner) {
02361       ast_mutex_unlock(&pvt->lock);
02362       ast_log(LOG_ERROR, "Channel has no owner\n");
02363       return;
02364    }
02365    update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02366    ast_mutex_unlock(&pvt->lock);
02367    return;
02368 }

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 407 of file chan_h323.c.

References ast_free.

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

00408 {
00409    if (cd->call_token) {
00410       ast_free(cd->call_token);
00411       cd->call_token = NULL;
00412    }
00413    if (cd->call_source_aliases) {
00414       ast_free(cd->call_source_aliases);
00415       cd->call_source_aliases = NULL;
00416    }
00417    if (cd->call_dest_alias) {
00418       ast_free(cd->call_dest_alias);
00419       cd->call_dest_alias = NULL;
00420    }
00421    if (cd->call_source_name) {
00422       ast_free(cd->call_source_name);
00423       cd->call_source_name = NULL;
00424    }
00425    if (cd->call_source_e164) {
00426       ast_free(cd->call_source_e164);
00427       cd->call_source_e164 = NULL;
00428    }
00429    if (cd->call_dest_e164) {
00430       ast_free(cd->call_dest_e164);
00431       cd->call_dest_e164 = NULL;
00432    }
00433    if (cd->sourceIp) {
00434       ast_free(cd->sourceIp);
00435       cd->sourceIp = NULL;
00436    }
00437    if (cd->redirect_number) {
00438       ast_free(cd->redirect_number);
00439       cd->redirect_number = NULL;
00440    }
00441 }

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

Call-back function to cleanup communication Returns nothing,.

Definition at line 2374 of file chan_h323.c.

References ast_channel::_softhangup, oh323_pvt::alreadygone, 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(), h323debug, oh323_pvt::lock, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.

Referenced by load_module().

02375 {
02376    struct oh323_pvt *pvt;
02377 
02378    if (h323debug)
02379       ast_debug(1, "Cleaning connection to %s\n", call_token);
02380 
02381    while (1) {
02382       pvt = find_call_locked(call_reference, call_token);
02383       if (!pvt) {
02384          if (h323debug)
02385             ast_debug(1, "No connection for %s\n", call_token);
02386          return;
02387       }
02388       if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02389          break;
02390 #if 1
02391       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02392 #ifdef DEBUG_THREADS
02393       /* XXX to be completed
02394        * If we want to print more info on who is holding the lock,
02395        * implement the relevant code in lock.h and use the routines
02396        * supplied there.
02397        */
02398 #endif
02399 #endif
02400       ast_mutex_unlock(&pvt->lock);
02401       usleep(1);
02402    }
02403    if (pvt->rtp) {
02404       /* Immediately stop RTP */
02405       ast_rtp_instance_destroy(pvt->rtp);
02406       pvt->rtp = NULL;
02407    }
02408    /* Free dsp used for in-band DTMF detection */
02409    if (pvt->vad) {
02410       ast_dsp_free(pvt->vad);
02411       pvt->vad = NULL;
02412    }
02413    cleanup_call_details(&pvt->cd);
02414    pvt->alreadygone = 1;
02415    /* Send hangup */
02416    if (pvt->owner) {
02417       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02418       ast_queue_hangup(pvt->owner);
02419       ast_channel_unlock(pvt->owner);
02420    }
02421    ast_mutex_unlock(&pvt->lock);
02422    if (h323debug)
02423       ast_debug(1, "Connection to %s cleaned\n", call_token);
02424    return;
02425 }

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

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

Referenced by load_module().

02083 {
02084    struct oh323_pvt *pvt;
02085 
02086    if (h323debug)
02087       ast_debug(1, "Call %s answered\n", token);
02088 
02089    pvt = find_call_locked(call_reference, token);
02090    if (!pvt) {
02091       ast_log(LOG_ERROR, "Something is wrong: connection\n");
02092       return;
02093    }
02094 
02095    /* Inform asterisk about remote party connected only on outgoing calls */
02096    if (!pvt->outgoing) {
02097       ast_mutex_unlock(&pvt->lock);
02098       return;
02099    }
02100    /* Do not send ANSWER message more than once */
02101    if (!pvt->connection_established) {
02102       pvt->connection_established = 1;
02103       update_state(pvt, -1, AST_CONTROL_ANSWER);
02104    }
02105    ast_mutex_unlock(&pvt->lock);
02106    return;
02107 }

static char* convertcap ( format_t  cap  )  [static]

Definition at line 3194 of file chan_h323.c.

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

Referenced by oh323_set_rtp_peer().

03195 {
03196    switch (cap) {
03197    case AST_FORMAT_G723_1:
03198       return "G.723";
03199    case AST_FORMAT_GSM:
03200       return "GSM";
03201    case AST_FORMAT_ULAW:
03202       return "ULAW";
03203    case AST_FORMAT_ALAW:
03204       return "ALAW";
03205    case AST_FORMAT_G722:
03206       return "G.722";
03207    case AST_FORMAT_ADPCM:
03208       return "G.728";
03209    case AST_FORMAT_G729A:
03210       return "G.729";
03211    case AST_FORMAT_SPEEX:
03212       return "SPEEX";
03213    case AST_FORMAT_ILBC:
03214       return "ILBC";
03215    default:
03216       ast_log(LOG_NOTICE, "Don't know how to deal with mode %" PRId64 "\n", cap);
03217       return NULL;
03218    }
03219 }

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

Definition at line 1676 of file chan_h323.c.

References ahp, ast_copy_string(), ast_gethostbyname(), ast_log(), AST_RTP_DTMF, ASTOBJ_UNREF, find_peer(), global_options, h323_signalling_port, hp, oh323_pvt::jointcapability, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_destroy_peer(), oh323_pvt::options, 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_request_call(), transmit_publish(), and transmit_register().

01677 {
01678    struct hostent *hp;
01679    struct ast_hostent ahp;
01680    struct oh323_peer *p;
01681    int portno;
01682    int found = 0;
01683    char *port;
01684    char *hostn;
01685    char peer[256] = "";
01686 
01687    ast_copy_string(peer, opeer, sizeof(peer));
01688    port = strchr(peer, ':');
01689    if (port) {
01690       *port = '\0';
01691       port++;
01692    }
01693    pvt->sa.sin_family = AF_INET;
01694    p = find_peer(peer, NULL, 1);
01695    if (p) {
01696       found++;
01697       memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01698       pvt->jointcapability = pvt->options.capability;
01699       if (pvt->options.dtmfmode) {
01700          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01701             pvt->nonCodecCapability |= AST_RTP_DTMF;
01702          } else {
01703             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01704          }
01705       }
01706       if (p->addr.sin_addr.s_addr) {
01707          pvt->sa.sin_addr = p->addr.sin_addr;
01708          pvt->sa.sin_port = p->addr.sin_port;
01709       }
01710       ASTOBJ_UNREF(p, oh323_destroy_peer);
01711    }
01712    if (!p && !found) {
01713       hostn = peer;
01714       if (port) {
01715          portno = atoi(port);
01716       } else {
01717          portno = h323_signalling_port;
01718       }
01719       hp = ast_gethostbyname(hostn, &ahp);
01720       if (hp) {
01721          memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01722          pvt->sa.sin_port = htons(portno);
01723          /* Look peer by address */
01724          p = find_peer(NULL, &pvt->sa, 1);
01725          memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01726          pvt->jointcapability = pvt->options.capability;
01727          if (p) {
01728             ASTOBJ_UNREF(p, oh323_destroy_peer);
01729          }
01730          if (pvt->options.dtmfmode) {
01731             if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01732                pvt->nonCodecCapability |= AST_RTP_DTMF;
01733             } else {
01734                pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01735             }
01736          }
01737          return 0;
01738       } else {
01739          ast_log(LOG_WARNING, "No such host: %s\n", peer);
01740          return -1;
01741       }
01742    } else if (!found) {
01743       return -1;
01744    } else {
01745       return 0;
01746    }
01747 }

static void delete_aliases ( void   )  [static]

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

02846 {
02847    int pruned = 0;
02848 
02849    /* Delete all aliases */
02850    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02851    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02852       ASTOBJ_RDLOCK(iterator);
02853       ASTOBJ_MARK(iterator);
02854       ++pruned;
02855       ASTOBJ_UNLOCK(iterator);
02856    } while (0) );
02857    if (pruned) {
02858       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02859    }
02860    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02861 }

static void delete_users ( void   )  [static]

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

02820 {
02821    int pruned = 0;
02822 
02823    /* Delete all users */
02824    ASTOBJ_CONTAINER_WRLOCK(&userl);
02825    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02826       ASTOBJ_RDLOCK(iterator);
02827       ASTOBJ_MARK(iterator);
02828       ++pruned;
02829       ASTOBJ_UNLOCK(iterator);
02830    } while (0) );
02831    if (pruned) {
02832       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02833    }
02834    ASTOBJ_CONTAINER_UNLOCK(&userl);
02835 
02836    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02837    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02838       ASTOBJ_RDLOCK(iterator);
02839       ASTOBJ_MARK(iterator);
02840       ASTOBJ_UNLOCK(iterator);
02841    } while (0) );
02842    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02843 }

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

Definition at line 2566 of file chan_h323.c.

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

02567 {
02568    int res;
02569    int reloading;
02570    struct oh323_pvt *oh323 = NULL;
02571 
02572    for(;;) {
02573       /* Check for a reload request */
02574       ast_mutex_lock(&h323_reload_lock);
02575       reloading = h323_reloading;
02576       h323_reloading = 0;
02577       ast_mutex_unlock(&h323_reload_lock);
02578       if (reloading) {
02579          ast_verb(1, "Reloading H.323\n");
02580          h323_do_reload();
02581       }
02582       /* Check for interfaces needing to be killed */
02583       if (!ast_mutex_trylock(&iflock)) {
02584 #if 1
02585          do {
02586             for (oh323 = iflist; oh323; oh323 = oh323->next) {
02587                if (!ast_mutex_trylock(&oh323->lock)) {
02588                   if (oh323->needdestroy) {
02589                      __oh323_destroy(oh323);
02590                      break;
02591                   }
02592                   ast_mutex_unlock(&oh323->lock);
02593                }
02594             }
02595          } while (/*oh323*/ 0);
02596 #else
02597 restartsearch:
02598          oh323 = iflist;
02599          while(oh323) {
02600             if (!ast_mutex_trylock(&oh323->lock)) {
02601                if (oh323->needdestroy) {
02602                   __oh323_destroy(oh323);
02603                   goto restartsearch;
02604                }
02605                ast_mutex_unlock(&oh323->lock);
02606                oh323 = oh323->next;
02607             }
02608          }
02609 #endif
02610          ast_mutex_unlock(&iflock);
02611       } else
02612          oh323 = (struct oh323_pvt *)1;   /* Force fast loop */
02613       pthread_testcancel();
02614       /* Wait for sched or io */
02615       res = ast_sched_wait(sched);
02616       if ((res < 0) || (res > 1000)) {
02617          res = 1000;
02618       }
02619       /* Do not wait if some channel(s) is destroyed, probably, more available too */
02620       if (oh323)
02621          res = 1;
02622       res = ast_io_wait(io, res);
02623       pthread_testcancel();
02624       ast_mutex_lock(&monlock);
02625       if (res >= 0) {
02626          ast_sched_runq(sched);
02627       }
02628       ast_mutex_unlock(&monlock);
02629    }
02630    /* Never reached */
02631    return NULL;
02632 }

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

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

Returns:
Returns the local RTP information

Definition at line 1921 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(), h323debug, oh323_pvt::lock, LOG_ERROR, and oh323_pvt::rtp.

Referenced by load_module().

01922 {
01923    struct oh323_pvt *pvt;
01924    struct sockaddr_in us;
01925    struct rtp_info *info;
01926 
01927    info = ast_calloc(1, sizeof(*info));
01928    if (!info) {
01929       ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01930       return NULL;
01931    }
01932    pvt = find_call_locked(call_reference, token);
01933    if (!pvt) {
01934       ast_free(info);
01935       ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01936       return NULL;
01937    }
01938    if (!pvt->rtp)
01939       __oh323_rtp_create(pvt);
01940    if (!pvt->rtp) {
01941       ast_mutex_unlock(&pvt->lock);
01942       ast_free(info);
01943       ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01944       return NULL;
01945    }
01946    /* figure out our local RTP port and tell the H.323 stack about it */
01947    {
01948       struct ast_sockaddr tmp;
01949 
01950       ast_rtp_instance_get_local_address(pvt->rtp, &tmp);
01951       ast_sockaddr_to_sin(&tmp, &us);
01952    }
01953    ast_mutex_unlock(&pvt->lock);
01954 
01955    ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01956    info->port = ntohs(us.sin_port);
01957    if (h323debug)
01958       ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01959    return info;
01960 }

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

Find a call by alias.

Definition at line 1837 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

01838 {
01839    struct oh323_alias *a;
01840 
01841    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01842 
01843    if (!a && realtime)
01844       a = realtime_alias(source_aliases);
01845 
01846    return a;
01847 }

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

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

01161 {
01162    struct oh323_pvt *pvt;
01163 
01164    ast_mutex_lock(&iflock);
01165    pvt = iflist;
01166    while(pvt) {
01167       if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01168          /* Found the call */
01169          if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01170             ast_mutex_lock(&pvt->lock);
01171             ast_mutex_unlock(&iflock);
01172             return pvt;
01173          } else if (token == NULL) {
01174             ast_log(LOG_WARNING, "Call Token is NULL\n");
01175             ast_mutex_lock(&pvt->lock);
01176             ast_mutex_unlock(&iflock);
01177             return pvt;
01178          }
01179       }
01180       pvt = pvt->next;
01181    }
01182    ast_mutex_unlock(&iflock);
01183    return NULL;
01184 }

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

Definition at line 1658 of file chan_h323.c.

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

Referenced by _sip_qualify_peer(), _sip_show_peer(), calltoken_required(), check_peer_ok(), create_addr(), dundi_encrypt(), function_iaxpeer(), function_sippeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), handle_command_response(), handle_request_notify(), iax2_devicestate(), register_verify(), registry_authrequest(), requirecalltoken_mark_auto(), set_config(), sip_devicestate(), sip_do_debug_peer(), sip_show_user(), sip_unregister(), transmit_register(), and update_registry().

01659 {
01660    struct oh323_peer *p;
01661 
01662    if (peer)
01663       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01664    else
01665       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01666 
01667    if (!p && realtime)
01668       p = realtime_peer(peer, sin);
01669 
01670    if (!p && h323debug)
01671       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>"));
01672 
01673    return p;
01674 }

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

Definition at line 1628 of file chan_h323.c.

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

01629 {
01630    struct oh323_user *u;
01631 
01632    if (userbyalias)
01633       u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01634    else
01635       u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01636 
01637    if (!u && realtime)
01638       u = realtime_user(cd);
01639 
01640    if (!u && h323debug)
01641       ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01642 
01643    return u;
01644 }

static int h323_do_reload ( void   )  [static]

Definition at line 3156 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03157 {
03158    reload_config(1);
03159    return 0;
03160 }

static int h323_reload ( void   )  [static]

Definition at line 3122 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

03123 {
03124    ast_mutex_lock(&h323_reload_lock);
03125    if (h323_reloading) {
03126       ast_verbose("Previous H.323 reload not yet done\n");
03127    } else {
03128       h323_reloading = 1;
03129    }
03130    ast_mutex_unlock(&h323_reload_lock);
03131    restart_monitor();
03132    return 0;
03133 }

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

Definition at line 2718 of file chan_h323.c.

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

02719 {
02720    switch (cmd) {
02721    case CLI_INIT:
02722       e->command = "h323 cycle gk";
02723       e->usage =
02724          "Usage: h323 cycle gk\n"
02725          "       Manually re-register with the Gatekeper (Currently Disabled)\n";
02726       return NULL;
02727    case CLI_GENERATE:
02728       return NULL;
02729    }
02730 
02731    if (a->argc != 3)
02732       return CLI_SHOWUSAGE;
02733 
02734    h323_gk_urq();
02735 
02736    /* Possibly register with a GK */
02737    if (!gatekeeper_disable) {
02738       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02739          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02740       }
02741    }
02742    return CLI_SUCCESS;
02743 }

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

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

02746 {
02747    switch (cmd) {
02748    case CLI_INIT:
02749       e->command = "h323 hangup";
02750       e->usage =
02751          "Usage: h323 hangup <token>\n"
02752          "       Manually try to hang up the call identified by <token>\n";
02753       return NULL;
02754    case CLI_GENERATE:
02755       return NULL;
02756    }
02757 
02758    if (a->argc != 3)
02759       return CLI_SHOWUSAGE;
02760    if (h323_soft_hangup(a->argv[2])) {
02761       ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02762    } else {
02763       ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02764    }
02765    return CLI_SUCCESS;
02766 }

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

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

03136 {
03137    switch (cmd) {
03138    case CLI_INIT:
03139       e->command = "h323 reload";
03140       e->usage =
03141          "Usage: h323 reload\n"
03142          "       Reloads H.323 configuration from h323.conf\n";
03143       return NULL;
03144    case CLI_GENERATE:
03145       return NULL;
03146    }
03147 
03148    if (a->argc != 2)
03149       return CLI_SHOWUSAGE;
03150 
03151    h323_reload();
03152 
03153    return CLI_SUCCESS;
03154 }

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

Definition at line 2695 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, h323debug, and ast_cli_entry::usage.

02696 {
02697    switch (cmd) {
02698    case CLI_INIT:
02699       e->command = "h323 set debug [on|off]";
02700       e->usage =
02701          "Usage: h323 set debug [on|off]\n"
02702          "       Enable/Disable H.323 debugging output\n";
02703       return NULL;
02704    case CLI_GENERATE:
02705       return NULL;
02706    }
02707 
02708    if (a->argc != e->args)
02709       return CLI_SHOWUSAGE;
02710    if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off"))
02711       return CLI_SHOWUSAGE;
02712 
02713    h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1;
02714    ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02715    return CLI_SUCCESS;
02716 }

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

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

02667 {
02668    switch (cmd) {
02669    case CLI_INIT:
02670       e->command = "h323 set trace [on|off]";
02671       e->usage =
02672          "Usage: h323 set trace (on|off|<trace level>)\n"
02673          "       Enable/Disable H.323 stack tracing for debugging purposes\n";
02674       return NULL;
02675    case CLI_GENERATE:
02676       return NULL;
02677    }
02678 
02679    if (a->argc != e->args)
02680       return CLI_SHOWUSAGE;
02681    if (!strcasecmp(a->argv[3], "off")) {
02682       h323_debug(0, 0);
02683       ast_cli(a->fd, "H.323 Trace Disabled\n");
02684    } else if (!strcasecmp(a->argv[3], "on")) {
02685       h323_debug(1, 1);
02686       ast_cli(a->fd, "H.323 Trace Enabled\n");
02687    } else {
02688       int tracelevel = atoi(a->argv[3]);
02689       h323_debug(1, tracelevel);
02690       ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02691    }
02692    return CLI_SUCCESS;
02693 }

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

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

02769 {
02770    switch (cmd) {
02771    case CLI_INIT:
02772       e->command = "h323 show tokens";
02773       e->usage =
02774          "Usage: h323 show tokens\n"
02775          "       Print out all active call tokens\n";
02776       return NULL;
02777    case CLI_GENERATE:
02778       return NULL;
02779    }
02780 
02781    if (a->argc != 3)
02782       return CLI_SHOWUSAGE;
02783 
02784    h323_show_tokens();
02785 
02786    return CLI_SUCCESS;
02787 }

static char* handle_cli_h323_show_version ( 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, 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 show version";
02794       e->usage =
02795          "Usage: h323 show version\n"
02796          "     Show the version of the H.323 library in use\n";
02797       return NULL;
02798    case CLI_GENERATE:
02799       return NULL;
02800    }
02801 
02802    if (a->argc != 3)
02803       return CLI_SHOWUSAGE;
02804 
02805    h323_show_version();
02806    
02807    return CLI_SUCCESS;
02808 }

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

Definition at line 2427 of file chan_h323.c.

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

Referenced by load_module().

02428 {
02429    struct oh323_pvt *pvt;
02430 
02431    if (h323debug)
02432       ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
02433 
02434    pvt = find_call_locked(call_reference, token);
02435    if (!pvt) {
02436       if (h323debug)
02437          ast_debug(1, "Connection to %s already cleared\n", token);
02438       return;
02439    }
02440    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02441       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02442       pvt->owner->hangupcause = pvt->hangupcause = cause;
02443       ast_queue_hangup_with_cause(pvt->owner, cause);
02444       ast_channel_unlock(pvt->owner);
02445    }
02446    else {
02447       pvt->needhangup = 1;
02448       pvt->hangupcause = cause;
02449       if (h323debug)
02450          ast_debug(1, "Hangup for %s is pending\n", token);
02451    }
02452    ast_mutex_unlock(&pvt->lock);
02453 }

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3259 of file chan_h323.c.

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

03260 {
03261    int res;
03262 
03263    h323debug = 0;
03264    sched = sched_context_create();
03265    if (!sched) {
03266       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03267       return AST_MODULE_LOAD_FAILURE;
03268    }
03269    io = io_context_create();
03270    if (!io) {
03271       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03272       return AST_MODULE_LOAD_FAILURE;
03273    }
03274    ast_cli_register(&cli_h323_reload);
03275    ASTOBJ_CONTAINER_INIT(&userl);
03276    ASTOBJ_CONTAINER_INIT(&peerl);
03277    ASTOBJ_CONTAINER_INIT(&aliasl);
03278    res = reload_config(0);
03279    if (res) {
03280       /* No config entry */
03281       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03282       ast_cli_unregister(&cli_h323_reload);
03283       io_context_destroy(io);
03284       io = NULL;
03285       sched_context_destroy(sched);
03286       sched = NULL;
03287       ASTOBJ_CONTAINER_DESTROY(&userl);
03288       ASTOBJ_CONTAINER_DESTROY(&peerl);
03289       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03290       return AST_MODULE_LOAD_DECLINE;
03291    } else {
03292       /* Make sure we can register our channel type */
03293       if (ast_channel_register(&oh323_tech)) {
03294          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03295          ast_cli_unregister(&cli_h323_reload);
03296          h323_end_process();
03297          io_context_destroy(io);
03298          sched_context_destroy(sched);
03299 
03300          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03301          ASTOBJ_CONTAINER_DESTROY(&userl);
03302          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03303          ASTOBJ_CONTAINER_DESTROY(&peerl);
03304          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03305          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03306 
03307          return AST_MODULE_LOAD_FAILURE;
03308       }
03309       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03310 
03311       ast_rtp_glue_register(&oh323_rtp_glue);
03312 
03313       /* Register our callback functions */
03314       h323_callback_register(setup_incoming_call,
03315                   setup_outgoing_call,
03316                   external_rtp_create,
03317                   setup_rtp_connection,
03318                   cleanup_connection,
03319                   chan_ringing,
03320                   connection_made,
03321                   receive_digit,
03322                   answer_call,
03323                   progress,
03324                   set_dtmf_payload,
03325                   hangup_connection,
03326                   set_local_capabilities,
03327                   set_peer_capabilities,
03328                   remote_hold);
03329       /* start the h.323 listener */
03330       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03331          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03332          ast_rtp_glue_unregister(&oh323_rtp_glue);
03333          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03334          ast_cli_unregister(&cli_h323_reload);
03335          h323_end_process();
03336          io_context_destroy(io);
03337          sched_context_destroy(sched);
03338 
03339          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03340          ASTOBJ_CONTAINER_DESTROY(&userl);
03341          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03342          ASTOBJ_CONTAINER_DESTROY(&peerl);
03343          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03344          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03345 
03346          return AST_MODULE_LOAD_DECLINE;
03347       }
03348       /* Possibly register with a GK */
03349       if (!gatekeeper_disable) {
03350          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03351             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03352             gatekeeper_disable = 1;
03353             res = AST_MODULE_LOAD_SUCCESS;
03354          }
03355       }
03356       /* And start the monitor for the first time */
03357       restart_monitor();
03358    }
03359    return res;
03360 }

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

Definition at line 1646 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01647 {
01648    int res;
01649 
01650    if (!sin)
01651       res = -1;
01652    else
01653       res = inaddrcmp(&addr , sin);
01654 
01655    return res;
01656 }

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

Definition at line 1623 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01624 {
01625    return strcmp(ast_inet_ntoa(inaddr), addr);
01626 }

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

Definition at line 1117 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(), iflist, iflock, and LOG_ERROR.

Referenced by oh323_request(), and setup_incoming_call().

01118 {
01119    struct oh323_pvt *pvt;
01120 
01121    pvt = ast_calloc(1, sizeof(*pvt));
01122    if (!pvt) {
01123       ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
01124       return NULL;
01125    }
01126    pvt->cd.redirect_reason = -1;
01127    pvt->cd.transfer_capability = -1;
01128    /* Ensure the call token is allocated for outgoing call */
01129    if (!callid) {
01130       if ((pvt->cd).call_token == NULL) {
01131          (pvt->cd).call_token = ast_calloc(1, 128);
01132       }
01133       if (!pvt->cd.call_token) {
01134          ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
01135          ast_rtp_instance_destroy(pvt->rtp);
01136          ast_free(pvt);
01137          return NULL;
01138       }
01139       memset((char *)(pvt->cd).call_token, 0, 128);
01140       pvt->cd.call_reference = callid;
01141    }
01142    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01143    pvt->jointcapability = pvt->options.capability;
01144    if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) {
01145       pvt->nonCodecCapability |= AST_RTP_DTMF;
01146    } else {
01147       pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01148    }
01149    ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
01150    pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
01151    ast_mutex_init(&pvt->lock);
01152    /* Add to interface list */
01153    ast_mutex_lock(&iflock);
01154    pvt->next = iflist;
01155    iflist = pvt;
01156    ast_mutex_unlock(&iflock);
01157    return pvt;
01158 }

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 659 of file chan_h323.c.

References ast_channel::_state, ast_debug, ast_free, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::lock, ast_channel::name, oh323_update_info(), and ast_channel::tech_pvt.

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

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

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

Definition at line 579 of file chan_h323.c.

References ast_channel::_state, 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, ast_channel::connected, oh323_pvt::exten, ast_party_redirecting::from, ast_party_connected_line::id, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_party_id::name, ast_channel::name, ast_party_id::number, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), ast_party_number::plan, ast_channel::redirecting, oh323_pvt::sa, ast_party_name::str, ast_party_number::str, ast_channel::tech_pvt, ast_channel::transfercapability, ast_party_name::valid, and ast_party_number::valid.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 488 of file chan_h323.c.

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

Referenced by oh323_request(), and setup_incoming_call().

00489 {
00490    if (h323debug) {
00491       ast_debug(1, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
00492    }
00493    ast_mutex_lock(&iflock);
00494    ast_mutex_lock(&pvt->lock);
00495    __oh323_destroy(pvt);
00496    ast_mutex_unlock(&iflock);
00497 }

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

Definition at line 279 of file chan_h323.c.

References ast_debug, and ast_free.

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

00280 {
00281    if (h323debug)
00282       ast_debug(1, "Destroying alias '%s'\n", alias->name);
00283    ast_free(alias);
00284 }

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

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

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

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

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

00287 {
00288    if (h323debug)
00289       ast_debug(1, "Destroying user '%s'\n", user->name);
00290    ast_free_ha(user->ha);
00291    ast_free(user);
00292 }

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

Definition at line 499 of file chan_h323.c.

References 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, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.

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

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

References 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, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.

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

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

Definition at line 943 of file chan_h323.c.

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

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

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

Definition at line 3174 of file chan_h323.c.

References ao2_ref, 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, oh323_pvt::rtp, and ast_channel::tech_pvt.

03175 {
03176    struct oh323_pvt *pvt;
03177    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
03178 
03179    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03180       return AST_RTP_GLUE_RESULT_FORBID;
03181 
03182    ast_mutex_lock(&pvt->lock);
03183    *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
03184 #if 0
03185    if (pvt->options.bridge) {
03186       res = AST_RTP_GLUE_RESULT_REMOTE;
03187    }
03188 #endif
03189    ast_mutex_unlock(&pvt->lock);
03190 
03191    return res;
03192 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 682 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_debug, ast_free, ast_log(), ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, cause, oh323_pvt::cd, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.

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

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

Definition at line 858 of file chan_h323.c.

References ast_channel::_state, oh323_pvt::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_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, ast_channel::name, oh323_update_info(), oh323_pvt::rtp, and ast_channel::tech_pvt.

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

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

Definition at line 804 of file chan_h323.c.

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

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

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

Definition at line 1748 of file chan_h323.c.

References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, 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, gatekeeper_disable, global_options, h323debug, oh323_pvt::jointcapability, ast_channel::linkedid, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, restart_monitor(), and unique.

01749 {
01750    format_t oldformat;
01751    struct oh323_pvt *pvt;
01752    struct ast_channel *tmpc = NULL;
01753    char *dest = (char *)data;
01754    char *ext, *host;
01755    char *h323id = NULL;
01756    char tmp[256], tmp1[256];
01757 
01758    if (h323debug)
01759       ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), format), (char *)data);
01760 
01761    pvt = oh323_alloc(0);
01762    if (!pvt) {
01763       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
01764       return NULL;
01765    }
01766    oldformat = format;
01767    format &= AST_FORMAT_AUDIO_MASK;
01768    if (!format) {
01769       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
01770       oh323_destroy(pvt);
01771       if (cause)
01772          *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01773       return NULL;
01774    }
01775    ast_copy_string(tmp, dest, sizeof(tmp));
01776    host = strchr(tmp, '@');
01777    if (host) {
01778       *host = '\0';
01779       host++;
01780       ext = tmp;
01781    } else {
01782       ext = strrchr(tmp, '/');
01783       if (ext)
01784          *ext++ = '\0';
01785       host = tmp;
01786    }
01787    strtok_r(host, "/", &(h323id));
01788    if (!ast_strlen_zero(h323id)) {
01789       h323_set_id(h323id);
01790    }
01791    if (ext) {
01792       ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01793    }
01794    if (h323debug)
01795       ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
01796 
01797    if (gatekeeper_disable) {
01798       if (create_addr(pvt, host)) {
01799          oh323_destroy(pvt);
01800          if (cause)
01801             *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01802          return NULL;
01803       }
01804    }
01805    else {
01806       memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01807       pvt->jointcapability = pvt->options.capability;
01808       if (pvt->options.dtmfmode) {
01809          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01810             pvt->nonCodecCapability |= AST_RTP_DTMF;
01811          } else {
01812             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01813          }
01814       }
01815    }
01816 
01817    ast_mutex_lock(&caplock);
01818    /* Generate unique channel identifier */
01819    snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01820    tmp1[sizeof(tmp1)-1] = '\0';
01821    ast_mutex_unlock(&caplock);
01822 
01823    ast_mutex_lock(&pvt->lock);
01824    tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? requestor->linkedid : NULL);
01825    ast_mutex_unlock(&pvt->lock);
01826    if (!tmpc) {
01827       oh323_destroy(pvt);
01828       if (cause)
01829          *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01830    }
01831    ast_update_use_count();
01832    restart_monitor();
01833    return tmpc;
01834 }

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

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

Definition at line 749 of file chan_h323.c.

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

Referenced by oh323_read().

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

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,
format_t  codecs,
int  nat_active 
) [static]

Definition at line 3221 of file chan_h323.c.

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

03222 {
03223    /* XXX Deal with Video */
03224    struct oh323_pvt *pvt;
03225    struct sockaddr_in them = { 0, };
03226    struct sockaddr_in us = { 0, };
03227    char *mode;
03228 
03229    if (!rtp) {
03230       return 0;
03231    }
03232 
03233    mode = convertcap(chan->writeformat);
03234    pvt = (struct oh323_pvt *) chan->tech_pvt;
03235    if (!pvt) {
03236       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03237       return -1;
03238    }
03239    {
03240       struct ast_sockaddr tmp;
03241 
03242       ast_rtp_instance_get_remote_address(rtp, &tmp);
03243       ast_sockaddr_to_sin(&tmp, &them);
03244       ast_rtp_instance_get_local_address(rtp, &tmp);
03245       ast_sockaddr_to_sin(&tmp, &us);
03246    }
03247 #if 0 /* Native bridge still isn't ready */
03248    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03249 #endif
03250    return 0;
03251 }

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

Definition at line 302 of file chan_h323.c.

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

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

Definition at line 396 of file chan_h323.c.

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

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

00397 {
00398    struct oh323_pvt *pvt = c->tech_pvt;
00399 
00400    if (pvt) {
00401       ast_mutex_lock(&pvt->lock);
00402       __oh323_update_info(c, pvt);
00403       ast_mutex_unlock(&pvt->lock);
00404    }
00405 }

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

Definition at line 829 of file chan_h323.c.

References __oh323_update_info(), 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::codec, ast_frame::frametype, oh323_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.

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

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

Definition at line 2109 of file chan_h323.c.

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

02110 {
02111    struct oh323_pvt *pvt;
02112 
02113    if (h323debug)
02114       ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02115 
02116    pvt = find_call_locked(call_reference, token);
02117    if (!pvt) {
02118       ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02119       return -1;
02120    }
02121    if (!pvt->owner) {
02122       ast_mutex_unlock(&pvt->lock);
02123       ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02124       return -1;
02125    }
02126    update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02127    ast_mutex_unlock(&pvt->lock);
02128 
02129    return 0;
02130 }

static void prune_peers ( void   )  [static]

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

02864 {
02865    /* Prune peers who still are supposed to be deleted */
02866    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02867 }

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

Definition at line 1242 of file chan_h323.c.

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

Referenced by find_alias().

01243 {
01244    struct ast_variable *var, *tmp;
01245    struct oh323_alias *a;
01246 
01247    var = ast_load_realtime("h323", "name", alias, SENTINEL);
01248 
01249    if (!var)
01250       return NULL;
01251 
01252    for (tmp = var; tmp; tmp = tmp->next) {
01253       if (!strcasecmp(tmp->name, "type") &&
01254       !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01255          ast_variables_destroy(var);
01256          return NULL;
01257       }
01258    }
01259 
01260    a = build_alias(alias, var, NULL, 1);
01261 
01262    ast_variables_destroy(var);
01263 
01264    return a;
01265 }

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

Definition at line 1580 of file chan_h323.c.

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

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

01581 {
01582    struct oh323_peer *peer;
01583    struct ast_variable *var;
01584    struct ast_variable *tmp;
01585    const char *addr = NULL;
01586 
01587    /* First check on peer name */
01588    if (peername)
01589       var = ast_load_realtime("h323", "name", peername, SENTINEL);
01590    else if (sin) /* Then check on IP address for dynamic peers */
01591       var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL);
01592    else
01593       return NULL;
01594 
01595    if (!var)
01596       return NULL;
01597 
01598    for (tmp = var; tmp; tmp = tmp->next) {
01599       /* If this is type=user, then skip this object. */
01600       if (!strcasecmp(tmp->name, "type") &&
01601             !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01602          ast_variables_destroy(var);
01603          return NULL;
01604       } else if (!peername && !strcasecmp(tmp->name, "name")) {
01605          peername = tmp->value;
01606       }
01607    }
01608 
01609    if (!peername) {  /* Did not find peer in realtime */
01610       ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01611       ast_variables_destroy(var);
01612       return NULL;
01613    }
01614 
01615    /* Peer found in realtime, now build it in memory */
01616    peer = build_peer(peername, var, NULL, 1);
01617 
01618    ast_variables_destroy(var);
01619 
01620    return peer;
01621 }

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

Definition at line 1461 of file chan_h323.c.

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

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

01462 {
01463    struct ast_variable *var, *tmp;
01464    struct oh323_user *user;
01465    const char *username;
01466 
01467    if (userbyalias)
01468       var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL);
01469    else {
01470       username = (char *)NULL;
01471       var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL);
01472    }
01473 
01474    if (!var)
01475       return NULL;
01476 
01477    for (tmp = var; tmp; tmp = tmp->next) {
01478       if (!strcasecmp(tmp->name, "type") &&
01479       !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01480          ast_variables_destroy(var);
01481          return NULL;
01482       } else if (!username && !strcasecmp(tmp->name, "name"))
01483          username = tmp->value;
01484    }
01485 
01486    if (!username) {
01487       ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01488       ast_variables_destroy(var);
01489       return NULL;
01490    }
01491 
01492    user = build_user(username, var, NULL, 1);
01493 
01494    ast_variables_destroy(var);
01495 
01496    return user;
01497 }

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

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

Referenced by load_module().

01854 {
01855    struct oh323_pvt *pvt;
01856    int res;
01857 
01858    pvt = find_call_locked(call_reference, token);
01859    if (!pvt) {
01860       ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01861       return -1;
01862    }
01863    if (h323debug)
01864       ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01865 
01866    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01867       if (digit == '!')
01868          res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01869       else {
01870          struct ast_frame f = {
01871             .frametype = AST_FRAME_DTMF_END,
01872             .subclass.integer = digit,
01873             .samples = duration * 8,
01874             .len = duration,
01875             .src = "SEND_DIGIT",
01876          };
01877          if (digit == ' ') {     /* signalUpdate message */
01878             f.subclass.integer = pvt->curDTMF;
01879             AST_SCHED_DEL(sched, pvt->DTMFsched);
01880          } else {          /* Regular input or signal message */
01881             if (pvt->DTMFsched >= 0) {
01882                /* We still don't send DTMF END from previous event, send it now */
01883                AST_SCHED_DEL(sched, pvt->DTMFsched);
01884                f.subclass.integer = pvt->curDTMF;
01885                f.samples = f.len = 0;
01886                ast_queue_frame(pvt->owner, &f);
01887                /* Restore values */
01888                f.subclass.integer = digit;
01889                f.samples = duration * 8;
01890                f.len = duration;
01891             }
01892             if (duration) {      /* This is a signal, signalUpdate follows */
01893                f.frametype = AST_FRAME_DTMF_BEGIN;
01894                pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01895                if (h323debug)
01896                   ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01897             }
01898             pvt->curDTMF = digit;
01899          }
01900          res = ast_queue_frame(pvt->owner, &f);
01901       }
01902       ast_channel_unlock(pvt->owner);
01903    } else {
01904       if (digit == '!')
01905          pvt->newcontrol = AST_CONTROL_FLASH;
01906       else {
01907          pvt->newduration = duration;
01908          pvt->newdigit = digit;
01909       }
01910       res = 0;
01911    }
01912    ast_mutex_unlock(&pvt->lock);
01913    return res;
01914 }

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

Definition at line 263 of file chan_h323.c.

Referenced by __oh323_new().

00264 {
00265    switch (redirectingreason) {
00266    case 0:
00267       return "UNKNOWN";
00268    case 1:
00269       return "BUSY";
00270    case 2:
00271       return "NO_REPLY";
00272    case 0xF:
00273       return "UNCONDITIONAL";
00274    default:
00275       return "NOREDIRECT";
00276    }
00277 }

static int reload ( void   )  [static]

Definition at line 3162 of file chan_h323.c.

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

03163 {
03164    if (!sched || !io) {
03165       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03166       return 0;
03167    }
03168    return h323_reload();
03169 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2869 of file chan_h323.c.

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

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

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

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

Definition at line 2540 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(), h323debug, oh323_pvt::lock, oh323_pvt::newcontrol, and oh323_pvt::owner.

Referenced by load_module().

02541 {
02542    struct oh323_pvt *pvt;
02543 
02544    if (h323debug)
02545       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02546 
02547    pvt = find_call_locked(call_reference, token);
02548    if (!pvt)
02549       return;
02550    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02551       if (is_hold)
02552          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02553       else
02554          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02555       ast_channel_unlock(pvt->owner);
02556    }
02557    else {
02558       if (is_hold)
02559          pvt->newcontrol = AST_CONTROL_HOLD;
02560       else
02561          pvt->newcontrol = AST_CONTROL_UNHOLD;
02562    }
02563    ast_mutex_unlock(&pvt->lock);
02564 }

static int restart_monitor ( void   )  [static]

Definition at line 2634 of file chan_h323.c.

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

02635 {
02636    /* If we're supposed to be stopped -- stay stopped */
02637    if (ast_mutex_lock(&monlock)) {
02638       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02639       return -1;
02640    }
02641    if (monitor_thread == AST_PTHREADT_STOP) {
02642       ast_mutex_unlock(&monlock);
02643       return 0;
02644    }
02645    if (monitor_thread == pthread_self()) {
02646       ast_mutex_unlock(&monlock);
02647       ast_log(LOG_WARNING, "Cannot kill myself\n");
02648       return -1;
02649    }
02650    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02651       /* Wake up the thread */
02652       pthread_kill(monitor_thread, SIGURG);
02653    } else {
02654       /* Start a new monitor */
02655       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02656          monitor_thread = AST_PTHREADT_NULL;
02657          ast_mutex_unlock(&monlock);
02658          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02659          return -1;
02660       }
02661    }
02662    ast_mutex_unlock(&monlock);
02663    return 0;
02664 }

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

Definition at line 2455 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(), h323debug, oh323_pvt::lock, and oh323_pvt::rtp.

Referenced by load_module().

02456 {
02457    struct oh323_pvt *pvt;
02458 
02459    if (h323debug)
02460       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02461 
02462    pvt = find_call_locked(call_reference, token);
02463    if (!pvt) {
02464       return;
02465    }
02466    if (pvt->rtp) {
02467       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);
02468    }
02469    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02470    ast_mutex_unlock(&pvt->lock);
02471    if (h323debug)
02472       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02473 }

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

Definition at line 2510 of file chan_h323.c.

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

Referenced by load_module().

02511 {
02512    struct oh323_pvt *pvt;
02513    int capability, dtmfmode, pref_codec;
02514    struct ast_codec_pref prefs;
02515 
02516    if (h323debug)
02517       ast_debug(1, "Setting capabilities for connection %s\n", token);
02518 
02519    pvt = find_call_locked(call_reference, token);
02520    if (!pvt)
02521       return;
02522    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02523    dtmfmode = pvt->options.dtmfmode;
02524    prefs = pvt->options.prefs;
02525    pref_codec = pvt->pref_codec;
02526    ast_mutex_unlock(&pvt->lock);
02527    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02528 
02529    if (h323debug) {
02530       int i;
02531       for (i = 0; i < 32; i++) {
02532          if (!prefs.order[i])
02533             break;
02534          ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02535       }
02536       ast_debug(1, "Capabilities for connection %s is set\n", token);
02537    }
02538 }

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

Definition at line 2475 of file chan_h323.c.

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

Referenced by load_module().

02476 {
02477    struct oh323_pvt *pvt;
02478 
02479    if (h323debug)
02480       ast_debug(1, "Got remote capabilities from connection %s\n", token);
02481 
02482    pvt = find_call_locked(call_reference, token);
02483    if (!pvt)
02484       return;
02485    pvt->peercapability = capabilities;
02486    pvt->jointcapability = pvt->options.capability & capabilities;
02487    if (prefs) {
02488       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02489       if (h323debug) {
02490          int i;
02491          for (i = 0; i < 32; ++i) {
02492             if (!prefs->order[i])
02493                break;
02494             ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02495          }
02496       }
02497       if (pvt->rtp) {
02498          if (pvt->options.autoframing) {
02499             ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02500             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
02501          } else {
02502             ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02503             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
02504          }
02505       }
02506    }
02507    ast_mutex_unlock(&pvt->lock);
02508 }

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

References acceptAnonymous, 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, default_context, oh323_pvt::exten, find_alias(), find_user(), gatekeeper, gatekeeper_disable, gkroute, global_options, h323debug, oh323_pvt::jointcapability, LOG_ERROR, LOG_NOTICE, oh323_alloc(), oh323_destroy(), oh323_destroy_user(), and oh323_pvt::options.

Referenced by load_module().

02138 {
02139    struct oh323_pvt *pvt;
02140    struct oh323_user *user = NULL;
02141    struct oh323_alias *alias = NULL;
02142 
02143    if (h323debug)
02144       ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
02145 
02146    /* allocate the call*/
02147    pvt = oh323_alloc(cd->call_reference);
02148 
02149    if (!pvt) {
02150       ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02151       cleanup_call_details(cd);
02152       return NULL;
02153    }
02154 
02155    /* Populate the call details in the private structure */
02156    memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02157    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02158    pvt->jointcapability = pvt->options.capability;
02159 
02160    if (h323debug) {
02161       ast_verb(3, "Setting up Call\n");
02162       ast_verb(3, " \tCall token:  [%s]\n", pvt->cd.call_token);
02163       ast_verb(3, " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);
02164       ast_verb(3, " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
02165       ast_verb(3, " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
02166       ast_verb(3, " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
02167       if (pvt->cd.redirect_reason >= 0)
02168          ast_verb(3, " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02169       ast_verb(3, " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
02170    }
02171 
02172    /* Decide if we are allowing Gatekeeper routed calls*/
02173    if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02174       if (!ast_strlen_zero(cd->call_dest_e164)) {
02175          ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02176          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02177       } else {
02178          alias = find_alias(cd->call_dest_alias, 1);
02179          if (!alias) {
02180             ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02181             oh323_destroy(pvt);
02182             return NULL;
02183          }
02184          ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02185          ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02186       }
02187    } else {
02188       /* Either this call is not from the Gatekeeper
02189          or we are not allowing gk routed calls */
02190       user = find_user(cd, 1);
02191       if (!user) {
02192          if (!acceptAnonymous) {
02193             ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02194             oh323_destroy(pvt);
02195             return NULL;
02196          }
02197          if (ast_strlen_zero(default_context)) {
02198             ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02199             oh323_destroy(pvt);
02200             return NULL;
02201          }
02202          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02203          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02204             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02205          } else {
02206             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02207          }
02208          if (h323debug)
02209             ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02210       } else {
02211          if (user->host) {
02212             if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02213                if (ast_strlen_zero(user->context)) {
02214                   if (ast_strlen_zero(default_context)) {
02215                      ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02216                      oh323_destroy(pvt);
02217                      ASTOBJ_UNREF(user, oh323_destroy_user);
02218                      return NULL;
02219                   }
02220                   ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02221                } else {
02222                   ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02223                }
02224                pvt->exten[0] = 'i';
02225                pvt->exten[1] = '\0';
02226                ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02227                oh323_destroy(pvt);
02228                ASTOBJ_UNREF(user, oh323_destroy_user);
02229                return NULL;   /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
02230             }
02231          }
02232          ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02233          memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02234          pvt->jointcapability = pvt->options.capability;
02235          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02236             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02237          } else {
02238             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02239          }
02240          if (!ast_strlen_zero(user->accountcode)) {
02241             ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02242          }
02243          if (user->amaflags) {
02244             pvt->amaflags = user->amaflags;
02245          }
02246          ASTOBJ_UNREF(user, oh323_destroy_user);
02247       }
02248    }
02249    return &pvt->options;
02250 }

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

References cleanup_call_details().

Referenced by load_module().

02337 {
02338    /* Use argument here or free it immediately */
02339    cleanup_call_details(cd);
02340 
02341    return 1;
02342 }

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

References __oh323_rtp_create(), oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_debug, AST_FORMAT_G726_AAL2, 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::code, find_call_locked(), h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, ast_channel::nativeformats, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_channel::writeformat.

Referenced by load_module().

01968 {
01969    struct oh323_pvt *pvt;
01970    struct sockaddr_in them;
01971    int nativeformats_changed;
01972    enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
01973 
01974    if (h323debug)
01975       ast_debug(1, "Setting up RTP connection for %s\n", token);
01976 
01977    /* Find the call or allocate a private structure if call not found */
01978    pvt = find_call_locked(call_reference, token);
01979    if (!pvt) {
01980       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
01981       return;
01982    }
01983    if (pvt->alreadygone) {
01984       ast_mutex_unlock(&pvt->lock);
01985       return;
01986    }
01987 
01988    if (!pvt->rtp)
01989       __oh323_rtp_create(pvt);
01990 
01991    if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
01992       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);
01993    }
01994 
01995    them.sin_family = AF_INET;
01996    /* only works for IPv4 */
01997    them.sin_addr.s_addr = inet_addr(remoteIp);
01998    them.sin_port = htons(remotePort);
01999 
02000    if (them.sin_addr.s_addr) {
02001       {
02002          struct ast_sockaddr tmp;
02003 
02004          ast_sockaddr_from_sin(&tmp, &them);
02005          ast_rtp_instance_set_remote_address(pvt->rtp, &tmp);
02006       }
02007       if (pvt->recvonly) {
02008          pvt->recvonly = 0;
02009          rtp_change = NEED_UNHOLD;
02010       }
02011    } else {
02012       ast_rtp_instance_stop(pvt->rtp);
02013       if (!pvt->recvonly) {
02014          pvt->recvonly = 1;
02015          rtp_change = NEED_HOLD;
02016       }
02017    }
02018 
02019    /* Change native format to reflect information taken from OLC/OLCAck */
02020    nativeformats_changed = 0;
02021    if (pt != 128 && pvt->rtp) {  /* Payload type is invalid, so try to use previously decided */
02022       struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
02023       if (h323debug)
02024          ast_debug(1, "Native format is set to %llu from %d by RTP payload type %d\n", (unsigned long long) rtptype.code, pvt->nativeformats, pt);
02025       if (pvt->nativeformats != rtptype.code) {
02026          pvt->nativeformats = rtptype.code;
02027          nativeformats_changed = 1;
02028       }
02029    } else if (h323debug)
02030       ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
02031 
02032    /* Don't try to lock the channel if nothing changed */
02033    if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
02034       if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02035          /* Re-build translation path only if native format(s) has been changed */
02036          if (pvt->owner->nativeformats != pvt->nativeformats) {
02037             if (h323debug) {
02038                char tmp[256], tmp2[256];
02039                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->nativeformats), ast_getformatname_multiple(tmp2, sizeof(tmp2), pvt->owner->nativeformats), ast_getformatname(pvt->owner->readformat), ast_getformatname(pvt->owner->writeformat));
02040             }
02041             pvt->owner->nativeformats = pvt->nativeformats;
02042             ast_set_read_format(pvt->owner, pvt->owner->readformat);
02043             ast_set_write_format(pvt->owner, pvt->owner->writeformat);
02044          }
02045          if (pvt->options.progress_audio)
02046             ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
02047          switch (rtp_change) {
02048          case NEED_HOLD:
02049             ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02050             break;
02051          case NEED_UNHOLD:
02052             ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02053             break;
02054          default:
02055             break;
02056          }
02057          ast_channel_unlock(pvt->owner);
02058       }
02059       else {
02060          if (pvt->options.progress_audio)
02061             pvt->newcontrol = AST_CONTROL_PROGRESS;
02062          else if (rtp_change == NEED_HOLD)
02063             pvt->newcontrol = AST_CONTROL_HOLD;
02064          else if (rtp_change == NEED_UNHOLD)
02065             pvt->newcontrol = AST_CONTROL_UNHOLD;
02066          if (h323debug)
02067             ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
02068       }
02069    }
02070    ast_mutex_unlock(&pvt->lock);
02071 
02072    if (h323debug)
02073       ast_debug(1, "RTP connection prepared for %s\n", token);
02074 
02075    return;
02076 }

static int unload_module ( void   )  [static]

Definition at line 3362 of file chan_h323.c.

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

03363 {
03364    struct oh323_pvt *p, *pl;
03365 
03366    /* unregister commands */
03367    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03368    ast_cli_unregister(&cli_h323_reload);
03369 
03370    ast_channel_unregister(&oh323_tech);
03371    ast_rtp_glue_unregister(&oh323_rtp_glue);
03372 
03373    if (!ast_mutex_lock(&iflock)) {
03374       /* hangup all interfaces if they have an owner */
03375       p = iflist;
03376       while(p) {
03377          if (p->owner) {
03378             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03379          }
03380          p = p->next;
03381       }
03382       iflist = NULL;
03383       ast_mutex_unlock(&iflock);
03384    } else {
03385       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03386       return -1;
03387    }
03388    if (!ast_mutex_lock(&monlock)) {
03389       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03390          if (monitor_thread != pthread_self()) {
03391             pthread_cancel(monitor_thread);
03392          }
03393          pthread_kill(monitor_thread, SIGURG);
03394          pthread_join(monitor_thread, NULL);
03395       }
03396       monitor_thread = AST_PTHREADT_STOP;
03397       ast_mutex_unlock(&monlock);
03398    } else {
03399       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03400       return -1;
03401    }
03402    if (!ast_mutex_lock(&iflock)) {
03403       /* destroy all the interfaces and free their memory */
03404       p = iflist;
03405       while(p) {
03406          pl = p;
03407          p = p->next;
03408          /* free associated memory */
03409          ast_mutex_destroy(&pl->lock);
03410          ast_free(pl);
03411       }
03412       iflist = NULL;
03413       ast_mutex_unlock(&iflock);
03414    } else {
03415       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03416       return -1;
03417    }
03418    if (!gatekeeper_disable)
03419       h323_gk_urq();
03420    h323_end_process();
03421    if (io)
03422       io_context_destroy(io);
03423    if (sched)
03424       sched_context_destroy(sched);
03425 
03426    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03427    ASTOBJ_CONTAINER_DESTROY(&userl);
03428    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03429    ASTOBJ_CONTAINER_DESTROY(&peerl);
03430    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03431    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03432 
03433    return 0;
03434 }

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

Definition at line 1267 of file chan_h323.c.

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

Referenced by build_peer(), and build_user().

01268 {
01269    int tmp = 0;
01270    char *val, *opt;
01271 
01272    if (!strcasecmp(v->name, "allow")) {
01273       ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
01274    } else if (!strcasecmp(v->name, "autoframing")) {
01275       options->autoframing = ast_true(v->value);
01276    } else if (!strcasecmp(v->name, "disallow")) {
01277       ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
01278    } else if (!strcasecmp(v->name, "dtmfmode")) {
01279       val = ast_strdupa(v->value);
01280       if ((opt = strchr(val, ':')) != (char *)NULL) {
01281          *opt++ = '\0';
01282          tmp = atoi(opt);
01283       }
01284       if (!strcasecmp(v->value, "inband")) {
01285          options->dtmfmode |= H323_DTMF_INBAND;
01286       } else if (!strcasecmp(val, "rfc2833")) {
01287          options->dtmfmode |= H323_DTMF_RFC2833;
01288          if (!opt) {
01289             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01290          } else if ((tmp >= 96) && (tmp < 128)) {
01291             options->dtmfcodec[0] = tmp;
01292          } else {
01293             options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
01294             ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]);
01295          }
01296       } else if (!strcasecmp(val, "cisco")) {
01297          options->dtmfmode |= H323_DTMF_CISCO;
01298          if (!opt) {
01299             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01300          } else if ((tmp >= 96) && (tmp < 128)) {
01301             options->dtmfcodec[1] = tmp;
01302          } else {
01303             options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
01304             ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]);
01305          }
01306       } else if (!strcasecmp(v->value, "h245-signal")) {
01307          options->dtmfmode |= H323_DTMF_SIGNAL;
01308       } else {
01309          ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno);
01310       }
01311    } else if (!strcasecmp(v->name, "dtmfcodec")) {
01312       ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno);
01313       tmp = atoi(v->value);
01314       if (tmp < 96)
01315          ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
01316       else
01317          options->dtmfcodec[0] = tmp;
01318    } else if (!strcasecmp(v->name, "bridge")) {
01319       options->bridge = ast_true(v->value);
01320    } else if (!strcasecmp(v->name, "nat")) {
01321       options->nat = ast_true(v->value);
01322    } else if (!strcasecmp(v->name, "fastStart")) {
01323       options->fastStart = ast_true(v->value);
01324    } else if (!strcasecmp(v->name, "h245Tunneling")) {
01325       options->h245Tunneling = ast_true(v->value);
01326    } else if (!strcasecmp(v->name, "silenceSuppression")) {
01327       options->silenceSuppression = ast_true(v->value);
01328    } else if (!strcasecmp(v->name, "progress_setup")) {
01329       tmp = atoi(v->value);
01330       if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
01331          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01332          tmp = 0;
01333       }
01334       options->progress_setup = tmp;
01335    } else if (!strcasecmp(v->name, "progress_alert")) {
01336       tmp = atoi(v->value);
01337       if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
01338          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
01339          tmp = 0;
01340       }
01341       options->progress_alert = tmp;
01342    } else if (!strcasecmp(v->name, "progress_audio")) {
01343       options->progress_audio = ast_true(v->value);
01344    } else if (!strcasecmp(v->name, "callerid")) {
01345       ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
01346    } else if (!strcasecmp(v->name, "fullname")) {
01347       ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
01348    } else if (!strcasecmp(v->name, "cid_number")) {
01349       ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
01350    } else if (!strcasecmp(v->name, "tunneling")) {
01351       if (!strcasecmp(v->value, "none"))
01352          options->tunnelOptions = 0;
01353       else if (!strcasecmp(v->value, "cisco"))
01354          options->tunnelOptions |= H323_TUNNEL_CISCO;
01355       else if (!strcasecmp(v->value, "qsig"))
01356          options->tunnelOptions |= H323_TUNNEL_QSIG;
01357       else
01358          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01359    } else if (!strcasecmp(v->name, "hold")) {
01360       if (!strcasecmp(v->value, "none"))
01361          options->holdHandling = ~0;
01362       else if (!strcasecmp(v->value, "notify"))
01363          options->holdHandling |= H323_HOLD_NOTIFY;
01364       else if (!strcasecmp(v->value, "q931only"))
01365          options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY;
01366       else if (!strcasecmp(v->value, "h450"))
01367          options->holdHandling |= H323_HOLD_H450;
01368       else
01369          ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
01370    } else
01371       return 1;
01372 
01373    return 0;
01374 }

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

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

01187 {
01188    if (!pvt)
01189       return 0;
01190    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01191       if (state >= 0)
01192          ast_setstate(pvt->owner, state);
01193       if (signal >= 0)
01194          ast_queue_control(pvt->owner, signal);
01195       ast_channel_unlock(pvt->owner);
01196       return 1;
01197    }
01198    else {
01199       if (state >= 0)
01200          pvt->newstate = state;
01201       if (signal >= 0)
01202          pvt->newcontrol = signal;
01203       return 0;
01204    }
01205 }


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

Definition at line 3441 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 142 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct h323_alias_list aliasl [static]

H323 alias list.

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

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3441 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 130 of file chan_h323.c.

ast_mutex_t caplock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [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 218 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2810 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_h323_reload [static]

Initial value:

   { .handler =  handle_cli_h323_reload , .summary =  "Reload H.323 configuration" ,__VA_ARGS__ }

Definition at line 3171 of file chan_h323.c.

Referenced by load_module(), and unload_module().

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

Definition at line 128 of file chan_h323.c.

unsigned int cos = 0 [static]

Definition at line 144 of file chan_h323.c.

Referenced by ast_playtones_start(), callerid_init(), goertzel_init(), reload_config(), smb_fft(), smb_pitch_shift(), tdd_init(), and tonepair_alloc().

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

Definition at line 129 of file chan_h323.c.

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

Definition at line 116 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 136 of file chan_h323.c.

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

int gatekeeper_disable = 1 [static]

Definition at line 137 of file chan_h323.c.

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

int gatekeeper_discover = 0 [static]

Definition at line 138 of file chan_h323.c.

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

int gkroute = 0 [static]

Definition at line 139 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct ast_jb_conf global_jbconf [static]

Definition at line 124 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 148 of file chan_h323.c.

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

ast_mutex_t h323_reload_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Protect the reload process.

Definition at line 221 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 222 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 135 of file chan_h323.c.

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

int h323debug

global debug flag

Definition at line 113 of file chan_h323.c.

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

struct oh323_pvt * iflist [static]

Private structure of a OpenH323 channel.

ast_mutex_t iflock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Protect the interface list (oh323_pvt)

Definition at line 211 of file chan_h323.c.

struct io_context* io [static]

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

ast_mutex_t monlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [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 215 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 3253 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech oh323_tech [static]

Definition at line 245 of file chan_h323.c.

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

answer_call_cb on_answer_call

Definition at line 105 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 102 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 104 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 103 of file chan_h323.c.

on_rtp_cb on_external_rtp_create

Definition at line 98 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 108 of file chan_h323.c.

onhold_cb on_hold

Definition at line 111 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 100 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 101 of file chan_h323.c.

progress_cb on_progress

Definition at line 106 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 97 of file chan_h323.c.

rfc2833_cb on_set_rfc2833_payload

Definition at line 107 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 109 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 110 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 99 of file chan_h323.c.

struct h323_peer_list peerl [static]

H323 peer list.

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

struct sched_context* sched [static]

Definition at line 208 of file chan_h323.c.

char secret[50] [static]

Definition at line 145 of file chan_h323.c.

Referenced by add_realm_authentication(), aji_act_hook(), authenticate_verify(), build_peer(), build_reply_digest(), build_user(), cache_get_callno_locked(), caldav_load_calendar(), check_access(), decrypt_frame(), ewscal_load_calendar(), exchangecal_load_calendar(), handle_cli_h323_cycle_gk(), iax2_call(), iax2_register(), ical_load_calendar(), load_module(), read_agent_config(), register_verify(), set_config(), set_peer_defaults(), sip_request_call(), and sip_subscribe_mwi().

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

Variables required by Asterisk

Definition at line 127 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 143 of file chan_h323.c.

Referenced by reload_config().

unsigned int unique = 0 [static]

Definition at line 146 of file chan_h323.c.

Referenced by oh323_request().

int userbyalias = 1 [static]

Definition at line 141 of file chan_h323.c.

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

struct h323_user_list userl [static]

H323 User list.

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


Generated on Wed Apr 6 11:29:56 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7