Sat Feb 11 06:34:32 2012

Asterisk developer's documentation


chan_h323.c File Reference

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

#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
#include "h323/chan_h323.h"

Include dependency graph for chan_h323.c:

Go to the source code of this file.

Data Structures

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

Defines

#define GLOBAL_CAPABILITY

Functions

static void __oh323_destroy (struct oh323_pvt *pvt)
static struct ast_channel__oh323_new (struct oh323_pvt *pvt, int state, const char *host, const char *linkedid)
 Private structure should be locked on a call.
static int __oh323_rtp_create (struct oh323_pvt *pvt)
static void __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt)
 Channel and private structures should be already locked.
static void __reg_module (void)
static void __unreg_module (void)
static int answer_call (unsigned call_reference, const char *token)
 Call-back function to start PBX when OpenH323 ready to serve incoming call.
static struct oh323_alias * build_alias (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_peer * build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_user * build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static void chan_ringing (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel is ringing Returns nothing.
static void cleanup_call_details (call_details_t *cd)
static void cleanup_connection (unsigned call_reference, const char *call_token)
 Call-back function to cleanup communication Returns nothing,.
static void connection_made (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel has been answered Returns nothing.
static int create_addr (struct oh323_pvt *pvt, char *opeer)
static void delete_aliases (void)
static void delete_users (void)
static void * do_monitor (void *data)
static struct rtp_info * external_rtp_create (unsigned call_reference, const char *token)
 Callback function used to inform the H.323 stack of the local rtp ip/port details.
static struct oh323_alias * find_alias (const char *source_aliases, int realtime)
 Find a call by alias.
static struct oh323_pvtfind_call_locked (int call_reference, const char *token)
static struct oh323_peer * find_peer (const char *peer, struct sockaddr_in *sin, int realtime)
static struct oh323_user * find_user (const call_details_t *cd, int realtime)
static int h323_do_reload (void)
static int h323_parse_allow_disallow (struct ast_codec_pref *pref, h323_format *formats, const char *list, int allowing)
static int h323_reload (void)
static char * handle_cli_h323_cycle_gk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_set_trace (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_show_tokens (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void hangup_connection (unsigned int call_reference, const char *token, int cause)
static enum ast_module_load_result load_module (void)
static int oh323_addrcmp (struct sockaddr_in addr, struct sockaddr_in *sin)
static int oh323_addrcmp_str (struct in_addr inaddr, char *addr)
static struct oh323_pvtoh323_alloc (int callid)
static int oh323_answer (struct ast_channel *c)
static int oh323_call (struct ast_channel *c, const char *dest, int timeout)
 Make a call over the specified channel to the specified destination. Returns -1 on error, 0 on success.
static void oh323_destroy (struct oh323_pvt *pvt)
static void oh323_destroy_alias (struct oh323_alias *alias)
static void oh323_destroy_peer (struct oh323_peer *peer)
static void oh323_destroy_user (struct oh323_user *user)
static int oh323_digit_begin (struct ast_channel *c, char digit)
static int oh323_digit_end (struct ast_channel *c, char digit, unsigned int duration)
 Send (play) the specified digit to the channel.
static int oh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_glue_result oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance)
static int oh323_hangup (struct ast_channel *c)
static int oh323_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen)
static struct ast_frameoh323_read (struct ast_channel *c)
static struct ast_channeloh323_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause)
static struct ast_frameoh323_rtp_read (struct oh323_pvt *pvt)
 Retrieve audio/etc from channel. Assumes pvt->lock is already held.
static int oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active)
static int oh323_simulate_dtmf_end (const void *data)
static void oh323_update_info (struct ast_channel *c)
 Only channel structure should be locked.
static int oh323_write (struct ast_channel *c, struct ast_frame *frame)
static int progress (unsigned call_reference, const char *token, int inband)
static void prune_peers (void)
static struct oh323_alias * realtime_alias (const char *alias)
static struct oh323_peer * realtime_peer (const char *peername, struct sockaddr_in *sin)
static struct oh323_user * realtime_user (const call_details_t *cd)
static int receive_digit (unsigned call_reference, char digit, const char *token, int duration)
 Callback for sending digits from H.323 up to asterisk.
static const char * redirectingreason2str (int redirectingreason)
static int reload (void)
static int reload_config (int is_reload)
static void remote_hold (unsigned call_reference, const char *token, int is_hold)
static int restart_monitor (void)
static void set_dtmf_payload (unsigned call_reference, const char *token, int payload, int is_cisco)
static void set_local_capabilities (unsigned call_reference, const char *token)
static void set_peer_capabilities (unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
static call_options_t * setup_incoming_call (call_details_t *cd)
 Call-back function for incoming calls.
static int setup_outgoing_call (call_details_t *cd)
 Call-back function to establish an outgoing H.323 call.
static void setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
 Call-back function passing remote ip/port information from H.323 to asterisk.
static int unload_module (void)
static int update_common_options (struct ast_variable *v, struct call_options *options)
static int update_state (struct oh323_pvt *pvt, int state, int signal)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static int acceptAnonymous = 1
static struct h323_alias_list aliasl
 H323 alias list.
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static ast_mutex_t caplock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_reload
static const char config [] = "h323.conf"
static unsigned int cos = 0
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration - by default, jb is disabled.
static char gatekeeper [100]
static int gatekeeper_disable = 1
static int gatekeeper_discover = 0
static int gkroute = 0
static struct ast_jb_conf global_jbconf
static call_options_t global_options
static ast_mutex_t h323_reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the reload process.
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
static struct oh323_pvtiflist
 Private structure of a OpenH323 channel.
static ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
 Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static struct ast_rtp_glue oh323_rtp_glue
static struct ast_channel_tech oh323_tech
answer_call_cb on_answer_call
chan_ringing_cb on_chan_ringing
clear_con_cb on_connection_cleared
con_established_cb on_connection_established
on_rtp_cb on_external_rtp_create
hangup_cb on_hangup
onhold_cb on_hold
setup_incoming_cb on_incoming_call
setup_outbound_cb on_outgoing_call
progress_cb on_progress
receive_digit_cb on_receive_digit
rfc2833_cb on_set_rfc2833_payload
setcapabilities_cb on_setcapabilities
setpeercapabilities_cb on_setpeercapabilities
start_rtp_cb on_start_rtp_channel
static struct h323_peer_list peerl
 H323 peer list.
static struct ast_sched_contextsched
static char secret [50]
static const char tdesc [] = "The NuFone Network's Open H.323 Channel Driver"
static unsigned int tos = 0
static unsigned int unique = 0
static int userbyalias = 1
static struct h323_user_list userl
 H323 User list.


Detailed Description

This file is part of the chan_h323 driver for Asterisk.

Author:
Jeremy McNamara
See also
  • Config_h323
ExtRef:
OpenH323 http://www.voxgratia.org/

Definition in file chan_h323.c.


Define Documentation

#define GLOBAL_CAPABILITY

Definition at line 137 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 454 of file chan_h323.c.

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

Referenced by do_monitor(), and oh323_destroy().

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

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

Private structure should be locked on a call.

Definition at line 1028 of file chan_h323.c.

References __oh323_rtp_create(), oh323_pvt::accountcode, ast_channel::amaflags, oh323_pvt::amaflags, ast_party_caller::ani, ast_best_codec(), ast_channel_alloc, ast_channel_name(), ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_features(), ast_format_cap_from_old_bitfield(), ast_format_cap_set(), ast_format_cap_to_old_bitfield(), ast_format_copy(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), ast_rtp_instance_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_udptl_fd(), 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_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().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 974 of file chan_h323.c.

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

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

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

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

Channel and private structures should be already locked.

Definition at line 342 of file chan_h323.c.

References ast_channel::_softhangup, ast_channel_name(), ast_channel_set_fd(), ast_debug, ast_format_cap_from_old_bitfield(), ast_format_cap_to_old_bitfield(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_jb_configure(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hangup_with_cause(), ast_rtp_instance_fd(), ast_sched_add(), AST_SCHED_DEL, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_SOFTHANGUP_DEV, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, ast_frame::frametype, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, ast_frame_subclass::integer, LOG_DTMF, 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, ast_frame::subclass, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

static void __reg_module ( void   )  [static]

Definition at line 3496 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_module().

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

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

Definition at line 1231 of file chan_h323.c.

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

Referenced by realtime_alias(), and reload_config().

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

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

Definition at line 1540 of file chan_h323.c.

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

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

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

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

Definition at line 1416 of file chan_h323.c.

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

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

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

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

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

Referenced by load_module().

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

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 418 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

Definition at line 2416 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(), oh323_pvt::lock, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.

Referenced by load_module().

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

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

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

Referenced by load_module().

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

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

Definition at line 1718 of file chan_h323.c.

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

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

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

static void delete_aliases ( void   )  [static]

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

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

static void delete_users ( void   )  [static]

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

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

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

Definition at line 2608 of file chan_h323.c.

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

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

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

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

Returns:
Returns the local RTP information

Definition at line 1959 of file chan_h323.c.

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

Referenced by load_module().

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

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

Find a call by alias.

Definition at line 1875 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

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

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

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

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

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

Definition at line 1700 of file chan_h323.c.

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

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

01701 {
01702    struct oh323_peer *p;
01703 
01704    if (peer)
01705       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01706    else
01707       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01708 
01709    if (!p && realtime)
01710       p = realtime_peer(peer, sin);
01711 
01712    if (!p && h323debug)
01713       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>"));
01714 
01715    return p;
01716 }

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

Definition at line 1670 of file chan_h323.c.

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

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

static int h323_do_reload ( void   )  [static]

Definition at line 3198 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03199 {
03200    reload_config(1);
03201    return 0;
03202 }

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

Definition at line 1291 of file chan_h323.c.

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

Referenced by update_common_options().

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

static int h323_reload ( void   )  [static]

Definition at line 3164 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

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

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

Definition at line 2760 of file chan_h323.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2469 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(), oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, oh323_pvt::needhangup, and oh323_pvt::owner.

Referenced by load_module().

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

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3308 of file chan_h323.c.

References aliasl, answer_call(), ast_channel_register(), ast_cli_register(), ast_cli_register_multiple(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_format_cap_add_all_by_type(), ast_format_cap_alloc(), AST_FORMAT_TYPE_AUDIO, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_rtp_glue_unregister(), ast_sched_context_create(), ast_sched_context_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, ast_channel_tech::capabilities, chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), hangup_connection(), io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.

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

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

Definition at line 1688 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

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

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

Definition at line 1665 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01666 {
01667    return strcmp(ast_inet_ntoa(inaddr), addr);
01668 }

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

Definition at line 1141 of file chan_h323.c.

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

Referenced by oh323_request(), and setup_incoming_call().

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

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 670 of file chan_h323.c.

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

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

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

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

Definition at line 590 of file chan_h323.c.

References ast_channel::_state, ast_channel_name(), 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_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.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 499 of file chan_h323.c.

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

Referenced by oh323_request(), and setup_incoming_call().

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

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

Definition at line 289 of file chan_h323.c.

References ast_debug, and ast_free.

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

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

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

Definition at line 304 of file chan_h323.c.

References ast_debug, ast_free, and ast_free_ha().

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

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

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

Definition at line 296 of file chan_h323.c.

References ast_debug, ast_free, and ast_free_ha().

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

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

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

Definition at line 510 of file chan_h323.c.

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

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

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

Send (play) the specified digit to the channel.

Definition at line 551 of file chan_h323.c.

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

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

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

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

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

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

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

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

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 693 of file chan_h323.c.

References oh323_pvt::alreadygone, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_REQUESTED_CHAN_UNAVAIL, AST_CAUSE_USER_BUSY, ast_channel_name(), 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, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.

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

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

Definition at line 871 of file chan_h323.c.

References ast_channel::_state, oh323_pvt::alreadygone, ast_channel_name(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, 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, oh323_update_info(), oh323_pvt::rtp, and ast_channel::tech_pvt.

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

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

Definition at line 817 of file chan_h323.c.

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

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

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

Definition at line 1790 of file chan_h323.c.

References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_channel_linkedid(), ast_copy_string(), ast_debug, ast_format_cap_has_type(), AST_FORMAT_TYPE_AUDIO, ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_RTP_DTMF, AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), caplock, create_addr(), ext, oh323_pvt::exten, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, and restart_monitor().

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

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

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

Definition at line 760 of file chan_h323.c.

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

Referenced by oh323_read().

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

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

Definition at line 3265 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, LOG_ERROR, ast_channel::tech_pvt, and ast_channel::writeformat.

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

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

Definition at line 312 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, AST_FRAME_DTMF_END, ast_mutex_lock, ast_mutex_unlock, ast_queue_frame(), oh323_pvt::curDTMF, DEADLOCK_AVOIDANCE, oh323_pvt::DTMFsched, ast_frame::frametype, oh323_pvt::lock, and oh323_pvt::owner.

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

Definition at line 407 of file chan_h323.c.

References __oh323_update_info(), ast_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().

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

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

Definition at line 842 of file chan_h323.c.

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

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

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

Definition at line 2151 of file chan_h323.c.

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

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

static void prune_peers ( void   )  [static]

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

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

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

Definition at line 1266 of file chan_h323.c.

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

Referenced by find_alias().

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

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

Definition at line 1622 of file chan_h323.c.

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

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

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

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

Definition at line 1502 of file chan_h323.c.

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

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

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

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

References ast_channel_trylock, ast_channel_unlock, AST_CONTROL_FLASH, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_unlock, ast_queue_control(), ast_queue_frame(), ast_sched_add(), AST_SCHED_DEL, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, find_call_locked(), ast_frame::frametype, ast_frame_subclass::integer, ast_frame::len, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_frame::samples, and ast_frame::subclass.

Referenced by load_module().

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

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

Definition at line 273 of file chan_h323.c.

Referenced by __oh323_new().

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

static int reload ( void   )  [static]

Definition at line 3204 of file chan_h323.c.

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

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

static int reload_config ( int  is_reload  )  [static]

Definition at line 2911 of file chan_h323.c.

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

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

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

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

Definition at line 2582 of file chan_h323.c.

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

Referenced by load_module().

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

static int restart_monitor ( void   )  [static]

Definition at line 2676 of file chan_h323.c.

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

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

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

Definition at line 2497 of file chan_h323.c.

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

Referenced by load_module().

02498 {
02499    struct oh323_pvt *pvt;
02500 
02501    if (h323debug)
02502       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02503 
02504    pvt = find_call_locked(call_reference, token);
02505    if (!pvt) {
02506       return;
02507    }
02508    if (pvt->rtp) {
02509       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);
02510    }
02511    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02512    ast_mutex_unlock(&pvt->lock);
02513    if (h323debug)
02514       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02515 }

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

Definition at line 2552 of file chan_h323.c.

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

Referenced by load_module().

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

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

Definition at line 2517 of file chan_h323.c.

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

Referenced by load_module().

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

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

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

Referenced by load_module().

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

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

References cleanup_call_details().

Referenced by load_module().

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

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 2005 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_cap_alloc_nolock(), ast_format_cap_copy(), ast_format_cap_destroy(), ast_format_cap_from_old_bitfield(), ast_format_cap_identical(), AST_FORMAT_G726_AAL2, ast_format_to_old_bitfield(), ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_unlock, ast_queue_control(), ast_rtp_codecs_payload_lookup(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_rtp_instance_stop(), AST_RTP_OPT_G726_NONSTANDARD, ast_set_read_format(), ast_set_write_format(), ast_sockaddr_from_sin, ast_rtp_payload_type::asterisk_format, find_call_locked(), ast_rtp_payload_type::format, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, 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().

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

static int unload_module ( void   )  [static]

Definition at line 3416 of file chan_h323.c.

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

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

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

Definition at line 1307 of file chan_h323.c.

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

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

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

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

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

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


Variable Documentation

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

Definition at line 3496 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 153 of file chan_h323.c.

struct h323_alias_list aliasl [static]

Definition at line 3496 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 135 of file chan_h323.c.

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

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

Definition at line 229 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2852 of file chan_h323.c.

struct ast_cli_entry cli_h323_reload [static]

Initial value:

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

Definition at line 3213 of file chan_h323.c.

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

Definition at line 133 of file chan_h323.c.

unsigned int cos = 0 [static]

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

Definition at line 134 of file chan_h323.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

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

Definition at line 121 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 147 of file chan_h323.c.

int gatekeeper_disable = 1 [static]

Definition at line 148 of file chan_h323.c.

int gatekeeper_discover = 0 [static]

Definition at line 149 of file chan_h323.c.

int gkroute = 0 [static]

Definition at line 150 of file chan_h323.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 129 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 159 of file chan_h323.c.

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

Protect the reload process.

Definition at line 232 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 233 of file chan_h323.c.

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 146 of file chan_h323.c.

int h323debug

global debug flag

Definition at line 117 of file chan_h323.c.

struct oh323_pvt * iflist [static]

Private structure of a OpenH323 channel.

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

Protect the interface list (oh323_pvt)

Definition at line 222 of file chan_h323.c.

struct io_context* io [static]

Definition at line 220 of file chan_h323.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 237 of file chan_h323.c.

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

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

Definition at line 226 of file chan_h323.c.

struct ast_rtp_glue oh323_rtp_glue [static]

Initial value:

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

Definition at line 3302 of file chan_h323.c.

struct ast_channel_tech oh323_tech [static]

Definition at line 256 of file chan_h323.c.

answer_call_cb on_answer_call

Definition at line 109 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 106 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 108 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 107 of file chan_h323.c.

Definition at line 102 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 112 of file chan_h323.c.

onhold_cb on_hold

Definition at line 115 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 104 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 105 of file chan_h323.c.

progress_cb on_progress

Definition at line 110 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 101 of file chan_h323.c.

Definition at line 111 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 113 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 114 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 103 of file chan_h323.c.

struct h323_peer_list peerl [static]

struct ast_sched_context* sched [static]

Definition at line 219 of file chan_h323.c.

char secret[50] [static]

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

Variables required by Asterisk

Definition at line 132 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 154 of file chan_h323.c.

unsigned int unique = 0 [static]

Definition at line 157 of file chan_h323.c.

int userbyalias = 1 [static]

Definition at line 152 of file chan_h323.c.

struct h323_user_list userl [static]


Generated on Sat Feb 11 06:34:33 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6