Wed Oct 28 13:32:01 2009

Asterisk developer's documentation


chan_h323.c File Reference

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

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

Include dependency graph for chan_h323.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

static void __oh323_destroy (struct oh323_pvt *pvt)
static struct ast_channel__oh323_new (struct oh323_pvt *pvt, int state, const char *host, const char *linkedid)
 Private structure should be locked on a call.
static int __oh323_rtp_create (struct oh323_pvt *pvt)
static void __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt)
 Channel and private structures should be already locked.
static void __reg_module (void)
static void __unreg_module (void)
static int answer_call (unsigned call_reference, const char *token)
 Call-back function to start PBX when OpenH323 ready to serve incoming call.
static struct oh323_alias * build_alias (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_peer * build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_user * build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static void chan_ringing (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel is ringing Returns nothing.
static void cleanup_call_details (call_details_t *cd)
static void cleanup_connection (unsigned call_reference, const char *call_token)
 Call-back function to cleanup communication Returns nothing,.
static void connection_made (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel has been answered Returns nothing.
static char * convertcap (int cap)
static int create_addr (struct oh323_pvt *pvt, char *opeer)
static void delete_aliases (void)
static void delete_users (void)
static void * do_monitor (void *data)
static struct rtp_info * external_rtp_create (unsigned call_reference, const char *token)
 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, int 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, int 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_DEFAULT , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 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
  • Config_h323
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 131 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 442 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, oh323_pvt::owner, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::vad.

Referenced by do_monitor(), and oh323_destroy().

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

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

Private structure should be locked on a call.

Definition at line 997 of file chan_h323.c.

References __oh323_rtp_create(), accountcode, oh323_pvt::accountcode, ast_channel::amaflags, oh323_pvt::amaflags, 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(), oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, cid_name, cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, ast_channel::context, oh323_pvt::context, DSP_FEATURE_DIGIT_DETECT, ast_channel::exten, oh323_pvt::exten, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, redirectingreason2str(), ast_channel::rings, oh323_pvt::rtp, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by answer_call(), and oh323_request().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 949 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, bindaddr, oh323_pvt::dtmf_pt, errno, global_jbconf, oh323_pvt::lock, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, and oh323_pvt::update_rtp_info.

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

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

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 331 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, ast_frame::frametype, 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, ast_frame::subclass, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

static void __reg_module ( void   )  [static]

Definition at line 3394 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_module().

02218 {
02219    struct oh323_pvt *pvt;
02220    struct ast_channel *c = NULL;
02221    enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
02222    char tmp_exten[sizeof(pvt->exten)];
02223 
02224    if (h323debug)
02225       ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
02226 
02227    /* Find the call or allocate a private structure if call not found */
02228    pvt = find_call_locked(call_reference, token);
02229    if (!pvt) {
02230       ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
02231       return 0;
02232    }
02233    /* Check if requested extension@context pair exists in the dialplan */
02234    ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
02235 
02236    /* Try to find best extension in specified context */
02237    if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
02238       if (tmp_exten[0] == 's')
02239          try_exten = ext_s;
02240       else if (tmp_exten[0] == 'i')
02241          try_exten = ext_i;
02242       else
02243          try_exten = ext_original;
02244    } else
02245       try_exten = ext_original;
02246    do {
02247       if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
02248          break;
02249       switch (try_exten) {
02250       case ext_original:
02251          tmp_exten[0] = 's';
02252          tmp_exten[1] = '\0';
02253          try_exten = ext_s;
02254          break;
02255       case ext_s:
02256          tmp_exten[0] = 'i';
02257          try_exten = ext_i;
02258          break;
02259       case ext_i:
02260          try_exten = ext_notexists;
02261          break;
02262       default:
02263          break;
02264       }
02265    } while (try_exten != ext_notexists);
02266 
02267    /* Drop the call if we don't have <exten>, s and i extensions */
02268    if (try_exten == ext_notexists) {
02269       ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
02270       ast_mutex_unlock(&pvt->lock);
02271       h323_clear_call(token, AST_CAUSE_UNALLOCATED);
02272       return 0;
02273    } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
02274       if (h323debug)
02275          ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
02276       ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
02277    }
02278 
02279    /* allocate a channel and tell asterisk about it */
02280    c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL);
02281 
02282    /* And release when done */
02283    ast_mutex_unlock(&pvt->lock);
02284    if (!c) {
02285       ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
02286       return 0;
02287    }
02288    return 1;
02289 }

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

Definition at line 1189 of file chan_h323.c.

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

Referenced by realtime_alias(), and reload_config().

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

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

Definition at line 1476 of file chan_h323.c.

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

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

01477 {
01478    struct oh323_peer *peer;
01479    struct ast_ha *oldha;
01480    int found = 0;
01481 
01482    peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
01483 
01484    if (peer)
01485       found++;
01486    else {
01487       if (!(peer = ast_calloc(1, sizeof(*peer))))
01488          return NULL;
01489       ASTOBJ_INIT(peer);
01490    }
01491    oldha = peer->ha;
01492    peer->ha = NULL;
01493    memcpy(&peer->options, &global_options, sizeof(peer->options));
01494    peer->options.dtmfmode = 0;
01495    peer->options.holdHandling = 0;
01496    peer->addr.sin_port = htons(h323_signalling_port);
01497    peer->addr.sin_family = AF_INET;
01498    if (!found && name)
01499       ast_copy_string(peer->name, name, sizeof(peer->name));
01500 
01501 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */
01502    if (peer->chanvars) {
01503       ast_variables_destroy(peer->chanvars);
01504       peer->chanvars = NULL;
01505    }
01506 #endif
01507    /* Default settings for mailbox */
01508    peer->mailbox[0] = '\0';
01509 
01510    for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
01511       if (!update_common_options(v, &peer->options))
01512          continue;
01513       if (!strcasecmp(v->name, "host")) {
01514          if (!strcasecmp(v->value, "dynamic")) {
01515             ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
01516             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01517             return NULL;
01518          }
01519          if (ast_get_ip(&peer->addr, v->value)) {
01520             ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
01521             ASTOBJ_UNREF(peer, oh323_destroy_peer);
01522             return NULL;
01523          }
01524       } else if (!strcasecmp(v->name, "port")) {
01525          peer->addr.sin_port = htons(atoi(v->value));
01526       } else if (!strcasecmp(v->name, "permit") ||
01527                !strcasecmp(v->name, "deny")) {
01528          int ha_error = 0;
01529 
01530          peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
01531          if (ha_error)
01532             ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
01533       } else if (!strcasecmp(v->name, "mailbox")) {
01534          ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
01535       } else if (!strcasecmp(v->name, "hasvoicemail")) {
01536          if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
01537             ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
01538          }
01539       }
01540    }
01541    if (!peer->options.dtmfmode)
01542       peer->options.dtmfmode = global_options.dtmfmode;
01543    if (peer->options.holdHandling == ~0)
01544       peer->options.holdHandling = 0;
01545    else if (!peer->options.holdHandling)
01546       peer->options.holdHandling = global_options.holdHandling;
01547    ASTOBJ_UNMARK(peer);
01548    ast_free_ha(oldha);
01549    return peer;
01550 }

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

Definition at line 1358 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_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, format, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_user(), update_common_options(), userl, and ast_variable::value.

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

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

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

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

Referenced by load_module().

02309 {
02310    struct oh323_pvt *pvt;
02311 
02312    if (h323debug)
02313       ast_debug(1, "Ringing on %s\n", token);
02314 
02315    pvt = find_call_locked(call_reference, token);
02316    if (!pvt) {
02317       ast_log(LOG_ERROR, "Something is wrong: ringing\n");
02318       return;
02319    }
02320    if (!pvt->owner) {
02321       ast_mutex_unlock(&pvt->lock);
02322       ast_log(LOG_ERROR, "Channel has no owner\n");
02323       return;
02324    }
02325    update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
02326    ast_mutex_unlock(&pvt->lock);
02327    return;
02328 }

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 406 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

Definition at line 2334 of file chan_h323.c.

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

Referenced by load_module().

02335 {
02336    struct oh323_pvt *pvt;
02337 
02338    if (h323debug)
02339       ast_debug(1, "Cleaning connection to %s\n", call_token);
02340 
02341    while (1) {
02342       pvt = find_call_locked(call_reference, call_token);
02343       if (!pvt) {
02344          if (h323debug)
02345             ast_debug(1, "No connection for %s\n", call_token);
02346          return;
02347       }
02348       if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02349          break;
02350 #if 1
02351       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02352 #ifdef DEBUG_THREADS
02353       /* XXX to be completed
02354        * If we want to print more info on who is holding the lock,
02355        * implement the relevant code in lock.h and use the routines
02356        * supplied there.
02357        */
02358 #endif
02359 #endif
02360       ast_mutex_unlock(&pvt->lock);
02361       usleep(1);
02362    }
02363    if (pvt->rtp) {
02364       /* Immediately stop RTP */
02365       ast_rtp_instance_destroy(pvt->rtp);
02366       pvt->rtp = NULL;
02367    }
02368    /* Free dsp used for in-band DTMF detection */
02369    if (pvt->vad) {
02370       ast_dsp_free(pvt->vad);
02371       pvt->vad = NULL;
02372    }
02373    cleanup_call_details(&pvt->cd);
02374    pvt->alreadygone = 1;
02375    /* Send hangup */
02376    if (pvt->owner) {
02377       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02378       ast_queue_hangup(pvt->owner);
02379       ast_channel_unlock(pvt->owner);
02380    }
02381    ast_mutex_unlock(&pvt->lock);
02382    if (h323debug)
02383       ast_debug(1, "Connection to %s cleaned\n", call_token);
02384    return;
02385 }

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

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

Referenced by load_module().

02043 {
02044    struct oh323_pvt *pvt;
02045 
02046    if (h323debug)
02047       ast_debug(1, "Call %s answered\n", token);
02048 
02049    pvt = find_call_locked(call_reference, token);
02050    if (!pvt) {
02051       ast_log(LOG_ERROR, "Something is wrong: connection\n");
02052       return;
02053    }
02054 
02055    /* Inform asterisk about remote party connected only on outgoing calls */
02056    if (!pvt->outgoing) {
02057       ast_mutex_unlock(&pvt->lock);
02058       return;
02059    }
02060    /* Do not send ANSWER message more than once */
02061    if (!pvt->connection_established) {
02062       pvt->connection_established = 1;
02063       update_state(pvt, -1, AST_CONTROL_ANSWER);
02064    }
02065    ast_mutex_unlock(&pvt->lock);
02066    return;
02067 }

static char* convertcap ( int  cap  )  [static]

Definition at line 3154 of file chan_h323.c.

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

Referenced by oh323_set_rtp_peer().

03155 {
03156    switch (cap) {
03157    case AST_FORMAT_G723_1:
03158       return "G.723";
03159    case AST_FORMAT_GSM:
03160       return "GSM";
03161    case AST_FORMAT_ULAW:
03162       return "ULAW";
03163    case AST_FORMAT_ALAW:
03164       return "ALAW";
03165    case AST_FORMAT_G722:
03166       return "G.722";
03167    case AST_FORMAT_ADPCM:
03168       return "G.728";
03169    case AST_FORMAT_G729A:
03170       return "G.729";
03171    case AST_FORMAT_SPEEX:
03172       return "SPEEX";
03173    case AST_FORMAT_ILBC:
03174       return "ILBC";
03175    default:
03176       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03177       return NULL;
03178    }
03179 }

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

Definition at line 1648 of file chan_h323.c.

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

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

01649 {
01650    struct hostent *hp;
01651    struct ast_hostent ahp;
01652    struct oh323_peer *p;
01653    int portno;
01654    int found = 0;
01655    char *port;
01656    char *hostn;
01657    char peer[256] = "";
01658 
01659    ast_copy_string(peer, opeer, sizeof(peer));
01660    port = strchr(peer, ':');
01661    if (port) {
01662       *port = '\0';
01663       port++;
01664    }
01665    pvt->sa.sin_family = AF_INET;
01666    p = find_peer(peer, NULL, 1);
01667    if (p) {
01668       found++;
01669       memcpy(&pvt->options, &p->options, sizeof(pvt->options));
01670       pvt->jointcapability = pvt->options.capability;
01671       if (pvt->options.dtmfmode) {
01672          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01673             pvt->nonCodecCapability |= AST_RTP_DTMF;
01674          } else {
01675             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01676          }
01677       }
01678       if (p->addr.sin_addr.s_addr) {
01679          pvt->sa.sin_addr = p->addr.sin_addr;
01680          pvt->sa.sin_port = p->addr.sin_port;
01681       }
01682       ASTOBJ_UNREF(p, oh323_destroy_peer);
01683    }
01684    if (!p && !found) {
01685       hostn = peer;
01686       if (port) {
01687          portno = atoi(port);
01688       } else {
01689          portno = h323_signalling_port;
01690       }
01691       hp = ast_gethostbyname(hostn, &ahp);
01692       if (hp) {
01693          memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
01694          pvt->sa.sin_port = htons(portno);
01695          /* Look peer by address */
01696          p = find_peer(NULL, &pvt->sa, 1);
01697          memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
01698          pvt->jointcapability = pvt->options.capability;
01699          if (p) {
01700             ASTOBJ_UNREF(p, oh323_destroy_peer);
01701          }
01702          if (pvt->options.dtmfmode) {
01703             if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01704                pvt->nonCodecCapability |= AST_RTP_DTMF;
01705             } else {
01706                pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01707             }
01708          }
01709          return 0;
01710       } else {
01711          ast_log(LOG_WARNING, "No such host: %s\n", peer);
01712          return -1;
01713       }
01714    } else if (!found) {
01715       return -1;
01716    } else {
01717       return 0;
01718    }
01719 }

static void delete_aliases ( void   )  [static]

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

02806 {
02807    int pruned = 0;
02808 
02809    /* Delete all aliases */
02810    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02811    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02812       ASTOBJ_RDLOCK(iterator);
02813       ASTOBJ_MARK(iterator);
02814       ++pruned;
02815       ASTOBJ_UNLOCK(iterator);
02816    } while (0) );
02817    if (pruned) {
02818       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02819    }
02820    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02821 }

static void delete_users ( void   )  [static]

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

02780 {
02781    int pruned = 0;
02782 
02783    /* Delete all users */
02784    ASTOBJ_CONTAINER_WRLOCK(&userl);
02785    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02786       ASTOBJ_RDLOCK(iterator);
02787       ASTOBJ_MARK(iterator);
02788       ++pruned;
02789       ASTOBJ_UNLOCK(iterator);
02790    } while (0) );
02791    if (pruned) {
02792       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02793    }
02794    ASTOBJ_CONTAINER_UNLOCK(&userl);
02795 
02796    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02797    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02798       ASTOBJ_RDLOCK(iterator);
02799       ASTOBJ_MARK(iterator);
02800       ASTOBJ_UNLOCK(iterator);
02801    } while (0) );
02802    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02803 }

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

Definition at line 2526 of file chan_h323.c.

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

02527 {
02528    int res;
02529    int reloading;
02530    struct oh323_pvt *oh323 = NULL;
02531 
02532    for(;;) {
02533       /* Check for a reload request */
02534       ast_mutex_lock(&h323_reload_lock);
02535       reloading = h323_reloading;
02536       h323_reloading = 0;
02537       ast_mutex_unlock(&h323_reload_lock);
02538       if (reloading) {
02539          ast_verb(1, "Reloading H.323\n");
02540          h323_do_reload();
02541       }
02542       /* Check for interfaces needing to be killed */
02543       if (!ast_mutex_trylock(&iflock)) {
02544 #if 1
02545          do {
02546             for (oh323 = iflist; oh323; oh323 = oh323->next) {
02547                if (!ast_mutex_trylock(&oh323->lock)) {
02548                   if (oh323->needdestroy) {
02549                      __oh323_destroy(oh323);
02550                      break;
02551                   }
02552                   ast_mutex_unlock(&oh323->lock);
02553                }
02554             }
02555          } while (/*oh323*/ 0);
02556 #else
02557 restartsearch:
02558          oh323 = iflist;
02559          while(oh323) {
02560             if (!ast_mutex_trylock(&oh323->lock)) {
02561                if (oh323->needdestroy) {
02562                   __oh323_destroy(oh323);
02563                   goto restartsearch;
02564                }
02565                ast_mutex_unlock(&oh323->lock);
02566                oh323 = oh323->next;
02567             }
02568          }
02569 #endif
02570          ast_mutex_unlock(&iflock);
02571       } else
02572          oh323 = (struct oh323_pvt *)1;   /* Force fast loop */
02573       pthread_testcancel();
02574       /* Wait for sched or io */
02575       res = ast_sched_wait(sched);
02576       if ((res < 0) || (res > 1000)) {
02577          res = 1000;
02578       }
02579       /* Do not wait if some channel(s) is destroyed, probably, more available too */
02580       if (oh323)
02581          res = 1;
02582       res = ast_io_wait(io, res);
02583       pthread_testcancel();
02584       ast_mutex_lock(&monlock);
02585       if (res >= 0) {
02586          ast_sched_runq(sched);
02587       }
02588       ast_mutex_unlock(&monlock);
02589    }
02590    /* Never reached */
02591    return NULL;
02592 }

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

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

Returns:
Returns the local RTP information

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

Referenced by load_module().

01894 {
01895    struct oh323_pvt *pvt;
01896    struct sockaddr_in us;
01897    struct rtp_info *info;
01898 
01899    info = ast_calloc(1, sizeof(*info));
01900    if (!info) {
01901       ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
01902       return NULL;
01903    }
01904    pvt = find_call_locked(call_reference, token);
01905    if (!pvt) {
01906       ast_free(info);
01907       ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
01908       return NULL;
01909    }
01910    if (!pvt->rtp)
01911       __oh323_rtp_create(pvt);
01912    if (!pvt->rtp) {
01913       ast_mutex_unlock(&pvt->lock);
01914       ast_free(info);
01915       ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
01916       return NULL;
01917    }
01918    /* figure out our local RTP port and tell the H.323 stack about it */
01919    ast_rtp_instance_get_local_address(pvt->rtp, &us);
01920    ast_mutex_unlock(&pvt->lock);
01921 
01922    ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
01923    info->port = ntohs(us.sin_port);
01924    if (h323debug)
01925       ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
01926    return info;
01927 }

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

Find a call by alias.

Definition at line 1809 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

01810 {
01811    struct oh323_alias *a;
01812 
01813    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01814 
01815    if (!a && realtime)
01816       a = realtime_alias(source_aliases);
01817 
01818    return a;
01819 }

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

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

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

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

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

Definition at line 1600 of file chan_h323.c.

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

01601 {
01602    struct oh323_user *u;
01603 
01604    if (userbyalias)
01605       u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
01606    else
01607       u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
01608 
01609    if (!u && realtime)
01610       u = realtime_user(cd);
01611 
01612    if (!u && h323debug)
01613       ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
01614 
01615    return u;
01616 }

static int h323_do_reload ( void   )  [static]

Definition at line 3116 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03117 {
03118    reload_config(1);
03119    return 0;
03120 }

static int h323_reload ( void   )  [static]

Definition at line 3082 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

03083 {
03084    ast_mutex_lock(&h323_reload_lock);
03085    if (h323_reloading) {
03086       ast_verbose("Previous H.323 reload not yet done\n");
03087    } else {
03088       h323_reloading = 1;
03089    }
03090    ast_mutex_unlock(&h323_reload_lock);
03091    restart_monitor();
03092    return 0;
03093 }

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

Definition at line 2678 of file chan_h323.c.

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

02679 {
02680    switch (cmd) {
02681    case CLI_INIT:
02682       e->command = "h323 cycle gk";
02683       e->usage =
02684          "Usage: h323 cycle gk\n"
02685          "       Manually re-register with the Gatekeper (Currently Disabled)\n";
02686       return NULL;
02687    case CLI_GENERATE:
02688       return NULL;
02689    }
02690 
02691    if (a->argc != 3)
02692       return CLI_SHOWUSAGE;
02693 
02694    h323_gk_urq();
02695 
02696    /* Possibly register with a GK */
02697    if (!gatekeeper_disable) {
02698       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02699          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02700       }
02701    }
02702    return CLI_SUCCESS;
02703 }

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

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

02706 {
02707    switch (cmd) {
02708    case CLI_INIT:
02709       e->command = "h323 hangup";
02710       e->usage =
02711          "Usage: h323 hangup <token>\n"
02712          "       Manually try to hang up the call identified by <token>\n";
02713       return NULL;
02714    case CLI_GENERATE:
02715       return NULL;
02716    }
02717 
02718    if (a->argc != 3)
02719       return CLI_SHOWUSAGE;
02720    if (h323_soft_hangup(a->argv[2])) {
02721       ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02722    } else {
02723       ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02724    }
02725    return CLI_SUCCESS;
02726 }

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

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

03096 {
03097    switch (cmd) {
03098    case CLI_INIT:
03099       e->command = "h323 reload";
03100       e->usage =
03101          "Usage: h323 reload\n"
03102          "       Reloads H.323 configuration from h323.conf\n";
03103       return NULL;
03104    case CLI_GENERATE:
03105       return NULL;
03106    }
03107 
03108    if (a->argc != 2)
03109       return CLI_SHOWUSAGE;
03110 
03111    h323_reload();
03112 
03113    return CLI_SUCCESS;
03114 }

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

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

02656 {
02657    switch (cmd) {
02658    case CLI_INIT:
02659       e->command = "h323 set debug [on|off]";
02660       e->usage =
02661          "Usage: h323 set debug [on|off]\n"
02662          "       Enable/Disable H.323 debugging output\n";
02663       return NULL;
02664    case CLI_GENERATE:
02665       return NULL;
02666    }
02667 
02668    if (a->argc != e->args)
02669       return CLI_SHOWUSAGE;
02670    if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off"))
02671       return CLI_SHOWUSAGE;
02672 
02673    h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1;
02674    ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02675    return CLI_SUCCESS;
02676 }

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

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

02627 {
02628    switch (cmd) {
02629    case CLI_INIT:
02630       e->command = "h323 set trace [on|off]";
02631       e->usage =
02632          "Usage: h323 set trace (on|off|<trace level>)\n"
02633          "       Enable/Disable H.323 stack tracing for debugging purposes\n";
02634       return NULL;
02635    case CLI_GENERATE:
02636       return NULL;
02637    }
02638 
02639    if (a->argc != e->args)
02640       return CLI_SHOWUSAGE;
02641    if (!strcasecmp(a->argv[3], "off")) {
02642       h323_debug(0, 0);
02643       ast_cli(a->fd, "H.323 Trace Disabled\n");
02644    } else if (!strcasecmp(a->argv[3], "on")) {
02645       h323_debug(1, 1);
02646       ast_cli(a->fd, "H.323 Trace Enabled\n");
02647    } else {
02648       int tracelevel = atoi(a->argv[3]);
02649       h323_debug(1, tracelevel);
02650       ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02651    }
02652    return CLI_SUCCESS;
02653 }

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

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

02729 {
02730    switch (cmd) {
02731    case CLI_INIT:
02732       e->command = "h323 show tokens";
02733       e->usage =
02734          "Usage: h323 show tokens\n"
02735          "       Print out all active call tokens\n";
02736       return NULL;
02737    case CLI_GENERATE:
02738       return NULL;
02739    }
02740 
02741    if (a->argc != 3)
02742       return CLI_SHOWUSAGE;
02743 
02744    h323_show_tokens();
02745 
02746    return CLI_SUCCESS;
02747 }

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

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

02750 {
02751    switch (cmd) {
02752    case CLI_INIT:
02753       e->command = "h323 show version";
02754       e->usage =
02755          "Usage: h323 show version\n"
02756          "     Show the version of the H.323 library in use\n";
02757       return NULL;
02758    case CLI_GENERATE:
02759       return NULL;
02760    }
02761 
02762    if (a->argc != 3)
02763       return CLI_SHOWUSAGE;
02764 
02765    h323_show_version();
02766    
02767    return CLI_SUCCESS;
02768 }

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

Definition at line 2387 of file chan_h323.c.

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

Referenced by load_module().

02388 {
02389    struct oh323_pvt *pvt;
02390 
02391    if (h323debug)
02392       ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
02393 
02394    pvt = find_call_locked(call_reference, token);
02395    if (!pvt) {
02396       if (h323debug)
02397          ast_debug(1, "Connection to %s already cleared\n", token);
02398       return;
02399    }
02400    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02401       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02402       pvt->owner->hangupcause = pvt->hangupcause = cause;
02403       ast_queue_hangup_with_cause(pvt->owner, cause);
02404       ast_channel_unlock(pvt->owner);
02405    }
02406    else {
02407       pvt->needhangup = 1;
02408       pvt->hangupcause = cause;
02409       if (h323debug)
02410          ast_debug(1, "Hangup for %s is pending\n", token);
02411    }
02412    ast_mutex_unlock(&pvt->lock);
02413 }

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3213 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(), connection_made(), external_rtp_create(), hangup_connection(), io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), sched_context_create(), sched_context_destroy(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.

03214 {
03215    int res;
03216 
03217    h323debug = 0;
03218    sched = sched_context_create();
03219    if (!sched) {
03220       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03221       return AST_MODULE_LOAD_FAILURE;
03222    }
03223    io = io_context_create();
03224    if (!io) {
03225       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03226       return AST_MODULE_LOAD_FAILURE;
03227    }
03228    ast_cli_register(&cli_h323_reload);
03229    ASTOBJ_CONTAINER_INIT(&userl);
03230    ASTOBJ_CONTAINER_INIT(&peerl);
03231    ASTOBJ_CONTAINER_INIT(&aliasl);
03232    res = reload_config(0);
03233    if (res) {
03234       /* No config entry */
03235       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03236       ast_cli_unregister(&cli_h323_reload);
03237       io_context_destroy(io);
03238       io = NULL;
03239       sched_context_destroy(sched);
03240       sched = NULL;
03241       ASTOBJ_CONTAINER_DESTROY(&userl);
03242       ASTOBJ_CONTAINER_DESTROY(&peerl);
03243       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03244       return AST_MODULE_LOAD_DECLINE;
03245    } else {
03246       /* Make sure we can register our channel type */
03247       if (ast_channel_register(&oh323_tech)) {
03248          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03249          ast_cli_unregister(&cli_h323_reload);
03250          h323_end_process();
03251          io_context_destroy(io);
03252          sched_context_destroy(sched);
03253 
03254          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03255          ASTOBJ_CONTAINER_DESTROY(&userl);
03256          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03257          ASTOBJ_CONTAINER_DESTROY(&peerl);
03258          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03259          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03260 
03261          return AST_MODULE_LOAD_FAILURE;
03262       }
03263       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03264 
03265       ast_rtp_glue_register(&oh323_rtp_glue);
03266 
03267       /* Register our callback functions */
03268       h323_callback_register(setup_incoming_call,
03269                   setup_outgoing_call,
03270                   external_rtp_create,
03271                   setup_rtp_connection,
03272                   cleanup_connection,
03273                   chan_ringing,
03274                   connection_made,
03275                   receive_digit,
03276                   answer_call,
03277                   progress,
03278                   set_dtmf_payload,
03279                   hangup_connection,
03280                   set_local_capabilities,
03281                   set_peer_capabilities,
03282                   remote_hold);
03283       /* start the h.323 listener */
03284       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03285          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03286          ast_rtp_glue_unregister(&oh323_rtp_glue);
03287          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03288          ast_cli_unregister(&cli_h323_reload);
03289          h323_end_process();
03290          io_context_destroy(io);
03291          sched_context_destroy(sched);
03292 
03293          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03294          ASTOBJ_CONTAINER_DESTROY(&userl);
03295          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03296          ASTOBJ_CONTAINER_DESTROY(&peerl);
03297          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03298          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03299 
03300          return AST_MODULE_LOAD_FAILURE;
03301       }
03302       /* Possibly register with a GK */
03303       if (!gatekeeper_disable) {
03304          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03305             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03306             gatekeeper_disable = 1;
03307             res = AST_MODULE_LOAD_SUCCESS;
03308          }
03309       }
03310       /* And start the monitor for the first time */
03311       restart_monitor();
03312    }
03313    return res;
03314 }

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

Definition at line 1618 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01619 {
01620    int res;
01621 
01622    if (!sin)
01623       res = -1;
01624    else
01625       res = inaddrcmp(&addr , sin);
01626 
01627    return res;
01628 }

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

Definition at line 1595 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01596 {
01597    return strcmp(ast_inet_ntoa(inaddr), addr);
01598 }

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

Definition at line 1099 of file chan_h323.c.

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

Referenced by oh323_request(), and setup_incoming_call().

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

static int oh323_answer ( struct ast_channel c  )  [static]

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

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

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 578 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_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verb, oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_rdnis, ast_channel::connected, oh323_pvt::exten, ast_party_connected_line::id, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_party_id::name, ast_channel::name, ast_party_id::number, ast_party_id::number_presentation, ast_party_id::number_type, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), oh323_pvt::sa, ast_channel::tech_pvt, and ast_channel::transfercapability.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

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

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

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

Definition at line 278 of file chan_h323.c.

References ast_debug, and ast_free.

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

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

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

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

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

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

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

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

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

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

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

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 539 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.

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

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

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

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

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

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

03135 {
03136    struct oh323_pvt *pvt;
03137    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
03138 
03139    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03140       return AST_RTP_GLUE_RESULT_FORBID;
03141 
03142    ast_mutex_lock(&pvt->lock);
03143    *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
03144 #if 0
03145    if (pvt->options.bridge) {
03146       res = AST_RTP_GLUE_RESULT_REMOTE;
03147    }
03148 #endif
03149    ast_mutex_unlock(&pvt->lock);
03150 
03151    return res;
03152 }

static int oh323_hangup ( struct ast_channel c  )  [static]

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

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

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

Definition at line 854 of file chan_h323.c.

References ast_channel::_state, oh323_pvt::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_free, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_instance_new_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.

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

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

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

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

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

Definition at line 1720 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_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_DTMF, AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), caplock, create_addr(), ext, oh323_pvt::exten, oh323_pvt::jointcapability, ast_channel::linkedid, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, and restart_monitor().

01721 {
01722    int oldformat;
01723    struct oh323_pvt *pvt;
01724    struct ast_channel *tmpc = NULL;
01725    char *dest = (char *)data;
01726    char *ext, *host;
01727    char *h323id = NULL;
01728    char tmp[256], tmp1[256];
01729 
01730    if (h323debug)
01731       ast_debug(1, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
01732 
01733    pvt = oh323_alloc(0);
01734    if (!pvt) {
01735       ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
01736       return NULL;
01737    }
01738    oldformat = format;
01739    format &= AST_FORMAT_AUDIO_MASK;
01740    if (!format) {
01741       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
01742       oh323_destroy(pvt);
01743       if (cause)
01744          *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
01745       return NULL;
01746    }
01747    ast_copy_string(tmp, dest, sizeof(tmp));
01748    host = strchr(tmp, '@');
01749    if (host) {
01750       *host = '\0';
01751       host++;
01752       ext = tmp;
01753    } else {
01754       ext = strrchr(tmp, '/');
01755       if (ext)
01756          *ext++ = '\0';
01757       host = tmp;
01758    }
01759    strtok_r(host, "/", &(h323id));
01760    if (!ast_strlen_zero(h323id)) {
01761       h323_set_id(h323id);
01762    }
01763    if (ext) {
01764       ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
01765    }
01766    if (h323debug)
01767       ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
01768 
01769    if (gatekeeper_disable) {
01770       if (create_addr(pvt, host)) {
01771          oh323_destroy(pvt);
01772          if (cause)
01773             *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
01774          return NULL;
01775       }
01776    }
01777    else {
01778       memcpy(&pvt->options, &global_options, sizeof(pvt->options));
01779       pvt->jointcapability = pvt->options.capability;
01780       if (pvt->options.dtmfmode) {
01781          if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
01782             pvt->nonCodecCapability |= AST_RTP_DTMF;
01783          } else {
01784             pvt->nonCodecCapability &= ~AST_RTP_DTMF;
01785          }
01786       }
01787    }
01788 
01789    ast_mutex_lock(&caplock);
01790    /* Generate unique channel identifier */
01791    snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
01792    tmp1[sizeof(tmp1)-1] = '\0';
01793    ast_mutex_unlock(&caplock);
01794 
01795    ast_mutex_lock(&pvt->lock);
01796    tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? requestor->linkedid : NULL);
01797    ast_mutex_unlock(&pvt->lock);
01798    if (!tmpc) {
01799       oh323_destroy(pvt);
01800       if (cause)
01801          *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
01802    }
01803    ast_update_use_count();
01804    restart_monitor();
01805    return tmpc;
01806 }

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

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

Definition at line 746 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, ast_frame::frametype, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, ast_frame::subclass, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by oh323_read().

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

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

Definition at line 3181 of file chan_h323.c.

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

03182 {
03183    /* XXX Deal with Video */
03184    struct oh323_pvt *pvt;
03185    struct sockaddr_in them = { 0, };
03186    struct sockaddr_in us = { 0, };
03187    char *mode;
03188 
03189    if (!rtp) {
03190       return 0;
03191    }
03192 
03193    mode = convertcap(chan->writeformat);
03194    pvt = (struct oh323_pvt *) chan->tech_pvt;
03195    if (!pvt) {
03196       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03197       return -1;
03198    }
03199    ast_rtp_instance_get_remote_address(rtp, &them);
03200    ast_rtp_instance_get_local_address(rtp, &us);
03201 #if 0 /* Native bridge still isn't ready */
03202    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03203 #endif
03204    return 0;
03205 }

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

Definition at line 301 of file chan_h323.c.

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

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

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

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

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

Definition at line 826 of file chan_h323.c.

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

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

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

Definition at line 2069 of file chan_h323.c.

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

02070 {
02071    struct oh323_pvt *pvt;
02072 
02073    if (h323debug)
02074       ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
02075 
02076    pvt = find_call_locked(call_reference, token);
02077    if (!pvt) {
02078       ast_log(LOG_ERROR, "Private structure not found in progress.\n");
02079       return -1;
02080    }
02081    if (!pvt->owner) {
02082       ast_mutex_unlock(&pvt->lock);
02083       ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
02084       return -1;
02085    }
02086    update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
02087    ast_mutex_unlock(&pvt->lock);
02088 
02089    return 0;
02090 }

static void prune_peers ( void   )  [static]

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

02824 {
02825    /* Prune peers who still are supposed to be deleted */
02826    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02827 }

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

Definition at line 1224 of file chan_h323.c.

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

Referenced by find_alias().

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

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

Definition at line 1552 of file chan_h323.c.

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

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

01553 {
01554    struct oh323_peer *peer;
01555    struct ast_variable *var;
01556    struct ast_variable *tmp;
01557    const char *addr = NULL;
01558 
01559    /* First check on peer name */
01560    if (peername)
01561       var = ast_load_realtime("h323", "name", peername, SENTINEL);
01562    else if (sin) /* Then check on IP address for dynamic peers */
01563       var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL);
01564    else
01565       return NULL;
01566 
01567    if (!var)
01568       return NULL;
01569 
01570    for (tmp = var; tmp; tmp = tmp->next) {
01571       /* If this is type=user, then skip this object. */
01572       if (!strcasecmp(tmp->name, "type") &&
01573             !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
01574          ast_variables_destroy(var);
01575          return NULL;
01576       } else if (!peername && !strcasecmp(tmp->name, "name")) {
01577          peername = tmp->value;
01578       }
01579    }
01580 
01581    if (!peername) {  /* Did not find peer in realtime */
01582       ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
01583       ast_variables_destroy(var);
01584       return NULL;
01585    }
01586 
01587    /* Peer found in realtime, now build it in memory */
01588    peer = build_peer(peername, var, NULL, 1);
01589 
01590    ast_variables_destroy(var);
01591 
01592    return peer;
01593 }

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

Definition at line 1438 of file chan_h323.c.

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

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

01439 {
01440    struct ast_variable *var, *tmp;
01441    struct oh323_user *user;
01442    const char *username;
01443 
01444    if (userbyalias)
01445       var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL);
01446    else {
01447       username = (char *)NULL;
01448       var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL);
01449    }
01450 
01451    if (!var)
01452       return NULL;
01453 
01454    for (tmp = var; tmp; tmp = tmp->next) {
01455       if (!strcasecmp(tmp->name, "type") &&
01456       !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
01457          ast_variables_destroy(var);
01458          return NULL;
01459       } else if (!username && !strcasecmp(tmp->name, "name"))
01460          username = tmp->value;
01461    }
01462 
01463    if (!username) {
01464       ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
01465       ast_variables_destroy(var);
01466       return NULL;
01467    }
01468 
01469    user = build_user(username, var, NULL, 1);
01470 
01471    ast_variables_destroy(var);
01472 
01473    return user;
01474 }

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

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

Referenced by load_module().

01826 {
01827    struct oh323_pvt *pvt;
01828    int res;
01829 
01830    pvt = find_call_locked(call_reference, token);
01831    if (!pvt) {
01832       ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
01833       return -1;
01834    }
01835    if (h323debug)
01836       ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
01837 
01838    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01839       if (digit == '!')
01840          res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
01841       else {
01842          struct ast_frame f = {
01843             .frametype = AST_FRAME_DTMF_END,
01844             .subclass = digit,
01845             .samples = duration * 8,
01846             .len = duration,
01847             .src = "SEND_DIGIT",
01848          };
01849          if (digit == ' ') {     /* signalUpdate message */
01850             f.subclass = pvt->curDTMF;
01851             AST_SCHED_DEL(sched, pvt->DTMFsched);
01852          } else {          /* Regular input or signal message */
01853             if (pvt->DTMFsched >= 0) {
01854                /* We still don't send DTMF END from previous event, send it now */
01855                AST_SCHED_DEL(sched, pvt->DTMFsched);
01856                f.subclass = pvt->curDTMF;
01857                f.samples = f.len = 0;
01858                ast_queue_frame(pvt->owner, &f);
01859                /* Restore values */
01860                f.subclass = digit;
01861                f.samples = duration * 8;
01862                f.len = duration;
01863             }
01864             if (duration) {      /* This is a signal, signalUpdate follows */
01865                f.frametype = AST_FRAME_DTMF_BEGIN;
01866                pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
01867                if (h323debug)
01868                   ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
01869             }
01870             pvt->curDTMF = digit;
01871          }
01872          res = ast_queue_frame(pvt->owner, &f);
01873       }
01874       ast_channel_unlock(pvt->owner);
01875    } else {
01876       if (digit == '!')
01877          pvt->newcontrol = AST_CONTROL_FLASH;
01878       else {
01879          pvt->newduration = duration;
01880          pvt->newdigit = digit;
01881       }
01882       res = 0;
01883    }
01884    ast_mutex_unlock(&pvt->lock);
01885    return res;
01886 }

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

Definition at line 262 of file chan_h323.c.

Referenced by __oh323_new().

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

static int reload ( void   )  [static]

Definition at line 3122 of file chan_h323.c.

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

03123 {
03124    if (!sched || !io) {
03125       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03126       return 0;
03127    }
03128    return h323_reload();
03129 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2829 of file chan_h323.c.

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

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

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

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

Definition at line 2500 of file chan_h323.c.

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

Referenced by load_module().

02501 {
02502    struct oh323_pvt *pvt;
02503 
02504    if (h323debug)
02505       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02506 
02507    pvt = find_call_locked(call_reference, token);
02508    if (!pvt)
02509       return;
02510    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02511       if (is_hold)
02512          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02513       else
02514          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02515       ast_channel_unlock(pvt->owner);
02516    }
02517    else {
02518       if (is_hold)
02519          pvt->newcontrol = AST_CONTROL_HOLD;
02520       else
02521          pvt->newcontrol = AST_CONTROL_UNHOLD;
02522    }
02523    ast_mutex_unlock(&pvt->lock);
02524 }

static int restart_monitor ( void   )  [static]

Definition at line 2594 of file chan_h323.c.

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

02595 {
02596    /* If we're supposed to be stopped -- stay stopped */
02597    if (ast_mutex_lock(&monlock)) {
02598       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02599       return -1;
02600    }
02601    if (monitor_thread == AST_PTHREADT_STOP) {
02602       ast_mutex_unlock(&monlock);
02603       return 0;
02604    }
02605    if (monitor_thread == pthread_self()) {
02606       ast_mutex_unlock(&monlock);
02607       ast_log(LOG_WARNING, "Cannot kill myself\n");
02608       return -1;
02609    }
02610    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02611       /* Wake up the thread */
02612       pthread_kill(monitor_thread, SIGURG);
02613    } else {
02614       /* Start a new monitor */
02615       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02616          monitor_thread = AST_PTHREADT_NULL;
02617          ast_mutex_unlock(&monlock);
02618          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02619          return -1;
02620       }
02621    }
02622    ast_mutex_unlock(&monlock);
02623    return 0;
02624 }

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

Definition at line 2415 of file chan_h323.c.

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

Referenced by load_module().

02416 {
02417    struct oh323_pvt *pvt;
02418 
02419    if (h323debug)
02420       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02421 
02422    pvt = find_call_locked(call_reference, token);
02423    if (!pvt) {
02424       return;
02425    }
02426    if (pvt->rtp) {
02427       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);
02428    }
02429    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02430    ast_mutex_unlock(&pvt->lock);
02431    if (h323debug)
02432       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02433 }

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

Definition at line 2470 of file chan_h323.c.

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

Referenced by load_module().

02471 {
02472    struct oh323_pvt *pvt;
02473    int capability, dtmfmode, pref_codec;
02474    struct ast_codec_pref prefs;
02475 
02476    if (h323debug)
02477       ast_debug(1, "Setting capabilities for connection %s\n", token);
02478 
02479    pvt = find_call_locked(call_reference, token);
02480    if (!pvt)
02481       return;
02482    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02483    dtmfmode = pvt->options.dtmfmode;
02484    prefs = pvt->options.prefs;
02485    pref_codec = pvt->pref_codec;
02486    ast_mutex_unlock(&pvt->lock);
02487    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02488 
02489    if (h323debug) {
02490       int i;
02491       for (i = 0; i < 32; i++) {
02492          if (!prefs.order[i])
02493             break;
02494          ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02495       }
02496       ast_debug(1, "Capabilities for connection %s is set\n", token);
02497    }
02498 }

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

Definition at line 2435 of file chan_h323.c.

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

Referenced by load_module().

02436 {
02437    struct oh323_pvt *pvt;
02438 
02439    if (h323debug)
02440       ast_debug(1, "Got remote capabilities from connection %s\n", token);
02441 
02442    pvt = find_call_locked(call_reference, token);
02443    if (!pvt)
02444       return;
02445    pvt->peercapability = capabilities;
02446    pvt->jointcapability = pvt->options.capability & capabilities;
02447    if (prefs) {
02448       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02449       if (h323debug) {
02450          int i;
02451          for (i = 0; i < 32; ++i) {
02452             if (!prefs->order[i])
02453                break;
02454             ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02455          }
02456       }
02457       if (pvt->rtp) {
02458          if (pvt->options.autoframing) {
02459             ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02460             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
02461          } else {
02462             ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02463             ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
02464          }
02465       }
02466    }
02467    ast_mutex_unlock(&pvt->lock);
02468 }

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

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

Referenced by load_module().

02098 {
02099    struct oh323_pvt *pvt;
02100    struct oh323_user *user = NULL;
02101    struct oh323_alias *alias = NULL;
02102 
02103    if (h323debug)
02104       ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
02105 
02106    /* allocate the call*/
02107    pvt = oh323_alloc(cd->call_reference);
02108 
02109    if (!pvt) {
02110       ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
02111       cleanup_call_details(cd);
02112       return NULL;
02113    }
02114 
02115    /* Populate the call details in the private structure */
02116    memcpy(&pvt->cd, cd, sizeof(pvt->cd));
02117    memcpy(&pvt->options, &global_options, sizeof(pvt->options));
02118    pvt->jointcapability = pvt->options.capability;
02119 
02120    if (h323debug) {
02121       ast_verb(3, "Setting up Call\n");
02122       ast_verb(3, " \tCall token:  [%s]\n", pvt->cd.call_token);
02123       ast_verb(3, " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);
02124       ast_verb(3, " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);
02125       ast_verb(3, " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);
02126       ast_verb(3, " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);
02127       if (pvt->cd.redirect_reason >= 0)
02128          ast_verb(3, " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
02129       ast_verb(3, " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);
02130    }
02131 
02132    /* Decide if we are allowing Gatekeeper routed calls*/
02133    if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
02134       if (!ast_strlen_zero(cd->call_dest_e164)) {
02135          ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02136          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02137       } else {
02138          alias = find_alias(cd->call_dest_alias, 1);
02139          if (!alias) {
02140             ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
02141             oh323_destroy(pvt);
02142             return NULL;
02143          }
02144          ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
02145          ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
02146       }
02147    } else {
02148       /* Either this call is not from the Gatekeeper
02149          or we are not allowing gk routed calls */
02150       user = find_user(cd, 1);
02151       if (!user) {
02152          if (!acceptAnonymous) {
02153             ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02154             oh323_destroy(pvt);
02155             return NULL;
02156          }
02157          if (ast_strlen_zero(default_context)) {
02158             ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
02159             oh323_destroy(pvt);
02160             return NULL;
02161          }
02162          ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02163          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02164             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02165          } else {
02166             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02167          }
02168          if (h323debug)
02169             ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
02170       } else {
02171          if (user->host) {
02172             if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
02173                if (ast_strlen_zero(user->context)) {
02174                   if (ast_strlen_zero(default_context)) {
02175                      ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
02176                      oh323_destroy(pvt);
02177                      ASTOBJ_UNREF(user, oh323_destroy_user);
02178                      return NULL;
02179                   }
02180                   ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
02181                } else {
02182                   ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02183                }
02184                pvt->exten[0] = 'i';
02185                pvt->exten[1] = '\0';
02186                ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
02187                oh323_destroy(pvt);
02188                ASTOBJ_UNREF(user, oh323_destroy_user);
02189                return NULL;   /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
02190             }
02191          }
02192          ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
02193          memcpy(&pvt->options, &user->options, sizeof(pvt->options));
02194          pvt->jointcapability = pvt->options.capability;
02195          if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
02196             ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
02197          } else {
02198             ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
02199          }
02200          if (!ast_strlen_zero(user->accountcode)) {
02201             ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
02202          }
02203          if (user->amaflags) {
02204             pvt->amaflags = user->amaflags;
02205          }
02206          ASTOBJ_UNREF(user, oh323_destroy_user);
02207       }
02208    }
02209    return &pvt->options;
02210 }

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

References cleanup_call_details().

Referenced by load_module().

02297 {
02298    /* Use argument here or free it immediately */
02299    cleanup_call_details(cd);
02300 
02301    return 1;
02302 }

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 1934 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_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_rtp_payload_type::code, find_call_locked(), 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().

01935 {
01936    struct oh323_pvt *pvt;
01937    struct sockaddr_in them;
01938    int nativeformats_changed;
01939    enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
01940 
01941    if (h323debug)
01942       ast_debug(1, "Setting up RTP connection for %s\n", token);
01943 
01944    /* Find the call or allocate a private structure if call not found */
01945    pvt = find_call_locked(call_reference, token);
01946    if (!pvt) {
01947       ast_log(LOG_ERROR, "Something is wrong: rtp\n");
01948       return;
01949    }
01950    if (pvt->alreadygone) {
01951       ast_mutex_unlock(&pvt->lock);
01952       return;
01953    }
01954 
01955    if (!pvt->rtp)
01956       __oh323_rtp_create(pvt);
01957 
01958    if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
01959       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);
01960    }
01961 
01962    them.sin_family = AF_INET;
01963    /* only works for IPv4 */
01964    them.sin_addr.s_addr = inet_addr(remoteIp);
01965    them.sin_port = htons(remotePort);
01966 
01967    if (them.sin_addr.s_addr) {
01968       ast_rtp_instance_set_remote_address(pvt->rtp, &them);
01969       if (pvt->recvonly) {
01970          pvt->recvonly = 0;
01971          rtp_change = NEED_UNHOLD;
01972       }
01973    } else {
01974       ast_rtp_instance_stop(pvt->rtp);
01975       if (!pvt->recvonly) {
01976          pvt->recvonly = 1;
01977          rtp_change = NEED_HOLD;
01978       }
01979    }
01980 
01981    /* Change native format to reflect information taken from OLC/OLCAck */
01982    nativeformats_changed = 0;
01983    if (pt != 128 && pvt->rtp) {  /* Payload type is invalid, so try to use previously decided */
01984       struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
01985       if (h323debug)
01986          ast_debug(1, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);
01987       if (pvt->nativeformats != rtptype.code) {
01988          pvt->nativeformats = rtptype.code;
01989          nativeformats_changed = 1;
01990       }
01991    } else if (h323debug)
01992       ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
01993 
01994    /* Don't try to lock the channel if nothing changed */
01995    if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
01996       if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
01997          /* Re-build translation path only if native format(s) has been changed */
01998          if (pvt->owner->nativeformats != pvt->nativeformats) {
01999             if (h323debug)
02000                ast_debug(1, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat);
02001             pvt->owner->nativeformats = pvt->nativeformats;
02002             ast_set_read_format(pvt->owner, pvt->owner->readformat);
02003             ast_set_write_format(pvt->owner, pvt->owner->writeformat);
02004          }
02005          if (pvt->options.progress_audio)
02006             ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
02007          switch (rtp_change) {
02008          case NEED_HOLD:
02009             ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02010             break;
02011          case NEED_UNHOLD:
02012             ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02013             break;
02014          default:
02015             break;
02016          }
02017          ast_channel_unlock(pvt->owner);
02018       }
02019       else {
02020          if (pvt->options.progress_audio)
02021             pvt->newcontrol = AST_CONTROL_PROGRESS;
02022          else if (rtp_change == NEED_HOLD)
02023             pvt->newcontrol = AST_CONTROL_HOLD;
02024          else if (rtp_change == NEED_UNHOLD)
02025             pvt->newcontrol = AST_CONTROL_UNHOLD;
02026          if (h323debug)
02027             ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
02028       }
02029    }
02030    ast_mutex_unlock(&pvt->lock);
02031 
02032    if (h323debug)
02033       ast_debug(1, "RTP connection prepared for %s\n", token);
02034 
02035    return;
02036 }

static int unload_module ( void   )  [static]

Definition at line 3316 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, iflist, iflock, io_context_destroy(), oh323_pvt::lock, LOG_WARNING, monlock, oh323_pvt::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_pvt::owner, peerl, sched_context_destroy(), and userl.

03317 {
03318    struct oh323_pvt *p, *pl;
03319 
03320    /* unregister commands */
03321    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03322    ast_cli_unregister(&cli_h323_reload);
03323 
03324    ast_channel_unregister(&oh323_tech);
03325    ast_rtp_glue_unregister(&oh323_rtp_glue);
03326 
03327    if (!ast_mutex_lock(&iflock)) {
03328       /* hangup all interfaces if they have an owner */
03329       p = iflist;
03330       while(p) {
03331          if (p->owner) {
03332             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03333          }
03334          p = p->next;
03335       }
03336       iflist = NULL;
03337       ast_mutex_unlock(&iflock);
03338    } else {
03339       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03340       return -1;
03341    }
03342    if (!ast_mutex_lock(&monlock)) {
03343       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03344          if (monitor_thread != pthread_self()) {
03345             pthread_cancel(monitor_thread);
03346          }
03347          pthread_kill(monitor_thread, SIGURG);
03348          pthread_join(monitor_thread, NULL);
03349       }
03350       monitor_thread = AST_PTHREADT_STOP;
03351       ast_mutex_unlock(&monlock);
03352    } else {
03353       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03354       return -1;
03355    }
03356    if (!ast_mutex_lock(&iflock)) {
03357       /* destroy all the interfaces and free their memory */
03358       p = iflist;
03359       while(p) {
03360          pl = p;
03361          p = p->next;
03362          /* free associated memory */
03363          ast_mutex_destroy(&pl->lock);
03364          ast_free(pl);
03365       }
03366       iflist = NULL;
03367       ast_mutex_unlock(&iflock);
03368    } else {
03369       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03370       return -1;
03371    }
03372    if (!gatekeeper_disable)
03373       h323_gk_urq();
03374    h323_end_process();
03375    if (io)
03376       io_context_destroy(io);
03377    if (sched)
03378       sched_context_destroy(sched);
03379 
03380    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03381    ASTOBJ_CONTAINER_DESTROY(&userl);
03382    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03383    ASTOBJ_CONTAINER_DESTROY(&peerl);
03384    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03385    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03386 
03387    return 0;
03388 }

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

Definition at line 1249 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(), build_user(), and reload_config().

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

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

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

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


Variable Documentation

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

Definition at line 3394 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 141 of file chan_h323.c.

struct h323_alias_list aliasl [static]

Definition at line 3394 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 129 of file chan_h323.c.

ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [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 217 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2770 of file chan_h323.c.

struct ast_cli_entry cli_h323_reload [static]

Initial value:

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

Definition at line 3131 of file chan_h323.c.

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

Definition at line 127 of file chan_h323.c.

unsigned int cos = 0 [static]

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

Definition at line 128 of file chan_h323.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

Definition at line 116 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 135 of file chan_h323.c.

int gatekeeper_disable = 1 [static]

Definition at line 136 of file chan_h323.c.

int gatekeeper_discover = 0 [static]

Definition at line 137 of file chan_h323.c.

int gkroute = 0 [static]

Definition at line 138 of file chan_h323.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 123 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 147 of file chan_h323.c.

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

Protect the reload process.

Definition at line 220 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 221 of file chan_h323.c.

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 134 of file chan_h323.c.

int h323debug

global debug flag

Definition at line 113 of file chan_h323.c.

struct oh323_pvt * iflist [static]

Private structure of a OpenH323 channel.

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

Protect the interface list (oh323_pvt)

Definition at line 210 of file chan_h323.c.

struct io_context* io [static]

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

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [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 214 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 3207 of file chan_h323.c.

struct ast_channel_tech oh323_tech [static]

Definition at line 244 of file chan_h323.c.

answer_call_cb on_answer_call

Definition at line 105 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 102 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 104 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 103 of file chan_h323.c.

Definition at line 98 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 108 of file chan_h323.c.

onhold_cb on_hold

Definition at line 111 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 100 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 101 of file chan_h323.c.

progress_cb on_progress

Definition at line 106 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 97 of file chan_h323.c.

Definition at line 107 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 109 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 110 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 99 of file chan_h323.c.

struct h323_peer_list peerl [static]

struct sched_context* sched [static]

Definition at line 207 of file chan_h323.c.

char secret[50] [static]

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

Variables required by Asterisk

Definition at line 126 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 142 of file chan_h323.c.

unsigned int unique = 0 [static]

Definition at line 145 of file chan_h323.c.

int userbyalias = 1 [static]

Definition at line 140 of file chan_h323.c.

struct h323_user_list userl [static]


Generated on Wed Oct 28 13:32:02 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6