Tue Mar 2 17:32:50 2010

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"
Include dependency graph for chan_h323.c:

Go to the source code of this file.

Data Structures

struct  h323_alias_list
 H323 alias list. More...
struct  h323_peer_list
 H323 peer list. More...
struct  h323_user_list
 H323 User list. More...
struct  oh323_pvt
 Private structure of a OpenH323 channel. More...
struct  rtpPayloadType
 Structure representing a RTP session. 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
struct 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
  • Config_h323
ExtRef:
OpenH323 http://www.voxgratia.org/

Definition in file chan_h323.c.


Define Documentation

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

Definition at line 131 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 442 of file chan_h323.c.

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

Referenced by do_monitor(), and oh323_destroy().

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

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

Private structure should be locked on a call.

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

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

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

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

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

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

Channel and private structures should be already locked.

Definition at line 331 of file chan_h323.c.

References ast_channel::_softhangup, ast_channel_set_fd(), ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_jb_configure(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hangup_with_cause(), ast_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, ast_frame::frametype, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DTMF, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, ast_frame::subclass, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

static void __reg_module ( void   )  [static]

Definition at line 3393 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_module().

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

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

Definition at line 1190 of file chan_h323.c.

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

Referenced by realtime_alias(), and reload_config().

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

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

Definition at line 1477 of file chan_h323.c.

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

Referenced by realtime_peer(), and reload_config().

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

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

Definition at line 1359 of file chan_h323.c.

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

Referenced by realtime_user(), and reload_config().

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

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

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

Referenced by load_module().

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

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 406 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

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

Referenced by load_module().

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

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

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

Referenced by load_module().

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

static char* convertcap ( int  cap  )  [static]

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

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

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

Definition at line 1649 of file chan_h323.c.

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

Referenced by oh323_request().

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

static void delete_aliases ( void   )  [static]

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

02814 {
02815    int pruned = 0;
02816 
02817    /* Delete all aliases */
02818    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
02819    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
02820       ASTOBJ_RDLOCK(iterator);
02821       ASTOBJ_MARK(iterator);
02822       ++pruned;
02823       ASTOBJ_UNLOCK(iterator);
02824    } while (0) );
02825    if (pruned) {
02826       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
02827    }
02828    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
02829 }

static void delete_users ( void   )  [static]

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

02788 {
02789    int pruned = 0;
02790 
02791    /* Delete all users */
02792    ASTOBJ_CONTAINER_WRLOCK(&userl);
02793    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
02794       ASTOBJ_RDLOCK(iterator);
02795       ASTOBJ_MARK(iterator);
02796       ++pruned;
02797       ASTOBJ_UNLOCK(iterator);
02798    } while (0) );
02799    if (pruned) {
02800       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
02801    }
02802    ASTOBJ_CONTAINER_UNLOCK(&userl);
02803 
02804    ASTOBJ_CONTAINER_WRLOCK(&peerl);
02805    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
02806       ASTOBJ_RDLOCK(iterator);
02807       ASTOBJ_MARK(iterator);
02808       ASTOBJ_UNLOCK(iterator);
02809    } while (0) );
02810    ASTOBJ_CONTAINER_UNLOCK(&peerl);
02811 }

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

Definition at line 2537 of file chan_h323.c.

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

Referenced by restart_monitor().

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

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

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

Returns:
Returns the local RTP information

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

Referenced by load_module().

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

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

Find a call by alias.

Definition at line 1810 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

Referenced by setup_incoming_call().

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

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

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

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

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

Definition at line 1631 of file chan_h323.c.

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

Referenced by create_addr().

01632 {
01633    struct oh323_peer *p;
01634 
01635    if (peer)
01636       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01637    else
01638       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01639 
01640    if (!p && realtime)
01641       p = realtime_peer(peer, sin);
01642 
01643    if (!p && h323debug)
01644       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>"));
01645 
01646    return p;
01647 }

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

Definition at line 1601 of file chan_h323.c.

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

Referenced by setup_incoming_call().

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

static int h323_do_reload ( void   )  [static]

Definition at line 3109 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03110 {
03111    reload_config(1);
03112    return 0;
03113 }

static int h323_reload ( void   )  [static]

Definition at line 3075 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

03076 {
03077    ast_mutex_lock(&h323_reload_lock);
03078    if (h323_reloading) {
03079       ast_verbose("Previous H.323 reload not yet done\n");
03080    } else {
03081       h323_reloading = 1;
03082    }
03083    ast_mutex_unlock(&h323_reload_lock);
03084    restart_monitor();
03085    return 0;
03086 }

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

Definition at line 2686 of file chan_h323.c.

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

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

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

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

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

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

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

03089 {
03090    switch (cmd) {
03091    case CLI_INIT:
03092       e->command = "h323 reload";
03093       e->usage =
03094          "Usage: h323 reload\n"
03095          "       Reloads H.323 configuration from h323.conf\n";
03096       return NULL;
03097    case CLI_GENERATE:
03098       return NULL;
03099    }
03100 
03101    if (a->argc != 2)
03102       return CLI_SHOWUSAGE;
03103 
03104    h323_reload();
03105 
03106    return CLI_SUCCESS;
03107 }

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

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

02664 {
02665    switch (cmd) {
02666    case CLI_INIT:
02667       e->command = "h323 set debug [off]";
02668       e->usage =
02669          "Usage: h323 set debug [off]\n"
02670          "       Enable/Disable H.323 debugging output\n";
02671       return NULL;
02672    case CLI_GENERATE:
02673       return NULL;
02674    }
02675 
02676    if (a->argc < 3 || a->argc > 4)
02677       return CLI_SHOWUSAGE;
02678    if (a->argc == 4 && strcasecmp(a->argv[3], "off"))
02679       return CLI_SHOWUSAGE;
02680 
02681    h323debug = (a->argc == 3) ? 1 : 0;
02682    ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
02683    return CLI_SUCCESS;
02684 }

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

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

02638 {
02639    switch (cmd) {
02640    case CLI_INIT:
02641       e->command = "h323 set trace [off]";
02642       e->usage =
02643          "Usage: h323 set trace (off|<trace level>)\n"
02644          "       Enable/Disable H.323 stack tracing for debugging purposes\n";
02645       return NULL;
02646    case CLI_GENERATE:
02647       return NULL;
02648    }
02649 
02650    if (a->argc != 4)
02651       return CLI_SHOWUSAGE;
02652    if (!strcasecmp(a->argv[3], "off")) {
02653       h323_debug(0, 0);
02654       ast_cli(a->fd, "H.323 Trace Disabled\n");
02655    } else {
02656       int tracelevel = atoi(a->argv[3]);
02657       h323_debug(1, tracelevel);
02658       ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
02659    }
02660    return CLI_SUCCESS;
02661 }

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

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

02737 {
02738    switch (cmd) {
02739    case CLI_INIT:
02740       e->command = "h323 show tokens";
02741       e->usage =
02742          "Usage: h323 show tokens\n"
02743          "       Print out all active call tokens\n";
02744       return NULL;
02745    case CLI_GENERATE:
02746       return NULL;
02747    }
02748 
02749    if (a->argc != 3)
02750       return CLI_SHOWUSAGE;
02751 
02752    h323_show_tokens();
02753 
02754    return CLI_SUCCESS;
02755 }

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

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

02758 {
02759    switch (cmd) {
02760    case CLI_INIT:
02761       e->command = "h323 show version";
02762       e->usage =
02763          "Usage: h323 show version\n"
02764          "     Show the version of the H.323 library in use\n";
02765       return NULL;
02766    case CLI_GENERATE:
02767       return NULL;
02768    }
02769 
02770    if (a->argc != 3)
02771       return CLI_SHOWUSAGE;
02772 
02773    h323_show_version();
02774    
02775    return CLI_SUCCESS;
02776 }

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

Definition at line 2398 of file chan_h323.c.

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

Referenced by load_module().

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

static enum ast_module_load_result load_module ( void   )  [static]

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

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

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

Definition at line 1619 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

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

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

Definition at line 1596 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

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

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

Definition at line 1100 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, oh323_pvt::cd, oh323_pvt::context, oh323_pvt::DTMFsched, iflist, iflock, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newstate, oh323_pvt::next, oh323_pvt::nonCodecCapability, oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::update_rtp_info.

Referenced by oh323_request(), and setup_incoming_call().

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

static int oh323_answer ( struct ast_channel c  )  [static]

Definition at line 657 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, oh323_update_info(), and ast_channel::tech_pvt.

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

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

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

Definition at line 578 of file chan_h323.c.

References ast_channel::_state, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verb, oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_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, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), oh323_pvt::sa, ast_channel::tech_pvt, and ast_channel::transfercapability.

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

Definition at line 487 of file chan_h323.c.

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

Referenced by oh323_request(), and setup_incoming_call().

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

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

Definition at line 278 of file chan_h323.c.

References ast_debug, and ast_free.

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

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

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

Definition at line 293 of file chan_h323.c.

References ast_debug, ast_free, and ast_free_ha().

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

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

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

Definition at line 285 of file chan_h323.c.

References ast_debug, ast_free, and ast_free_ha().

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

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

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

Definition at line 498 of file chan_h323.c.

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

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

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

Send (play) the specified digit to the channel.

Definition at line 539 of file chan_h323.c.

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

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

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

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

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

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

Definition at line 3127 of file chan_h323.c.

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

03128 {
03129    struct oh323_pvt *pvt;
03130    enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
03131 
03132    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03133       return AST_RTP_GET_FAILED;
03134 
03135    ast_mutex_lock(&pvt->lock);
03136    *rtp = pvt->rtp;
03137 #if 0
03138    if (pvt->options.bridge) {
03139       res = AST_RTP_TRY_NATIVE;
03140    }
03141 #endif
03142    ast_mutex_unlock(&pvt->lock);
03143 
03144    return res;
03145 }

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

Definition at line 3147 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03148 {
03149    return AST_RTP_GET_FAILED;
03150 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 680 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, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.

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

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

Definition at line 855 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, oh323_update_info(), oh323_pvt::rtp, and ast_channel::tech_pvt.

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

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

Definition at line 802 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, oh323_rtp_read(), oh323_pvt::rtp, and ast_channel::tech_pvt.

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

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

Definition at line 1721 of file chan_h323.c.

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

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

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

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

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

Referenced by oh323_read().

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

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

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

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

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

Definition at line 301 of file chan_h323.c.

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

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

Definition at line 395 of file chan_h323.c.

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

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

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

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

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

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

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

Definition at line 2080 of file chan_h323.c.

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

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

static void prune_peers ( void   )  [static]

Definition at line 2831 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.

Referenced by reload_config().

02832 {
02833    /* Prune peers who still are supposed to be deleted */
02834    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02835 }

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

Definition at line 1225 of file chan_h323.c.

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

Referenced by find_alias().

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

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

Definition at line 1553 of file chan_h323.c.

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

Referenced by find_peer().

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

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

Definition at line 1439 of file chan_h323.c.

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

Referenced by find_user().

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

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

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

Referenced by load_module().

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

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

Definition at line 262 of file chan_h323.c.

Referenced by __oh323_new().

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

static int reload ( void   )  [static]

Definition at line 3115 of file chan_h323.c.

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

03116 {
03117    if (!sched || !io) {
03118       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03119       return 0;
03120    }
03121    return h323_reload();
03122 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2837 of file chan_h323.c.

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

Referenced by h323_do_reload(), and load_module().

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

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

Definition at line 2511 of file chan_h323.c.

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

Referenced by load_module().

02512 {
02513    struct oh323_pvt *pvt;
02514 
02515    if (h323debug)
02516       ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
02517 
02518    pvt = find_call_locked(call_reference, token);
02519    if (!pvt)
02520       return;
02521    if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
02522       if (is_hold)
02523          ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
02524       else
02525          ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
02526       ast_channel_unlock(pvt->owner);
02527    }
02528    else {
02529       if (is_hold)
02530          pvt->newcontrol = AST_CONTROL_HOLD;
02531       else
02532          pvt->newcontrol = AST_CONTROL_UNHOLD;
02533    }
02534    ast_mutex_unlock(&pvt->lock);
02535 }

static int restart_monitor ( void   )  [static]

Definition at line 2605 of file chan_h323.c.

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

Referenced by h323_reload(), load_module(), and oh323_request().

02606 {
02607    /* If we're supposed to be stopped -- stay stopped */
02608    if (ast_mutex_lock(&monlock)) {
02609       ast_log(LOG_WARNING, "Unable to lock monitor\n");
02610       return -1;
02611    }
02612    if (monitor_thread == AST_PTHREADT_STOP) {
02613       ast_mutex_unlock(&monlock);
02614       return 0;
02615    }
02616    if (monitor_thread == pthread_self()) {
02617       ast_mutex_unlock(&monlock);
02618       ast_log(LOG_WARNING, "Cannot kill myself\n");
02619       return -1;
02620    }
02621    if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
02622       /* Wake up the thread */
02623       pthread_kill(monitor_thread, SIGURG);
02624    } else {
02625       /* Start a new monitor */
02626       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
02627          monitor_thread = AST_PTHREADT_NULL;
02628          ast_mutex_unlock(&monlock);
02629          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
02630          return -1;
02631       }
02632    }
02633    ast_mutex_unlock(&monlock);
02634    return 0;
02635 }

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

Definition at line 2426 of file chan_h323.c.

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

Referenced by load_module().

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

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

Definition at line 2481 of file chan_h323.c.

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

Referenced by load_module().

02482 {
02483    struct oh323_pvt *pvt;
02484    int capability, dtmfmode, pref_codec;
02485    struct ast_codec_pref prefs;
02486 
02487    if (h323debug)
02488       ast_debug(1, "Setting capabilities for connection %s\n", token);
02489 
02490    pvt = find_call_locked(call_reference, token);
02491    if (!pvt)
02492       return;
02493    capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
02494    dtmfmode = pvt->options.dtmfmode;
02495    prefs = pvt->options.prefs;
02496    pref_codec = pvt->pref_codec;
02497    ast_mutex_unlock(&pvt->lock);
02498    h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
02499 
02500    if (h323debug) {
02501       int i;
02502       for (i = 0; i < 32; i++) {
02503          if (!prefs.order[i])
02504             break;
02505          ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]);
02506       }
02507       ast_debug(1, "Capabilities for connection %s is set\n", token);
02508    }
02509 }

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

Definition at line 2446 of file chan_h323.c.

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

Referenced by load_module().

02447 {
02448    struct oh323_pvt *pvt;
02449 
02450    if (h323debug)
02451       ast_debug(1, "Got remote capabilities from connection %s\n", token);
02452 
02453    pvt = find_call_locked(call_reference, token);
02454    if (!pvt)
02455       return;
02456    pvt->peercapability = capabilities;
02457    pvt->jointcapability = pvt->options.capability & capabilities;
02458    if (prefs) {
02459       memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
02460       if (h323debug) {
02461          int i;
02462          for (i = 0; i < 32; ++i) {
02463             if (!prefs->order[i])
02464                break;
02465             ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]);
02466          }
02467       }
02468       if (pvt->rtp) {
02469          if (pvt->options.autoframing) {
02470             ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
02471             ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs);
02472          } else {
02473             ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
02474             ast_rtp_codec_setpref(pvt->rtp, &pvt->options.prefs);
02475          }
02476       }
02477    }
02478    ast_mutex_unlock(&pvt->lock);
02479 }

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

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

Referenced by load_module().

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

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

References cleanup_call_details().

Referenced by load_module().

02308 {
02309    /* Use argument here or free it immediately */
02310    cleanup_call_details(cd);
02311 
02312    return 1;
02313 }

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 1944 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(), 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().

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

static int unload_module ( void   )  [static]

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

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

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

Definition at line 1250 of file chan_h323.c.

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

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

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

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

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

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


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

int acceptAnonymous = 1 [static]

Definition at line 141 of file chan_h323.c.

struct h323_alias_list aliasl [static]

Definition at line 3393 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

Definition at line 129 of file chan_h323.c.

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

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

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2778 of file chan_h323.c.

struct ast_cli_entry cli_h323_reload [static]
Initial value:
   AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration")

Definition at line 3124 of file chan_h323.c.

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

Definition at line 127 of file chan_h323.c.

unsigned int cos = 0 [static]
char default_context[AST_MAX_CONTEXT] = "default" [static]

Definition at line 128 of file chan_h323.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

Definition at line 116 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 135 of file chan_h323.c.

int gatekeeper_disable = 1 [static]

Definition at line 136 of file chan_h323.c.

int gatekeeper_discover = 0 [static]

Definition at line 137 of file chan_h323.c.

int gkroute = 0 [static]

Definition at line 138 of file chan_h323.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 123 of file chan_h323.c.

Referenced by __oh323_rtp_create(), __oh323_update_info(), and reload_config().

call_options_t global_options [static]

Definition at line 147 of file chan_h323.c.

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

Protect the reload process.

Definition at line 220 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 221 of file chan_h323.c.

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 134 of file chan_h323.c.

int h323debug

global debug flag

Definition at line 113 of file chan_h323.c.

struct oh323_pvt * iflist

Private structure of a OpenH323 channel.

Referenced by __oh323_destroy(), do_monitor(), find_call_locked(), oh323_alloc(), and unload_module().

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

Protect the interface list (oh323_pvt)

Definition at line 210 of file chan_h323.c.

Referenced by do_monitor(), find_call_locked(), oh323_alloc(), oh323_destroy(), and unload_module().

struct io_context* io [static]

Definition at line 208 of file chan_h323.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 225 of file chan_h323.c.

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

Referenced by do_monitor(), restart_monitor(), and unload_module().

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3205 of file chan_h323.c.

struct ast_channel_tech oh323_tech [static]

Definition at line 244 of file chan_h323.c.

answer_call_cb on_answer_call

Definition at line 105 of file chan_h323.c.

chan_ringing_cb on_chan_ringing

Definition at line 102 of file chan_h323.c.

clear_con_cb on_connection_cleared

Definition at line 104 of file chan_h323.c.

con_established_cb on_connection_established

Definition at line 103 of file chan_h323.c.

Definition at line 98 of file chan_h323.c.

hangup_cb on_hangup

Definition at line 108 of file chan_h323.c.

onhold_cb on_hold

Definition at line 111 of file chan_h323.c.

setup_incoming_cb on_incoming_call

Definition at line 100 of file chan_h323.c.

setup_outbound_cb on_outgoing_call

Definition at line 101 of file chan_h323.c.

progress_cb on_progress

Definition at line 106 of file chan_h323.c.

receive_digit_cb on_receive_digit

Definition at line 97 of file chan_h323.c.

Definition at line 107 of file chan_h323.c.

setcapabilities_cb on_setcapabilities

Definition at line 109 of file chan_h323.c.

setpeercapabilities_cb on_setpeercapabilities

Definition at line 110 of file chan_h323.c.

start_rtp_cb on_start_rtp_channel

Definition at line 99 of file chan_h323.c.

struct h323_peer_list peerl [static]
struct sched_context* sched [static]

Definition at line 207 of file chan_h323.c.

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

Variables required by Asterisk

Definition at line 126 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 142 of file chan_h323.c.

unsigned int unique = 0 [static]

Definition at line 145 of file chan_h323.c.

int userbyalias = 1 [static]

Definition at line 140 of file chan_h323.c.

struct h323_user_list userl [static]

Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1