Sat Mar 10 01:54:54 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 "h323/chan_h323.h"

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .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_RECURSIVE_MUTEX_INITIALIZER_NP , 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_RECURSIVE_MUTEX_INITIALIZER_NP , 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_RECURSIVE_MUTEX_INITIALIZER_NP , 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_RECURSIVE_MUTEX_INITIALIZER_NP , 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 sched_contextsched
static char secret [50]
static const char tdesc [] = "The NuFone Network's Open H.323 Channel Driver"
static unsigned int tos = 0
static unsigned int unique = 0
static int userbyalias = 1
static struct h323_user_list userl
 H323 User list.


Detailed Description

This file is part of the chan_h323 driver for Asterisk.

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

Definition in file chan_h323.c.


Define Documentation

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

Definition at line 135 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 446 of file chan_h323.c.

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

Referenced by do_monitor(), and oh323_destroy().

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

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

Private structure should be locked on a call.

Definition at line 1018 of file chan_h323.c.

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

Referenced by answer_call(), and oh323_request().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 964 of file chan_h323.c.

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

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

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

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

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 3456 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_module().

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

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

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

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

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

Definition at line 1508 of file chan_h323.c.

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

Referenced by reload_config(), and set_config().

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

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

Definition at line 1384 of file chan_h323.c.

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

Referenced by reload_config(), and set_config().

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

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

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

Referenced by load_module().

02357 {
02358    struct oh323_pvt *pvt;
02359 
02360    if (h323debug)
02361       ast_debug(1, "Ringing on %s\n", token);
02362 
02363    pvt = find_call_locked(call_reference, token);
02364    if (!pvt) {
02365       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02366       return;
02367    }
02368    if (!pvt->owner) {
02369       ast_mutex_unlock(&pvt->lock);
02370       ast_log(LOG_ERROR, "Channel has no owner\n");
02371       return;
02372    }
02373    update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02374    ast_mutex_unlock(&pvt->lock);
02375    return;
02376 }

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 410 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

Definition at line 2382 of file chan_h323.c.

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

Referenced by load_module().

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

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

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

Referenced by load_module().

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

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

Definition at line 1686 of file chan_h323.c.

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

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

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

static void delete_aliases ( void   )  [static]

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

02854 {
02855    int pruned = 0;
02856 
02857    /* Delete all aliases */
02858    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02859    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02860       ASTOBJ_RDLOCK(iterator);
02861       ASTOBJ_MARK(iterator);
02862       ++pruned;
02863       ASTOBJ_UNLOCK(iterator);
02864    } while (0) );
02865    if (pruned) {
02866       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02867    }
02868    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02869 }

static void delete_users ( void   )  [static]

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

02828 {
02829    int pruned = 0;
02830 
02831    /* Delete all users */
02832    ASTOBJ_CONTAINER_WRLOCK(&userl);
02833    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02834       ASTOBJ_RDLOCK(iterator);
02835       ASTOBJ_MARK(iterator);
02836       ++pruned;
02837       ASTOBJ_UNLOCK(iterator);
02838    } while (0) );
02839    if (pruned) {
02840       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02841    }
02842    ASTOBJ_CONTAINER_UNLOCK(&userl);
02843 
02844    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02845    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02846       ASTOBJ_RDLOCK(iterator);
02847       ASTOBJ_MARK(iterator);
02848       ASTOBJ_UNLOCK(iterator);
02849    } while (0) );
02850    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02851 }

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

Definition at line 2574 of file chan_h323.c.

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

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

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

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

Returns:
Returns the local RTP information

Definition at line 1929 of file chan_h323.c.

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

Referenced by load_module().

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

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

Find a call by alias.

Definition at line 1845 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

01846 {
01847    struct oh323_alias *a;
01848 
01849    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01850 
01851    if (!a && realtime)
01852       a = realtime_alias(source_aliases);
01853 
01854    return a;
01855 }

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

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

01169 {
01170    struct oh323_pvt *pvt;
01171 
01172    ast_mutex_lock(&iflock);
01173    pvt = iflist;
01174    while(pvt) {
01175       if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
01176          /* Found the call */
01177          if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
01178             ast_mutex_lock(&pvt->lock);
01179             ast_mutex_unlock(&iflock);
01180             return pvt;
01181          } else if (token == NULL) {
01182             ast_log(LOG_WARNING, "Call Token is NULL\n");
01183             ast_mutex_lock(&pvt->lock);
01184             ast_mutex_unlock(&iflock);
01185             return pvt;
01186          }
01187       }
01188       pvt = pvt->next;
01189    }
01190    ast_mutex_unlock(&iflock);
01191    return NULL;
01192 }

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

Definition at line 1668 of file chan_h323.c.

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

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

01669 {
01670    struct oh323_peer *p;
01671 
01672    if (peer)
01673       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01674    else
01675       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01676 
01677    if (!p && realtime)
01678       p = realtime_peer(peer, sin);
01679 
01680    if (!p && h323debug)
01681       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>"));
01682 
01683    return p;
01684 }

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

Definition at line 1638 of file chan_h323.c.

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

01639 {
01640    struct oh323_user *u;
01641 
01642    if (userbyalias)
01643       u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01644    else
01645       u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01646 
01647    if (!u && realtime)
01648       u = realtime_user(cd);
01649 
01650    if (!u && h323debug)
01651       ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01652 
01653    return u;
01654 }

static int h323_do_reload ( void   )  [static]

Definition at line 3164 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03165 {
03166    reload_config(1);
03167    return 0;
03168 }

static int h323_reload ( void   )  [static]

Definition at line 3130 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

03131 {
03132    ast_mutex_lock(&h323_reload_lock);
03133    if (h323_reloading) {
03134       ast_verbose("Previous H.323 reload not yet done\n");
03135    } else {
03136       h323_reloading = 1;
03137    }
03138    ast_mutex_unlock(&h323_reload_lock);
03139    restart_monitor();
03140    return 0;
03141 }

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

Definition at line 2726 of file chan_h323.c.

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

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

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

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

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

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

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

03144 {
03145    switch (cmd) {
03146    case CLI_INIT:
03147       e->command = "h323 reload";
03148       e->usage =
03149          "Usage: h323 reload\n"
03150          "       Reloads H.323 configuration from h323.conf\n";
03151       return NULL;
03152    case CLI_GENERATE:
03153       return NULL;
03154    }
03155 
03156    if (a->argc != 2)
03157       return CLI_SHOWUSAGE;
03158 
03159    h323_reload();
03160 
03161    return CLI_SUCCESS;
03162 }

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

Definition at line 2703 of file chan_h323.c.

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

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

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

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

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

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

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

02777 {
02778    switch (cmd) {
02779    case CLI_INIT:
02780       e->command = "h323 show tokens";
02781       e->usage =
02782          "Usage: h323 show tokens\n"
02783          "       Print out all active call tokens\n";
02784       return NULL;
02785    case CLI_GENERATE:
02786       return NULL;
02787    }
02788 
02789    if (a->argc != 3)
02790       return CLI_SHOWUSAGE;
02791 
02792    h323_show_tokens();
02793 
02794    return CLI_SUCCESS;
02795 }

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

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

02798 {
02799    switch (cmd) {
02800    case CLI_INIT:
02801       e->command = "h323 show version";
02802       e->usage =
02803          "Usage: h323 show version\n"
02804          "     Show the version of the H.323 library in use\n";
02805       return NULL;
02806    case CLI_GENERATE:
02807       return NULL;
02808    }
02809 
02810    if (a->argc != 3)
02811       return CLI_SHOWUSAGE;
02812 
02813    h323_show_version();
02814    
02815    return CLI_SUCCESS;
02816 }

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

Definition at line 2435 of file chan_h323.c.

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

Referenced by load_module().

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

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3274 of file chan_h323.c.

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

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

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

Definition at line 1656 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01657 {
01658    int res;
01659 
01660    if (!sin)
01661       res = -1;
01662    else
01663       res = inaddrcmp(&addr , sin);
01664 
01665    return res;
01666 }

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

Definition at line 1633 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01634 {
01635    return strcmp(ast_inet_ntoa(inaddr), addr);
01636 }

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

Definition at line 1125 of file chan_h323.c.

References ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, AST_RTP_DTMF, ast_rtp_instance_destroy(), iflist, iflock, and LOG_ERROR.

Referenced by oh323_request(), and setup_incoming_call().

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

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 662 of file chan_h323.c.

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

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

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

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

Definition at line 582 of file chan_h323.c.

References ast_channel::_state, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_party_id_presentation(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verb, oh323_pvt::cd, ast_channel::connected, oh323_pvt::exten, ast_party_redirecting::from, ast_party_connected_line::id, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_party_id::name, ast_channel::name, ast_party_id::number, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), ast_party_number::plan, ast_channel::redirecting, oh323_pvt::sa, ast_party_name::str, ast_party_number::str, ast_channel::tech_pvt, ast_channel::transfercapability, ast_party_name::valid, and ast_party_number::valid.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 491 of file chan_h323.c.

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

Referenced by oh323_request(), and setup_incoming_call().

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

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

Definition at line 282 of file chan_h323.c.

References ast_debug, and ast_free.

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

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

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

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

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

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

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

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

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

Definition at line 502 of file chan_h323.c.

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

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

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

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

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

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

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

00951 {
00952    struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt;
00953 
00954    ast_mutex_lock(&pvt->lock);
00955    if (pvt->owner != oldchan) {
00956       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
00957       return -1;
00958    }
00959    pvt->owner = newchan;
00960    ast_mutex_unlock(&pvt->lock);
00961    return 0;
00962 }

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

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

03183 {
03184    struct oh323_pvt *pvt;
03185    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
03186 
03187    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03188       return AST_RTP_GLUE_RESULT_FORBID;
03189 
03190    ast_mutex_lock(&pvt->lock);
03191    *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
03192 #if 0
03193    if (pvt->options.bridge) {
03194       res = AST_RTP_GLUE_RESULT_REMOTE;
03195    }
03196 #endif
03197    ast_mutex_unlock(&pvt->lock);
03198 
03199    return res;
03200 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 685 of file chan_h323.c.

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

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

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

Definition at line 861 of file chan_h323.c.

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

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

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

Definition at line 807 of file chan_h323.c.

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

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

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

Definition at line 1758 of file chan_h323.c.

References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_RTP_DTMF, AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), caplock, create_addr(), ext, oh323_pvt::exten, gatekeeper_disable, global_options, h323debug, oh323_pvt::jointcapability, ast_channel::linkedid, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, restart_monitor(), and unique.

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

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

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

Definition at line 752 of file chan_h323.c.

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

Referenced by oh323_read().

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

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

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

03232 {
03233    /* XXX Deal with Video */
03234    struct oh323_pvt *pvt;
03235    struct sockaddr_in them = { 0, };
03236    struct sockaddr_in us = { 0, };
03237 #if 0 /* Native bridge still isn't ready */
03238    char *mode;
03239 #endif
03240 
03241    if (!rtp) {
03242       return 0;
03243    }
03244 
03245 #if 0 /* Native bridge still isn't ready */
03246    mode = convertcap(chan->writeformat);
03247 #endif
03248 
03249    pvt = (struct oh323_pvt *) chan->tech_pvt;
03250    if (!pvt) {
03251       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03252       return -1;
03253    }
03254    {
03255       struct ast_sockaddr tmp;
03256 
03257       ast_rtp_instance_get_remote_address(rtp, &tmp);
03258       ast_sockaddr_to_sin(&tmp, &them);
03259       ast_rtp_instance_get_local_address(rtp, &tmp);
03260       ast_sockaddr_to_sin(&tmp, &us);
03261    }
03262 #if 0 /* Native bridge still isn't ready */
03263    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03264 #endif
03265    return 0;
03266 }

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

Definition at line 305 of file chan_h323.c.

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

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

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

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

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

Definition at line 832 of file chan_h323.c.

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

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

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

Definition at line 2117 of file chan_h323.c.

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

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

static void prune_peers ( void   )  [static]

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

02872 {
02873    /* Prune peers who still are supposed to be deleted */
02874    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02875 }

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

Definition at line 1250 of file chan_h323.c.

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

Referenced by find_alias().

01251 {
01252    struct ast_variable *var, *tmp;
01253    struct oh323_alias *a;
01254 
01255    var = ast_load_realtime("h323", "name", alias, SENTINEL);
01256 
01257    if (!var)
01258       return NULL;
01259 
01260    for (tmp = var; tmp; tmp = tmp->next) {
01261       if (!strcasecmp(tmp->name, "type") &&
01262       !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
01263          ast_variables_destroy(var);
01264          return NULL;
01265       }
01266    }
01267 
01268    a = build_alias(alias, var, NULL, 1);
01269 
01270    ast_variables_destroy(var);
01271 
01272    return a;
01273 }

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

Definition at line 1590 of file chan_h323.c.

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

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

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

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

Definition at line 1470 of file chan_h323.c.

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

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

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

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

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

Referenced by load_module().

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

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

Definition at line 266 of file chan_h323.c.

Referenced by __oh323_new().

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

static int reload ( void   )  [static]

Definition at line 3170 of file chan_h323.c.

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

03171 {
03172    if (!sched || !io) {
03173       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03174       return 0;
03175    }
03176    return h323_reload();
03177 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2877 of file chan_h323.c.

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

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

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

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

Definition at line 2548 of file chan_h323.c.

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

Referenced by load_module().

02549 {
02550    struct oh323_pvt *pvt;
02551 
02552    if (h323debug)
02553       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02554 
02555    pvt = find_call_locked(call_reference, token);
02556    if (!pvt)
02557       return;
02558    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02559       if (is_hold)
02560          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02561       else
02562          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02563       ast_channel_unlock(pvt->owner);
02564    }
02565    else {
02566       if (is_hold)
02567          pvt->newcontrol = AST_CONTROL_HOLD;
02568       else
02569          pvt->newcontrol = AST_CONTROL_UNHOLD;
02570    }
02571    ast_mutex_unlock(&pvt->lock);
02572 }

static int restart_monitor ( void   )  [static]

Definition at line 2642 of file chan_h323.c.

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

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

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

Definition at line 2463 of file chan_h323.c.

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

Referenced by load_module().

02464 {
02465    struct oh323_pvt *pvt;
02466 
02467    if (h323debug)
02468       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02469 
02470    pvt = find_call_locked(call_reference, token);
02471    if (!pvt) {
02472       return;
02473    }
02474    if (pvt->rtp) {
02475       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);
02476    }
02477    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02478    ast_mutex_unlock(&pvt->lock);
02479    if (h323debug)
02480       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02481 }

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

Definition at line 2518 of file chan_h323.c.

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

Referenced by load_module().

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

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

Definition at line 2483 of file chan_h323.c.

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

Referenced by load_module().

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

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

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

Referenced by load_module().

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

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

References cleanup_call_details().

Referenced by load_module().

02345 {
02346    /* Use argument here or free it immediately */
02347    cleanup_call_details(cd);
02348 
02349    return 1;
02350 }

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

References __oh323_rtp_create(), oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_debug, AST_FORMAT_G726_AAL2, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_unlock, ast_queue_control(), ast_rtp_codecs_payload_lookup(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_rtp_instance_stop(), AST_RTP_OPT_G726_NONSTANDARD, ast_set_read_format(), ast_set_write_format(), ast_sockaddr_from_sin, ast_rtp_payload_type::code, find_call_locked(), h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, ast_channel::nativeformats, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_channel::writeformat.

Referenced by load_module().

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

static int unload_module ( void   )  [static]

Definition at line 3377 of file chan_h323.c.

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

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

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

Definition at line 1275 of file chan_h323.c.

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

Referenced by build_peer(), and build_user().

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

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

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

01195 {
01196    if (!pvt)
01197       return 0;
01198    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01199       if (state >= 0)
01200          ast_setstate(pvt->owner, state);
01201       if (signal >= 0)
01202          ast_queue_control(pvt->owner, signal);
01203       ast_channel_unlock(pvt->owner);
01204       return 1;
01205    }
01206    else {
01207       if (state >= 0)
01208          pvt->newstate = state;
01209       if (signal >= 0)
01210          pvt->newcontrol = signal;
01211       return 0;
01212    }
01213 }


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

Definition at line 3456 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 145 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct h323_alias_list aliasl [static]

H323 alias list.

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

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3456 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 133 of file chan_h323.c.

ast_mutex_t caplock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , 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 221 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2818 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_h323_reload [static]

Initial value:

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

Definition at line 3179 of file chan_h323.c.

Referenced by load_module(), and unload_module().

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

Definition at line 131 of file chan_h323.c.

unsigned int cos = 0 [static]

Definition at line 147 of file chan_h323.c.

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

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

Definition at line 132 of file chan_h323.c.

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

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

Definition at line 119 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 139 of file chan_h323.c.

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

int gatekeeper_disable = 1 [static]

Definition at line 140 of file chan_h323.c.

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

int gatekeeper_discover = 0 [static]

Definition at line 141 of file chan_h323.c.

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

int gkroute = 0 [static]

Definition at line 142 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct ast_jb_conf global_jbconf [static]

Definition at line 127 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 151 of file chan_h323.c.

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

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

Protect the reload process.

Definition at line 224 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 225 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 138 of file chan_h323.c.

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

int h323debug

global debug flag

Definition at line 115 of file chan_h323.c.

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

struct oh323_pvt * iflist [static]

Private structure of a OpenH323 channel.

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

Protect the interface list (oh323_pvt)

Definition at line 214 of file chan_h323.c.

struct io_context* io [static]

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

ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , 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 218 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 3268 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech oh323_tech [static]

Definition at line 248 of file chan_h323.c.

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

answer_call_cb on_answer_call

Definition at line 107 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 104 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 106 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 105 of file chan_h323.c.

on_rtp_cb on_external_rtp_create

Definition at line 100 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 110 of file chan_h323.c.

onhold_cb on_hold

Definition at line 113 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 102 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 103 of file chan_h323.c.

progress_cb on_progress

Definition at line 108 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 99 of file chan_h323.c.

rfc2833_cb on_set_rfc2833_payload

Definition at line 109 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 111 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 112 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 101 of file chan_h323.c.

struct h323_peer_list peerl [static]

H323 peer list.

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

struct sched_context* sched [static]

Definition at line 211 of file chan_h323.c.

char secret[50] [static]

Definition at line 148 of file chan_h323.c.

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

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

Variables required by Asterisk

Definition at line 130 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 146 of file chan_h323.c.

Referenced by reload_config().

unsigned int unique = 0 [static]

Definition at line 149 of file chan_h323.c.

Referenced by oh323_request().

int userbyalias = 1 [static]

Definition at line 144 of file chan_h323.c.

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

struct h323_user_list userl [static]

H323 User list.

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


Generated on Sat Mar 10 01:54:55 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7