Wed Aug 18 22:34:08 2010

Asterisk developer's documentation


chan_h323.c File Reference

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

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

Go to the source code of this file.

Data Structures

struct  h323_alias_list
 H323 alias list. More...
struct  h323_peer_list
 H323 peer list. More...
struct  h323_user_list
 H323 User list. More...
struct  oh323_pvt
 Private structure of a OpenH323 channel. More...
struct  rtpPayloadType
 Structure representing a RTP session.The value of each payload format mapping:. More...

Defines

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

Functions

static void __oh323_destroy (struct oh323_pvt *pvt)
static struct ast_channel__oh323_new (struct oh323_pvt *pvt, int state, const char *host)
 Private structure should be locked on a call.
static int __oh323_rtp_create (struct oh323_pvt *pvt)
static void __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt)
 Channel and private structures should be already locked.
static void __reg_module (void)
static void __unreg_module (void)
static int answer_call (unsigned call_reference, const char *token)
 Call-back function to start PBX when OpenH323 ready to serve incoming call.
static struct oh323_alias * build_alias (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_peer * build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static struct oh323_user * build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static void chan_ringing (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel is ringing Returns nothing.
static void cleanup_call_details (call_details_t *cd)
static void cleanup_connection (unsigned call_reference, const char *call_token)
 Call-back function to cleanup communication Returns nothing,.
static void connection_made (unsigned call_reference, const char *token)
 Call-back function to signal asterisk that the channel has been answered Returns nothing.
static char * convertcap (int cap)
static int create_addr (struct oh323_pvt *pvt, char *opeer)
static void delete_aliases (void)
static void delete_users (void)
static void * do_monitor (void *data)
static struct rtp_info * external_rtp_create (unsigned call_reference, const char *token)
 Callback function used to inform the H.323 stack of the local rtp ip/port details.
static struct oh323_alias * find_alias (const char *source_aliases, int realtime)
 Find a call by alias.
static struct oh323_pvtfind_call_locked (int call_reference, const char *token)
static struct oh323_peer * find_peer (const char *peer, struct sockaddr_in *sin, int realtime)
static struct oh323_user * find_user (const call_details_t *cd, int realtime)
static int h323_do_reload (void)
static int h323_reload (void)
static char * handle_cli_h323_cycle_gk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_set_trace (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_show_tokens (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_h323_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void hangup_connection (unsigned int call_reference, const char *token, int cause)
static enum ast_module_load_result load_module (void)
static int oh323_addrcmp (struct sockaddr_in addr, struct sockaddr_in *sin)
static int oh323_addrcmp_str (struct in_addr inaddr, char *addr)
static struct oh323_pvtoh323_alloc (int callid)
static int oh323_answer (struct ast_channel *c)
static int oh323_call (struct ast_channel *c, char *dest, int timeout)
 Make a call over the specified channel to the specified destination. Returns -1 on error, 0 on success.
static void oh323_destroy (struct oh323_pvt *pvt)
static void oh323_destroy_alias (struct oh323_alias *alias)
static void oh323_destroy_peer (struct oh323_peer *peer)
static void oh323_destroy_user (struct oh323_user *user)
static int oh323_digit_begin (struct ast_channel *c, char digit)
static int oh323_digit_end (struct ast_channel *c, char digit, unsigned int duration)
 Send (play) the specified digit to the channel.
static int oh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_get_result oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static enum ast_rtp_get_result oh323_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
static int oh323_hangup (struct ast_channel *c)
static int oh323_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen)
static struct ast_frameoh323_read (struct ast_channel *c)
static struct ast_channeloh323_request (const char *type, int format, void *data, int *cause)
static struct ast_frameoh323_rtp_read (struct oh323_pvt *pvt)
 Retrieve audio/etc from channel. Assumes pvt->lock is already held.
static int oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
static int oh323_simulate_dtmf_end (const void *data)
static void oh323_update_info (struct ast_channel *c)
 Only channel structure should be locked.
static int oh323_write (struct ast_channel *c, struct ast_frame *frame)
static int progress (unsigned call_reference, const char *token, int inband)
static void prune_peers (void)
static struct oh323_alias * realtime_alias (const char *alias)
static struct oh323_peer * realtime_peer (const char *peername, struct sockaddr_in *sin)
static struct oh323_user * realtime_user (const call_details_t *cd)
static int receive_digit (unsigned call_reference, char digit, const char *token, int duration)
 Callback for sending digits from H.323 up to asterisk.
static const char * redirectingreason2str (int redirectingreason)
static int reload (void)
static int reload_config (int is_reload)
static void remote_hold (unsigned call_reference, const char *token, int is_hold)
static int restart_monitor (void)
static void set_dtmf_payload (unsigned call_reference, const char *token, int payload, int is_cisco)
static void set_local_capabilities (unsigned call_reference, const char *token)
static void set_peer_capabilities (unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs)
static call_options_t * setup_incoming_call (call_details_t *cd)
 Call-back function for incoming calls.
static int setup_outgoing_call (call_details_t *cd)
 Call-back function to establish an outgoing H.323 call.
static void setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
 Call-back function passing remote ip/port information from H.323 to asterisk.
static int unload_module (void)
static int update_common_options (struct ast_variable *v, struct call_options *options)
static int update_state (struct oh323_pvt *pvt, int state, int signal)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static int acceptAnonymous = 1
static struct h323_alias_list aliasl
 H323 alias list.
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_reload
static const char config [] = "h323.conf"
static unsigned int cos = 0
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration - by default, jb is disabled.
static char gatekeeper [100]
static int gatekeeper_disable = 1
static int gatekeeper_discover = 0
static int gkroute = 0
static struct ast_jb_conf global_jbconf
static call_options_t global_options
static ast_mutex_t h323_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the reload process.
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
oh323_pvtiflist
 Private structure of a OpenH323 channel.
static ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static struct ast_rtp_protocol oh323_rtp
static struct ast_channel_tech oh323_tech
answer_call_cb on_answer_call
chan_ringing_cb on_chan_ringing
clear_con_cb on_connection_cleared
con_established_cb on_connection_established
on_rtp_cb on_external_rtp_create
hangup_cb on_hangup
onhold_cb on_hold
setup_incoming_cb on_incoming_call
setup_outbound_cb on_outgoing_call
progress_cb on_progress
receive_digit_cb on_receive_digit
rfc2833_cb on_set_rfc2833_payload
setcapabilities_cb on_setcapabilities
setpeercapabilities_cb on_setpeercapabilities
start_rtp_cb on_start_rtp_channel
static struct h323_peer_list peerl
 H323 peer list.
static struct sched_contextsched
static char secret [50]
static const char tdesc [] = "The NuFone Network's Open H.323 Channel Driver"
static unsigned int tos = 0
static unsigned int unique = 0
static int userbyalias = 1
static struct h323_user_list userl
 H323 User list.


Detailed Description

This file is part of the chan_h323 driver for Asterisk.

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

Definition in file chan_h323.c.


Define Documentation

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

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

Referenced by do_monitor(), and oh323_destroy().

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]

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

Referenced by answer_call(), and oh323_request().

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(), oh323_pvt::dtmf_pt, errno, global_jbconf, io, oh323_pvt::lock, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, sched, and oh323_pvt::update_rtp_info.

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

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

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

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

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_module().

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

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

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.

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]

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

Referenced by reload_config(), and set_config().

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]

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

Referenced by reload_config(), and set_config().

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

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

Referenced by load_module().

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

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

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

Referenced by load_module().

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

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

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

Referenced by load_module().

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

static char* convertcap ( int  cap  )  [static]

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

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

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

Definition at line 1654 of file chan_h323.c.

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

Referenced by cache_get_callno_locked(), 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 2818 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().

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

static void delete_users ( void   )  [static]

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

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

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

Definition at line 2542 of file chan_h323.c.

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

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

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

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

Returns:
Returns the local RTP information

Definition at line 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(), h323debug, 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]

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]

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]

Definition at line 1636 of file chan_h323.c.

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

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

01637 {
01638    struct oh323_peer *p;
01639 
01640    if (peer)
01641       p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
01642    else
01643       p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
01644 
01645    if (!p && realtime)
01646       p = realtime_peer(peer, sin);
01647 
01648    if (!p && h323debug)
01649       ast_debug(1, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
01650 
01651    return p;
01652 }

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

Definition at line 1606 of file chan_h323.c.

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

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

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

References reload_config().

Referenced by do_monitor().

03115 {
03116    reload_config(1);
03117    return 0;
03118 }

static int h323_reload ( void   )  [static]

Definition at line 3080 of file chan_h323.c.

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

Referenced by handle_cli_h323_reload(), and reload().

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

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

Definition at line 2691 of file chan_h323.c.

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

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

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

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

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

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

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

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

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

Definition at line 2668 of file chan_h323.c.

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

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

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

Definition at line 2642 of file chan_h323.c.

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

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

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

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

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

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

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

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

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

Definition at line 2403 of file chan_h323.c.

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

Referenced by load_module().

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

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 3217 of file chan_h323.c.

References aliasl, answer_call(), ast_channel_register(), ast_cli_register(), ast_cli_register_multiple(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), ast_rtp_proto_unregister(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, chan_ringing(), cleanup_connection(), cli_h323, cli_h323_reload, connection_made(), external_rtp_create(), gatekeeper, gatekeeper_disable, gatekeeper_discover, h323_signalling_port, h323debug, hangup_connection(), io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), sched_context_create(), sched_context_destroy(), secret, set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.

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

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]

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, iflist, iflock, and LOG_ERROR.

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(), 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 3132 of file chan_h323.c.

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

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

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

Definition at line 3152 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03153 {
03154    return AST_RTP_GET_FAILED;
03155 }

static int oh323_hangup ( struct ast_channel c  )  [static]

Definition at line 681 of file chan_h323.c.

References oh323_pvt::alreadygone, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_REQUESTED_CHAN_UNAVAIL, AST_CAUSE_USER_BUSY, ast_debug, ast_free, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, oh323_pvt::cd, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_WARNING, 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]

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]

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

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]

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, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by oh323_read().

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

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

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

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(), DEADLOCK_AVOIDANCE, and f.

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

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

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

static void prune_peers ( void   )  [static]

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

02837 {
02838    /* Prune peers who still are supposed to be deleted */
02839    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
02840 }

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

Definition at line 1230 of file chan_h323.c.

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

Referenced by find_alias().

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]

Definition at line 1558 of file chan_h323.c.

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

Referenced by authenticate_reply(), 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]

Definition at line 1444 of file chan_h323.c.

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

Referenced by 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, f, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_simulate_dtmf_end(), and oh323_pvt::owner.

Referenced by load_module().

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.

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

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

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

static int reload_config ( int  is_reload  )  [static]

Definition at line 2842 of file chan_h323.c.

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

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

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

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

Definition at line 2516 of file chan_h323.c.

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

Referenced by load_module().

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

static int restart_monitor ( void   )  [static]

Definition at line 2610 of file chan_h323.c.

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

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

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

Definition at line 2431 of file chan_h323.c.

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

Referenced by load_module().

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

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

Definition at line 2486 of file chan_h323.c.

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

Referenced by load_module().

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

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

Definition at line 2451 of file chan_h323.c.

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

Referenced by load_module().

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

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

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

Referenced by load_module().

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

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

References cleanup_call_details().

Referenced by load_module().

02313 {
02314    /* Use argument here or free it immediately */
02315    cleanup_call_details(cd);
02316 
02317    return 1;
02318 }

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

References __oh323_rtp_create(), oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_debug, AST_FORMAT_G726_AAL2, ast_log(), ast_mutex_unlock(), ast_queue_control(), ast_rtp_lookup_pt(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp_set_peer(), ast_rtp_set_rtpmap_type(), ast_rtp_stop(), ast_set_read_format(), ast_set_write_format(), rtpPayloadType::code, find_call_locked(), h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, ast_channel::nativeformats, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_channel::writeformat.

Referenced by load_module().

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

static int unload_module ( void   )  [static]

Definition at line 3320 of file chan_h323.c.

References aliasl, ast_channel_unregister(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_free, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, cli_h323, cli_h323_reload, gatekeeper_disable, iflist, iflock, io, io_context_destroy(), oh323_pvt::lock, LOG_WARNING, monitor_thread, monlock, oh323_pvt::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, oh323_pvt::owner, peerl, sched_context_destroy(), and userl.

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

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

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

Definition at line 3398 of file chan_h323.c.

int acceptAnonymous = 1 [static]

Definition at line 142 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct h323_alias_list aliasl [static]

H323 alias list.

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

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3398 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_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

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

Definition at line 218 of file chan_h323.c.

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

Definition at line 2783 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_h323_reload [static]

Initial value:

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

Definition at line 3129 of file chan_h323.c.

Referenced by load_module(), and unload_module().

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

Definition at line 128 of file chan_h323.c.

unsigned int cos = 0 [static]

Definition at line 144 of file chan_h323.c.

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

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

Definition at line 129 of file chan_h323.c.

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled.

Definition at line 116 of file chan_h323.c.

char gatekeeper[100] [static]

Definition at line 136 of file chan_h323.c.

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

int gatekeeper_disable = 1 [static]

Definition at line 137 of file chan_h323.c.

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

int gatekeeper_discover = 0 [static]

Definition at line 138 of file chan_h323.c.

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

int gkroute = 0 [static]

Definition at line 139 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

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.

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

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

Protect the reload process.

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

Referenced by do_monitor(), and h323_reload().

int h323_signalling_port = 1720 [static]

H.323 configuration values

Definition at line 135 of file chan_h323.c.

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

int h323debug

global debug flag

Definition at line 113 of file chan_h323.c.

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

struct oh323_pvt * iflist

Private structure of a OpenH323 channel.

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

Protect the interface list (oh323_pvt)

Definition at line 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_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

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

Definition at line 215 of file chan_h323.c.

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3210 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech oh323_tech [static]

Definition at line 245 of file chan_h323.c.

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

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.

on_rtp_cb on_external_rtp_create

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.

rfc2833_cb on_set_rfc2833_payload

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]

H323 peer list.

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

struct sched_context* sched [static]

Definition at line 208 of file chan_h323.c.

char secret[50] [static]

Definition at line 145 of file chan_h323.c.

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

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

Variables required by Asterisk

Definition at line 127 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 143 of file chan_h323.c.

Referenced by reload_config().

unsigned int unique = 0 [static]

Definition at line 146 of file chan_h323.c.

Referenced by oh323_request().

int userbyalias = 1 [static]

Definition at line 141 of file chan_h323.c.

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

struct h323_user_list userl [static]

H323 User list.

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


Generated on Wed Aug 18 22:34:08 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7