Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:04 2007

Asterisk developer's documentation :: Codename Pineapple


chan_h323.c File Reference


Detailed Description

This file is part of the chan_h323 driver for Asterisk.

Author:
Jeremy McNamara
See also

Definition in file chan_h323.c.

#include "asterisk.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 <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "h323/chan_h323.h"

Include dependency graph for chan_h323.c:

Go to the source code of this file.

Data Structures

struct  ast_alias_list
struct  ast_peer_list
 The peer list: Peers and Friends. More...
struct  ast_user_list
 The user list: Users and friends. More...
struct  oh323_pvt
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)
static int __oh323_rtp_create (struct oh323_pvt *pvt)
static void __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt)
static int answer_call (unsigned call_reference, const char *token)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"The NuFone Network's OpenH323 Channel Driver",.load=load_module,.unload=unload_module,.reload=reload,)
 AST_MUTEX_DEFINE_STATIC (h323_reload_lock)
 AST_MUTEX_DEFINE_STATIC (caplock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 AST_MUTEX_DEFINE_STATIC (iflock)
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 (char *name, struct ast_variable *v, struct ast_variable *alt, int realtime)
static void chan_ringing (unsigned call_reference, const char *token)
static void cleanup_call_details (call_details_t *cd)
static void cleanup_connection (unsigned call_reference, const char *call_token)
static void connection_made (unsigned call_reference, const char *token)
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)
static struct oh323_alias * find_alias (const char *source_aliases, int realtime)
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_debug (int fd, int argc, char *argv[])
static int h323_do_reload (void)
static int h323_do_trace (int fd, int argc, char *argv[])
static int h323_ep_hangup (int fd, int argc, char *argv[])
static int h323_gk_cycle (int fd, int argc, char *argv[])
static int h323_no_debug (int fd, int argc, char *argv[])
static int h323_no_trace (int fd, int argc, char *argv[])
static int h323_reload (int fd, int argc, char *argv[])
static int h323_tokens_show (int fd, int argc, char *argv[])
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)
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)
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)
static int oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
static int oh323_simulate_dtmf_end (void *data)
static void oh323_update_info (struct ast_channel *c)
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)
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)
 Start the channel monitor thread.
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)
static int setup_outgoing_call (call_details_t *cd)
static void setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
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 int acceptAnonymous = 1
static struct ast_alias_list aliasl
static struct sockaddr_in bindaddr
static struct ast_cli_entry cli_h323 []
static struct ast_cli_entry cli_h323_debug_deprecated
static struct ast_cli_entry cli_h323_gk_cycle_deprecated
static struct ast_cli_entry cli_h323_hangup_deprecated
static struct ast_cli_entry cli_h323_no_debug_deprecated
static struct ast_cli_entry cli_h323_no_trace_deprecated
static struct ast_cli_entry cli_h323_reload
static struct ast_cli_entry cli_h323_reload_deprecated
static struct ast_cli_entry cli_h323_show_tokens_deprecated
static struct ast_cli_entry cli_h323_trace_deprecated
static const char config [] = "h323.conf"
static char debug_usage []
static char default_context [AST_MAX_CONTEXT] = "default"
static struct ast_jb_conf default_jbconf
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 char h323_reload_usage []
static int h323_reloading = 0
static int h323_signalling_port = 1720
int h323debug
oh323_pvtiflist
static struct io_contextio
static pthread_t monitor_thread = AST_PTHREADT_NULL
static char no_debug_usage []
static char no_trace_usage []
static struct ast_rtp_protocol oh323_rtp
static const 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 ast_peer_list peerl
static struct sched_contextsched
static char secret [50]
static char show_cycle_usage []
static char show_hangup_usage []
static char show_tokens_usage []
static const char tdesc [] = "The NuFone Network's Open H.323 Channel Driver"
static int tos = 0
static char trace_usage []
static unsigned int unique = 0
static int userbyalias = 1
static struct ast_user_list userl


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

Referenced by reload_config().


Function Documentation

static void __oh323_destroy struct oh323_pvt pvt  )  [static]
 

Definition at line 451 of file chan_h323.c.

References ast_channel_lock, ast_channel_unlock, ast_dsp_free(), ast_log(), ast_mutex_destroy(), ast_mutex_unlock(), ast_rtp_destroy(), ast_sched_del(), oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, free, iflist, oh323_pvt::lock, LOG_DEBUG, LOG_WARNING, oh323_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, sched, ast_channel::tech_pvt, and oh323_pvt::vad.

Referenced by do_monitor(), and oh323_destroy().

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

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

Definition at line 1006 of file chan_h323.c.

References accountcode, oh323_pvt::accountcode, ast_channel::amaflags, oh323_pvt::amaflags, ast_best_codec(), ast_channel_alloc(), ast_codec_choose(), 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, ast_callerid::cid_name, cid_name, ast_callerid::cid_num, cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, oh323_pvt::context, ast_channel::context, DSP_FEATURE_DTMF_DETECT, oh323_pvt::exten, ast_channel::exten, ast_channel::fds, fmt, 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, strdup, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by answer_call(), and oh323_request().

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

static int __oh323_rtp_create struct oh323_pvt pvt  )  [static]
 

Definition at line 958 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, 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_settos(), oh323_pvt::dtmf_pt, ast_channel::fds, global_jbconf, io, oh323_pvt::lock, LOG_DEBUG, 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 external_rtp_create(), and setup_rtp_connection().

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

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

Definition at line 339 of file chan_h323.c.

References ast_channel::_softhangup, 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, ast_channel::fds, ast_frame::frametype, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DEBUG, LOG_DTMF, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, sched, ast_frame::subclass, oh323_pvt::update_rtp_info, and ast_channel::writeformat.

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

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

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

References __oh323_new(), AST_CAUSE_UNALLOCATED, 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_DEBUG, LOG_ERROR, and LOG_NOTICE.

Referenced by load_module().

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

AST_MODULE_INFO ASTERISK_GPL_KEY  ,
AST_MODFLAG_DEFAULT  ,
"The NuFone Network's OpenH323 Channel Driver"  ,
load = load_module,
unload = unload_module,
reload = reload
 

AST_MUTEX_DEFINE_STATIC h323_reload_lock   ) 
 

AST_MUTEX_DEFINE_STATIC caplock   ) 
 

AST_MUTEX_DEFINE_STATIC monlock   ) 
 

AST_MUTEX_DEFINE_STATIC iflock   ) 
 

Protect the interface list (oh323_pvt)

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

Definition at line 1199 of file chan_h323.c.

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

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

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

Definition at line 1484 of file chan_h323.c.

References ast_append_ha(), ast_get_ip(), ast_log(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNREF, calloc, 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 set_config().

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

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

Definition at line 1366 of file chan_h323.c.

References ast_append_ha(), ast_cdr_amaflags2int(), ast_get_ip(), ast_log(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNREF, calloc, 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 realtime_user(), reload_config(), and set_config().

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

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

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

Referenced by load_module().

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

static void cleanup_call_details call_details_t *  cd  )  [static]
 

Definition at line 415 of file chan_h323.c.

References free.

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

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

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

Call-back function to cleanup communication Returns nothing,

Definition at line 2340 of file chan_h323.c.

References ast_channel::_softhangup, oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, 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, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.

Referenced by load_module().

02341 {
02342    struct oh323_pvt *pvt;
02343 
02344    if (h323debug)
02345       ast_log(LOG_DEBUG, "Cleaning connection to %s\n", call_token);
02346 
02347    while (1) {
02348       pvt = find_call_locked(call_reference, call_token);
02349       if (!pvt) {
02350          if (h323debug)
02351             ast_log(LOG_DEBUG, "No connection for %s\n", call_token);
02352          return;
02353       }
02354       if (!pvt->owner || !ast_channel_trylock(pvt->owner))
02355          break;
02356 #if 1
02357 #ifdef DEBUG_THREADS
02358       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s, locked at %ld/%d by %s (%s:%d)\n", call_token, pvt->owner->lock.thread[0], pvt->owner->lock.reentrancy, pvt->owner->lock.func[0], pvt->owner->lock.file[0], pvt->owner->lock.lineno[0]);
02359 #else
02360       ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
02361 #endif
02362 #endif
02363       ast_mutex_unlock(&pvt->lock);
02364       usleep(1);
02365    }
02366    if (pvt->rtp) {
02367       /* Immediately stop RTP */
02368       ast_rtp_destroy(pvt->rtp);
02369       pvt->rtp = NULL;
02370    }
02371    /* Free dsp used for in-band DTMF detection */
02372    if (pvt->vad) {
02373       ast_dsp_free(pvt->vad);
02374       pvt->vad = NULL;
02375    }
02376    cleanup_call_details(&pvt->cd);
02377    pvt->alreadygone = 1;
02378    /* Send hangup */
02379    if (pvt->owner) {
02380       pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
02381       ast_queue_hangup(pvt->owner);
02382       ast_channel_unlock(pvt->owner);
02383    }
02384    ast_mutex_unlock(&pvt->lock);
02385    if (h323debug)
02386       ast_log(LOG_DEBUG, "Connection to %s cleaned\n", call_token);
02387    return;
02388 }

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

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

Referenced by load_module().

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

static char* convertcap int  cap  )  [static]
 

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

03124 {
03125    switch (cap) {
03126    case AST_FORMAT_G723_1:
03127       return "G.723";
03128    case AST_FORMAT_GSM:
03129       return "GSM";
03130    case AST_FORMAT_ULAW:
03131       return "ULAW";
03132    case AST_FORMAT_ALAW:
03133       return "ALAW";
03134    case AST_FORMAT_G722:
03135       return "G.722";
03136    case AST_FORMAT_ADPCM:
03137       return "G.728";
03138    case AST_FORMAT_G729A:
03139       return "G.729";
03140    case AST_FORMAT_SPEEX:
03141       return "SPEEX";
03142    case AST_FORMAT_ILBC:
03143       return "ILBC";
03144    default:
03145       ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap);
03146       return NULL;
03147    }
03148 }

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

Definition at line 1652 of file chan_h323.c.

References ahp, 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 iax2_call(), iax2_provision(), iax2_request(), oh323_request(), sip_request_call(), and transmit_register().

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

static void delete_aliases void   )  [static]
 

Definition at line 3037 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, and ASTOBJ_UNLOCK.

Referenced by h323_do_reload().

03038 {
03039    int pruned = 0;
03040 
03041    /* Delete all aliases */
03042    ASTOBJ_CONTAINER_WRLOCK(&aliasl);
03043    ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
03044       ASTOBJ_RDLOCK(iterator);
03045       ASTOBJ_MARK(iterator);
03046       ++pruned;
03047       ASTOBJ_UNLOCK(iterator);
03048    } while (0) );
03049    if (pruned) {
03050       ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
03051    }
03052    ASTOBJ_CONTAINER_UNLOCK(&aliasl);
03053 }

static void delete_users void   )  [static]
 

Definition at line 3011 of file chan_h323.c.

References ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and userl.

Referenced by __unload_module(), h323_do_reload(), and reload_config().

03012 {
03013    int pruned = 0;
03014 
03015    /* Delete all users */
03016    ASTOBJ_CONTAINER_WRLOCK(&userl);
03017    ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
03018       ASTOBJ_RDLOCK(iterator);
03019       ASTOBJ_MARK(iterator);
03020       ++pruned;
03021       ASTOBJ_UNLOCK(iterator);
03022    } while (0) );
03023    if (pruned) {
03024       ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
03025    }
03026    ASTOBJ_CONTAINER_UNLOCK(&userl);
03027 
03028    ASTOBJ_CONTAINER_WRLOCK(&peerl);
03029    ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
03030       ASTOBJ_RDLOCK(iterator);
03031       ASTOBJ_MARK(iterator);
03032       ASTOBJ_UNLOCK(iterator);
03033    } while (0) );
03034    ASTOBJ_CONTAINER_UNLOCK(&peerl);
03035 }

static void* do_monitor void *  data  )  [static]
 

Definition at line 2515 of file chan_h323.c.

References __oh323_destroy(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_verbose(), h323_do_reload(), h323_reloading, iflist, oh323_pvt::lock, oh323_pvt::needdestroy, oh323_pvt::next, option_verbose, and VERBOSE_PREFIX_1.

Referenced by restart_monitor().

02516 {
02517    int res;
02518    int reloading;
02519    struct oh323_pvt *oh323 = NULL;
02520 
02521    for(;;) {
02522       /* Check for a reload request */
02523       ast_mutex_lock(&h323_reload_lock);
02524       reloading = h323_reloading;
02525       h323_reloading = 0;
02526       ast_mutex_unlock(&h323_reload_lock);
02527       if (reloading) {
02528          if (option_verbose > 0) {
02529             ast_verbose(VERBOSE_PREFIX_1 "Reloading H.323\n");
02530          }
02531          h323_do_reload();
02532       }
02533       /* Check for interfaces needing to be killed */
02534       if (!ast_mutex_trylock(&iflock)) {
02535 #if 1
02536          do {
02537             for (oh323 = iflist; oh323; oh323 = oh323->next) {
02538                if (!ast_mutex_trylock(&oh323->lock)) {
02539                   if (oh323->needdestroy) {
02540                      __oh323_destroy(oh323);
02541                      break;
02542                   }
02543                   ast_mutex_unlock(&oh323->lock);
02544                }
02545             }
02546          } while (/*oh323*/ 0);
02547 #else
02548 restartsearch:
02549          oh323 = iflist;
02550          while(oh323) {
02551             if (!ast_mutex_trylock(&oh323->lock)) {
02552                if (oh323->needdestroy) {
02553                   __oh323_destroy(oh323);
02554                   goto restartsearch;
02555                }
02556                ast_mutex_unlock(&oh323->lock);
02557                oh323 = oh323->next;
02558             }
02559          }
02560 #endif
02561          ast_mutex_unlock(&iflock);
02562       } else
02563          oh323 = (struct oh323_pvt *)1;   /* Force fast loop */
02564       pthread_testcancel();
02565       /* Wait for sched or io */
02566       res = ast_sched_wait(sched);
02567       if ((res < 0) || (res > 1000)) {
02568          res = 1000;
02569       }
02570       /* Do not wait if some channel(s) is destroyed, probably, more available too */
02571       if (oh323)
02572          res = 1;
02573       res = ast_io_wait(io, res);
02574       pthread_testcancel();
02575       ast_mutex_lock(&monlock);
02576       if (res >= 0) {
02577          ast_sched_runq(sched);
02578       }
02579       ast_mutex_unlock(&monlock);
02580    }
02581    /* Never reached */
02582    return NULL;
02583 }

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 the local RTP information

Definition at line 1890 of file chan_h323.c.

References __oh323_rtp_create(), ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_rtp_get_us(), find_call_locked(), free, h323debug, oh323_pvt::lock, LOG_DEBUG, LOG_ERROR, malloc, and oh323_pvt::rtp.

Referenced by load_module().

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

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

Find a call by alias

Definition at line 1813 of file chan_h323.c.

References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().

Referenced by add_header(), and setup_incoming_call().

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

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

Definition at line 1152 of file chan_h323.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::cd, iflist, 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().

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

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

Definition at line 1634 of file chan_h323.c.

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

Referenced by _sip_show_peer(), check_peer_ok(), create_addr(), dundi_encrypt(), function_iaxpeer(), function_sippeer(), handle_command_response(), iax2_devicestate(), iax2_prune_realtime(), iax2_show_peer(), register_verify(), registry_authrequest(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), update_call_counter(), and update_registry().

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

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

Definition at line 1604 of file chan_h323.c.

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

Referenced by check_user_ok(), setup_incoming_call(), sip_show_user(), and update_call_counter().

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

static int h323_do_debug int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 2640 of file chan_h323.c.

References ast_cli(), h323debug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02641 {
02642    if (argc < 2 || argc > 3) {
02643       return RESULT_SHOWUSAGE;
02644    }
02645    h323debug = 1;
02646    ast_cli(fd, "H.323 debug enabled\n");
02647    return RESULT_SUCCESS;
02648 }

static int h323_do_reload void   )  [static]
 

Definition at line 3074 of file chan_h323.c.

References delete_aliases(), delete_users(), prune_peers(), and reload_config().

Referenced by do_monitor().

03075 {
03076    delete_users();
03077    delete_aliases();
03078    prune_peers();
03079    reload_config(1);
03080    return 0;
03081 }

static int h323_do_trace int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 2620 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02621 {
02622    if (argc != 4) {
02623       return RESULT_SHOWUSAGE;
02624    }
02625    h323_debug(1, atoi(argv[3]));
02626    ast_cli(fd, "H.323 trace set to level %s\n", argv[2]);
02627    return RESULT_SUCCESS;
02628 }

static int h323_ep_hangup int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 2676 of file chan_h323.c.

References ast_verbose(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and VERBOSE_PREFIX_3.

02677 {
02678    if (argc != 3) {
02679       return RESULT_SHOWUSAGE;
02680    }
02681    if (h323_soft_hangup(argv[2])) {
02682       ast_verbose(VERBOSE_PREFIX_3 "Hangup succeeded on %s\n", argv[2]);
02683    } else {
02684       ast_verbose(VERBOSE_PREFIX_3 "Hangup failed for %s\n", argv[2]);
02685    }
02686    return RESULT_SUCCESS;
02687 }

static int h323_gk_cycle int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 2660 of file chan_h323.c.

References ast_log(), gatekeeper, gatekeeper_disable, gatekeeper_discover, LOG_ERROR, RESULT_SHOWUSAGE, RESULT_SUCCESS, and secret.

02661 {
02662    if (argc != 3) {
02663       return RESULT_SHOWUSAGE;
02664    }
02665    h323_gk_urq();
02666 
02667    /* Possibly register with a GK */
02668    if (!gatekeeper_disable) {
02669       if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
02670          ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
02671       }
02672    }
02673    return RESULT_SUCCESS;
02674 }

static int h323_no_debug int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 2650 of file chan_h323.c.

References ast_cli(), h323debug, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02651 {
02652    if (argc < 3 || argc > 4) {
02653       return RESULT_SHOWUSAGE;
02654    }
02655    h323debug = 0;
02656    ast_cli(fd, "H.323 debug disabled\n");
02657    return RESULT_SUCCESS;
02658 }

static int h323_no_trace int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 2630 of file chan_h323.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02631 {
02632    if (argc < 3 || argc > 4) {
02633       return RESULT_SHOWUSAGE;
02634    }
02635    h323_debug(0,0);
02636    ast_cli(fd, "H.323 trace disabled\n");
02637    return RESULT_SUCCESS;
02638 }

static int h323_reload int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 3061 of file chan_h323.c.

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

Referenced by reload().

03062 {
03063    ast_mutex_lock(&h323_reload_lock);
03064    if (h323_reloading) {
03065       ast_verbose("Previous H.323 reload not yet done\n");
03066    } else {
03067       h323_reloading = 1;
03068    }
03069    ast_mutex_unlock(&h323_reload_lock);
03070    restart_monitor();
03071    return 0;
03072 }

static int h323_tokens_show int  fd,
int  argc,
char *  argv[]
[static]
 

Definition at line 2689 of file chan_h323.c.

References RESULT_SHOWUSAGE, and RESULT_SUCCESS.

02690 {
02691    if (argc != 3) {
02692       return RESULT_SHOWUSAGE;
02693    }
02694    h323_show_tokens();
02695    return RESULT_SUCCESS;
02696 }

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

Definition at line 2390 of file chan_h323.c.

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

Referenced by load_module().

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

static enum ast_module_load_result load_module void   )  [static]
 

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

03184 {
03185    int res;
03186 
03187    h323debug = 0;
03188    sched = sched_context_create();
03189    if (!sched) {
03190       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03191       return AST_MODULE_LOAD_FAILURE;
03192    }
03193    io = io_context_create();
03194    if (!io) {
03195       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03196       return AST_MODULE_LOAD_FAILURE;
03197    }
03198    ast_cli_register(&cli_h323_reload);
03199    ASTOBJ_CONTAINER_INIT(&userl);
03200    ASTOBJ_CONTAINER_INIT(&peerl);
03201    ASTOBJ_CONTAINER_INIT(&aliasl);
03202    res = reload_config(0);
03203    if (res) {
03204       /* No config entry */
03205       ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
03206       ast_cli_unregister(&cli_h323_reload);
03207       io_context_destroy(io);
03208       io = NULL;
03209       sched_context_destroy(sched);
03210       sched = NULL;
03211       ASTOBJ_CONTAINER_DESTROY(&userl);
03212       ASTOBJ_CONTAINER_DESTROY(&peerl);
03213       ASTOBJ_CONTAINER_DESTROY(&aliasl);
03214       return AST_MODULE_LOAD_DECLINE;
03215    } else {
03216       /* Make sure we can register our channel type */
03217       if (ast_channel_register(&oh323_tech)) {
03218          ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
03219          ast_cli_unregister(&cli_h323_reload);
03220          h323_end_process();
03221          io_context_destroy(io);
03222          sched_context_destroy(sched);
03223 
03224          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03225          ASTOBJ_CONTAINER_DESTROY(&userl);
03226          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03227          ASTOBJ_CONTAINER_DESTROY(&peerl);
03228          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03229          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03230 
03231          return AST_MODULE_LOAD_FAILURE;
03232       }
03233       ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03234 
03235       ast_rtp_proto_register(&oh323_rtp);
03236 
03237       /* Register our callback functions */
03238       h323_callback_register(setup_incoming_call,
03239                   setup_outgoing_call,
03240                   external_rtp_create,
03241                   setup_rtp_connection,
03242                   cleanup_connection,
03243                   chan_ringing,
03244                   connection_made,
03245                   receive_digit,
03246                   answer_call,
03247                   progress,
03248                   set_dtmf_payload,
03249                   hangup_connection,
03250                   set_local_capabilities,
03251                   set_peer_capabilities,
03252                   remote_hold);
03253       /* start the h.323 listener */
03254       if (h323_start_listener(h323_signalling_port, bindaddr)) {
03255          ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
03256          ast_rtp_proto_unregister(&oh323_rtp);
03257          ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
03258          ast_cli_unregister(&cli_h323_reload);
03259          h323_end_process();
03260          io_context_destroy(io);
03261          sched_context_destroy(sched);
03262 
03263          ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
03264          ASTOBJ_CONTAINER_DESTROY(&userl);
03265          ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
03266          ASTOBJ_CONTAINER_DESTROY(&peerl);
03267          ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
03268          ASTOBJ_CONTAINER_DESTROY(&aliasl);
03269 
03270          return AST_MODULE_LOAD_FAILURE;
03271       }
03272       /* Possibly register with a GK */
03273       if (!gatekeeper_disable) {
03274          if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
03275             ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
03276             gatekeeper_disable = 1;
03277             res = AST_MODULE_LOAD_SUCCESS;
03278          }
03279       }
03280       /* And start the monitor for the first time */
03281       restart_monitor();
03282    }
03283    return res;
03284 }

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

Definition at line 1622 of file chan_h323.c.

References inaddrcmp().

Referenced by find_peer().

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

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

Definition at line 1599 of file chan_h323.c.

References ast_inet_ntoa().

Referenced by find_user().

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

static struct oh323_pvt* oh323_alloc int  callid  )  [static]
 

Definition at line 1108 of file chan_h323.c.

References ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), AST_RTP_DTMF, oh323_pvt::cd, oh323_pvt::context, oh323_pvt::DTMFsched, free, iflist, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, malloc, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newstate, oh323_pvt::next, oh323_pvt::nonCodecCapability, oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::update_rtp_info.

Referenced by oh323_request(), and setup_incoming_call().

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

static int oh323_answer struct ast_channel c  )  [static]
 

Definition at line 669 of file chan_h323.c.

References ast_channel::_state, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, oh323_pvt::cd, free, oh323_pvt::lock, LOG_DEBUG, oh323_update_info(), strdup, and ast_channel::tech_pvt.

00670 {
00671    int res;
00672    struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
00673    char *token;
00674 
00675    if (h323debug)
00676       ast_log(LOG_DEBUG, "Answering on %s\n", c->name);
00677 
00678    ast_mutex_lock(&pvt->lock);
00679    token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;
00680    ast_mutex_unlock(&pvt->lock);
00681    res = h323_answering_call(token, 0);
00682    if (token)
00683       free(token);
00684 
00685    oh323_update_info(c);
00686    if (c->_state != AST_STATE_UP) {
00687       ast_setstate(c, AST_STATE_UP);
00688    }
00689    return res;
00690 }

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

References ast_channel::_state, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), 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_DEBUG, LOG_NOTICE, LOG_WARNING, oh323_update_info(), option_verbose, oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), oh323_pvt::sa, ast_channel::tech_pvt, ast_channel::transfercapability, and VERBOSE_PREFIX_3.

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

static void oh323_destroy struct oh323_pvt pvt  )  [static]
 

Definition at line 499 of file chan_h323.c.

References __oh323_destroy(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::lock, LOG_DEBUG, and oh323_pvt::owner.

Referenced by oh323_request(), and setup_incoming_call().

00500 {
00501    if (h323debug) {
00502       ast_log(LOG_DEBUG, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));
00503    }
00504    ast_mutex_lock(&iflock);
00505    ast_mutex_lock(&pvt->lock);
00506    __oh323_destroy(pvt);
00507    ast_mutex_unlock(&iflock);
00508 }

static void oh323_destroy_alias struct oh323_alias *  alias  )  [static]
 

Definition at line 284 of file chan_h323.c.

References ast_log(), free, and LOG_DEBUG.

Referenced by load_module(), and unload_module().

00285 {
00286    if (h323debug)
00287       ast_log(LOG_DEBUG, "Destroying alias '%s'\n", alias->name);
00288    free(alias);
00289 }

static void oh323_destroy_peer struct oh323_peer *  peer  )  [static]
 

Definition at line 299 of file chan_h323.c.

References ast_free_ha(), ast_log(), free, and LOG_DEBUG.

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

00300 {
00301    if (h323debug)
00302       ast_log(LOG_DEBUG, "Destroying peer '%s'\n", peer->name);
00303    ast_free_ha(peer->ha);
00304    free(peer);
00305 }

static void oh323_destroy_user struct oh323_user *  user  )  [static]
 

Definition at line 291 of file chan_h323.c.

References ast_free_ha(), ast_log(), free, and LOG_DEBUG.

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

00292 {
00293    if (h323debug)
00294       ast_log(LOG_DEBUG, "Destroying user '%s'\n", user->name);
00295    ast_free_ha(user->ha);
00296    free(user);
00297 }

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

Definition at line 510 of file chan_h323.c.

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

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

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

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

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

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

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

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

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

Definition at line 3100 of file chan_h323.c.

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

03101 {
03102    struct oh323_pvt *pvt;
03103    enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
03104 
03105    if (!(pvt = (struct oh323_pvt *)chan->tech_pvt))
03106       return res;
03107 
03108    ast_mutex_lock(&pvt->lock);
03109    if (pvt->rtp && pvt->options.bridge) {
03110       *rtp = pvt->rtp;
03111       res = AST_RTP_TRY_NATIVE;
03112    }
03113    ast_mutex_unlock(&pvt->lock);
03114 
03115    return res;
03116 }

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

Definition at line 3118 of file chan_h323.c.

References AST_RTP_GET_FAILED.

03119 {
03120    return AST_RTP_GET_FAILED;
03121 }

static int oh323_hangup struct ast_channel c  )  [static]
 

Definition at line 692 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_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::cd, free, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_DEBUG, LOG_WARNING, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), strdup, and ast_channel::tech_pvt.

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

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

Definition at line 867 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_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, oh323_pvt::cd, free, oh323_pvt::got_progress, oh323_pvt::lock, LOG_DEBUG, LOG_WARNING, oh323_update_info(), strdup, and ast_channel::tech_pvt.

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

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

Definition at line 814 of file chan_h323.c.

References __oh323_update_info(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_rtcp_read(), ast_channel::fdno, oh323_pvt::lock, LOG_ERROR, oh323_rtp_read(), oh323_pvt::rtp, and ast_channel::tech_pvt.

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

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

Definition at line 1724 of file chan_h323.c.

References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, AST_FORMAT_MAX_AUDIO, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_DTMF, AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), create_addr(), ext, oh323_pvt::exten, gatekeeper_disable, global_options, h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, restart_monitor(), and unique.

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

static struct ast_frame* oh323_rtp_read struct oh323_pvt pvt  )  [static]
 

Definition at line 758 of file chan_h323.c.

References ast_channel_trylock, ast_channel_unlock, 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(), ast_frame::frametype, LOG_DEBUG, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, ast_frame::subclass, oh323_pvt::vad, and ast_channel::writeformat.

Referenced by oh323_read().

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

static int oh323_set_rtp_peer struct ast_channel chan,
struct ast_rtp rtp,
struct ast_rtp vrtp,
int  codecs,
int  nat_active
[static]
 

Definition at line 3150 of file chan_h323.c.

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

03151 {
03152    /* XXX Deal with Video */
03153    struct oh323_pvt *pvt;
03154    struct sockaddr_in them;
03155    struct sockaddr_in us;
03156    char *mode;
03157 
03158    if (!rtp) {
03159       return 0;
03160    }
03161 
03162    mode = convertcap(chan->writeformat);
03163    pvt = (struct oh323_pvt *) chan->tech_pvt;
03164    if (!pvt) {
03165       ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
03166       return -1;
03167    }
03168    ast_rtp_get_peer(rtp, &them);
03169    ast_rtp_get_us(rtp, &us);
03170 #if 0 /* Native bridge still isn't ready */
03171    h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
03172 #endif
03173    return 0;
03174 }

static int oh323_simulate_dtmf_end void *  data  )  [static]
 

Definition at line 307 of file chan_h323.c.

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

Referenced by __oh323_update_info(), and receive_digit().

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

static void oh323_update_info struct ast_channel c  )  [static]
 

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

00405 {
00406    struct oh323_pvt *pvt = c->tech_pvt;
00407 
00408    if (pvt) {
00409       ast_mutex_lock(&pvt->lock);
00410       __oh323_update_info(c, pvt);
00411       ast_mutex_unlock(&pvt->lock);
00412    }
00413 }

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

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

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

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

Definition at line 2075 of file chan_h323.c.

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

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

static void prune_peers void   )  [static]
 

Definition at line 3055 of file chan_h323.c.

References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.

Referenced by __expire_registry(), h323_do_reload(), reload_config(), and set_config().

03056 {
03057    /* Prune peers who still are supposed to be deleted */
03058    ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
03059 }

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

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

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

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

Definition at line 1556 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_device(), find_peer(), and iax2_getpeername().

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

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

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

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

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

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

Referenced by load_module().

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

static const char* redirectingreason2str int  redirectingreason  )  [static]
 

Definition at line 268 of file chan_h323.c.

Referenced by __oh323_new().

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

static int reload void   )  [static]
 

Definition at line 3083 of file chan_h323.c.

References h323_reload().

03084 {
03085    return h323_reload(0, 0, NULL);
03086 }

static int reload_config int  is_reload  )  [static]
 

Definition at line 2795 of file chan_h323.c.

References acceptAnonymous, ahp, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTOBJ_CONTAINER_LINK, ASTOBJ_UNREF, bindaddr, build_user(), config, default_context, default_jbconf, format, gatekeeper, gatekeeper_disable, gatekeeper_discover, gkroute, GLOBAL_CAPABILITY, global_jbconf, global_options, h323_signalling_port, hp, LOG_NOTICE, oh323_destroy_user(), tos, userbyalias, and userl.

Referenced by h323_do_reload(), iax2_prune_realtime(), iax2_reload(), load_module(), mgcp_do_reload(), misdn_reload(), and reload().

02796 {
02797    int format;
02798    struct ast_config *cfg, *ucfg;
02799    struct ast_variable *v;
02800    struct oh323_peer *peer = NULL;
02801    struct oh323_user *user = NULL;
02802    struct oh323_alias *alias = NULL;
02803    struct ast_hostent ahp; struct hostent *hp;
02804    char *cat;
02805    const char *utype;
02806    int is_user, is_peer, is_alias;
02807    char _gatekeeper[100];
02808    int gk_discover, gk_disable, gk_changed;
02809 
02810    cfg = ast_config_load(config);
02811 
02812    /* We *must* have a config file otherwise stop immediately */
02813    if (!cfg) {
02814       ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
02815       return 1;
02816    }
02817 
02818    /* fire up the H.323 Endpoint */
02819    if (!h323_end_point_exist()) {
02820       h323_end_point_create();
02821    }
02822    ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
02823    gk_discover = gatekeeper_discover;
02824    gk_disable = gatekeeper_disable;
02825    memset(&bindaddr, 0, sizeof(bindaddr));
02826    memset(&global_options, 0, sizeof(global_options));
02827    global_options.fastStart = 1;
02828    global_options.h245Tunneling = 1;
02829    global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
02830    global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
02831    global_options.dtmfmode = 0;
02832    global_options.holdHandling = 0;
02833    global_options.capability = GLOBAL_CAPABILITY;
02834    global_options.bridge = 1;    /* Do native bridging by default */
02835    strcpy(default_context, "default");
02836    h323_signalling_port = 1720;
02837    gatekeeper_disable = 1;
02838    gatekeeper_discover = 0;
02839    gkroute = 0;
02840    userbyalias = 1;
02841    acceptAnonymous = 1;
02842    tos = 0;
02843 
02844    /* Copy the default jb config over global_jbconf */
02845    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
02846 
02847    /* Load configuration from users.conf */
02848    ucfg = ast_config_load("users.conf");
02849    if (ucfg) {
02850       struct ast_variable *gen;
02851       int genhas_h323;
02852       const char *has_h323;
02853 
02854       genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
02855       gen = ast_variable_browse(ucfg, "general");
02856       for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
02857          if (strcasecmp(cat, "general")) {
02858             has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
02859             if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
02860                user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
02861                if (user) {
02862                   ASTOBJ_CONTAINER_LINK(&userl, user);
02863                   ASTOBJ_UNREF(user, oh323_destroy_user);
02864                }
02865             }
02866          }
02867       }
02868       ast_config_destroy(ucfg);
02869    }
02870 
02871    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
02872       /* handle jb conf */
02873       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
02874          continue;
02875       /* Create the interface list */
02876       if (!strcasecmp(v->name, "port")) {
02877          h323_signalling_port = (int)strtol(v->value, NULL, 10);
02878       } else if (!strcasecmp(v->name, "bindaddr")) {
02879          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
02880             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
02881          } else {
02882             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
02883          }
02884       } else if (!strcasecmp(v->name, "tos")) {
02885          if (sscanf(v->value, "%d", &format)) {
02886             tos = format & 0xff;
02887          } else if (!strcasecmp(v->value, "lowdelay")) {
02888             tos = IPTOS_LOWDELAY;
02889          } else if (!strcasecmp(v->value, "throughput")) {
02890             tos = IPTOS_THROUGHPUT;
02891          } else if (!strcasecmp(v->value, "reliability")) {
02892             tos = IPTOS_RELIABILITY;
02893          } else if (!strcasecmp(v->value, "mincost")) {
02894             tos = IPTOS_MINCOST;
02895          } else if (!strcasecmp(v->value, "none")) {
02896             tos = 0;
02897          } else {
02898             ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
02899          }
02900       } else if (!strcasecmp(v->name, "gatekeeper")) {
02901          if (!strcasecmp(v->value, "DISABLE")) {
02902