Thu Jul 9 13:40:57 2009

Asterisk developer's documentation


chan_h323.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, }
static int acceptAnonymous = 1
static struct h323_alias_list aliasl
 H323 alias list.
static const 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 131 of file chan_h323.c.

Referenced by reload_config().


Function Documentation

static void __oh323_destroy ( struct oh323_pvt pvt  )  [static]

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

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

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 1002 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_DTMF_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().

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

static int __oh323_rtp_create ( struct oh323_pvt pvt  )  [static]

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

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 3395 of file chan_h323.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

static void cleanup_call_details ( call_details_t *  cd  )  [static]

Definition at line 411 of file chan_h323.c.

References ast_free.

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

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

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

Call-back function to cleanup communication Returns nothing,.

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

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

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

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

static char* convertcap ( int  cap  )  [static]

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

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

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

Definition at line 1653 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(), oh323_request(), sip_notify(), sip_request_call(), and transmit_register().

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

static void delete_aliases ( void   )  [static]

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

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

static void delete_users ( void   )  [static]

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

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

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

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

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

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

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

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

Find a call by alias.

Definition at line 1814 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

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

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

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

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

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

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

Definition at line 1635 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_show_peer(), check_peer_ok(), create_addr(), dundi_encrypt(), function_iaxpeer(), function_sippeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), handle_command_response(), iax2_devicestate(), register_verify(), registry_authrequest(), set_config(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), sip_unregister(), st_get_mode(), st_get_refresher(), st_get_se(), update_call_counter(), and update_registry().

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

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

Definition at line 1605 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(), check_user_ok(), forward_message(), handle_cli_iax2_prune_realtime(), leave_voicemail(), setup_incoming_call(), sip_show_user(), st_get_mode(), st_get_refresher(), st_get_se(), update_call_counter(), vm_authenticate(), vm_box_exists(), and vm_execmain().

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

static int h323_do_reload ( void   )  [static]

Definition at line 3113 of file chan_h323.c.

References reload_config().

Referenced by do_monitor().

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

static int h323_reload ( void   )  [static]

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

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

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

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

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

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

Definition at line 2717 of file chan_h323.c.

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

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

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

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

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

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

Definition at line 2667 of file chan_h323.c.

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 2402 of file chan_h323.c.

References ast_channel::_softhangup, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_mutex_unlock(), ast_queue_hangup(), 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().

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

static enum ast_module_load_result load_module ( void   )  [static]

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

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

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

Definition at line 1623 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

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

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

Definition at line 1600 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

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

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

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

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

static int oh323_answer ( struct ast_channel c  )  [static]

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

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

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

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

static void oh323_destroy ( struct oh323_pvt pvt  )  [static]

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

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

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

Definition at line 281 of file chan_h323.c.

References ast_debug, and ast_free.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 3149 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03150 {
03151    return AST_RTP_GET_FAILED;
03152 }

static int oh323_hangup ( struct ast_channel c  )  [static]

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

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

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

Definition at line 859 of file chan_h323.c.

References ast_channel::_state, oh323_pvt::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_free, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::got_progress, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_update_info(), oh323_pvt::rtp, and ast_channel::tech_pvt.

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 304 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(), and f.

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info ( struct ast_channel c  )  [static]

Only channel structure should be locked.

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

00401 {
00402    struct oh323_pvt *pvt = c->tech_pvt;
00403 
00404    if (pvt) {
00405       ast_mutex_lock(&pvt->lock);
00406       __oh323_update_info(c, pvt);
00407       ast_mutex_unlock(&pvt->lock);
00408    }
00409 }

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

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

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

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

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

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

static void prune_peers ( void   )  [static]

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

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

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

Definition at line 1229 of file chan_h323.c.

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

Referenced by find_alias().

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

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

Definition at line 1557 of file chan_h323.c.

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

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

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

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

Definition at line 1443 of file chan_h323.c.

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

Referenced by check_access(), and find_user().

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

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

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

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

Definition at line 265 of file chan_h323.c.

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

static int reload ( void   )  [static]

Definition at line 3119 of file chan_h323.c.

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

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

static int reload_config ( int  is_reload  )  [static]

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

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

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

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

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

static int restart_monitor ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

References cleanup_call_details().

Referenced by load_module().

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

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

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

static int unload_module ( void   )  [static]

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

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

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

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

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

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

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

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


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

Definition at line 3395 of file chan_h323.c.

int acceptAnonymous = 1 [static]

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

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3395 of file chan_h323.c.

struct sockaddr_in bindaddr [static]

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

Referenced by oh323_request().

struct ast_cli_entry cli_h323[] [static]

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

Referenced by load_module(), and unload_module().

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

Definition at line 127 of file chan_h323.c.

unsigned int cos = 0 [static]

Definition at line 143 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 128 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 135 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 136 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 137 of file chan_h323.c.

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

int gkroute = 0 [static]

Definition at line 138 of file chan_h323.c.

Referenced by reload_config(), and setup_incoming_call().

struct ast_jb_conf global_jbconf [static]

Definition at line 123 of file chan_h323.c.

call_options_t global_options [static]

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

Referenced by do_monitor(), and h323_reload().

int h323_reloading = 0 [static]

Definition at line 221 of file chan_h323.c.

Referenced by do_monitor(), and h323_reload().

int h323_signalling_port = 1720 [static]

H.323 configuration values

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

struct io_context* io [static]

Definition at line 208 of file chan_h323.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 225 of file chan_h323.c.

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

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

Definition at line 214 of file chan_h323.c.

struct ast_rtp_protocol oh323_rtp [static]

Definition at line 3207 of file chan_h323.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech oh323_tech [static]

Definition at line 244 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 _sip_show_peers(), build_peer(), complete_sip_peer(), complete_sip_registered_peer(), delete_users(), expire_register(), find_peer(), load_module(), prune_peers(), register_verify(), reload_config(), sip_do_reload(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_inuse(), sip_show_objects(), and unload_module().

struct sched_context* sched [static]

Definition at line 207 of file chan_h323.c.

char secret[50] [static]

Definition at line 144 of file chan_h323.c.

Referenced by aji_act_hook(), authenticate_verify(), build_peer(), 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(), and set_config().

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

Variables required by Asterisk

Definition at line 126 of file chan_h323.c.

unsigned int tos = 0 [static]

Definition at line 142 of file chan_h323.c.

Referenced by reload_config().

unsigned int unique = 0 [static]

Definition at line 145 of file chan_h323.c.

Referenced by oh323_request().

int userbyalias = 1 [static]

Definition at line 140 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(), complete_sip_user(), delete_users(), find_user(), load_module(), reload_config(), sip_show_inuse(), sip_show_objects(), sip_show_users(), and unload_module().


Generated on Thu Jul 9 13:40:58 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7