This file is part of the chan_h323 driver for Asterisk. More...
#include "asterisk.h"#include <sys/types.h>#include <sys/socket.h>#include <sys/signal.h>#include <sys/param.h>#include <arpa/inet.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netdb.h>#include <fcntl.h>#include "asterisk/lock.h"#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/module.h"#include "asterisk/musiconhold.h"#include "asterisk/pbx.h"#include "asterisk/utils.h"#include "asterisk/sched.h"#include "asterisk/io.h"#include "asterisk/rtp_engine.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 "asterisk/format.h"#include "asterisk/format_cap.h"#include "h323/chan_h323.h"
Go to the source code of this file.
Data Structures | |
| struct | h323_alias_list |
| H323 alias list. More... | |
| struct | h323_peer_list |
| H323 peer list. More... | |
| struct | h323_user_list |
| H323 User list. More... | |
| struct | oh323_pvt |
| Private structure of a OpenH323 channel. More... | |
Defines | |
| #define | GLOBAL_CAPABILITY |
Functions | |
| static void | __oh323_destroy (struct oh323_pvt *pvt) |
| static struct ast_channel * | __oh323_new (struct oh323_pvt *pvt, int state, const char *host, const char *linkedid) |
| Private structure should be locked on a call. | |
| static int | __oh323_rtp_create (struct oh323_pvt *pvt) |
| static void | __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt) |
| Channel and private structures should be already locked. | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| static int | answer_call (unsigned call_reference, const char *token) |
| Call-back function to start PBX when OpenH323 ready to serve incoming call. | |
| static struct oh323_alias * | build_alias (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
| static struct oh323_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
| static struct oh323_user * | build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
| static void | chan_ringing (unsigned call_reference, const char *token) |
| Call-back function to signal asterisk that the channel is ringing Returns nothing. | |
| static void | cleanup_call_details (call_details_t *cd) |
| static void | cleanup_connection (unsigned call_reference, const char *call_token) |
| Call-back function to cleanup communication Returns nothing,. | |
| static void | connection_made (unsigned call_reference, const char *token) |
| Call-back function to signal asterisk that the channel has been answered Returns nothing. | |
| static int | create_addr (struct oh323_pvt *pvt, char *opeer) |
| static void | delete_aliases (void) |
| static void | delete_users (void) |
| static void * | do_monitor (void *data) |
| static struct rtp_info * | external_rtp_create (unsigned call_reference, const char *token) |
| Callback function used to inform the H.323 stack of the local rtp ip/port details. | |
| static struct oh323_alias * | find_alias (const char *source_aliases, int realtime) |
| Find a call by alias. | |
| static struct oh323_pvt * | find_call_locked (int call_reference, const char *token) |
| static struct oh323_peer * | find_peer (const char *peer, struct sockaddr_in *sin, int realtime) |
| static struct oh323_user * | find_user (const call_details_t *cd, int realtime) |
| static int | h323_do_reload (void) |
| static int | h323_parse_allow_disallow (struct ast_codec_pref *pref, h323_format *formats, const char *list, int allowing) |
| static int | h323_reload (void) |
| static char * | handle_cli_h323_cycle_gk (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_h323_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_h323_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_h323_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_h323_set_trace (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_h323_show_tokens (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static char * | handle_cli_h323_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| static void | hangup_connection (unsigned int call_reference, const char *token, int cause) |
| static enum ast_module_load_result | load_module (void) |
| static int | oh323_addrcmp (struct sockaddr_in addr, struct sockaddr_in *sin) |
| static int | oh323_addrcmp_str (struct in_addr inaddr, char *addr) |
| static struct oh323_pvt * | oh323_alloc (int callid) |
| static int | oh323_answer (struct ast_channel *c) |
| static int | oh323_call (struct ast_channel *c, const char *dest, int timeout) |
| Make a call over the specified channel to the specified destination. Returns -1 on error, 0 on success. | |
| static void | oh323_destroy (struct oh323_pvt *pvt) |
| static void | oh323_destroy_alias (struct oh323_alias *alias) |
| static void | oh323_destroy_peer (struct oh323_peer *peer) |
| static void | oh323_destroy_user (struct oh323_user *user) |
| static int | oh323_digit_begin (struct ast_channel *c, char digit) |
| static int | oh323_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
| Send (play) the specified digit to the channel. | |
| static int | oh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static enum ast_rtp_glue_result | oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
| 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_frame * | oh323_read (struct ast_channel *c) |
| static struct ast_channel * | oh323_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest, int *cause) |
| static struct ast_frame * | oh323_rtp_read (struct oh323_pvt *pvt) |
| Retrieve audio/etc from channel. Assumes pvt->lock is already held. | |
| static int | oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active) |
| static int | oh323_simulate_dtmf_end (const void *data) |
| static void | oh323_update_info (struct ast_channel *c) |
| Only channel structure should be locked. | |
| static int | oh323_write (struct ast_channel *c, struct ast_frame *frame) |
| static int | progress (unsigned call_reference, const char *token, int inband) |
| static void | prune_peers (void) |
| static struct oh323_alias * | realtime_alias (const char *alias) |
| static struct oh323_peer * | realtime_peer (const char *peername, struct sockaddr_in *sin) |
| static struct oh323_user * | realtime_user (const call_details_t *cd) |
| static int | receive_digit (unsigned call_reference, char digit, const char *token, int duration) |
| Callback for sending digits from H.323 up to asterisk. | |
| static const char * | redirectingreason2str (int redirectingreason) |
| static int | reload (void) |
| static int | reload_config (int is_reload) |
| static void | remote_hold (unsigned call_reference, const char *token, int is_hold) |
| static int | restart_monitor (void) |
| static void | set_dtmf_payload (unsigned call_reference, const char *token, int payload, int is_cisco) |
| static void | set_local_capabilities (unsigned call_reference, const char *token) |
| static void | set_peer_capabilities (unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs) |
| static call_options_t * | setup_incoming_call (call_details_t *cd) |
| Call-back function for incoming calls. | |
| static int | setup_outgoing_call (call_details_t *cd) |
| Call-back function to establish an outgoing H.323 call. | |
| static void | setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt) |
| Call-back function passing remote ip/port information from H.323 to asterisk. | |
| static int | unload_module (void) |
| static int | update_common_options (struct ast_variable *v, struct call_options *options) |
| static int | update_state (struct oh323_pvt *pvt, int state, int signal) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } |
| static int | acceptAnonymous = 1 |
| static struct h323_alias_list | aliasl |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sockaddr_in | bindaddr |
| static ast_mutex_t | caplock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. | |
| static struct ast_cli_entry | cli_h323 [] |
| static struct ast_cli_entry | cli_h323_reload |
| static const char | config [] = "h323.conf" |
| static unsigned int | cos = 0 |
| static char | default_context [AST_MAX_CONTEXT] = "default" |
| static struct ast_jb_conf | default_jbconf |
| Global jitterbuffer configuration - by default, jb is disabled. | |
| static char | gatekeeper [100] |
| static int | gatekeeper_disable = 1 |
| static int | gatekeeper_discover = 0 |
| static int | gkroute = 0 |
| static struct ast_jb_conf | global_jbconf |
| static call_options_t | global_options |
| static ast_mutex_t | h323_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| Protect the reload process. | |
| static int | h323_reloading = 0 |
| static int | h323_signalling_port = 1720 |
| int | h323debug |
| static struct oh323_pvt * | iflist |
| static ast_mutex_t | iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| static struct io_context * | io |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
| static ast_mutex_t | monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| static struct ast_rtp_glue | oh323_rtp_glue |
| static struct ast_channel_tech | oh323_tech |
| answer_call_cb | on_answer_call |
| chan_ringing_cb | on_chan_ringing |
| clear_con_cb | on_connection_cleared |
| con_established_cb | on_connection_established |
| on_rtp_cb | on_external_rtp_create |
| hangup_cb | on_hangup |
| onhold_cb | on_hold |
| setup_incoming_cb | on_incoming_call |
| setup_outbound_cb | on_outgoing_call |
| progress_cb | on_progress |
| receive_digit_cb | on_receive_digit |
| rfc2833_cb | on_set_rfc2833_payload |
| setcapabilities_cb | on_setcapabilities |
| setpeercapabilities_cb | on_setpeercapabilities |
| start_rtp_cb | on_start_rtp_channel |
| static struct h323_peer_list | peerl |
| static struct ast_sched_context * | sched |
| static char | secret [50] |
| static const char | tdesc [] = "The NuFone Network's Open H.323 Channel Driver" |
| static unsigned int | tos = 0 |
| static unsigned int | unique = 0 |
| static int | userbyalias = 1 |
| static struct h323_user_list | userl |
This file is part of the chan_h323 driver for Asterisk.
Definition in file chan_h323.c.
| #define GLOBAL_CAPABILITY |
Definition at line 137 of file chan_h323.c.
Referenced by reload_config().
| static void __oh323_destroy | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 454 of file chan_h323.c.
References ast_channel_lock, ast_channel_name(), ast_channel_tech_pvt_set(), ast_channel_unlock, ast_debug, ast_dsp_free(), ast_free, ast_log(), ast_mutex_destroy, ast_mutex_unlock, ast_rtp_instance_destroy(), AST_SCHED_DEL, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, iflist, oh323_pvt::lock, LOG_WARNING, oh323_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.
Referenced by do_monitor(), and oh323_destroy().
{
struct oh323_pvt *cur, *prev = NULL;
AST_SCHED_DEL(sched, pvt->DTMFsched);
if (pvt->rtp) {
ast_rtp_instance_destroy(pvt->rtp);
}
/* Free dsp used for in-band DTMF detection */
if (pvt->vad) {
ast_dsp_free(pvt->vad);
}
cleanup_call_details(&pvt->cd);
/* Unlink us from the owner if we have one */
if (pvt->owner) {
ast_channel_lock(pvt->owner);
if (h323debug)
ast_debug(1, "Detaching from %s\n", ast_channel_name(pvt->owner));
ast_channel_tech_pvt_set(pvt->owner, NULL);
ast_channel_unlock(pvt->owner);
}
cur = iflist;
while(cur) {
if (cur == pvt) {
if (prev)
prev->next = cur->next;
else
iflist = cur->next;
break;
}
prev = cur;
cur = cur->next;
}
if (!cur) {
ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur);
} else {
ast_mutex_unlock(&pvt->lock);
ast_mutex_destroy(&pvt->lock);
ast_free(pvt);
}
}
| static struct ast_channel* __oh323_new | ( | struct oh323_pvt * | pvt, |
| int | state, | ||
| const char * | host, | ||
| const char * | linkedid | ||
| ) | [static, read] |
Private structure should be locked on a call.
Definition at line 1032 of file chan_h323.c.
References __oh323_rtp_create(), oh323_pvt::accountcode, oh323_pvt::amaflags, ast_party_caller::ani, ast_best_codec(), ast_channel_alloc(), ast_channel_amaflags_set(), ast_channel_caller(), ast_channel_context_set(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_priority_set(), ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_channel_readformat(), ast_channel_redirecting(), ast_channel_rings_set(), ast_channel_set_fd(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_transfercapability_set(), ast_channel_writeformat(), ast_codec_choose(), ast_dsp_new(), ast_dsp_set_features(), ast_format_cap_from_old_bitfield(), ast_format_cap_set(), ast_format_cap_to_old_bitfield(), ast_format_copy(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock, ast_mutex_unlock, ast_pbx_start(), ast_rtp_instance_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_strlen_zero(), ast_udptl_fd(), oh323_pvt::cd, cid_name, cid_num, oh323_pvt::context, DSP_FEATURE_DIGIT_DETECT, oh323_pvt::exten, ast_party_redirecting::from, ast_party_caller::id, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_WARNING, ast_party_id::name, oh323_pvt::nativeformats, ast_party_id::number, ast_party_dialed::number, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_party_number::plan, ast_party_name::presentation, ast_party_number::presentation, redirectingreason2str(), oh323_pvt::rtp, ast_module_info::self, ast_party_number::str, ast_party_dialed::str, oh323_pvt::vad, and ast_party_number::valid.
Referenced by answer_call(), and oh323_request().
{
struct ast_channel *ch;
char *cid_num, *cid_name;
h323_format fmt;
struct ast_format tmpfmt;
if (!ast_strlen_zero(pvt->options.cid_num))
cid_num = pvt->options.cid_num;
else
cid_num = pvt->cd.call_source_e164;
if (!ast_strlen_zero(pvt->options.cid_name))
cid_name = pvt->options.cid_name;
else
cid_name = pvt->cd.call_source_name;
/* Don't hold a oh323_pvt lock while we allocate a chanel */
ast_mutex_unlock(&pvt->lock);
ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, linkedid, pvt->amaflags, "H323/%s", host);
/* Update usage counter */
ast_module_ref(ast_module_info->self);
ast_mutex_lock(&pvt->lock);
if (ch) {
ast_channel_tech_set(ch, &oh323_tech);
if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
fmt = global_options.capability;
ast_format_cap_from_old_bitfield(ast_channel_nativeformats(ch), fmt);
ast_codec_choose(&pvt->options.prefs, ast_channel_nativeformats(ch), 1, &tmpfmt)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
ast_format_cap_set(ast_channel_nativeformats(ch), &tmpfmt);
pvt->nativeformats = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(ch));
ast_best_codec(ast_channel_nativeformats(ch), &tmpfmt);
ast_format_copy(ast_channel_writeformat(ch), &tmpfmt);
ast_format_copy(ast_channel_rawwriteformat(ch), &tmpfmt);
ast_format_copy(ast_channel_readformat(ch), &tmpfmt);
ast_format_copy(ast_channel_rawreadformat(ch), &tmpfmt);
if (!pvt->rtp)
__oh323_rtp_create(pvt);
#if 0
ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(pvt->rtp, 0));
ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(pvt->rtp, 1));
#endif
#ifdef VIDEO_SUPPORT
if (pvt->vrtp) {
ast_channel_set_fd(ch, 2, ast_rtp_instance_fd(pvt->vrtp, 0));
ast_channel_set_fd(ch, 3, ast_rtp_instance_fd(pvt->vrtp, 1));
}
#endif
#ifdef T38_SUPPORT
if (pvt->udptl) {
ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl));
}
#endif
if (state == AST_STATE_RING) {
ast_channel_rings_set(ch, 1);
}
/* Allocate dsp for in-band DTMF support */
if (pvt->options.dtmfmode & H323_DTMF_INBAND) {
pvt->vad = ast_dsp_new();
ast_dsp_set_features(pvt->vad, DSP_FEATURE_DIGIT_DETECT);
}
/* Register channel functions. */
ast_channel_tech_pvt_set(ch, pvt);
/* Set the owner of this channel */
pvt->owner = ch;
ast_channel_context_set(ch, pvt->context);
ast_channel_exten_set(ch, pvt->exten);
ast_channel_priority_set(ch, 1);
if (!ast_strlen_zero(pvt->accountcode)) {
ast_channel_accountcode_set(ch, pvt->accountcode);
}
if (pvt->amaflags) {
ast_channel_amaflags_set(ch, pvt->amaflags);
}
/* Don't use ast_set_callerid() here because it will
* generate a needless NewCallerID event */
if (!ast_strlen_zero(cid_num)) {
ast_channel_caller(ch)->ani.number.valid = 1;
ast_channel_caller(ch)->ani.number.str = ast_strdup(cid_num);
}
if (pvt->cd.redirect_reason >= 0) {
ast_channel_redirecting(ch)->from.number.valid = 1;
ast_channel_redirecting(ch)->from.number.str = ast_strdup(pvt->cd.redirect_number);
pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
}
ast_channel_caller(ch)->id.name.presentation = pvt->cd.presentation;
ast_channel_caller(ch)->id.number.presentation = pvt->cd.presentation;
ast_channel_caller(ch)->id.number.plan = pvt->cd.type_of_number;
if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
ast_channel_dialed(ch)->number.str = ast_strdup(pvt->exten);
}
if (pvt->cd.transfer_capability >= 0)
ast_channel_transfercapability_set(ch, pvt->cd.transfer_capability);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(ch)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch));
ast_hangup(ch);
ch = NULL;
}
}
} else {
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
}
return ch;
}
| static int __oh323_rtp_create | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 978 of file chan_h323.c.
References ast_channel_set_fd(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_find_ourip(), ast_jb_configure(), ast_log(), ast_mutex_unlock, ast_null_frame, ast_queue_frame(), ast_rtp_codecs_packetization_set(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, ast_sockaddr_from_sin, bindaddr, oh323_pvt::dtmf_pt, errno, global_jbconf, oh323_pvt::lock, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, ast_sockaddr::ss, and oh323_pvt::update_rtp_info.
Referenced by __oh323_new(), external_rtp_create(), and setup_rtp_connection().
{
struct ast_sockaddr our_addr;
if (pvt->rtp)
return 0;
{
struct ast_sockaddr tmp;
ast_sockaddr_from_sin(&tmp, &bindaddr);
if (ast_find_ourip(&our_addr, &tmp, AF_INET)) {
ast_mutex_unlock(&pvt->lock);
ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n");
return -1;
}
}
our_addr.ss.ss_family = AF_INET;
pvt->rtp = ast_rtp_instance_new("asterisk", sched, &our_addr, NULL);
if (!pvt->rtp) {
ast_mutex_unlock(&pvt->lock);
ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
return -1;
}
if (h323debug)
ast_debug(1, "Created RTP channel\n");
ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP");
if (h323debug)
ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat);
ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
if (pvt->dtmf_pt[0] > 0)
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0);
if (pvt->dtmf_pt[1] > 0)
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0);
if (pvt->peercapability)
ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
ast_jb_configure(pvt->owner, &global_jbconf);
ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
ast_channel_unlock(pvt->owner);
} else
pvt->update_rtp_info = 1;
return 0;
}
| static void __oh323_update_info | ( | struct ast_channel * | c, |
| struct oh323_pvt * | pvt | ||
| ) | [static] |
Channel and private structures should be already locked.
Definition at line 342 of file chan_h323.c.
References ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_set_fd(), ast_channel_softhangup_internal_flag_add(), ast_channel_writeformat(), ast_debug, ast_format_cap_from_old_bitfield(), ast_format_cap_to_old_bitfield(), AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_jb_configure(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hangup_with_cause(), ast_rtp_instance_fd(), ast_sched_add(), AST_SCHED_DEL, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_SOFTHANGUP_DEV, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, ast_frame::frametype, global_jbconf, oh323_pvt::hangupcause, ast_frame_subclass::integer, LOG_DTMF, oh323_pvt::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, oh323_pvt::rtp, ast_frame::subclass, and oh323_pvt::update_rtp_info.
Referenced by oh323_read(), oh323_update_info(), and oh323_write().
{
h323_format chan_nativeformats_bits = ast_format_cap_to_old_bitfield(ast_channel_nativeformats(c));
if (chan_nativeformats_bits != pvt->nativeformats) {
if (h323debug)
ast_debug(1, "Preparing %s for new native format\n", ast_channel_name(c));
ast_format_cap_from_old_bitfield(ast_channel_nativeformats(c), pvt->nativeformats);
ast_set_read_format(c, ast_channel_readformat(c));
ast_set_write_format(c, ast_channel_writeformat(c));
}
if (pvt->needhangup) {
if (h323debug)
ast_debug(1, "Process pending hangup for %s\n", ast_channel_name(c));
ast_channel_softhangup_internal_flag_add(c, AST_SOFTHANGUP_DEV);
ast_channel_hangupcause_set(c, pvt->hangupcause);
ast_queue_hangup_with_cause(c, pvt->hangupcause);
pvt->needhangup = 0;
pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->DTMFsched = -1;
}
if (pvt->newstate >= 0) {
ast_setstate(c, pvt->newstate);
pvt->newstate = -1;
}
if (pvt->newcontrol >= 0) {
ast_queue_control(c, pvt->newcontrol);
pvt->newcontrol = -1;
}
if (pvt->newdigit >= 0) {
struct ast_frame f = {
.frametype = AST_FRAME_DTMF_END,
.subclass.integer = pvt->newdigit,
.samples = pvt->newduration * 8,
.len = pvt->newduration,
.src = "UPDATE_INFO",
};
if (pvt->newdigit == ' ') { /* signalUpdate message */
f.subclass.integer = pvt->curDTMF;
if (pvt->DTMFsched >= 0) {
AST_SCHED_DEL(sched, pvt->DTMFsched);
}
} else { /* Regular input or signal message */
if (pvt->newduration) { /* This is a signal, signalUpdate follows */
f.frametype = AST_FRAME_DTMF_BEGIN;
AST_SCHED_DEL(sched, pvt->DTMFsched);
pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt);
if (h323debug)
ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched);
}
pvt->curDTMF = pvt->newdigit;
}
ast_queue_frame(c, &f);
pvt->newdigit = -1;
}
if (pvt->update_rtp_info > 0) {
if (pvt->rtp) {
ast_jb_configure(c, &global_jbconf);
ast_channel_set_fd(c, 0, ast_rtp_instance_fd(pvt->rtp, 0));
ast_channel_set_fd(c, 1, ast_rtp_instance_fd(pvt->rtp, 1));
ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */
}
pvt->update_rtp_info = -1;
}
}
| static void __reg_module | ( | void | ) | [static] |
Definition at line 3505 of file chan_h323.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 3505 of file chan_h323.c.
| static int answer_call | ( | unsigned | call_reference, |
| const char * | token | ||
| ) | [static] |
Call-back function to start PBX when OpenH323 ready to serve incoming call.
Returns 1 on success
Definition at line 2308 of file chan_h323.c.
References __oh323_new(), AST_CAUSE_UNALLOCATED, ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), ast_mutex_unlock, AST_STATE_RINGING, oh323_pvt::cd, oh323_pvt::context, oh323_pvt::exten, find_call_locked(), oh323_pvt::lock, LOG_ERROR, and LOG_NOTICE.
Referenced by load_module().
{
struct oh323_pvt *pvt;
struct ast_channel *c = NULL;
enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;
char tmp_exten[sizeof(pvt->exten)];
if (h323debug)
ast_debug(1, "Preparing Asterisk to answer for %s\n", token);
/* Find the call or allocate a private structure if call not found */
pvt = find_call_locked(call_reference, token);
if (!pvt) {
ast_log(LOG_ERROR, "Something is wrong: answer_call\n");
return 0;
}
/* Check if requested extension@context pair exists in the dialplan */
ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));
/* Try to find best extension in specified context */
if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {
if (tmp_exten[0] == 's')
try_exten = ext_s;
else if (tmp_exten[0] == 'i')
try_exten = ext_i;
else
try_exten = ext_original;
} else
try_exten = ext_original;
do {
if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))
break;
switch (try_exten) {
case ext_original:
tmp_exten[0] = 's';
tmp_exten[1] = '\0';
try_exten = ext_s;
break;
case ext_s:
tmp_exten[0] = 'i';
try_exten = ext_i;
break;
case ext_i:
try_exten = ext_notexists;
break;
default:
break;
}
} while (try_exten != ext_notexists);
/* Drop the call if we don't have <exten>, s and i extensions */
if (try_exten == ext_notexists) {
ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context);
ast_mutex_unlock(&pvt->lock);
h323_clear_call(token, AST_CAUSE_UNALLOCATED);
return 0;
} else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) {
if (h323debug)
ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context);
ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten));
}
/* allocate a channel and tell asterisk about it */
c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL);
/* And release when done */
ast_mutex_unlock(&pvt->lock);
if (!c) {
ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
return 0;
}
return 1;
}
| static struct oh323_alias* build_alias | ( | const char * | name, |
| struct ast_variable * | v, | ||
| struct ast_variable * | alt, | ||
| int | realtime | ||
| ) | [static, read] |
Definition at line 1235 of file chan_h323.c.
References aliasl, ast_calloc, ast_copy_string(), ast_log(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by realtime_alias(), and reload_config().
{
struct oh323_alias *alias;
int found = 0;
alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp);
if (alias)
found++;
else {
if (!(alias = ast_calloc(1, sizeof(*alias))))
return NULL;
ASTOBJ_INIT(alias);
}
if (!found && name)
ast_copy_string(alias->name, name, sizeof(alias->name));
for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
if (!strcasecmp(v->name, "e164")) {
ast_copy_string(alias->e164, v->value, sizeof(alias->e164));
} else if (!strcasecmp(v->name, "prefix")) {
ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix));
} else if (!strcasecmp(v->name, "context")) {
ast_copy_string(alias->context, v->value, sizeof(alias->context));
} else if (!strcasecmp(v->name, "secret")) {
ast_copy_string(alias->secret, v->value, sizeof(alias->secret));
} else {
if (strcasecmp(v->value, "h323")) {
ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name);
}
}
}
ASTOBJ_UNMARK(alias);
return alias;
}
| static struct oh323_peer* build_peer | ( | const char * | name, |
| struct ast_variable * | v, | ||
| struct ast_variable * | alt, | ||
| int | realtime | ||
| ) | [static, read] |
Definition at line 1545 of file chan_h323.c.
References ast_append_ha(), ast_calloc, ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_sockaddr_to_sin, ast_strlen_zero(), ast_true(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, oh323_destroy_peer(), peerl, ast_sockaddr::ss, update_common_options(), and ast_variable::value.
Referenced by realtime_peer(), and reload_config().
{
struct oh323_peer *peer;
struct ast_ha *oldha;
int found = 0;
peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp);
if (peer)
found++;
else {
if (!(peer = ast_calloc(1, sizeof(*peer))))
return NULL;
ASTOBJ_INIT(peer);
}
oldha = peer->ha;
peer->ha = NULL;
memcpy(&peer->options, &global_options, sizeof(peer->options));
peer->options.dtmfmode = 0;
peer->options.holdHandling = 0;
peer->addr.sin_port = htons(h323_signalling_port);
peer->addr.sin_family = AF_INET;
if (!found && name)
ast_copy_string(peer->name, name, sizeof(peer->name));
#if 0 /* XXX Port channel variables functionality from chan_sip XXX */
if (peer->chanvars) {
ast_variables_destroy(peer->chanvars);
peer->chanvars = NULL;
}
#endif
/* Default settings for mailbox */
peer->mailbox[0] = '\0';
for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
if (!update_common_options(v, &peer->options))
continue;
if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) {
ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
ASTOBJ_UNREF(peer, oh323_destroy_peer);
return NULL;
}
{
struct ast_sockaddr tmp;
tmp.ss.ss_family = AF_INET;
if (ast_get_ip(&tmp, v->value)) {
ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value);
ASTOBJ_UNREF(peer, oh323_destroy_peer);
return NULL;
}
ast_sockaddr_to_sin(&tmp, &peer->addr);
}
} else if (!strcasecmp(v->name, "port")) {
peer->addr.sin_port = htons(atoi(v->value));
} else if (!strcasecmp(v->name, "permit") ||
!strcasecmp(v->name, "deny")) {
int ha_error = 0;
peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error);
if (ha_error)
ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
} else if (!strcasecmp(v->name, "mailbox")) {
ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox));
} else if (!strcasecmp(v->name, "hasvoicemail")) {
if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) {
ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox));
}
}
}
if (!peer->options.dtmfmode)
peer->options.dtmfmode = global_options.dtmfmode;
if (peer->options.holdHandling == ~0)
peer->options.holdHandling = 0;
else if (!peer->options.holdHandling)
peer->options.holdHandling = global_options.holdHandling;
ASTOBJ_UNMARK(peer);
ast_free_ha(oldha);
return peer;
}
| static struct oh323_user* build_user | ( | const char * | name, |
| struct ast_variable * | v, | ||
| struct ast_variable * | alt, | ||
| int | realtime | ||
| ) | [static, read] |
Definition at line 1420 of file chan_h323.c.
References ast_append_ha(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_sockaddr_to_sin, ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, format, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_user(), ast_sockaddr::ss, update_common_options(), user, userl, and ast_variable::value.
Referenced by realtime_user(), and reload_config().
{
struct oh323_user *user;
struct ast_ha *oldha;
int found = 0;
int format;
user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp);
if (user)
found++;
else {
if (!(user = ast_calloc(1, sizeof(*user))))
return NULL;
ASTOBJ_INIT(user);
}
oldha = user->ha;
user->ha = (struct ast_ha *)NULL;
memcpy(&user->options, &global_options, sizeof(user->options));
user->options.dtmfmode = 0;
user->options.holdHandling = 0;
/* Set default context */
ast_copy_string(user->context, default_context, sizeof(user->context));
if (!found) {
ast_copy_string(user->name, name, sizeof(user->name));
}
#if 0 /* XXX Port channel variables functionality from chan_sip XXX */
if (user->chanvars) {
ast_variables_destroy(user->chanvars);
user->chanvars = NULL;
}
#endif
for (; v || ((v = alt) && !(alt = NULL)); v = v->next) {
if (!update_common_options(v, &user->options))
continue;
if (!strcasecmp(v->name, "context")) {
ast_copy_string(user->context, v->value, sizeof(user->context));
} else if (!strcasecmp(v->name, "secret")) {
ast_copy_string(user->secret, v->value, sizeof(user->secret));
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
} else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) {
ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
ASTOBJ_UNREF(user, oh323_destroy_user);
return NULL;
} else {
struct ast_sockaddr tmp;
tmp.ss.ss_family = AF_INET;
if (ast_get_ip(&tmp, v->value)) {
ASTOBJ_UNREF(user, oh323_destroy_user);
return NULL;
}
ast_sockaddr_to_sin(&tmp, &user->addr);
}
/* Let us know we need to use ip authentication */
user->host = 1;
} else if (!strcasecmp(v->name, "amaflags")) {
format = ast_cdr_amaflags2int(v->value);
if (format < 0) {
ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
} else {
user->amaflags = format;
}
} else if (!strcasecmp(v->name, "permit") ||
!strcasecmp(v->name, "deny")) {
int ha_error = 0;
user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error);
if (ha_error)
ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value);
}
}
if (!user->options.dtmfmode)
user->options.dtmfmode = global_options.dtmfmode;
if (user->options.holdHandling == ~0)
user->options.holdHandling = 0;
else if (!user->options.holdHandling)
user->options.holdHandling = global_options.holdHandling;
ASTOBJ_UNMARK(user);
ast_free_ha(oldha);
return user;
}
| 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 2399 of file chan_h323.c.
References AST_CONTROL_RINGING, ast_debug, ast_log(), ast_mutex_unlock, AST_STATE_RINGING, find_call_locked(), oh323_pvt::lock, LOG_ERROR, oh323_pvt::owner, and update_state().
Referenced by load_module().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Ringing on %s\n", token);
pvt = find_call_locked(call_reference, token);
if (!pvt) {
ast_log(LOG_ERROR, "Something is wrong: ringing\n");
return;
}
if (!pvt->owner) {
ast_mutex_unlock(&pvt->lock);
ast_log(LOG_ERROR, "Channel has no owner\n");
return;
}
update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING);
ast_mutex_unlock(&pvt->lock);
return;
}
| static void cleanup_call_details | ( | call_details_t * | cd | ) | [static] |
Definition at line 418 of file chan_h323.c.
References ast_free.
Referenced by __oh323_destroy(), cleanup_connection(), setup_incoming_call(), and setup_outgoing_call().
{
if (cd->call_token) {
ast_free(cd->call_token);
cd->call_token = NULL;
}
if (cd->call_source_aliases) {
ast_free(cd->call_source_aliases);
cd->call_source_aliases = NULL;
}
if (cd->call_dest_alias) {
ast_free(cd->call_dest_alias);
cd->call_dest_alias = NULL;
}
if (cd->call_source_name) {
ast_free(cd->call_source_name);
cd->call_source_name = NULL;
}
if (cd->call_source_e164) {
ast_free(cd->call_source_e164);
cd->call_source_e164 = NULL;
}
if (cd->call_dest_e164) {
ast_free(cd->call_dest_e164);
cd->call_dest_e164 = NULL;
}
if (cd->sourceIp) {
ast_free(cd->sourceIp);
cd->sourceIp = NULL;
}
if (cd->redirect_number) {
ast_free(cd->redirect_number);
cd->redirect_number = NULL;
}
}
| static void cleanup_connection | ( | unsigned | call_reference, |
| const char * | call_token | ||
| ) | [static] |
Call-back function to cleanup communication Returns nothing,.
Definition at line 2425 of file chan_h323.c.
References oh323_pvt::alreadygone, ast_channel_softhangup_internal_flag_add(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_dsp_free(), ast_log(), ast_mutex_unlock, ast_queue_hangup(), ast_rtp_instance_destroy(), AST_SOFTHANGUP_DEV, oh323_pvt::cd, cleanup_call_details(), find_call_locked(), oh323_pvt::lock, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.
Referenced by load_module().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Cleaning connection to %s\n", call_token);
while (1) {
pvt = find_call_locked(call_reference, call_token);
if (!pvt) {
if (h323debug)
ast_debug(1, "No connection for %s\n", call_token);
return;
}
if (!pvt->owner || !ast_channel_trylock(pvt->owner))
break;
#if 1
ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
#ifdef DEBUG_THREADS
/* XXX to be completed
* If we want to print more info on who is holding the lock,
* implement the relevant code in lock.h and use the routines
* supplied there.
*/
#endif
#endif
ast_mutex_unlock(&pvt->lock);
usleep(1);
}
if (pvt->rtp) {
/* Immediately stop RTP */
ast_rtp_instance_destroy(pvt->rtp);
pvt->rtp = NULL;
}
/* Free dsp used for in-band DTMF detection */
if (pvt->vad) {
ast_dsp_free(pvt->vad);
pvt->vad = NULL;
}
cleanup_call_details(&pvt->cd);
pvt->alreadygone = 1;
/* Send hangup */
if (pvt->owner) {
ast_channel_softhangup_internal_flag_add(pvt->owner, AST_SOFTHANGUP_DEV);
ast_queue_hangup(pvt->owner);
ast_channel_unlock(pvt->owner);
}
ast_mutex_unlock(&pvt->lock);
if (h323debug)
ast_debug(1, "Connection to %s cleaned\n", call_token);
return;
}
| 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 2133 of file chan_h323.c.
References AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_mutex_unlock, oh323_pvt::connection_established, find_call_locked(), oh323_pvt::lock, LOG_ERROR, oh323_pvt::outgoing, and update_state().
Referenced by load_module().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Call %s answered\n", token);
pvt = find_call_locked(call_reference, token);
if (!pvt) {
ast_log(LOG_ERROR, "Something is wrong: connection\n");
return;
}
/* Inform asterisk about remote party connected only on outgoing calls */
if (!pvt->outgoing) {
ast_mutex_unlock(&pvt->lock);
return;
}
/* Do not send ANSWER message more than once */
if (!pvt->connection_established) {
pvt->connection_established = 1;
update_state(pvt, -1, AST_CONTROL_ANSWER);
}
ast_mutex_unlock(&pvt->lock);
return;
}
| static int create_addr | ( | struct oh323_pvt * | pvt, |
| char * | opeer | ||
| ) | [static] |
Definition at line 1723 of file chan_h323.c.
References ast_copy_string(), ast_gethostbyname(), ast_log(), AST_RTP_DTMF, ASTOBJ_UNREF, find_peer(), h323_signalling_port, hp, oh323_pvt::jointcapability, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_destroy_peer(), oh323_pvt::options, and oh323_pvt::sa.
Referenced by oh323_request().
{
struct hostent *hp;
struct ast_hostent ahp;
struct oh323_peer *p;
int portno;
int found = 0;
char *port;
char *hostn;
char peer[256] = "";
ast_copy_string(peer, opeer, sizeof(peer));
port = strchr(peer, ':');
if (port) {
*port = '\0';
port++;
}
pvt->sa.sin_family = AF_INET;
p = find_peer(peer, NULL, 1);
if (p) {
found++;
memcpy(&pvt->options, &p->options, sizeof(pvt->options));
pvt->jointcapability = pvt->options.capability;
if (pvt->options.dtmfmode) {
if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
pvt->nonCodecCapability |= AST_RTP_DTMF;
} else {
pvt->nonCodecCapability &= ~AST_RTP_DTMF;
}
}
if (p->addr.sin_addr.s_addr) {
pvt->sa.sin_addr = p->addr.sin_addr;
pvt->sa.sin_port = p->addr.sin_port;
}
ASTOBJ_UNREF(p, oh323_destroy_peer);
}
if (!p && !found) {
hostn = peer;
if (port) {
portno = atoi(port);
} else {
portno = h323_signalling_port;
}
hp = ast_gethostbyname(hostn, &ahp);
if (hp) {
memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
pvt->sa.sin_port = htons(portno);
/* Look peer by address */
p = find_peer(NULL, &pvt->sa, 1);
memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options));
pvt->jointcapability = pvt->options.capability;
if (p) {
ASTOBJ_UNREF(p, oh323_destroy_peer);
}
if (pvt->options.dtmfmode) {
if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
pvt->nonCodecCapability |= AST_RTP_DTMF;
} else {
pvt->nonCodecCapability &= ~AST_RTP_DTMF;
}
}
return 0;
} else {
ast_log(LOG_WARNING, "No such host: %s\n", peer);
return -1;
}
} else if (!found) {
return -1;
} else {
return 0;
}
}
| static void delete_aliases | ( | void | ) | [static] |
Definition at line 2896 of file chan_h323.c.
References aliasl, ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, and oh323_destroy_alias().
Referenced by reload_config().
{
int pruned = 0;
/* Delete all aliases */
ASTOBJ_CONTAINER_WRLOCK(&aliasl);
ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
ASTOBJ_RDLOCK(iterator);
ASTOBJ_MARK(iterator);
++pruned;
ASTOBJ_UNLOCK(iterator);
} while (0) );
if (pruned) {
ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias);
}
ASTOBJ_CONTAINER_UNLOCK(&aliasl);
}
| static void delete_users | ( | void | ) | [static] |
Definition at line 2870 of file chan_h323.c.
References ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, oh323_destroy_user(), peerl, and userl.
Referenced by reload_config().
{
int pruned = 0;
/* Delete all users */
ASTOBJ_CONTAINER_WRLOCK(&userl);
ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do {
ASTOBJ_RDLOCK(iterator);
ASTOBJ_MARK(iterator);
++pruned;
ASTOBJ_UNLOCK(iterator);
} while (0) );
if (pruned) {
ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user);
}
ASTOBJ_CONTAINER_UNLOCK(&userl);
ASTOBJ_CONTAINER_WRLOCK(&peerl);
ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
ASTOBJ_RDLOCK(iterator);
ASTOBJ_MARK(iterator);
ASTOBJ_UNLOCK(iterator);
} while (0) );
ASTOBJ_CONTAINER_UNLOCK(&peerl);
}
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 2617 of file chan_h323.c.
References __oh323_destroy(), ast_io_wait(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_sched_runq(), ast_sched_wait(), ast_verb, h323_do_reload(), h323_reload_lock, h323_reloading, iflist, iflock, oh323_pvt::lock, monlock, oh323_pvt::needdestroy, and oh323_pvt::next.
Referenced by restart_monitor().
{
int res;
int reloading;
struct oh323_pvt *oh323 = NULL;
for(;;) {
/* Check for a reload request */
ast_mutex_lock(&h323_reload_lock);
reloading = h323_reloading;
h323_reloading = 0;
ast_mutex_unlock(&h323_reload_lock);
if (reloading) {
ast_verb(1, "Reloading H.323\n");
h323_do_reload();
}
/* Check for interfaces needing to be killed */
if (!ast_mutex_trylock(&iflock)) {
#if 1
do {
for (oh323 = iflist; oh323; oh323 = oh323->next) {
if (!ast_mutex_trylock(&oh323->lock)) {
if (oh323->needdestroy) {
__oh323_destroy(oh323);
break;
}
ast_mutex_unlock(&oh323->lock);
}
}
} while (/*oh323*/ 0);
#else
restartsearch:
oh323 = iflist;
while(oh323) {
if (!ast_mutex_trylock(&oh323->lock)) {
if (oh323->needdestroy) {
__oh323_destroy(oh323);
goto restartsearch;
}
ast_mutex_unlock(&oh323->lock);
oh323 = oh323->next;
}
}
#endif
ast_mutex_unlock(&iflock);
} else
oh323 = (struct oh323_pvt *)1; /* Force fast loop */
pthread_testcancel();
/* Wait for sched or io */
res = ast_sched_wait(sched);
if ((res < 0) || (res > 1000)) {
res = 1000;
}
/* Do not wait if some channel(s) is destroyed, probably, more available too */
if (oh323)
res = 1;
res = ast_io_wait(io, res);
pthread_testcancel();
ast_mutex_lock(&monlock);
if (res >= 0) {
ast_sched_runq(sched);
}
ast_mutex_unlock(&monlock);
}
/* Never reached */
return NULL;
}
| static struct rtp_info* external_rtp_create | ( | unsigned | call_reference, |
| const char * | token | ||
| ) | [static, read] |
Callback function used to inform the H.323 stack of the local rtp ip/port details.
Definition at line 1964 of file chan_h323.c.
References __oh323_rtp_create(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_unlock, ast_rtp_instance_get_local_address(), ast_sockaddr_to_sin, find_call_locked(), oh323_pvt::lock, LOG_ERROR, and oh323_pvt::rtp.
Referenced by load_module().
{
struct oh323_pvt *pvt;
struct sockaddr_in us;
struct rtp_info *info;
info = ast_calloc(1, sizeof(*info));
if (!info) {
ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
return NULL;
}
pvt = find_call_locked(call_reference, token);
if (!pvt) {
ast_free(info);
ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
return NULL;
}
if (!pvt->rtp)
__oh323_rtp_create(pvt);
if (!pvt->rtp) {
ast_mutex_unlock(&pvt->lock);
ast_free(info);
ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);
return NULL;
}
/* figure out our local RTP port and tell the H.323 stack about it */
{
struct ast_sockaddr tmp;
ast_rtp_instance_get_local_address(pvt->rtp, &tmp);
ast_sockaddr_to_sin(&tmp, &us);
}
ast_mutex_unlock(&pvt->lock);
ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));
info->port = ntohs(us.sin_port);
if (h323debug)
ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port);
return info;
}
| static struct oh323_alias* find_alias | ( | const char * | source_aliases, |
| int | realtime | ||
| ) | [static, read] |
Find a call by alias.
Definition at line 1880 of file chan_h323.c.
References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().
Referenced by setup_incoming_call().
{
struct oh323_alias *a;
a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases);
if (!a && realtime)
a = realtime_alias(source_aliases);
return a;
}
| static struct oh323_pvt* find_call_locked | ( | int | call_reference, |
| const char * | token | ||
| ) | [static, read] |
Definition at line 1188 of file chan_h323.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, oh323_pvt::cd, iflist, iflock, oh323_pvt::lock, LOG_WARNING, oh323_pvt::needdestroy, and oh323_pvt::next.
Referenced by answer_call(), chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), hangup_connection(), progress(), receive_digit(), remote_hold(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), and setup_rtp_connection().
{
struct oh323_pvt *pvt;
ast_mutex_lock(&iflock);
pvt = iflist;
while(pvt) {
if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) {
/* Found the call */
if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) {
ast_mutex_lock(&pvt->lock);
ast_mutex_unlock(&iflock);
return pvt;
} else if (token == NULL) {
ast_log(LOG_WARNING, "Call Token is NULL\n");
ast_mutex_lock(&pvt->lock);
ast_mutex_unlock(&iflock);
return pvt;
}
}
pvt = pvt->next;
}
ast_mutex_unlock(&iflock);
return NULL;
}
| static struct oh323_peer* find_peer | ( | const char * | peer, |
| struct sockaddr_in * | sin, | ||
| int | realtime | ||
| ) | [static, read] |
Definition at line 1705 of file chan_h323.c.
References ast_debug, ast_inet_ntoa(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, oh323_addrcmp(), peerl, and realtime_peer().
Referenced by create_addr().
{
struct oh323_peer *p;
if (peer)
p = ASTOBJ_CONTAINER_FIND(&peerl, peer);
else
p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp);
if (!p && realtime)
p = realtime_peer(peer, sin);
if (!p && h323debug)
ast_debug(1, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>"));
return p;
}
| static struct oh323_user* find_user | ( | const call_details_t * | cd, |
| int | realtime | ||
| ) | [static, read] |
Definition at line 1675 of file chan_h323.c.
References ast_debug, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, oh323_addrcmp_str(), realtime_user(), and userl.
Referenced by setup_incoming_call().
{
struct oh323_user *u;
if (userbyalias)
u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases);
else
u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str);
if (!u && realtime)
u = realtime_user(cd);
if (!u && h323debug)
ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp);
return u;
}
| static int h323_do_reload | ( | void | ) | [static] |
Definition at line 3207 of file chan_h323.c.
References reload_config().
Referenced by do_monitor().
{
reload_config(1);
return 0;
}
| static int h323_parse_allow_disallow | ( | struct ast_codec_pref * | pref, |
| h323_format * | formats, | ||
| const char * | list, | ||
| int | allowing | ||
| ) | [static] |
Definition at line 1295 of file chan_h323.c.
References ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_cap_from_old_bitfield(), ast_format_cap_to_old_bitfield(), and ast_parse_allow_disallow().
Referenced by update_common_options().
{
int res;
struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
if (!cap) {
return 1;
}
ast_format_cap_from_old_bitfield(cap, *formats);
res = ast_parse_allow_disallow(pref, cap, list, allowing);
*formats = ast_format_cap_to_old_bitfield(cap);
cap = ast_format_cap_destroy(cap);
return res;
}
| static int h323_reload | ( | void | ) | [static] |
Definition at line 3173 of file chan_h323.c.
References ast_mutex_lock, ast_mutex_unlock, ast_verbose(), h323_reload_lock, and restart_monitor().
Referenced by handle_cli_h323_reload(), and reload().
{
ast_mutex_lock(&h323_reload_lock);
if (h323_reloading) {
ast_verbose("Previous H.323 reload not yet done\n");
} else {
h323_reloading = 1;
}
ast_mutex_unlock(&h323_reload_lock);
restart_monitor();
return 0;
}
| static char* handle_cli_h323_cycle_gk | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 2769 of file chan_h323.c.
References ast_cli_args::argc, ast_log(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, LOG_ERROR, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "h323 cycle gk";
e->usage =
"Usage: h323 cycle gk\n"
" Manually re-register with the Gatekeper (Currently Disabled)\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
h323_gk_urq();
/* Possibly register with a GK */
if (!gatekeeper_disable) {
if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
}
}
return CLI_SUCCESS;
}
| static char* handle_cli_h323_hangup | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 2796 of file chan_h323.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_verb, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "h323 hangup";
e->usage =
"Usage: h323 hangup <token>\n"
" Manually try to hang up the call identified by <token>\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
if (h323_soft_hangup(a->argv[2])) {
ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]);
} else {
ast_verb(3, "Hangup failed for %s\n", a->argv[2]);
}
return CLI_SUCCESS;
}
| static char* handle_cli_h323_reload | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 3186 of file chan_h323.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, h323_reload(), and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "h323 reload";
e->usage =
"Usage: h323 reload\n"
" Reloads H.323 configuration from h323.conf\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 2)
return CLI_SHOWUSAGE;
h323_reload();
return CLI_SUCCESS;
}
| static char* handle_cli_h323_set_debug | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 2746 of file chan_h323.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "h323 set debug [on|off]";
e->usage =
"Usage: h323 set debug [on|off]\n"
" Enable/Disable H.323 debugging output\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off"))
return CLI_SHOWUSAGE;
h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1;
ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled");
return CLI_SUCCESS;
}
| static char* handle_cli_h323_set_trace | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 2717 of file chan_h323.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "h323 set trace [on|off]";
e->usage =
"Usage: h323 set trace (on|off|<trace level>)\n"
" Enable/Disable H.323 stack tracing for debugging purposes\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
if (!strcasecmp(a->argv[3], "off")) {
h323_debug(0, 0);
ast_cli(a->fd, "H.323 Trace Disabled\n");
} else if (!strcasecmp(a->argv[3], "on")) {
h323_debug(1, 1);
ast_cli(a->fd, "H.323 Trace Enabled\n");
} else {
int tracelevel = atoi(a->argv[3]);
h323_debug(1, tracelevel);
ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel);
}
return CLI_SUCCESS;
}
| static char* handle_cli_h323_show_tokens | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 2819 of file chan_h323.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "h323 show tokens";
e->usage =
"Usage: h323 show tokens\n"
" Print out all active call tokens\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
h323_show_tokens();
return CLI_SUCCESS;
}
| static char* handle_cli_h323_show_version | ( | struct ast_cli_entry * | e, |
| int | cmd, | ||
| struct ast_cli_args * | a | ||
| ) | [static] |
Definition at line 2840 of file chan_h323.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
{
switch (cmd) {
case CLI_INIT:
e->command = "h323 show version";
e->usage =
"Usage: h323 show version\n"
" Show the version of the H.323 library in use\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
h323_show_version();
return CLI_SUCCESS;
}
| static void hangup_connection | ( | unsigned int | call_reference, |
| const char * | token, | ||
| int | cause | ||
| ) | [static] |
Definition at line 2478 of file chan_h323.c.
References ast_channel_hangupcause_set(), ast_channel_softhangup_internal_flag_add(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_mutex_unlock, ast_queue_hangup_with_cause(), AST_SOFTHANGUP_DEV, find_call_locked(), oh323_pvt::hangupcause, oh323_pvt::lock, oh323_pvt::needhangup, and oh323_pvt::owner.
Referenced by load_module().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause);
pvt = find_call_locked(call_reference, token);
if (!pvt) {
if (h323debug)
ast_debug(1, "Connection to %s already cleared\n", token);
return;
}
if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
ast_channel_softhangup_internal_flag_add(pvt->owner, AST_SOFTHANGUP_DEV);
ast_channel_hangupcause_set(pvt->owner, pvt->hangupcause = cause);
ast_queue_hangup_with_cause(pvt->owner, cause);
ast_channel_unlock(pvt->owner);
}
else {
pvt->needhangup = 1;
pvt->hangupcause = cause;
if (h323debug)
ast_debug(1, "Hangup for %s is pending\n", token);
}
ast_mutex_unlock(&pvt->lock);
}
| static enum ast_module_load_result load_module | ( | void | ) | [static] |
Definition at line 3317 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_format_cap_add_all_by_type(), ast_format_cap_alloc(), AST_FORMAT_TYPE_AUDIO, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_rtp_glue_unregister(), ast_sched_context_create(), ast_sched_context_destroy(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, ast_channel_tech::capabilities, chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), hangup_connection(), io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.
{
int res;
if (!(oh323_tech.capabilities = ast_format_cap_alloc())) {
return AST_MODULE_LOAD_FAILURE;
}
ast_format_cap_add_all_by_type(oh323_tech.capabilities, AST_FORMAT_TYPE_AUDIO);
h323debug = 0;
sched = ast_sched_context_create();
if (!sched) {
ast_log(LOG_WARNING, "Unable to create schedule context\n");
return AST_MODULE_LOAD_FAILURE;
}
io = io_context_create();
if (!io) {
ast_log(LOG_WARNING, "Unable to create I/O context\n");
return AST_MODULE_LOAD_FAILURE;
}
ast_cli_register(&cli_h323_reload);
ASTOBJ_CONTAINER_INIT(&userl);
ASTOBJ_CONTAINER_INIT(&peerl);
ASTOBJ_CONTAINER_INIT(&aliasl);
res = reload_config(0);
if (res) {
/* No config entry */
ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
ast_cli_unregister(&cli_h323_reload);
io_context_destroy(io);
io = NULL;
ast_sched_context_destroy(sched);
sched = NULL;
ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_DESTROY(&peerl);
ASTOBJ_CONTAINER_DESTROY(&aliasl);
return AST_MODULE_LOAD_DECLINE;
} else {
/* Make sure we can register our channel type */
if (ast_channel_register(&oh323_tech)) {
ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n");
ast_cli_unregister(&cli_h323_reload);
h323_end_process();
io_context_destroy(io);
ast_sched_context_destroy(sched);
ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
ASTOBJ_CONTAINER_DESTROY(&peerl);
ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
ASTOBJ_CONTAINER_DESTROY(&aliasl);
return AST_MODULE_LOAD_FAILURE;
}
ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
ast_rtp_glue_register(&oh323_rtp_glue);
/* Register our callback functions */
h323_callback_register(setup_incoming_call,
setup_outgoing_call,
external_rtp_create,
setup_rtp_connection,
cleanup_connection,
chan_ringing,
connection_made,
receive_digit,
answer_call,
progress,
set_dtmf_payload,
hangup_connection,
set_local_capabilities,
set_peer_capabilities,
remote_hold);
/* start the h.323 listener */
if (h323_start_listener(h323_signalling_port, bindaddr)) {
ast_log(LOG_ERROR, "Unable to create H323 listener.\n");
ast_rtp_glue_unregister(&oh323_rtp_glue);
ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
ast_cli_unregister(&cli_h323_reload);
h323_end_process();
io_context_destroy(io);
ast_sched_context_destroy(sched);
ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
ASTOBJ_CONTAINER_DESTROY(&peerl);
ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
ASTOBJ_CONTAINER_DESTROY(&aliasl);
return AST_MODULE_LOAD_DECLINE;
}
/* Possibly register with a GK */
if (!gatekeeper_disable) {
if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
gatekeeper_disable = 1;
res = AST_MODULE_LOAD_SUCCESS;
}
}
/* And start the monitor for the first time */
restart_monitor();
}
return res;
}
| static int oh323_addrcmp | ( | struct sockaddr_in | addr, |
| struct sockaddr_in * | sin | ||
| ) | [static] |
Definition at line 1693 of file chan_h323.c.
References inaddrcmp().
Referenced by find_peer().
{
int res;
if (!sin)
res = -1;
else
res = inaddrcmp(&addr , sin);
return res;
}
| static int oh323_addrcmp_str | ( | struct in_addr | inaddr, |
| char * | addr | ||
| ) | [static] |
Definition at line 1670 of file chan_h323.c.
References ast_inet_ntoa().
Referenced by find_user().
{
return strcmp(ast_inet_ntoa(inaddr), addr);
}
| static struct oh323_pvt* oh323_alloc | ( | int | callid | ) | [static, read] |
Definition at line 1145 of file chan_h323.c.
References ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, AST_RTP_DTMF, ast_rtp_instance_destroy(), oh323_pvt::cd, oh323_pvt::context, oh323_pvt::DTMFsched, iflist, iflock, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newstate, oh323_pvt::next, oh323_pvt::nonCodecCapability, oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::update_rtp_info.
Referenced by oh323_request(), and setup_incoming_call().
{
struct oh323_pvt *pvt;
pvt = ast_calloc(1, sizeof(*pvt));
if (!pvt) {
ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n");
return NULL;
}
pvt->cd.redirect_reason = -1;
pvt->cd.transfer_capability = -1;
/* Ensure the call token is allocated for outgoing call */
if (!callid) {
if ((pvt->cd).call_token == NULL) {
(pvt->cd).call_token = ast_calloc(1, 128);
}
if (!pvt->cd.call_token) {
ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
ast_rtp_instance_destroy(pvt->rtp);
ast_free(pvt);
return NULL;
}
memset((char *)(pvt->cd).call_token, 0, 128);
pvt->cd.call_reference = callid;
}
memcpy(&pvt->options, &global_options, sizeof(pvt->options));
pvt->jointcapability = pvt->options.capability;
if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) {
pvt->nonCodecCapability |= AST_RTP_DTMF;
} else {
pvt->nonCodecCapability &= ~AST_RTP_DTMF;
}
ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1;
ast_mutex_init(&pvt->lock);
/* Add to interface list */
ast_mutex_lock(&iflock);
pvt->next = iflist;
iflist = pvt;
ast_mutex_unlock(&iflock);
return pvt;
}
| static int oh323_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 670 of file chan_h323.c.
References ast_channel_name(), ast_channel_tech_pvt(), ast_debug, ast_free, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::lock, and oh323_update_info().
{
int res;
struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
char *token;
if (h323debug)
ast_debug(1, "Answering on %s\n", ast_channel_name(c));
ast_mutex_lock(&pvt->lock);
token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
ast_mutex_unlock(&pvt->lock);
res = h323_answering_call(token, 0);
if (token)
ast_free(token);
oh323_update_info(c);
if (ast_channel_state(c) != AST_STATE_UP) {
ast_setstate(c, AST_STATE_UP);
}
return res;
}
| static int oh323_call | ( | struct ast_channel * | c, |
| const 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_connected(), ast_channel_name(), ast_channel_redirecting(), ast_channel_tech_pvt(), ast_channel_transfercapability(), ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_party_id_presentation(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verb, oh323_pvt::cd, oh323_pvt::exten, ast_party_connected_line::id, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, name, ast_party_id::number, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), ast_party_number::plan, oh323_pvt::sa, ast_party_number::str, and ast_party_number::valid.
{
int res = 0;
struct oh323_pvt *pvt = (struct oh323_pvt *)ast_channel_tech_pvt(c);
const char *addr;
char called_addr[1024];
if (h323debug) {
ast_debug(1, "Calling to %s on %s\n", dest, ast_channel_name(c));
}
if ((ast_channel_state(c) != AST_STATE_DOWN) && (ast_channel_state(c) != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "Line is already in use (%s)\n", ast_channel_name(c));
return -1;
}
ast_mutex_lock(&pvt->lock);
if (!gatekeeper_disable) {
if (ast_strlen_zero(pvt->exten)) {
ast_copy_string(called_addr, dest, sizeof(called_addr));
} else {
snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);
}
} else {
res = htons(pvt->sa.sin_port);
addr = ast_inet_ntoa(pvt->sa.sin_addr);
if (ast_strlen_zero(pvt->exten)) {
snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);
} else {
snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);
}
}
/* make sure null terminated */
called_addr[sizeof(called_addr) - 1] = '\0';
if (ast_channel_connected(c)->id.number.valid && ast_channel_connected(c)->id.number.str) {
ast_copy_string(pvt->options.cid_num, ast_channel_connected(c)->id.number.str, sizeof(pvt->options.cid_num));
}
if (ast_channel_connected(c)->id.name.valid && ast_channel_connected(c)->id.name.str) {
ast_copy_string(pvt->options.cid_name, ast_channel_connected(c)->id.name.str, sizeof(pvt->options.cid_name));
}
if (ast_channel_redirecting(c)->from.number.valid && ast_channel_redirecting(c)->from.number.str) {
ast_copy_string(pvt->options.cid_rdnis, ast_channel_redirecting(c)->from.number.str, sizeof(pvt->options.cid_rdnis));
}
pvt->options.presentation = ast_party_id_presentation(&ast_channel_connected(c)->id);
pvt->options.type_of_number = ast_channel_connected(c)->id.number.plan;
if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
if (!strcasecmp(addr, "UNKNOWN"))
pvt->options.redirect_reason = 0;
else if (!strcasecmp(addr, "BUSY"))
pvt->options.redirect_reason = 1;
else if (!strcasecmp(addr, "NO_REPLY"))
pvt->options.redirect_reason = 2;
else if (!strcasecmp(addr, "UNCONDITIONAL"))
pvt->options.redirect_reason = 15;
else
pvt->options.redirect_reason = -1;
} else
pvt->options.redirect_reason = -1;
pvt->options.transfer_capability = ast_channel_transfercapability(c);
/* indicate that this is an outgoing call */
pvt->outgoing = 1;
ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast_channel_transfercapability(c), ast_transfercapability2str(ast_channel_transfercapability(c)));
if (h323debug)
ast_debug(1, "Placing outgoing call to %s, %d/%d\n", called_addr, pvt->options.dtmfcodec[0], pvt->options.dtmfcodec[1]);
ast_mutex_unlock(&pvt->lock);
res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);
if (res) {
ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", ast_channel_name(c));
return -1;
}
oh323_update_info(c);
return 0;
}
| static void oh323_destroy | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 499 of file chan_h323.c.
References __oh323_destroy(), ast_channel_name(), ast_debug, ast_mutex_lock, ast_mutex_unlock, iflock, oh323_pvt::lock, and oh323_pvt::owner.
Referenced by oh323_request(), and setup_incoming_call().
{
if (h323debug) {
ast_debug(1, "Destroying channel %s\n", (pvt->owner ? ast_channel_name(pvt->owner) : "<unknown>"));
}
ast_mutex_lock(&iflock);
ast_mutex_lock(&pvt->lock);
__oh323_destroy(pvt);
ast_mutex_unlock(&iflock);
}
| static void oh323_destroy_alias | ( | struct oh323_alias * | alias | ) | [static] |
Definition at line 289 of file chan_h323.c.
References ast_debug, and ast_free.
Referenced by delete_aliases(), load_module(), reload_config(), and unload_module().
| static void oh323_destroy_peer | ( | struct oh323_peer * | peer | ) | [static] |
Definition at line 304 of file chan_h323.c.
References ast_debug, ast_free, and ast_free_ha().
Referenced by build_peer(), create_addr(), load_module(), prune_peers(), reload_config(), and unload_module().
{
if (h323debug)
ast_debug(1, "Destroying peer '%s'\n", peer->name);
ast_free_ha(peer->ha);
ast_free(peer);
}
| static void oh323_destroy_user | ( | struct oh323_user * | user | ) | [static] |
Definition at line 296 of file chan_h323.c.
References ast_debug, ast_free, and ast_free_ha().
Referenced by build_user(), delete_users(), load_module(), reload_config(), setup_incoming_call(), and unload_module().
| static int oh323_digit_begin | ( | struct ast_channel * | c, |
| char | digit | ||
| ) | [static] |
Definition at line 510 of file chan_h323.c.
References ast_channel_name(), ast_channel_tech_pvt(), ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_begin(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::txDtmfDigit.
{
struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
char *token;
if (!pvt) {
ast_log(LOG_ERROR, "No private structure?! This is bad\n");
return -1;
}
ast_mutex_lock(&pvt->lock);
if (pvt->rtp &&
(((pvt->options.dtmfmode & H323_DTMF_RFC2833) && pvt->dtmf_pt[0])
/*|| ((pvt->options.dtmfmode & H323_DTMF_CISCO) && pvt->dtmf_pt[1]))*/)) {
/* out-of-band DTMF */
if (h323debug) {
ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, ast_channel_name(c));
}
ast_rtp_instance_dtmf_begin(pvt->rtp, digit);
ast_mutex_unlock(&pvt->lock);
} else if (pvt->txDtmfDigit != digit) {
/* in-band DTMF */
if (h323debug) {
ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, ast_channel_name(c));
}
pvt->txDtmfDigit = digit;
token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
ast_mutex_unlock(&pvt->lock);
h323_send_tone(token, digit);
if (token) {
ast_free(token);
}
} else
ast_mutex_unlock(&pvt->lock);
oh323_update_info(c);
return 0;
}
| 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_channel_name(), ast_channel_tech_pvt(), ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_dtmf_end(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::txDtmfDigit.
{
struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
char *token;
if (!pvt) {
ast_log(LOG_ERROR, "No private structure?! This is bad\n");
return -1;
}
ast_mutex_lock(&pvt->lock);
if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && ((pvt->dtmf_pt[0] > 0) || (pvt->dtmf_pt[0] > 0))) {
/* out-of-band DTMF */
if (h323debug) {
ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, ast_channel_name(c), duration);
}
ast_rtp_instance_dtmf_end(pvt->rtp, digit);
ast_mutex_unlock(&pvt->lock);
} else {
/* in-band DTMF */
if (h323debug) {
ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, ast_channel_name(c), duration);
}
pvt->txDtmfDigit = ' ';
token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
ast_mutex_unlock(&pvt->lock);
h323_send_tone(token, ' ');
if (token) {
ast_free(token);
}
}
oh323_update_info(c);
return 0;
}
| static int oh323_fixup | ( | struct ast_channel * | oldchan, |
| struct ast_channel * | newchan | ||
| ) | [static] |
Definition at line 964 of file chan_h323.c.
References ast_channel_tech_pvt(), ast_log(), ast_mutex_lock, ast_mutex_unlock, oh323_pvt::lock, LOG_WARNING, and oh323_pvt::owner.
{
struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(newchan);
ast_mutex_lock(&pvt->lock);
if (pvt->owner != oldchan) {
ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner);
return -1;
}
pvt->owner = newchan;
ast_mutex_unlock(&pvt->lock);
return 0;
}
| static enum ast_rtp_glue_result oh323_get_rtp_peer | ( | struct ast_channel * | chan, |
| struct ast_rtp_instance ** | instance | ||
| ) | [static] |
Definition at line 3225 of file chan_h323.c.
References ao2_ref, ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, oh323_pvt::lock, oh323_pvt::options, and oh323_pvt::rtp.
{
struct oh323_pvt *pvt;
enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
if (!(pvt = (struct oh323_pvt *)ast_channel_tech_pvt(chan)))
return AST_RTP_GLUE_RESULT_FORBID;
ast_mutex_lock(&pvt->lock);
*instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
#if 0
if (pvt->options.bridge) {
res = AST_RTP_GLUE_RESULT_REMOTE;
}
#endif
ast_mutex_unlock(&pvt->lock);
return res;
}
| static int oh323_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 693 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_channel_hangupcause(), ast_channel_name(), ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), ast_debug, ast_free, ast_log(), ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, ast_strdup, oh323_pvt::cd, oh323_pvt::hangupcause, oh323_pvt::lock, LOG_WARNING, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), and ast_module_info::self.
{
struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
int q931cause = AST_CAUSE_NORMAL_CLEARING;
char *call_token;
if (h323debug)
ast_debug(1, "Hanging up and scheduling destroy of call %s\n", ast_channel_name(c));
if (!ast_channel_tech_pvt(c)) {
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
}
ast_mutex_lock(&pvt->lock);
/* Determine how to disconnect */
if (pvt->owner != c) {
ast_log(LOG_WARNING, "Huh? We aren't the owner?\n");
ast_mutex_unlock(&pvt->lock);
return 0;
}
pvt->owner = NULL;
ast_channel_tech_pvt_set(c, NULL);
if (ast_channel_hangupcause(c)) {
q931cause = ast_channel_hangupcause(c);
} else {
const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
if (cause) {
if (!strcmp(cause, "CONGESTION")) {
q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
} else if (!strcmp(cause, "BUSY")) {
q931cause = AST_CAUSE_USER_BUSY;
} else if (!strcmp(cause, "CHANISUNVAIL")) {
q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
} else if (!strcmp(cause, "NOANSWER")) {
q931cause = AST_CAUSE_NO_ANSWER;
} else if (!strcmp(cause, "CANCEL")) {
q931cause = AST_CAUSE_CALL_REJECTED;
}
}
}
/* Start the process if it's not already started */
if (!pvt->alreadygone && !pvt->hangupcause) {
call_token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL;
if (call_token) {
/* Release lock to eliminate deadlock */
ast_mutex_unlock(&pvt->lock);
if (h323_clear_call(call_token, q931cause)) {
ast_log(LOG_WARNING, "ClearCall failed.\n");
}
ast_free(call_token);
ast_mutex_lock(&pvt->lock);
}
}
pvt->needdestroy = 1;
ast_mutex_unlock(&pvt->lock);
/* Update usage counter */
ast_module_unref(ast_module_info->self);
return 0;
}
| static int oh323_indicate | ( | struct ast_channel * | c, |
| int | condition, | ||
| const void * | data, | ||
| size_t | datalen | ||
| ) | [static] |
Definition at line 874 of file chan_h323.c.
References oh323_pvt::alreadygone, ast_channel_name(), ast_channel_tech_pvt(), AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_free, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::got_progress, oh323_pvt::lock, LOG_WARNING, oh323_update_info(), and oh323_pvt::rtp.
{
struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
char *token = (char *)NULL;
int res = -1;
int got_progress;
ast_mutex_lock(&pvt->lock);
token = (pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL);
got_progress = pvt->got_progress;
if (condition == AST_CONTROL_PROGRESS)
pvt->got_progress = 1;
else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))
pvt->alreadygone = 1;
ast_mutex_unlock(&pvt->lock);
if (h323debug)
ast_debug(1, "OH323: Indicating %d on %s (%s)\n", condition, token, ast_channel_name(c));
switch(condition) {
case AST_CONTROL_RINGING:
if (ast_channel_state(c) == AST_STATE_RING || ast_channel_state(c) == AST_STATE_RINGING) {
h323_send_alerting(token);
res = (got_progress ? 0 : -1); /* Do not simulate any audio tones if we got PROGRESS message */
}
break;
case AST_CONTROL_PROGRESS:
if (ast_channel_state(c) != AST_STATE_UP) {
/* Do not send PROGRESS message more than once */
if (!got_progress)
h323_send_progress(token);
res = 0;
}
break;
case AST_CONTROL_BUSY:
if (ast_channel_state(c) != AST_STATE_UP) {
h323_answering_call(token, 1);
ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
res = 0;
}
break;
case AST_CONTROL_INCOMPLETE:
/* While h323 does support overlapped dialing, this channel driver does not
* at this time. Treat a response of Incomplete as if it were congestion.
*/
case AST_CONTROL_CONGESTION:
if (ast_channel_state(c) != AST_STATE_UP) {
h323_answering_call(token, 1);
ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
res = 0;
}
break;
case AST_CONTROL_HOLD:
h323_hold_call(token, 1);
/* We should start MOH only if remote party isn't provide audio for us */
ast_moh_start(c, data, NULL);
res = 0;
break;
case AST_CONTROL_UNHOLD:
h323_hold_call(token, 0);
ast_moh_stop(c);
res = 0;
break;
case AST_CONTROL_SRCUPDATE:
ast_rtp_instance_update_source(pvt->rtp);
res = 0;
break;
case AST_CONTROL_SRCCHANGE:
ast_rtp_instance_change_source(pvt->rtp);
res = 0;
break;
case AST_CONTROL_PROCEEDING:
case AST_CONTROL_PVT_CAUSE_CODE:
case -1:
break;
default:
ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token);
break;
}
if (h323debug)
ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res);
if (token)
ast_free(token);
oh323_update_info(c);
return res;
}
| static struct ast_frame * oh323_read | ( | struct ast_channel * | c | ) | [static, read] |
Definition at line 817 of file chan_h323.c.
References __oh323_update_info(), ast_channel_fdno(), ast_channel_name(), ast_channel_tech_pvt(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_null_frame, ast_rtp_instance_read(), oh323_pvt::lock, LOG_ERROR, oh323_rtp_read(), and oh323_pvt::rtp.
{
struct ast_frame *fr;
struct oh323_pvt *pvt = (struct oh323_pvt *)ast_channel_tech_pvt(c);
ast_mutex_lock(&pvt->lock);
__oh323_update_info(c, pvt);
switch(ast_channel_fdno(c)) {
case 0:
fr = oh323_rtp_read(pvt);
break;
case 1:
if (pvt->rtp)
fr = ast_rtp_instance_read(pvt->rtp, 1);
else
fr = &ast_null_frame;
break;
default:
ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", ast_channel_fdno(c), ast_channel_name(c));
fr = &ast_null_frame;
break;
}
ast_mutex_unlock(&pvt->lock);
return fr;
}
| static struct ast_channel * oh323_request | ( | const char * | type, |
| struct ast_format_cap * | cap, | ||
| const struct ast_channel * | requestor, | ||
| const char * | dest, | ||
| int * | cause | ||
| ) | [static, read] |
Definition at line 1795 of file chan_h323.c.
References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_channel_linkedid(), ast_copy_string(), ast_debug, ast_format_cap_has_type(), AST_FORMAT_TYPE_AUDIO, ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_RTP_DTMF, AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), caplock, create_addr(), ext, oh323_pvt::exten, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, and restart_monitor().
{
struct oh323_pvt *pvt;
struct ast_channel *tmpc = NULL;
char *ext, *host;
char *h323id = NULL;
char tmp[256], tmp1[256];
if (h323debug)
ast_debug(1, "type=%s, format=%s, data=%s.\n", type, ast_getformatname_multiple(tmp, sizeof(tmp), cap), dest);
pvt = oh323_alloc(0);
if (!pvt) {
ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", dest);
return NULL;
}
if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
oh323_destroy(pvt);
if (cause)
*cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
return NULL;
}
ast_copy_string(tmp, dest, sizeof(tmp));
host = strchr(tmp, '@');
if (host) {
*host = '\0';
host++;
ext = tmp;
} else {
ext = strrchr(tmp, '/');
if (ext)
*ext++ = '\0';
host = tmp;
}
strtok_r(host, "/", &(h323id));
if (!ast_strlen_zero(h323id)) {
h323_set_id(h323id);
}
if (ext) {
ast_copy_string(pvt->exten, ext, sizeof(pvt->exten));
}
if (h323debug)
ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host);
if (gatekeeper_disable) {
if (create_addr(pvt, host)) {
oh323_destroy(pvt);
if (cause)
*cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
return NULL;
}
}
else {
memcpy(&pvt->options, &global_options, sizeof(pvt->options));
pvt->jointcapability = pvt->options.capability;
if (pvt->options.dtmfmode) {
if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
pvt->nonCodecCapability |= AST_RTP_DTMF;
} else {
pvt->nonCodecCapability &= ~AST_RTP_DTMF;
}
}
}
ast_mutex_lock(&caplock);
/* Generate unique channel identifier */
snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique);
tmp1[sizeof(tmp1)-1] = '\0';
ast_mutex_unlock(&caplock);
ast_mutex_lock(&pvt->lock);
tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? ast_channel_linkedid(requestor) : NULL);
ast_mutex_unlock(&pvt->lock);
if (!tmpc) {
oh323_destroy(pvt);
if (cause)
*cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
}
ast_update_use_count();
restart_monitor();
return tmpc;
}
| static struct ast_frame* oh323_rtp_read | ( | struct oh323_pvt * | pvt | ) | [static, read] |
Retrieve audio/etc from channel. Assumes pvt->lock is already held.
Definition at line 760 of file chan_h323.c.
References ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_trylock, ast_channel_unlock, ast_channel_writeformat(), ast_debug, ast_dsp_process(), AST_FORMAT_ALAW, ast_format_cap_iscompatible(), ast_format_cap_set(), AST_FORMAT_SLINEAR, ast_format_to_old_bitfield(), AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_instance_read(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_NAT, ast_set_read_format(), ast_set_write_format(), f, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::rtp, ast_frame::subclass, and oh323_pvt::vad.
Referenced by oh323_read().
{
struct ast_frame *f;
/* Only apply it for the first packet, we just need the correct ip/port */
if (pvt->options.nat) {
ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat);
pvt->options.nat = 0;
}
f = ast_rtp_instance_read(pvt->rtp, 0);
/* Don't send RFC2833 if we're not supposed to */
if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) {
return &ast_null_frame;
}
if (f && pvt->owner) {
/* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) {
if (!ast_format_cap_iscompatible(ast_channel_nativeformats(pvt->owner), &f->subclass.format)) {
/* Try to avoid deadlock */
if (ast_channel_trylock(pvt->owner)) {
ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n");
return &ast_null_frame;
}
if (h323debug)
ast_debug(1, "Oooh, format changed to '%s'\n", ast_getformatname(&f->subclass.format));
ast_format_cap_set(ast_channel_nativeformats(pvt->owner), &f->subclass.format);
pvt->nativeformats = ast_format_to_old_bitfield(&f->subclass.format);
ast_set_read_format(pvt->owner, ast_channel_readformat(pvt->owner));
ast_set_write_format(pvt->owner, ast_channel_writeformat(pvt->owner));
ast_channel_unlock(pvt->owner);
}
/* Do in-band DTMF detection */
if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) {
if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) {
if (!ast_channel_trylock(pvt->owner)) {
f = ast_dsp_process(pvt->owner, pvt->vad, f);
ast_channel_unlock(pvt->owner);
}
else
ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");
} else if (pvt->nativeformats && !pvt->noInbandDtmf) {
ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(&f->subclass.format));
pvt->noInbandDtmf = 1;
}
if (f &&(f->frametype == AST_FRAME_DTMF)) {
if (h323debug)
ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass.integer);
}
}
}
}
return f;
}
| static int oh323_set_rtp_peer | ( | struct ast_channel * | chan, |
| struct ast_rtp_instance * | rtp, | ||
| struct ast_rtp_instance * | vrtp, | ||
| struct ast_rtp_instance * | trtp, | ||
| const struct ast_format_cap * | codecs, | ||
| int | nat_active | ||
| ) | [static] |
Definition at line 3274 of file chan_h323.c.
References ast_channel_tech_pvt(), ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_sockaddr_to_sin, oh323_pvt::cd, LOG_ERROR, and ast_channel::writeformat.
{
/* XXX Deal with Video */
struct oh323_pvt *pvt;
struct sockaddr_in them = { 0, };
struct sockaddr_in us = { 0, };
#if 0 /* Native bridge still isn't ready */
char *mode;
#endif
if (!rtp) {
return 0;
}
#if 0 /* Native bridge still isn't ready */
mode = convertcap(&chan->writeformat);
#endif
pvt = (struct oh323_pvt *) ast_channel_tech_pvt(chan);
if (!pvt) {
ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
return -1;
}
{
struct ast_sockaddr tmp;
ast_rtp_instance_get_remote_address(rtp, &tmp);
ast_sockaddr_to_sin(&tmp, &them);
ast_rtp_instance_get_local_address(rtp, &tmp);
ast_sockaddr_to_sin(&tmp, &us);
}
#if 0 /* Native bridge still isn't ready */
h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode);
#endif
return 0;
}
| static int oh323_simulate_dtmf_end | ( | const void * | data | ) | [static] |
Definition at line 312 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, AST_FRAME_DTMF_END, ast_mutex_lock, ast_mutex_unlock, ast_queue_frame(), oh323_pvt::curDTMF, DEADLOCK_AVOIDANCE, oh323_pvt::DTMFsched, ast_frame::frametype, oh323_pvt::lock, and oh323_pvt::owner.
Referenced by __oh323_update_info(), and receive_digit().
{
struct oh323_pvt *pvt = (struct oh323_pvt *)data;
if (pvt) {
ast_mutex_lock(&pvt->lock);
/* Don't hold pvt lock while trying to lock the channel */
while (pvt->owner && ast_channel_trylock(pvt->owner)) {
DEADLOCK_AVOIDANCE(&pvt->lock);
}
if (pvt->owner) {
struct ast_frame f = {
.frametype = AST_FRAME_DTMF_END,
.subclass.integer = pvt->curDTMF,
.samples = 0,
.src = "SIMULATE_DTMF_END",
};
ast_queue_frame(pvt->owner, &f);
ast_channel_unlock(pvt->owner);
}
pvt->DTMFsched = -1;
ast_mutex_unlock(&pvt->lock);
}
return 0;
}
| static void oh323_update_info | ( | struct ast_channel * | c | ) | [static] |
Only channel structure should be locked.
Definition at line 407 of file chan_h323.c.
References __oh323_update_info(), ast_channel_tech_pvt(), ast_mutex_lock, ast_mutex_unlock, and oh323_pvt::lock.
Referenced by oh323_answer(), oh323_call(), oh323_digit_begin(), oh323_digit_end(), and oh323_indicate().
{
struct oh323_pvt *pvt = ast_channel_tech_pvt(c);
if (pvt) {
ast_mutex_lock(&pvt->lock);
__oh323_update_info(c, pvt);
ast_mutex_unlock(&pvt->lock);
}
}
| static int oh323_write | ( | struct ast_channel * | c, |
| struct ast_frame * | frame | ||
| ) | [static] |
Definition at line 842 of file chan_h323.c.
References __oh323_update_info(), ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_tech_pvt(), ast_channel_writeformat(), ast_format_cap_iscompatible(), AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_write(), ast_frame_subclass::format, ast_frame::frametype, oh323_pvt::lock, LOG_WARNING, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_frame::subclass.
{
struct oh323_pvt *pvt = (struct oh323_pvt *) ast_channel_tech_pvt(c);
int res = 0;
if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype == AST_FRAME_IMAGE) {
return 0;
} else {
ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
return 0;
}
} else {
if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(c), &frame->subclass.format))) {
char tmp[256];
ast_log(LOG_WARNING, "Asked to transmit frame type '%s', while native formats is '%s' (read/write = %s/%s)\n",
ast_getformatname(&frame->subclass.format),
ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(c)),
ast_getformatname(ast_channel_readformat(c)),
ast_getformatname(ast_channel_writeformat(c)));
return 0;
}
}
if (pvt) {
ast_mutex_lock(&pvt->lock);
if (pvt->rtp && !pvt->recvonly)
res = ast_rtp_instance_write(pvt->rtp, frame);
__oh323_update_info(c, pvt);
ast_mutex_unlock(&pvt->lock);
}
return res;
}
| static int progress | ( | unsigned | call_reference, |
| const char * | token, | ||
| int | inband | ||
| ) | [static] |
Definition at line 2160 of file chan_h323.c.
References AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_debug, ast_log(), ast_mutex_unlock, find_call_locked(), oh323_pvt::lock, LOG_ERROR, oh323_pvt::owner, and update_state().
Referenced by build_progress(), and enc_ie_progress().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
pvt = find_call_locked(call_reference, token);
if (!pvt) {
ast_log(LOG_ERROR, "Private structure not found in progress.\n");
return -1;
}
if (!pvt->owner) {
ast_mutex_unlock(&pvt->lock);
ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");
return -1;
}
update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));
ast_mutex_unlock(&pvt->lock);
return 0;
}
| static void prune_peers | ( | void | ) | [static] |
Definition at line 2914 of file chan_h323.c.
References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.
Referenced by reload_config().
{
/* Prune peers who still are supposed to be deleted */
ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer);
}
| static struct oh323_alias* realtime_alias | ( | const char * | alias | ) | [static, read] |
Definition at line 1270 of file chan_h323.c.
References ast_load_realtime(), ast_variables_destroy(), build_alias(), ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
Referenced by find_alias().
{
struct ast_variable *var, *tmp;
struct oh323_alias *a;
var = ast_load_realtime("h323", "name", alias, SENTINEL);
if (!var)
return NULL;
for (tmp = var; tmp; tmp = tmp->next) {
if (!strcasecmp(tmp->name, "type") &&
!(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) {
ast_variables_destroy(var);
return NULL;
}
}
a = build_alias(alias, var, NULL, 1);
ast_variables_destroy(var);
return a;
}
| static struct oh323_peer* realtime_peer | ( | const char * | peername, |
| struct sockaddr_in * | sin | ||
| ) | [static, read] |
Definition at line 1627 of file chan_h323.c.
References ast_inet_ntoa(), ast_load_realtime(), ast_log(), ast_variables_destroy(), build_peer(), LOG_WARNING, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
Referenced by find_peer().
{
struct oh323_peer *peer;
struct ast_variable *var;
struct ast_variable *tmp;
const char *addr = NULL;
/* First check on peer name */
if (peername)
var = ast_load_realtime("h323", "name", peername, SENTINEL);
else if (sin) /* Then check on IP address for dynamic peers */
var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL);
else
return NULL;
if (!var)
return NULL;
for (tmp = var; tmp; tmp = tmp->next) {
/* If this is type=user, then skip this object. */
if (!strcasecmp(tmp->name, "type") &&
!(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) {
ast_variables_destroy(var);
return NULL;
} else if (!peername && !strcasecmp(tmp->name, "name")) {
peername = tmp->value;
}
}
if (!peername) { /* Did not find peer in realtime */
ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr);
ast_variables_destroy(var);
return NULL;
}
/* Peer found in realtime, now build it in memory */
peer = build_peer(peername, var, NULL, 1);
ast_variables_destroy(var);
return peer;
}
| static struct oh323_user* realtime_user | ( | const call_details_t * | cd | ) | [static, read] |
Definition at line 1507 of file chan_h323.c.
References ast_load_realtime(), ast_log(), ast_variables_destroy(), build_user(), LOG_WARNING, ast_variable::name, ast_variable::next, SENTINEL, user, ast_variable::value, and var.
Referenced by find_user().
{
struct ast_variable *var, *tmp;
struct oh323_user *user;
const char *username;
if (userbyalias)
var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL);
else {
username = (char *)NULL;
var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL);
}
if (!var)
return NULL;
for (tmp = var; tmp; tmp = tmp->next) {
if (!strcasecmp(tmp->name, "type") &&
!(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) {
ast_variables_destroy(var);
return NULL;
} else if (!username && !strcasecmp(tmp->name, "name"))
username = tmp->value;
}
if (!username) {
ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp);
ast_variables_destroy(var);
return NULL;
}
user = build_user(username, var, NULL, 1);
ast_variables_destroy(var);
return user;
}
| 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 1896 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, AST_CONTROL_FLASH, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_unlock, ast_queue_control(), ast_queue_frame(), ast_sched_add(), AST_SCHED_DEL, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, find_call_locked(), ast_frame::frametype, ast_frame_subclass::integer, ast_frame::len, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_frame::samples, and ast_frame::subclass.
Referenced by load_module().
{
struct oh323_pvt *pvt;
int res;
pvt = find_call_locked(call_reference, token);
if (!pvt) {
ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);
return -1;
}
if (h323debug)
ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);
if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
if (digit == '!')
res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
else {
struct ast_frame f = {
.frametype = AST_FRAME_DTMF_END,
.subclass.integer = digit,
.samples = duration * 8,
.len = duration,
.src = "SEND_DIGIT",
};
if (digit == ' ') { /* signalUpdate message */
f.subclass.integer = pvt->curDTMF;
AST_SCHED_DEL(sched, pvt->DTMFsched);
} else { /* Regular input or signal message */
if (pvt->DTMFsched >= 0) {
/* We still don't send DTMF END from previous event, send it now */
AST_SCHED_DEL(sched, pvt->DTMFsched);
f.subclass.integer = pvt->curDTMF;
f.samples = f.len = 0;
ast_queue_frame(pvt->owner, &f);
/* Restore values */
f.subclass.integer = digit;
f.samples = duration * 8;
f.len = duration;
}
if (duration) { /* This is a signal, signalUpdate follows */
f.frametype = AST_FRAME_DTMF_BEGIN;
pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);
if (h323debug)
ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);
}
pvt->curDTMF = digit;
}
res = ast_queue_frame(pvt->owner, &f);
}
ast_channel_unlock(pvt->owner);
} else {
if (digit == '!')
pvt->newcontrol = AST_CONTROL_FLASH;
else {
pvt->newduration = duration;
pvt->newdigit = digit;
}
res = 0;
}
ast_mutex_unlock(&pvt->lock);
return res;
}
| static const char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 273 of file chan_h323.c.
Referenced by __oh323_new().
{
switch (redirectingreason) {
case 0:
return "UNKNOWN";
case 1:
return "BUSY";
case 2:
return "NO_REPLY";
case 0xF:
return "UNCONDITIONAL";
default:
return "NOREDIRECT";
}
}
| static int reload | ( | void | ) | [static] |
Definition at line 3213 of file chan_h323.c.
References ast_log(), h323_reload(), and LOG_NOTICE.
{
if (!sched || !io) {
ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n");
return 0;
}
return h323_reload();
}
| static int reload_config | ( | int | is_reload | ) | [static] |
Definition at line 2920 of file chan_h323.c.
References aliasl, ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_str2cos(), ast_str2tos(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, ASTOBJ_UNREF, bindaddr, build_alias(), build_peer(), build_user(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, delete_aliases(), delete_users(), gatekeeper_disable, gatekeeper_discover, gen, GLOBAL_CAPABILITY, global_jbconf, hp, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, prune_peers(), update_common_options(), userl, and ast_variable::value.
Referenced by h323_do_reload(), and load_module().
{
struct ast_config *cfg, *ucfg;
struct ast_variable *v;
struct oh323_peer *peer = NULL;
struct oh323_user *user = NULL;
struct oh323_alias *alias = NULL;
struct ast_hostent ahp; struct hostent *hp;
char *cat;
const char *utype;
int is_user, is_peer, is_alias;
char _gatekeeper[100];
int gk_discover, gk_disable, gk_changed;
struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
cfg = ast_config_load(config, config_flags);
/* We *must* have a config file otherwise stop immediately */
if (!cfg) {
ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config);
return 1;
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
ucfg = ast_config_load("users.conf", config_flags);
if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
} else if (ucfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
return 0;
}
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
ast_config_destroy(ucfg);
return 0;
}
} else if (cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
return 0;
} else {
ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
ast_config_destroy(cfg);
return 0;
}
}
if (is_reload) {
delete_users();
delete_aliases();
prune_peers();
}
/* fire up the H.323 Endpoint */
if (!h323_end_point_exist()) {
h323_end_point_create();
}
ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper));
gk_discover = gatekeeper_discover;
gk_disable = gatekeeper_disable;
memset(&bindaddr, 0, sizeof(bindaddr));
memset(&global_options, 0, sizeof(global_options));
global_options.fastStart = 1;
global_options.h245Tunneling = 1;
global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT;
global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT;
global_options.dtmfmode = 0;
global_options.holdHandling = 0;
global_options.capability = GLOBAL_CAPABILITY;
global_options.bridge = 1; /* Do native bridging by default */
global_options.autoframing = 0;
strcpy(default_context, "default");
h323_signalling_port = 1720;
gatekeeper_disable = 1;
gatekeeper_discover = 0;
gkroute = 0;
userbyalias = 1;
acceptAnonymous = 1;
tos = 0;
cos = 0;
/* Copy the default jb config over global_jbconf */
memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
if (ucfg) {
struct ast_variable *gen;
int genhas_h323;
const char *has_h323;
genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323"));
gen = ast_variable_browse(ucfg, "general");
for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) {
if (strcasecmp(cat, "general")) {
has_h323 = ast_variable_retrieve(ucfg, cat, "hash323");
if (ast_true(has_h323) || (!has_h323 && genhas_h323)) {
user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0);
if (user) {
ASTOBJ_CONTAINER_LINK(&userl, user);
ASTOBJ_UNREF(user, oh323_destroy_user);
}
peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
if (peer) {
ASTOBJ_CONTAINER_LINK(&peerl, peer);
ASTOBJ_UNREF(peer, oh323_destroy_peer);
}
}
}
}
ast_config_destroy(ucfg);
}
for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
/* handle jb conf */
if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
continue;
/* Create the interface list */
if (!strcasecmp(v->name, "port")) {
h323_signalling_port = (int)strtol(v->value, NULL, 10);
} else if (!strcasecmp(v->name, "bindaddr")) {
if (!(hp = ast_gethostbyname(v->value, &ahp))) {
ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
} else {
memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
}
} else if (!strcasecmp(v->name, "tos")) { /* Needs to be removed in next release */
ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n");
if (ast_str2tos(v->value, &tos)) {
ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
}
} else if (!strcasecmp(v->name, "tos_audio")) {
if (ast_str2tos(v->value, &tos)) {
ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
}
} else if (!strcasecmp(v->name, "cos")) {
ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n");
if (ast_str2cos(v->value, &cos)) {
ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
}
} else if (!strcasecmp(v->name, "cos_audio")) {
if (ast_str2cos(v->value, &cos)) {
ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
}
} else if (!strcasecmp(v->name, "gatekeeper")) {
if (!strcasecmp(v->value, "DISABLE")) {
gatekeeper_disable = 1;
} else if (!strcasecmp(v->value, "DISCOVER")) {
gatekeeper_disable = 0;
gatekeeper_discover = 1;
} else {
gatekeeper_disable = 0;
ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper));
}
} else if (!strcasecmp(v->name, "secret")) {
ast_copy_string(secret, v->value, sizeof(secret));
} else if (!strcasecmp(v->name, "AllowGKRouted")) {
gkroute = ast_true(v->value);
} else if (!strcasecmp(v->name, "context")) {
ast_copy_string(default_context, v->value, sizeof(default_context));
ast_verb(2, "Setting default context to %s\n", default_context);
} else if (!strcasecmp(v->name, "UserByAlias")) {
userbyalias = ast_true(v->value);
} else if (!strcasecmp(v->name, "AcceptAnonymous")) {
acceptAnonymous = ast_true(v->value);
} else if (!update_common_options(v, &global_options)) {
/* dummy */
}
}
if (!global_options.dtmfmode)
global_options.dtmfmode = H323_DTMF_RFC2833;
if (global_options.holdHandling == ~0)
global_options.holdHandling = 0;
else if (!global_options.holdHandling)
global_options.holdHandling = H323_HOLD_H450;
for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) {
if (strcasecmp(cat, "general")) {
utype = ast_variable_retrieve(cfg, cat, "type");
if (utype) {
is_user = is_peer = is_alias = 0;
if (!strcasecmp(utype, "user"))
is_user = 1;
else if (!strcasecmp(utype, "peer"))
is_peer = 1;
else if (!strcasecmp(utype, "friend"))
is_user = is_peer = 1;
else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias"))
is_alias = 1;
else {
ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config);
continue;
}
if (is_user) {
user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0);
if (user) {
ASTOBJ_CONTAINER_LINK(&userl, user);
ASTOBJ_UNREF(user, oh323_destroy_user);
}
}
if (is_peer) {
peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
if (peer) {
ASTOBJ_CONTAINER_LINK(&peerl, peer);
ASTOBJ_UNREF(peer, oh323_destroy_peer);
}
}
if (is_alias) {
alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0);
if (alias) {
ASTOBJ_CONTAINER_LINK(&aliasl, alias);
ASTOBJ_UNREF(alias, oh323_destroy_alias);
}
}
} else {
ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat);
}
}
}
ast_config_destroy(cfg);
/* Register our H.323 aliases if any*/
ASTOBJ_CONTAINER_WRLOCK(&aliasl);
ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do {
ASTOBJ_RDLOCK(iterator);
if (h323_set_alias(iterator)) {
ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name);
ASTOBJ_UNLOCK(iterator);
continue;
}
ASTOBJ_UNLOCK(iterator);
} while (0) );
ASTOBJ_CONTAINER_UNLOCK(&aliasl);
/* Don't touch GK if nothing changed because URQ will drop all existing calls */
gk_changed = 0;
if (gatekeeper_disable != gk_disable)
gk_changed = is_reload;
else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover))
gk_changed = is_reload;
else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0))
gk_changed = is_reload;
if (gk_changed) {
if(!gk_disable)
h323_gk_urq();
if (!gatekeeper_disable) {
if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
gatekeeper_disable = 1;
}
}
}
return 0;
}
| static void remote_hold | ( | unsigned | call_reference, |
| const char * | token, | ||
| int | is_hold | ||
| ) | [static] |
Definition at line 2591 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, ast_mutex_unlock, ast_queue_control(), find_call_locked(), oh323_pvt::lock, oh323_pvt::newcontrol, and oh323_pvt::owner.
Referenced by load_module().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token);
pvt = find_call_locked(call_reference, token);
if (!pvt)
return;
if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
if (is_hold)
ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
else
ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
ast_channel_unlock(pvt->owner);
}
else {
if (is_hold)
pvt->newcontrol = AST_CONTROL_HOLD;
else
pvt->newcontrol = AST_CONTROL_UNHOLD;
}
ast_mutex_unlock(&pvt->lock);
}
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 2685 of file chan_h323.c.
References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, and monlock.
Referenced by h323_reload(), load_module(), and oh323_request().
{
/* If we're supposed to be stopped -- stay stopped */
if (ast_mutex_lock(&monlock)) {
ast_log(LOG_WARNING, "Unable to lock monitor\n");
return -1;
}
if (monitor_thread == AST_PTHREADT_STOP) {
ast_mutex_unlock(&monlock);
return 0;
}
if (monitor_thread == pthread_self()) {
ast_mutex_unlock(&monlock);
ast_log(LOG_WARNING, "Cannot kill myself\n");
return -1;
}
if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) {
/* Wake up the thread */
pthread_kill(monitor_thread, SIGURG);
} else {
/* Start a new monitor */
if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
monitor_thread = AST_PTHREADT_NULL;
ast_mutex_unlock(&monlock);
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
return -1;
}
}
ast_mutex_unlock(&monlock);
return 0;
}
| static void set_dtmf_payload | ( | unsigned | call_reference, |
| const char * | token, | ||
| int | payload, | ||
| int | is_cisco | ||
| ) | [static] |
Definition at line 2506 of file chan_h323.c.
References ast_debug, ast_mutex_unlock, ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), oh323_pvt::dtmf_pt, find_call_locked(), oh323_pvt::lock, and oh323_pvt::rtp.
Referenced by load_module().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token);
pvt = find_call_locked(call_reference, token);
if (!pvt) {
return;
}
if (pvt->rtp) {
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0);
}
pvt->dtmf_pt[is_cisco ? 1 : 0] = payload;
ast_mutex_unlock(&pvt->lock);
if (h323debug)
ast_debug(1, "DTMF payload on %s set to %d\n", token, payload);
}
| static void set_local_capabilities | ( | unsigned | call_reference, |
| const char * | token | ||
| ) | [static] |
Definition at line 2561 of file chan_h323.c.
References ast_debug, ast_getformatname(), ast_mutex_unlock, dtmfmode, find_call_locked(), ast_codec_pref::formats, ast_codec_pref::framing, oh323_pvt::jointcapability, oh323_pvt::lock, oh323_pvt::options, ast_codec_pref::order, and oh323_pvt::pref_codec.
Referenced by load_module().
{
struct oh323_pvt *pvt;
int capability, dtmfmode, pref_codec;
struct ast_codec_pref prefs;
if (h323debug)
ast_debug(1, "Setting capabilities for connection %s\n", token);
pvt = find_call_locked(call_reference, token);
if (!pvt)
return;
capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
dtmfmode = pvt->options.dtmfmode;
prefs = pvt->options.prefs;
pref_codec = pvt->pref_codec;
ast_mutex_unlock(&pvt->lock);
h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
if (h323debug) {
int i;
for (i = 0; i < 32; i++) {
if (!prefs.order[i])
break;
ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(&prefs.formats[i]) : "<none>"), prefs.framing[i]);
}
ast_debug(1, "Capabilities for connection %s is set\n", token);
}
}
| static void set_peer_capabilities | ( | unsigned | call_reference, |
| const char * | token, | ||
| int | capabilities, | ||
| struct ast_codec_pref * | prefs | ||
| ) | [static] |
Definition at line 2526 of file chan_h323.c.
References ast_debug, ast_getformatname(), ast_mutex_unlock, ast_rtp_codecs_packetization_set(), ast_rtp_instance_get_codecs(), capabilities, find_call_locked(), ast_codec_pref::formats, ast_codec_pref::framing, oh323_pvt::jointcapability, oh323_pvt::lock, oh323_pvt::options, ast_codec_pref::order, oh323_pvt::peer_prefs, oh323_pvt::peercapability, and oh323_pvt::rtp.
Referenced by load_module().
{
struct oh323_pvt *pvt;
if (h323debug)
ast_debug(1, "Got remote capabilities from connection %s\n", token);
pvt = find_call_locked(call_reference, token);
if (!pvt)
return;
pvt->peercapability = capabilities;
pvt->jointcapability = pvt->options.capability & capabilities;
if (prefs) {
memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs));
if (h323debug) {
int i;
for (i = 0; i < 32; ++i) {
if (!prefs->order[i])
break;
ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(&prefs->formats[i]) : "<none>"), prefs->framing[i]);
}
}
if (pvt->rtp) {
if (pvt->options.autoframing) {
ast_debug(2, "Autoframing option set, using peer's packetization settings\n");
ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs);
} else {
ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n");
ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs);
}
}
}
ast_mutex_unlock(&pvt->lock);
}
| static call_options_t* setup_incoming_call | ( | call_details_t * | cd | ) | [static] |
Call-back function for incoming calls.
Returns 1 on success
Definition at line 2188 of file chan_h323.c.
References oh323_pvt::accountcode, oh323_pvt::amaflags, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), ast_verb, ASTOBJ_UNREF, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::context, oh323_pvt::exten, find_alias(), find_user(), oh323_pvt::jointcapability, LOG_ERROR, LOG_NOTICE, oh323_alloc(), oh323_destroy(), oh323_destroy_user(), and oh323_pvt::options.
Referenced by load_module().
{
struct oh323_pvt *pvt;
struct oh323_user *user = NULL;
struct oh323_alias *alias = NULL;
if (h323debug)
ast_debug(1, "Setting up incoming call for %s\n", cd->call_token);
/* allocate the call*/
pvt = oh323_alloc(cd->call_reference);
if (!pvt) {
ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
cleanup_call_details(cd);
return NULL;
}
/* Populate the call details in the private structure */
memcpy(&pvt->cd, cd, sizeof(pvt->cd));
memcpy(&pvt->options, &global_options, sizeof(pvt->options));
pvt->jointcapability = pvt->options.capability;
if (h323debug) {
ast_verb(3, "Setting up Call\n");
ast_verb(3, " \tCall token: [%s]\n", pvt->cd.call_token);
ast_verb(3, " \tCalling party name: [%s]\n", pvt->cd.call_source_name);
ast_verb(3, " \tCalling party number: [%s]\n", pvt->cd.call_source_e164);
ast_verb(3, " \tCalled party name: [%s]\n", pvt->cd.call_dest_alias);
ast_verb(3, " \tCalled party number: [%s]\n", pvt->cd.call_dest_e164);
if (pvt->cd.redirect_reason >= 0)
ast_verb(3, " \tRedirecting party number: [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);
ast_verb(3, " \tCalling party IP: [%s]\n", pvt->cd.sourceIp);
}
/* Decide if we are allowing Gatekeeper routed calls*/
if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {
if (!ast_strlen_zero(cd->call_dest_e164)) {
ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
} else {
alias = find_alias(cd->call_dest_alias, 1);
if (!alias) {
ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);
oh323_destroy(pvt);
return NULL;
}
ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));
ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));
}
} else {
/* Either this call is not from the Gatekeeper
or we are not allowing gk routed calls */
user = find_user(cd, 1);
if (!user) {
if (!acceptAnonymous) {
ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
oh323_destroy(pvt);
return NULL;
}
if (ast_strlen_zero(default_context)) {
ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
oh323_destroy(pvt);
return NULL;
}
ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
} else {
ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
}
if (h323debug)
ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);
} else {
if (user->host) {
if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {
if (ast_strlen_zero(user->context)) {
if (ast_strlen_zero(default_context)) {
ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);
oh323_destroy(pvt);
ASTOBJ_UNREF(user, oh323_destroy_user);
return NULL;
}
ast_copy_string(pvt->context, default_context, sizeof(pvt->context));
} else {
ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
}
pvt->exten[0] = 'i';
pvt->exten[1] = '\0';
ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);
oh323_destroy(pvt);
ASTOBJ_UNREF(user, oh323_destroy_user);
return NULL; /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
}
}
ast_copy_string(pvt->context, user->context, sizeof(pvt->context));
memcpy(&pvt->options, &user->options, sizeof(pvt->options));
pvt->jointcapability = pvt->options.capability;
if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));
} else {
ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));
}
if (!ast_strlen_zero(user->accountcode)) {
ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));
}
if (user->amaflags) {
pvt->amaflags = user->amaflags;
}
ASTOBJ_UNREF(user, oh323_destroy_user);
}
}
return &pvt->options;
}
| static int setup_outgoing_call | ( | call_details_t * | cd | ) | [static] |
Call-back function to establish an outgoing H.323 call.
Returns 1 on success
Definition at line 2387 of file chan_h323.c.
References cleanup_call_details().
Referenced by load_module().
{
/* Use argument here or free it immediately */
cleanup_call_details(cd);
return 1;
}
| static void setup_rtp_connection | ( | unsigned | call_reference, |
| const char * | remoteIp, | ||
| int | remotePort, | ||
| const char * | token, | ||
| int | pt | ||
| ) | [static] |
Call-back function passing remote ip/port information from H.323 to asterisk.
Returns nothing
Definition at line 2010 of file chan_h323.c.
References __oh323_rtp_create(), oh323_pvt::alreadygone, ast_channel_nativeformats(), ast_channel_readformat(), ast_channel_trylock, ast_channel_unlock, ast_channel_writeformat(), AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_debug, ast_format_cap_alloc_nolock(), ast_format_cap_copy(), ast_format_cap_destroy(), ast_format_cap_from_old_bitfield(), ast_format_cap_identical(), AST_FORMAT_G726_AAL2, ast_format_to_old_bitfield(), ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_mutex_unlock, ast_queue_control(), ast_rtp_codecs_payload_lookup(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_rtp_instance_stop(), AST_RTP_OPT_G726_NONSTANDARD, ast_set_read_format(), ast_set_write_format(), ast_sockaddr_from_sin, ast_rtp_payload_type::asterisk_format, find_call_locked(), ast_rtp_payload_type::format, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::recvonly, and oh323_pvt::rtp.
Referenced by load_module().
{
struct oh323_pvt *pvt;
struct sockaddr_in them;
int nativeformats_changed;
enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;
if (h323debug)
ast_debug(1, "Setting up RTP connection for %s\n", token);
/* Find the call or allocate a private structure if call not found */
pvt = find_call_locked(call_reference, token);
if (!pvt) {
ast_log(LOG_ERROR, "Something is wrong: rtp\n");
return;
}
if (pvt->alreadygone) {
ast_mutex_unlock(&pvt->lock);
return;
}
if (!pvt->rtp)
__oh323_rtp_create(pvt);
if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) {
ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
}
them.sin_family = AF_INET;
/* only works for IPv4 */
them.sin_addr.s_addr = inet_addr(remoteIp);
them.sin_port = htons(remotePort);
if (them.sin_addr.s_addr) {
{
struct ast_sockaddr tmp;
ast_sockaddr_from_sin(&tmp, &them);
ast_rtp_instance_set_remote_address(pvt->rtp, &tmp);
}
if (pvt->recvonly) {
pvt->recvonly = 0;
rtp_change = NEED_UNHOLD;
}
} else {
ast_rtp_instance_stop(pvt->rtp);
if (!pvt->recvonly) {
pvt->recvonly = 1;
rtp_change = NEED_HOLD;
}
}
/* Change native format to reflect information taken from OLC/OLCAck */
nativeformats_changed = 0;
if (pt != 128 && pvt->rtp) { /* Payload type is invalid, so try to use previously decided */
struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt);
if (rtptype.asterisk_format) {
if (pvt->nativeformats != ast_format_to_old_bitfield(&rtptype.format)) {
pvt->nativeformats = ast_format_to_old_bitfield(&rtptype.format);
nativeformats_changed = 1;
}
}
} else if (h323debug)
ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");
/* Don't try to lock the channel if nothing changed */
if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {
if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
struct ast_format_cap *pvt_native = ast_format_cap_alloc_nolock();
ast_format_cap_from_old_bitfield(pvt_native, pvt->nativeformats);
/* Re-build translation path only if native format(s) has been changed */
if (!(ast_format_cap_identical(ast_channel_nativeformats(pvt->owner), pvt_native))) {
if (h323debug) {
char tmp[256], tmp2[256];
ast_debug(1, "Native format changed to '%s' from '%s', read format is %s, write format is %s\n",
ast_getformatname_multiple(tmp, sizeof(tmp), pvt_native),
ast_getformatname_multiple(tmp2, sizeof(tmp2), ast_channel_nativeformats(pvt->owner)),
ast_getformatname(ast_channel_readformat(pvt->owner)),
ast_getformatname(ast_channel_readformat(pvt->owner)));
}
ast_format_cap_copy(ast_channel_nativeformats(pvt->owner), pvt_native);
ast_set_read_format(pvt->owner, ast_channel_readformat(pvt->owner));
ast_set_write_format(pvt->owner, ast_channel_writeformat(pvt->owner));
}
if (pvt->options.progress_audio)
ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
switch (rtp_change) {
case NEED_HOLD:
ast_queue_control(pvt->owner, AST_CONTROL_HOLD);
break;
case NEED_UNHOLD:
ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);
break;
default:
break;
}
ast_channel_unlock(pvt->owner);
pvt_native = ast_format_cap_destroy(pvt_native);
}
else {
if (pvt->options.progress_audio)
pvt->newcontrol = AST_CONTROL_PROGRESS;
else if (rtp_change == NEED_HOLD)
pvt->newcontrol = AST_CONTROL_HOLD;
else if (rtp_change == NEED_UNHOLD)
pvt->newcontrol = AST_CONTROL_UNHOLD;
if (h323debug)
ast_debug(1, "RTP connection preparation for %s is pending...\n", token);
}
}
ast_mutex_unlock(&pvt->lock);
if (h323debug)
ast_debug(1, "RTP connection prepared for %s\n", token);
return;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 3425 of file chan_h323.c.
References aliasl, ast_channel_unregister(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_format_cap_destroy(), ast_free, ast_log(), ast_mutex_destroy, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_glue_unregister(), ast_sched_context_destroy(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ast_channel_tech::capabilities, iflist, iflock, io_context_destroy(), oh323_pvt::lock, LOG_WARNING, monlock, oh323_pvt::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_pvt::owner, peerl, and userl.
{
struct oh323_pvt *p, *pl;
/* unregister commands */
ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry));
ast_cli_unregister(&cli_h323_reload);
ast_channel_unregister(&oh323_tech);
ast_rtp_glue_unregister(&oh323_rtp_glue);
if (!ast_mutex_lock(&iflock)) {
/* hangup all interfaces if they have an owner */
p = iflist;
while(p) {
if (p->owner) {
ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
}
p = p->next;
}
iflist = NULL;
ast_mutex_unlock(&iflock);
} else {
ast_log(LOG_WARNING, "Unable to lock the interface list\n");
return -1;
}
if (!ast_mutex_lock(&monlock)) {
if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
if (monitor_thread != pthread_self()) {
pthread_cancel(monitor_thread);
}
pthread_kill(monitor_thread, SIGURG);
pthread_join(monitor_thread, NULL);
}
monitor_thread = AST_PTHREADT_STOP;
ast_mutex_unlock(&monlock);
} else {
ast_log(LOG_WARNING, "Unable to lock the monitor\n");
return -1;
}
if (!ast_mutex_lock(&iflock)) {
/* destroy all the interfaces and free their memory */
p = iflist;
while(p) {
pl = p;
p = p->next;
/* free associated memory */
ast_mutex_destroy(&pl->lock);
ast_free(pl);
}
iflist = NULL;
ast_mutex_unlock(&iflock);
} else {
ast_log(LOG_WARNING, "Unable to lock the interface list\n");
return -1;
}
if (!gatekeeper_disable)
h323_gk_urq();
h323_end_process();
if (io)
io_context_destroy(io);
if (sched)
ast_sched_context_destroy(sched);
ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user);
ASTOBJ_CONTAINER_DESTROY(&userl);
ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer);
ASTOBJ_CONTAINER_DESTROY(&peerl);
ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias);
ASTOBJ_CONTAINER_DESTROY(&aliasl);
oh323_tech.capabilities = ast_format_cap_destroy(oh323_tech.capabilities);
return 0;
}
| static int update_common_options | ( | struct ast_variable * | v, |
| struct call_options * | options | ||
| ) | [static] |
Definition at line 1311 of file chan_h323.c.
References ast_callerid_split(), ast_copy_string(), ast_log(), ast_true(), h323_parse_allow_disallow(), ast_variable::lineno, LOG_NOTICE, LOG_WARNING, ast_variable::name, and ast_variable::value.
Referenced by build_peer(), build_user(), and reload_config().
{
int tmp = 0;
char *val, *opt;
if (!strcasecmp(v->name, "allow")) {
h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
} else if (!strcasecmp(v->name, "autoframing")) {
options->autoframing = ast_true(v->value);
} else if (!strcasecmp(v->name, "disallow")) {
h323_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
} else if (!strcasecmp(v->name, "dtmfmode")) {
val = ast_strdupa(v->value);
if ((opt = strchr(val, ':')) != (char *)NULL) {
*opt++ = '\0';
tmp = atoi(opt);
}
if (!strcasecmp(v->value, "inband")) {
options->dtmfmode |= H323_DTMF_INBAND;
} else if (!strcasecmp(val, "rfc2833")) {
options->dtmfmode |= H323_DTMF_RFC2833;
if (!opt) {
options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
} else if ((tmp >= 96) && (tmp < 128)) {
options->dtmfcodec[0] = tmp;
} else {
options->dtmfcodec[0] = H323_DTMF_RFC2833_PT;
ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]);
}
} else if (!strcasecmp(val, "cisco")) {
options->dtmfmode |= H323_DTMF_CISCO;
if (!opt) {
options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
} else if ((tmp >= 96) && (tmp < 128)) {
options->dtmfcodec[1] = tmp;
} else {
options->dtmfcodec[1] = H323_DTMF_CISCO_PT;
ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]);
}
} else if (!strcasecmp(v->value, "h245-signal")) {
options->dtmfmode |= H323_DTMF_SIGNAL;
} else {
ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "dtmfcodec")) {
ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno);
tmp = atoi(v->value);
if (tmp < 96)
ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno);
else
options->dtmfcodec[0] = tmp;
} else if (!strcasecmp(v->name, "bridge")) {
options->bridge = ast_true(v->value);
} else if (!strcasecmp(v->name, "nat")) {
options->nat = ast_true(v->value);
} else if (!strcasecmp(v->name, "fastStart")) {
options->fastStart = ast_true(v->value);
} else if (!strcasecmp(v->name, "h245Tunneling")) {
options->h245Tunneling = ast_true(v->value);
} else if (!strcasecmp(v->name, "silenceSuppression")) {
options->silenceSuppression = ast_true(v->value);
} else if (!strcasecmp(v->name, "progress_setup")) {
tmp = atoi(v->value);
if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) {
ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
tmp = 0;
}
options->progress_setup = tmp;
} else if (!strcasecmp(v->name, "progress_alert")) {
tmp = atoi(v->value);
if ((tmp != 0) && (tmp != 1) && (tmp != 8)) {
ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno);
tmp = 0;
}
options->progress_alert = tmp;
} else if (!strcasecmp(v->name, "progress_audio")) {
options->progress_audio = ast_true(v->value);
} else if (!strcasecmp(v->name, "callerid")) {
ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num));
} else if (!strcasecmp(v->name, "fullname")) {
ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name));
} else if (!strcasecmp(v->name, "cid_number")) {
ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num));
} else if (!strcasecmp(v->name, "tunneling")) {
if (!strcasecmp(v->value, "none"))
options->tunnelOptions = 0;
else if (!strcasecmp(v->value, "cisco"))
options->tunnelOptions |= H323_TUNNEL_CISCO;
else if (!strcasecmp(v->value, "qsig"))
options->tunnelOptions |= H323_TUNNEL_QSIG;
else
ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
} else if (!strcasecmp(v->name, "hold")) {
if (!strcasecmp(v->value, "none"))
options->holdHandling = ~0;
else if (!strcasecmp(v->value, "notify"))
options->holdHandling |= H323_HOLD_NOTIFY;
else if (!strcasecmp(v->value, "q931only"))
options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY;
else if (!strcasecmp(v->value, "h450"))
options->holdHandling |= H323_HOLD_H450;
else
ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno);
} else
return 1;
return 0;
}
| static int update_state | ( | struct oh323_pvt * | pvt, |
| int | state, | ||
| int | signal | ||
| ) | [static] |
Definition at line 1214 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_control(), ast_setstate(), oh323_pvt::newcontrol, oh323_pvt::newstate, oh323_pvt::owner, and state.
Referenced by chan_ringing(), connection_made(), and progress().
{
if (!pvt)
return 0;
if (pvt->owner && !ast_channel_trylock(pvt->owner)) {
if (state >= 0)
ast_setstate(pvt->owner, state);
if (signal >= 0)
ast_queue_control(pvt->owner, signal);
ast_channel_unlock(pvt->owner);
return 1;
}
else {
if (state >= 0)
pvt->newstate = state;
if (signal >= 0)
pvt->newcontrol = signal;
return 0;
}
}
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static] |
Definition at line 3505 of file chan_h323.c.
int acceptAnonymous = 1 [static] |
Definition at line 153 of file chan_h323.c.
struct h323_alias_list aliasl [static] |
Referenced by build_alias(), delete_aliases(), find_alias(), load_module(), reload_config(), and unload_module().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3505 of file chan_h323.c.
struct sockaddr_in bindaddr [static] |
Definition at line 135 of file chan_h323.c.
ast_mutex_t caplock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
Definition at line 229 of file chan_h323.c.
Referenced by oh323_request().
struct ast_cli_entry cli_h323[] [static] |
Definition at line 2861 of file chan_h323.c.
struct ast_cli_entry cli_h323_reload [static] |
AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration")
Definition at line 3222 of file chan_h323.c.
const char config[] = "h323.conf" [static] |
Definition at line 133 of file chan_h323.c.
unsigned int cos = 0 [static] |
Definition at line 155 of file chan_h323.c.
Referenced by ast_playtones_start(), callerid_init(), goertzel_init(), smb_fft(), smb_pitch_shift(), tdd_init(), and tonepair_alloc().
char default_context[AST_MAX_CONTEXT] = "default" [static] |
Definition at line 134 of file chan_h323.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled.
Definition at line 121 of file chan_h323.c.
char gatekeeper[100] [static] |
Definition at line 147 of file chan_h323.c.
int gatekeeper_disable = 1 [static] |
Definition at line 148 of file chan_h323.c.
Referenced by reload_config().
int gatekeeper_discover = 0 [static] |
Definition at line 149 of file chan_h323.c.
Referenced by reload_config().
int gkroute = 0 [static] |
Definition at line 150 of file chan_h323.c.
struct ast_jb_conf global_jbconf [static] |
Definition at line 129 of file chan_h323.c.
Referenced by __oh323_rtp_create(), __oh323_update_info(), and reload_config().
call_options_t global_options [static] |
Definition at line 159 of file chan_h323.c.
ast_mutex_t h323_reload_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Protect the reload process.
Definition at line 232 of file chan_h323.c.
Referenced by do_monitor(), and h323_reload().
int h323_reloading = 0 [static] |
Definition at line 233 of file chan_h323.c.
Referenced by do_monitor().
int h323_signalling_port = 1720 [static] |
| int h323debug |
global debug flag
Definition at line 117 of file chan_h323.c.
Referenced by __oh323_destroy(), do_monitor(), find_call_locked(), oh323_alloc(), and unload_module().
ast_mutex_t iflock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Protect the interface list (oh323_pvt)
Definition at line 222 of file chan_h323.c.
Referenced by do_monitor(), find_call_locked(), oh323_alloc(), oh323_destroy(), and unload_module().
struct io_context* io [static] |
Definition at line 220 of file chan_h323.c.
pthread_t monitor_thread = AST_PTHREADT_NULL [static] |
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 237 of file chan_h323.c.
ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 226 of file chan_h323.c.
Referenced by do_monitor(), restart_monitor(), and unload_module().
struct ast_rtp_glue oh323_rtp_glue [static] |
{
.type = "H323",
.get_rtp_info = oh323_get_rtp_peer,
.update_peer = oh323_set_rtp_peer,
}
Definition at line 3311 of file chan_h323.c.
struct ast_channel_tech oh323_tech [static] |
Definition at line 256 of file chan_h323.c.
| answer_call_cb on_answer_call |
Definition at line 109 of file chan_h323.c.
| chan_ringing_cb on_chan_ringing |
Definition at line 106 of file chan_h323.c.
| clear_con_cb on_connection_cleared |
Definition at line 108 of file chan_h323.c.
| con_established_cb on_connection_established |
Definition at line 107 of file chan_h323.c.
| on_rtp_cb on_external_rtp_create |
Definition at line 102 of file chan_h323.c.
| hangup_cb on_hangup |
Definition at line 112 of file chan_h323.c.
| onhold_cb on_hold |
Definition at line 115 of file chan_h323.c.
| setup_incoming_cb on_incoming_call |
Definition at line 104 of file chan_h323.c.
| setup_outbound_cb on_outgoing_call |
Definition at line 105 of file chan_h323.c.
| progress_cb on_progress |
Definition at line 110 of file chan_h323.c.
| receive_digit_cb on_receive_digit |
Definition at line 101 of file chan_h323.c.
| rfc2833_cb on_set_rfc2833_payload |
Definition at line 111 of file chan_h323.c.
| setcapabilities_cb on_setcapabilities |
Definition at line 113 of file chan_h323.c.
| setpeercapabilities_cb on_setpeercapabilities |
Definition at line 114 of file chan_h323.c.
| start_rtp_cb on_start_rtp_channel |
Definition at line 103 of file chan_h323.c.
struct h323_peer_list peerl [static] |
Referenced by build_peer(), delete_users(), find_peer(), load_module(), prune_peers(), reload_config(), and unload_module().
struct ast_sched_context* sched [static] |
Definition at line 219 of file chan_h323.c.
char secret[50] [static] |
Definition at line 156 of file chan_h323.c.
Referenced by add_realm_authentication(), aji_act_hook(), authenticate_verify(), build_peer(), build_reply_digest(), build_user(), cache_get_callno_locked(), caldav_load_calendar(), check_access(), decrypt_frame(), ewscal_load_calendar(), exchangecal_load_calendar(), iax2_call(), iax2_register(), ical_load_calendar(), read_agent_config(), register_verify(), reload_config(), set_config(), set_peer_defaults(), sip_parse_register_line(), sip_request_call(), sip_subscribe_mwi(), and xmpp_component_authenticate().
const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver" [static] |
Variables required by Asterisk
Definition at line 132 of file chan_h323.c.
unsigned int tos = 0 [static] |
Definition at line 154 of file chan_h323.c.
unsigned int unique = 0 [static] |
Definition at line 157 of file chan_h323.c.
int userbyalias = 1 [static] |
Definition at line 152 of file chan_h323.c.
struct h323_user_list userl [static] |
Referenced by build_user(), delete_users(), find_user(), load_module(), reload_config(), and unload_module().