Thu Oct 11 06:48:14 2012

Asterisk developer's documentation


chan_h323.c File Reference

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

#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "h323/chan_h323.h"

Include dependency graph for chan_h323.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

static void __oh323_destroy (struct oh323_pvt *pvt)
static struct ast_channel__oh323_new (struct oh323_pvt *pvt, int state, const char *host)
 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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static int acceptAnonymous = 1
static struct h323_alias_list aliasl
 H323 alias list.
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_reload
static const char config [] = "h323.conf"
static unsigned int cos = 0
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration - by default, jb is disabled.
static char gatekeeper [100]
static int gatekeeper_disable = 1
static int gatekeeper_discover = 0
static int gkroute = 0
static struct ast_jb_conf global_jbconf
static call_options_t global_options
static ast_mutex_t h323_reload_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 Protect the reload process.
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
struct oh323_pvtiflist
 Private structure of a OpenH323 channel.
static ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
 Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static struct ast_rtp_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, ast_channel::name, oh323_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::vad.

Referenced by do_monitor(), and oh323_destroy().

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 1003 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, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, redirectingreason2str(), ast_channel::rings, oh323_pvt::rtp, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by answer_call(), and oh323_request().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

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

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

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, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, ast_frame::subclass, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

Definition at line 1482 of file chan_h323.c.

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

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

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

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

Definition at line 1364 of file chan_h323.c.

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

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

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

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

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

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

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

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

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

static char* convertcap ( int  cap  )  [static]

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

03167 {
03168    switch (cap) {
03169    case AST_FORMAT_G723_1:
03170       return "G.723";
03171    case AST_FORMAT_GSM:
03172       return "GSM";
03173    case AST_FORMAT_ULAW:
03174       return "ULAW";
03175    case AST_FORMAT_ALAW:
03176       return "ALAW";
03177    case AST_FORMAT_G722:
03178       return "G.722";
03179    case AST_FORMAT_ADPCM:
03180       return "G.728";
03181    case AST_FORMAT_G729A:
03182       return "G.729";
03183    case AST_FORMAT_SPEEX:
03184       return "SPEEX";
03185    case AST_FORMAT_ILBC:
03186       return "ILBC";
03187    default:
03188       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03189       return NULL;
03190    }
03191 }

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

Definition at line 1654 of file chan_h323.c.

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

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

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

static void delete_aliases ( void   )  [static]

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

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

static void delete_users ( void   )  [static]

Definition at line 2786 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, oh323_destroy_user(), peerl, and userl.

Referenced by __unload_module(), reload(), reload_config(), set_config_destroy(), and unload_module().

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

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

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

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

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

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

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

Find a call by alias.

Definition at line 1815 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

01816 {
01817    struct oh323_alias *a;
01818 
01819    a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
01820 
01821    if (!a && realtime)
01822       a = realtime_alias(source_aliases);
01823 
01824    return a;
01825 }

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

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

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

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

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

Definition at line 1606 of file chan_h323.c.

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

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

static int h323_do_reload ( void   )  [static]

Definition at line 3123 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

03124 {
03125    reload_config(1);
03126    return 0;
03127 }

static int h323_reload ( void   )  [static]

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

03090 {
03091    ast_mutex_lock(&h323_reload_lock);
03092    if (h323_reloading) {
03093       ast_verbose("Previous H.323 reload not yet done\n");
03094    } else {
03095       h323_reloading = 1;
03096    }
03097    ast_mutex_unlock(&h323_reload_lock);
03098    restart_monitor();
03099    return 0;
03100 }

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

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

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

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

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

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

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

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

03103 {
03104    switch (cmd) {
03105    case CLI_INIT:
03106       e->command = "h323 reload";
03107       e->usage =
03108          "Usage: h323 reload\n"
03109          "       Reloads H.323 configuration from h323.conf\n";
03110       return NULL;
03111    case CLI_GENERATE:
03112       return NULL;
03113    }
03114 
03115    if (a->argc != 2)
03116       return CLI_SHOWUSAGE;
03117 
03118    h323_reload();
03119 
03120    return CLI_SUCCESS;
03121 }

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

Definition at line 2662 of file chan_h323.c.

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

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

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

Definition at line 2633 of file chan_h323.c.

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

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

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

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

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

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

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

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

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

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

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

static enum ast_module_load_result load_module ( void   )  [static]

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

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

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

Definition at line 1624 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

01625 {
01626    int res;
01627 
01628    if (!sin)
01629       res = -1;
01630    else
01631       res = inaddrcmp(&addr , sin);
01632 
01633    return res;
01634 }

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

Definition at line 1601 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

01602 {
01603    return strcmp(ast_inet_ntoa(inaddr), addr);
01604 }

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

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

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

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, ast_channel::name, 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, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), oh323_pvt::sa, ast_channel::tech_pvt, and ast_channel::transfercapability.

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, ast_channel::name, 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, ast_channel::name, 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, ast_channel::name, 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 941 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.

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

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

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

03142 {
03143    struct oh323_pvt *pvt;
03144    enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
03145 
03146    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03147       return AST_RTP_GET_FAILED;
03148 
03149    ast_mutex_lock(&pvt->lock);
03150    *rtp = pvt->rtp;
03151 #if 0
03152    if (pvt->options.bridge) {
03153       res = AST_RTP_TRY_NATIVE;
03154    }
03155 #endif
03156    ast_mutex_unlock(&pvt->lock);
03157 
03158    return res;
03159 }

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

Definition at line 3161 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03162 {
03163    return AST_RTP_GET_FAILED;
03164 }

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, cause, oh323_pvt::cd, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.

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_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_free, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_change_source(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::got_progress, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_update_info(), oh323_pvt::rtp, and ast_channel::tech_pvt.

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_SRCCHANGE:
00921       ast_rtp_change_source(pvt->rtp);
00922       res = 0;
00923       break;
00924    case AST_CONTROL_PROCEEDING:
00925    case -1:
00926       break;
00927    default:
00928       ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
00929       break;
00930    }
00931 
00932    if (h323debug)
00933       ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
00934    if (token)
00935       ast_free(token);
00936    oh323_update_info(c);
00937 
00938    return res;
00939 }

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, ast_channel::name, 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 1726 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().

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

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

03194 {
03195    /* XXX Deal with Video */
03196    struct oh323_pvt *pvt;
03197    struct sockaddr_in them;
03198    struct sockaddr_in us;
03199    char *mode;
03200 
03201    if (!rtp) {
03202       return 0;
03203    }
03204 
03205    mode = convertcap(chan->writeformat);
03206    pvt = (struct oh323_pvt *) chan->tech_pvt;
03207    if (!pvt) {
03208       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03209       return -1;
03210    }
03211    ast_rtp_get_peer(rtp, &them);
03212    ast_rtp_get_us(rtp, &us);
03213 #if 0 /* Native bridge still isn't ready */
03214    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03215 #endif
03216    return 0;
03217 }

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

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

static void prune_peers ( void   )  [static]

Definition at line 2830 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.

Referenced by handle_cli_iax2_prune_realtime(), reload_config(), set_config(), and unload_module().

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

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

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

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

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

Definition at line 1558 of file chan_h323.c.

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

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

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

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

Definition at line 1444 of file chan_h323.c.

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

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

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

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

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

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

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

03130 {
03131    if (!sched || !io) {
03132       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03133       return 0;
03134    }
03135    return h323_reload();
03136 }

static int reload_config ( int  is_reload  )  [static]

Definition at line 2836 of file chan_h323.c.

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

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

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

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

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

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

static int restart_monitor ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References cleanup_call_details().

Referenced by load_module().

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

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

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

static int unload_module ( void   )  [static]

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

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

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

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

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

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

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

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


Variable Documentation

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

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

struct sockaddr_in bindaddr [static]

Definition at line 130 of file chan_h323.c.

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

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

Definition at line 218 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

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

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_MUTEX_INITIALIZER ) [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.

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

Protect the interface list (oh323_pvt)

Definition at line 211 of file chan_h323.c.

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_MUTEX_INITIALIZER ) [static]

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

Definition at line 215 of file chan_h323.c.

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3219 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 Thu Oct 11 06:48:15 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6