Thu Apr 8 01:21:59 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 132 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

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

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

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 999 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().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

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

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

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 332 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().

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

static void __reg_module ( void   )  [static]

Definition at line 3394 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

Definition at line 3394 of file chan_h323.c.

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

Call-back function to start PBX when OpenH323 ready to serve incoming call.

Returns 1 on success

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

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

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

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

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

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

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

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

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

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

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

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 2320 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().

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

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 407 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

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

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

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 2054 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().

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

static char* convertcap ( int  cap  )  [static]

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

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

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

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

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

static void delete_aliases ( void   )  [static]

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

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

static void delete_users ( void   )  [static]

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

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

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

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

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

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 1895 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().

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

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

Find a call by alias.

Definition at line 1811 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

Referenced by setup_incoming_call().

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

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

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

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

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

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

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

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

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

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

static int h323_do_reload ( void   )  [static]

Definition at line 3110 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

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

static int h323_reload ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2737 of file chan_h323.c.

References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.

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

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

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

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

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

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

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

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3213 of file chan_h323.c.

References aliasl, answer_call(), ast_channel_register(), ast_cli_register(), ast_cli_register_multiple(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_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.

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

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

Definition at line 1620 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

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

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

Definition at line 1597 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

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

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

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

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

static int oh323_answer ( struct ast_channel c  )  [static]

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

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

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

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

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

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

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

Definition at line 279 of file chan_h323.c.

References ast_debug, and ast_free.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3148 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03149 {
03150    return AST_RTP_GET_FAILED;
03151 }

static int oh323_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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 748 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().

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

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

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

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

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

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

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

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

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

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

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

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

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

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

static void prune_peers ( void   )  [static]

Definition at line 2832 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.

Referenced by reload_config().

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

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

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

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

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

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

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

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

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

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

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 1827 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().

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

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

Definition at line 263 of file chan_h323.c.

Referenced by __oh323_new().

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

static int reload ( void   )  [static]

Definition at line 3116 of file chan_h323.c.

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

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

static int reload_config ( int  is_reload  )  [static]

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

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

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

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

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

static int restart_monitor ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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 2109 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().

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

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

References cleanup_call_details().

Referenced by load_module().

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

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 1945 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().

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

static int unload_module ( void   )  [static]

Definition at line 3316 of file chan_h323.c.

References aliasl, ast_channel_unregister(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_free, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_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.

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

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

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

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

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

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

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


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

int acceptAnonymous = 1 [static]

Definition at line 142 of file chan_h323.c.

struct h323_alias_list aliasl [static]

Definition at line 3394 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

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

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

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

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

Definition at line 128 of file chan_h323.c.

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

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

int gatekeeper_disable = 1 [static]

Definition at line 137 of file chan_h323.c.

int gatekeeper_discover = 0 [static]

Definition at line 138 of file chan_h323.c.

int gkroute = 0 [static]

Definition at line 139 of file chan_h323.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 124 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 148 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 221 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 222 of file chan_h323.c.

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 135 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 211 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 209 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 226 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 215 of file chan_h323.c.

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

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3206 of file chan_h323.c.

struct ast_channel_tech oh323_tech [static]

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

unsigned int tos = 0 [static]

Definition at line 143 of file chan_h323.c.

unsigned int unique = 0 [static]

Definition at line 146 of file chan_h323.c.

int userbyalias = 1 [static]

Definition at line 141 of file chan_h323.c.

struct h323_user_list userl [static]

Generated on 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1