Fri Jul 24 00:41:22 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.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "h323/chan_h323.h"

Go to the source code of this file.

Data Structures

struct  h323_alias_list
 H323 alias list. More...
struct  h323_peer_list
 H323 peer list. More...
struct  h323_user_list
 H323 User list. More...
struct  oh323_pvt
 Private structure of a OpenH323 channel. More...
struct  rtpPayloadType
 Structure representing a RTP session.The value of each payload format mapping:. 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)
 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_get_result oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static enum ast_rtp_get_result oh323_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
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, 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 *rtp, struct ast_rtp *vrtp, struct ast_rtp *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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_reload
static const char config [] = "h323.conf"
static unsigned int cos = 0
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration - by default, jb is disabled.
static char gatekeeper [100]
static int gatekeeper_disable = 1
static int gatekeeper_discover = 0
static int gkroute = 0
static struct ast_jb_conf global_jbconf
static call_options_t global_options
static ast_mutex_t h323_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the reload process.
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
oh323_pvtiflist
 Private structure of a OpenH323 channel.
static ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static struct ast_rtp_protocol oh323_rtp
static struct ast_channel_tech oh323_tech
answer_call_cb on_answer_call
chan_ringing_cb on_chan_ringing
clear_con_cb on_connection_cleared
con_established_cb on_connection_established
on_rtp_cb on_external_rtp_create
hangup_cb on_hangup
onhold_cb on_hold
setup_incoming_cb on_incoming_call
setup_outbound_cb on_outgoing_call
progress_cb on_progress
receive_digit_cb on_receive_digit
rfc2833_cb on_set_rfc2833_payload
setcapabilities_cb on_setcapabilities
setpeercapabilities_cb on_setpeercapabilities
start_rtp_cb on_start_rtp_channel
static struct h323_peer_list peerl
 H323 peer list.
static struct sched_contextsched
static char secret [50]
static const char tdesc [] = "The NuFone Network's Open H.323 Channel Driver"
static unsigned int tos = 0
static unsigned int unique = 0
static int userbyalias = 1
static struct h323_user_list userl
 H323 User list.


Detailed Description

This file is part of the chan_h323 driver for Asterisk.

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

Definition in file chan_h323.c.


Define Documentation

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

Definition at line 129 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 440 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_destroy(), AST_SCHED_DEL, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, iflist, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::next, dahdi_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, sched, ast_channel::tech_pvt, and oh323_pvt::vad.

Referenced by do_monitor(), and oh323_destroy().

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

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

Private structure should be locked on a call.

Definition at line 995 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_rtcp_fd(), ast_rtp_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, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_tech, 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().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

Definition at line 947 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_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_rtpmap_type(), ast_rtp_setnat(), ast_rtp_setqos(), oh323_pvt::dtmf_pt, errno, global_jbconf, io, oh323_pvt::lock, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, sched, and oh323_pvt::update_rtp_info.

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

00948 {
00949    struct in_addr our_addr;
00950 
00951    if (pvt->rtp)
00952       return 0;
00953 
00954    if (ast_find_ourip(&our_addr, bindaddr)) {
00955       ast_mutex_unlock(&pvt->lock);
00956       ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
00957       return -1;
00958    }
00959    pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr);
00960    if (!pvt->rtp) {
00961       ast_mutex_unlock(&pvt->lock);
00962       ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
00963       return -1;
00964    }
00965    if (h323debug)
00966       ast_debug(1, "Created RTP channel\n");
00967 
00968    ast_rtp_setqos(pvt->rtp, tos, cos, "H323 RTP");
00969 
00970    if (h323debug)
00971       ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
00972    ast_rtp_setnat(pvt->rtp, pvt->options.nat);
00973 
00974    if (pvt->dtmf_pt[0] > 0)
00975       ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
00976    if (pvt->dtmf_pt[1] > 0)
00977       ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
00978 
00979    if (pvt->peercapability)
00980       ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
00981 
00982    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
00983       ast_jb_configure(pvt->owner, &global_jbconf);
00984       ast_channel_set_fd(pvt->owner, 0, ast_rtp_fd(pvt->rtp));
00985       ast_channel_set_fd(pvt->owner, 1, ast_rtcp_fd(pvt->rtp));
00986       ast_queue_frame(pvt->owner, &ast_null_frame);   /* Tell Asterisk to apply changes */
00987       ast_channel_unlock(pvt->owner);
00988    } else
00989       pvt->update_rtp_info = 1;
00990 
00991    return 0;
00992 }

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 329 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_rtcp_fd(), ast_rtp_fd(), ast_sched_add(), AST_SCHED_DEL, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_SOFTHANGUP_DEV, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, f, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DTMF, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, sched, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

static void __reg_module ( void   )  [static]

Definition at line 3373 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_module().

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

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

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

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

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

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

Referenced by reload_config(), and set_config().

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

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

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

Referenced by reload_config(), and set_config().

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

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

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

Referenced by load_module().

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

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 404 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

Definition at line 2340 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_destroy(), AST_SOFTHANGUP_DEV, oh323_pvt::cd, cleanup_call_details(), find_call_locked(), h323debug, oh323_pvt::lock, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.

Referenced by load_module().

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

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

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

Referenced by load_module().

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

static char* convertcap ( int  cap  )  [static]

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

03133 {
03134    switch (cap) {
03135    case AST_FORMAT_G723_1:
03136       return "G.723";
03137    case AST_FORMAT_GSM:
03138       return "GSM";
03139    case AST_FORMAT_ULAW:
03140       return "ULAW";
03141    case AST_FORMAT_ALAW:
03142       return "ALAW";
03143    case AST_FORMAT_G722:
03144       return "G.722";
03145    case AST_FORMAT_ADPCM:
03146       return "G.728";
03147    case AST_FORMAT_G729A:
03148       return "G.729";
03149    case AST_FORMAT_SPEEX:
03150       return "SPEEX";
03151    case AST_FORMAT_ILBC:
03152       return "ILBC";
03153    default:
03154       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03155       return NULL;
03156    }
03157 }

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

Definition at line 1644 of file chan_h323.c.

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

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

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

static void delete_aliases ( void   )  [static]

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

02795 {
02796    int pruned = 0;
02797 
02798    /* Delete all aliases */
02799    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02800    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02801       ASTOBJ_RDLOCK(iterator);
02802       ASTOBJ_MARK(iterator);
02803       ++pruned;
02804       ASTOBJ_UNLOCK(iterator);
02805    } while (0) );
02806    if (pruned) {
02807       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02808    }
02809    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02810 }

static void delete_users ( void   )  [static]

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

02769 {
02770    int pruned = 0;
02771 
02772    /* Delete all users */
02773    ASTOBJ_CONTAINER_WRLOCK(&userl);
02774    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02775       ASTOBJ_RDLOCK(iterator);
02776       ASTOBJ_MARK(iterator);
02777       ++pruned;
02778       ASTOBJ_UNLOCK(iterator);
02779    } while (0) );
02780    if (pruned) {
02781       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02782    }
02783    ASTOBJ_CONTAINER_UNLOCK(&userl);
02784 
02785    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02786    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02787       ASTOBJ_RDLOCK(iterator);
02788       ASTOBJ_MARK(iterator);
02789       ASTOBJ_UNLOCK(iterator);
02790    } while (0) );
02791    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02792 }

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

Definition at line 2518 of file chan_h323.c.

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

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

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

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

Returns:
Returns the local RTP information

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

Referenced by load_module().

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

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

Find a call by alias.

Definition at line 1805 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

01806 {
01807    struct oh323_alias *a;
01808 
01809    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01810 
01811    if (!a && realtime)
01812       a = realtime_alias(source_aliases);
01813 
01814    return a;
01815 }

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

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

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

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

Definition at line 1626 of file chan_h323.c.

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

Referenced by _sip_qualify_peer(), _sip_show_peer(), check_peer_ok(), create_addr(), dundi_encrypt(), function_iaxpeer(), function_sippeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), handle_command_response(), iax2_devicestate(), register_verify(), registry_authrequest(), set_config(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), sip_show_user(), sip_unregister(), st_get_mode(), st_get_refresher(), st_get_se(), update_call_counter(), and update_registry().

01627 {
01628    struct oh323_peer *p;
01629 
01630    if (peer)
01631       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01632    else
01633       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01634 
01635    if (!p && realtime)
01636       p = realtime_peer(peer, sin);
01637 
01638    if (!p && h323debug)
01639       ast_debug(1, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
01640 
01641    return p;
01642 }

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

Definition at line 1596 of file chan_h323.c.

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

Referenced by acf_mailbox_exists(), admin_exec(), advanced_options(), forward_message(), handle_cli_iax2_prune_realtime(), leave_voicemail(), pp_each_extension_exec(), setup_incoming_call(), vm_authenticate(), vm_box_exists(), and vm_execmain().

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

static int h323_do_reload ( void   )  [static]

Definition at line 3089 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03090 {
03091    reload_config(1);
03092    return 0;
03093 }

static int h323_reload ( void   )  [static]

Definition at line 3055 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

03056 {
03057    ast_mutex_lock(&h323_reload_lock);
03058    if (h323_reloading) {
03059       ast_verbose("Previous H.323 reload not yet done\n");
03060    } else {
03061       h323_reloading = 1;
03062    }
03063    ast_mutex_unlock(&h323_reload_lock);
03064    restart_monitor();
03065    return 0;
03066 }

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

Definition at line 2667 of file chan_h323.c.

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

02668 {
02669    switch (cmd) {
02670    case CLI_INIT:
02671       e->command = "h323 cycle gk";
02672       e->usage =
02673          "Usage: h323 cycle gk\n"
02674          "       Manually re-register with the Gatekeper (Currently Disabled)\n";
02675       return NULL;
02676    case CLI_GENERATE:
02677       return NULL;
02678    }
02679 
02680    if (a->argc != 3)
02681       return CLI_SHOWUSAGE;
02682 
02683    h323_gk_urq();
02684 
02685    /* Possibly register with a GK */
02686    if (!gatekeeper_disable) {
02687       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02688          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02689       }
02690    }
02691    return CLI_SUCCESS;
02692 }

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

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

02695 {
02696    switch (cmd) {
02697    case CLI_INIT:
02698       e->command = "h323 hangup";
02699       e->usage =
02700          "Usage: h323 hangup <token>\n"
02701          "       Manually try to hang up the call identified by <token>\n";
02702       return NULL;
02703    case CLI_GENERATE:
02704       return NULL;
02705    }
02706 
02707    if (a->argc != 3)
02708       return CLI_SHOWUSAGE;
02709    if (h323_soft_hangup(a->argv[2])) {
02710       ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
02711    } else {
02712       ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
02713    }
02714    return CLI_SUCCESS;
02715 }

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

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

03069 {
03070    switch (cmd) {
03071    case CLI_INIT:
03072       e->command = "h323 reload";
03073       e->usage =
03074          "Usage: h323 reload\n"
03075          "       Reloads H.323 configuration from h323.conf\n";
03076       return NULL;
03077    case CLI_GENERATE:
03078       return NULL;
03079    }
03080 
03081    if (a->argc != 2)
03082       return CLI_SHOWUSAGE;
03083 
03084    h323_reload();
03085 
03086    return CLI_SUCCESS;
03087 }

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

Definition at line 2644 of file chan_h323.c.

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

02645 {
02646    switch (cmd) {
02647    case CLI_INIT:
02648       e->command = "h323 set debug [off]";
02649       e->usage =
02650          "Usage: h323 set debug [off]\n"
02651          "       Enable/Disable H.323 debugging output\n";
02652       return NULL;
02653    case CLI_GENERATE:
02654       return NULL;
02655    }
02656 
02657    if (a->argc < 3 || a->argc > 4)
02658       return CLI_SHOWUSAGE;
02659    if (a->argc == 4 && strcasecmp(a->argv[3], "off"))
02660       return CLI_SHOWUSAGE;
02661 
02662    h323debug = (a->argc == 3) ? 1 : 0;
02663    ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02664    return CLI_SUCCESS;
02665 }

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

Definition at line 2618 of file chan_h323.c.

References ast_cli_args::argc, 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.

02619 {
02620    switch (cmd) {
02621    case CLI_INIT:
02622       e->command = "h323 set trace [off]";
02623       e->usage =
02624          "Usage: h323 set trace (off|<trace level>)\n"
02625          "       Enable/Disable H.323 stack tracing for debugging purposes\n";
02626       return NULL;
02627    case CLI_GENERATE:
02628       return NULL;
02629    }
02630 
02631    if (a->argc != 4)
02632       return CLI_SHOWUSAGE;
02633    if (!strcasecmp(a->argv[3], "off")) {
02634       h323_debug(0, 0);
02635       ast_cli(a->fd, "H.323 Trace Disabled\n");
02636    } else {
02637       int tracelevel = atoi(a->argv[3]);
02638       h323_debug(1, tracelevel);
02639       ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02640    }
02641    return CLI_SUCCESS;
02642 }

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

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

02718 {
02719    switch (cmd) {
02720    case CLI_INIT:
02721       e->command = "h323 show tokens";
02722       e->usage =
02723          "Usage: h323 show tokens\n"
02724          "       Print out all active call tokens\n";
02725       return NULL;
02726    case CLI_GENERATE:
02727       return NULL;
02728    }
02729 
02730    if (a->argc != 3)
02731       return CLI_SHOWUSAGE;
02732 
02733    h323_show_tokens();
02734 
02735    return CLI_SUCCESS;
02736 }

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

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

02739 {
02740    switch (cmd) {
02741    case CLI_INIT:
02742       e->command = "h323 show version";
02743       e->usage =
02744          "Usage: h323 show version\n"
02745          "     Show the version of the H.323 library in use\n";
02746       return NULL;
02747    case CLI_GENERATE:
02748       return NULL;
02749    }
02750 
02751    if (a->argc != 3)
02752       return CLI_SHOWUSAGE;
02753 
02754    h323_show_version();
02755    
02756    return CLI_SUCCESS;
02757 }

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

Definition at line 2393 of file chan_h323.c.

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

Referenced by load_module().

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

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3192 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_proto_register(), ast_rtp_proto_unregister(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, chan_ringing(), cleanup_connection(), cli_h323, cli_h323_reload, connection_made(), external_rtp_create(), gatekeeper, gatekeeper_disable, gatekeeper_discover, h323_signalling_port, h323debug, hangup_connection(), io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), sched_context_create(), sched_context_destroy(), secret, set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.

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

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

Definition at line 1614 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01615 {
01616    int res;
01617 
01618    if (!sin)
01619       res = -1;
01620    else
01621       res = inaddrcmp(&addr , sin);
01622 
01623    return res;
01624 }

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

Definition at line 1591 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01592 {
01593    return strcmp(ast_inet_ntoa(inaddr), addr);
01594 }

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

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

Referenced by oh323_request(), and setup_incoming_call().

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

static int oh323_answer ( struct ast_channel c  )  [static]

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

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

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 576 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_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, oh323_pvt::exten, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), oh323_pvt::sa, ast_channel::tech_pvt, and ast_channel::transfercapability.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

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

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

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

Definition at line 276 of file chan_h323.c.

References ast_debug, and ast_free.

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

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

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

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

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

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

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

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

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

Definition at line 496 of file chan_h323.c.

References ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_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.

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

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

References ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_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.

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

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

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

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

static enum ast_rtp_get_result oh323_get_rtp_peer ( struct ast_channel chan,
struct ast_rtp **  rtp 
) [static]

Definition at line 3107 of file chan_h323.c.

References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, chan, oh323_pvt::lock, oh323_pvt::options, oh323_pvt::rtp, and ast_channel::tech_pvt.

03108 {
03109    struct oh323_pvt *pvt;
03110    enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
03111 
03112    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03113       return AST_RTP_GET_FAILED;
03114 
03115    ast_mutex_lock(&pvt->lock);
03116    *rtp = pvt->rtp;
03117 #if 0
03118    if (pvt->options.bridge) {
03119       res = AST_RTP_TRY_NATIVE;
03120    }
03121 #endif
03122    ast_mutex_unlock(&pvt->lock);
03123 
03124    return res;
03125 }

static enum ast_rtp_get_result oh323_get_vrtp_peer ( struct ast_channel chan,
struct ast_rtp **  rtp 
) [static]

Definition at line 3127 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03128 {
03129    return AST_RTP_GET_FAILED;
03130 }

static int oh323_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

Definition at line 799 of file chan_h323.c.

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

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

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

Definition at line 1716 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, gatekeeper_disable, global_options, h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, restart_monitor(), and unique.

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

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

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

Definition at line 744 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_read(), ast_rtp_setnat(), ast_set_read_format(), ast_set_write_format(), f, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by oh323_read().

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

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

Definition at line 3159 of file chan_h323.c.

References ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_us(), oh323_pvt::cd, chan, convertcap(), LOG_ERROR, oh323_pvt::rtp, ast_channel::tech_pvt, and ast_channel::writeformat.

03160 {
03161    /* XXX Deal with Video */
03162    struct oh323_pvt *pvt;
03163    struct sockaddr_in them;
03164    struct sockaddr_in us;
03165    char *mode;
03166 
03167    if (!rtp) {
03168       return 0;
03169    }
03170 
03171    mode = convertcap(chan->writeformat);
03172    pvt = (struct oh323_pvt *) chan->tech_pvt;
03173    if (!pvt) {
03174       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03175       return -1;
03176    }
03177    ast_rtp_get_peer(rtp, &them);
03178    ast_rtp_get_us(rtp, &us);
03179 #if 0 /* Native bridge still isn't ready */
03180    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03181 #endif
03182    return 0;
03183 }

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

Definition at line 299 of file chan_h323.c.

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

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

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

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

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

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

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

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

Definition at line 2075 of file chan_h323.c.

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

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

static void prune_peers ( void   )  [static]

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

02813 {
02814    /* Prune peers who still are supposed to be deleted */
02815    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02816 }

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

Definition at line 1222 of file chan_h323.c.

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

Referenced by find_alias().

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

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

Definition at line 1548 of file chan_h323.c.

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

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

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

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

Definition at line 1434 of file chan_h323.c.

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

Referenced by check_access(), and find_user().

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

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

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

Referenced by load_module().

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

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

Definition at line 260 of file chan_h323.c.

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

static int reload ( void   )  [static]

Definition at line 3095 of file chan_h323.c.

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

03096 {
03097    if (!sched || !io) {
03098       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03099       return 0;
03100    }
03101    return h323_reload();
03102 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2818 of file chan_h323.c.

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

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

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

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

Definition at line 2492 of file chan_h323.c.

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

Referenced by load_module().

02493 {
02494    struct oh323_pvt *pvt;
02495 
02496    if (h323debug)
02497       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02498 
02499    pvt = find_call_locked(call_reference, token);
02500    if (!pvt)
02501       return;
02502    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02503       if (is_hold)
02504          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02505       else
02506          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02507       ast_channel_unlock(pvt->owner);
02508    }
02509    else {
02510       if (is_hold)
02511          pvt->newcontrol = AST_CONTROL_HOLD;
02512       else
02513          pvt->newcontrol = AST_CONTROL_UNHOLD;
02514    }
02515    ast_mutex_unlock(&pvt->lock);
02516 }

static int restart_monitor ( void   )  [static]

Definition at line 2586 of file chan_h323.c.

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

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

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

Definition at line 2421 of file chan_h323.c.

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

Referenced by load_module().

02422 {
02423    struct oh323_pvt *pvt;
02424 
02425    if (h323debug)
02426       ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
02427 
02428    pvt = find_call_locked(call_reference, token);
02429    if (!pvt) {
02430       return;
02431    }
02432    if (pvt->rtp) {
02433       ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
02434    }
02435    pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
02436    ast_mutex_unlock(&pvt->lock);
02437    if (h323debug)
02438       ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
02439 }

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

Definition at line 2469 of file chan_h323.c.

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

Referenced by load_module().

02470 {
02471    struct oh323_pvt *pvt;
02472    int capability, dtmfmode, pref_codec;
02473    struct ast_codec_pref prefs;
02474 
02475    if (h323debug)
02476       ast_debug(1, "Setting capabilities for connection %s\n", token);
02477 
02478    pvt = find_call_locked(call_reference, token);
02479    if (!pvt)
02480       return;
02481    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02482    dtmfmode = pvt->options.dtmfmode;
02483    prefs = pvt->options.prefs;
02484    pref_codec = pvt->pref_codec;
02485    ast_mutex_unlock(&pvt->lock);
02486    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02487 
02488    if (h323debug)
02489       ast_debug(1, "Capabilities for connection %s is set\n", token);
02490 }

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

Definition at line 2441 of file chan_h323.c.

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

Referenced by load_module().

02442 {
02443    struct oh323_pvt *pvt;
02444 
02445    if (h323debug)
02446       ast_debug(1, "Got remote capabilities from connection %s\n", token);
02447 
02448    pvt = find_call_locked(call_reference, token);
02449    if (!pvt)
02450       return;
02451    pvt->peercapability = capabilities;
02452    pvt->jointcapability = pvt->options.capability & capabilities;
02453    if (prefs) {
02454       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02455       if (h323debug) {
02456          int i;
02457          for (i = 0; i < 32; ++i) {
02458             if (!prefs->order[i])
02459                break;
02460             ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02461          }
02462       }
02463       if (pvt->rtp)
02464          ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
02465    }
02466    ast_mutex_unlock(&pvt->lock);
02467 }

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

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

Referenced by load_module().

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

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

References cleanup_call_details().

Referenced by load_module().

02303 {
02304    /* Use argument here or free it immediately */
02305    cleanup_call_details(cd);
02306 
02307    return 1;
02308 }

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 1939 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_lookup_pt(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp_set_peer(), ast_rtp_set_rtpmap_type(), ast_rtp_stop(), ast_set_read_format(), ast_set_write_format(), rtpPayloadType::code, find_call_locked(), h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, ast_channel::nativeformats, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_channel::writeformat.

Referenced by load_module().

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

static int unload_module ( void   )  [static]

Definition at line 3295 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_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, cli_h323, cli_h323_reload, gatekeeper_disable, iflist, iflock, io, io_context_destroy(), oh323_pvt::lock, LOG_WARNING, monitor_thread, monlock, oh323_pvt::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, oh323_pvt::owner, peerl, sched_context_destroy(), and userl.

03296 {
03297    struct oh323_pvt *p, *pl;
03298 
03299    /* unregister commands */
03300    ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03301    ast_cli_unregister(&cli_h323_reload);
03302 
03303    ast_channel_unregister(&oh323_tech);
03304    ast_rtp_proto_unregister(&oh323_rtp);
03305 
03306    if (!ast_mutex_lock(&iflock)) {
03307       /* hangup all interfaces if they have an owner */
03308       p = iflist;
03309       while(p) {
03310          if (p->owner) {
03311             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
03312          }
03313          p = p->next;
03314       }
03315       iflist = NULL;
03316       ast_mutex_unlock(&iflock);
03317    } else {
03318       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03319       return -1;
03320    }
03321    if (!ast_mutex_lock(&monlock)) {
03322       if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
03323          if (monitor_thread != pthread_self()) {
03324             pthread_cancel(monitor_thread);
03325          }
03326          pthread_kill(monitor_thread, SIGURG);
03327          pthread_join(monitor_thread, NULL);
03328       }
03329       monitor_thread = AST_PTHREADT_STOP;
03330       ast_mutex_unlock(&monlock);
03331    } else {
03332       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03333       return -1;
03334    }
03335    if (!ast_mutex_lock(&iflock)) {
03336       /* destroy all the interfaces and free their memory */
03337       p = iflist;
03338       while(p) {
03339          pl = p;
03340          p = p->next;
03341          /* free associated memory */
03342          ast_mutex_destroy(&pl->lock);
03343          ast_free(pl);
03344       }
03345       iflist = NULL;
03346       ast_mutex_unlock(&iflock);
03347    } else {
03348       ast_log(LOG_WARNING, "Unable to lock the interface list\n");
03349       return -1;
03350    }
03351    if (!gatekeeper_disable)
03352       h323_gk_urq();
03353    h323_end_process();
03354    if (io)
03355       io_context_destroy(io);
03356    if (sched)
03357       sched_context_destroy(sched);
03358 
03359    ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03360    ASTOBJ_CONTAINER_DESTROY(&userl);
03361    ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03362    ASTOBJ_CONTAINER_DESTROY(&peerl);
03363    ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03364    ASTOBJ_CONTAINER_DESTROY(&aliasl);
03365 
03366    return 0;
03367 }

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

Definition at line 1247 of file chan_h323.c.

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

Referenced by build_peer(), and build_user().

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

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

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

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


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

Definition at line 3373 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 139 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct h323_alias_list aliasl [static]

H323 alias list.

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

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3373 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 127 of file chan_h323.c.

ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

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

Definition at line 215 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2759 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_h323_reload [static]

Initial value:

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

Definition at line 3104 of file chan_h323.c.

Referenced by load_module(), and unload_module().

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

Definition at line 125 of file chan_h323.c.

unsigned int cos = 0 [static]

Definition at line 141 of file chan_h323.c.

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

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

Definition at line 126 of file chan_h323.c.

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

Definition at line 114 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 133 of file chan_h323.c.

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

int gatekeeper_disable = 1 [static]

Definition at line 134 of file chan_h323.c.

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

int gatekeeper_discover = 0 [static]

Definition at line 135 of file chan_h323.c.

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

int gkroute = 0 [static]

Definition at line 136 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct ast_jb_conf global_jbconf [static]

Definition at line 121 of file chan_h323.c.

call_options_t global_options [static]

Definition at line 145 of file chan_h323.c.

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

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

Protect the reload process.

Definition at line 218 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 219 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 132 of file chan_h323.c.

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

int h323debug

global debug flag

Definition at line 111 of file chan_h323.c.

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

struct oh323_pvt * iflist

Private structure of a OpenH323 channel.

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

Protect the interface list (oh323_pvt)

Definition at line 208 of file chan_h323.c.

struct io_context* io [static]

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

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

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

Definition at line 212 of file chan_h323.c.

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3185 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech oh323_tech [static]

Definition at line 242 of file chan_h323.c.

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

answer_call_cb on_answer_call

Definition at line 103 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 100 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 102 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 101 of file chan_h323.c.

on_rtp_cb on_external_rtp_create

Definition at line 96 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 106 of file chan_h323.c.

onhold_cb on_hold

Definition at line 109 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 98 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 99 of file chan_h323.c.

progress_cb on_progress

Definition at line 104 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 95 of file chan_h323.c.

rfc2833_cb on_set_rfc2833_payload

Definition at line 105 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 107 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 108 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 97 of file chan_h323.c.

struct h323_peer_list peerl [static]

H323 peer list.

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

struct sched_context* sched [static]

Definition at line 205 of file chan_h323.c.

char secret[50] [static]

Definition at line 142 of file chan_h323.c.

Referenced by add_realm_authentication(), aji_act_hook(), authenticate_verify(), build_peer(), build_reply_digest(), build_user(), cache_get_callno_locked(), check_access(), decrypt_frame(), handle_cli_h323_cycle_gk(), iax2_call(), iax2_register(), load_module(), read_agent_config(), register_verify(), set_config(), sip_register(), and sip_request_call().

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

Variables required by Asterisk

Definition at line 124 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 140 of file chan_h323.c.

Referenced by reload_config().

unsigned int unique = 0 [static]

Definition at line 143 of file chan_h323.c.

Referenced by oh323_request().

int userbyalias = 1 [static]

Definition at line 138 of file chan_h323.c.

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

struct h323_user_list userl [static]

H323 User list.

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


Generated on Fri Jul 24 00:41:23 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7