#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "h323/chan_h323.h"
Go to the source code of this file.
Data Structures | |
struct | h323_alias_list |
H323 alias list. More... | |
struct | h323_peer_list |
H323 peer list. More... | |
struct | h323_user_list |
H323 User list. More... | |
struct | oh323_pvt |
Private structure of a OpenH323 channel. More... | |
struct | rtpPayloadType |
Structure representing a RTP session.The value of each payload format mapping:. More... | |
Defines | |
#define | GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261) |
Functions | |
static void | __oh323_destroy (struct oh323_pvt *pvt) |
static struct ast_channel * | __oh323_new (struct oh323_pvt *pvt, int state, const char *host) |
Private structure should be locked on a call. | |
static int | __oh323_rtp_create (struct oh323_pvt *pvt) |
static void | __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt) |
Channel and private structures should be already locked. | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | answer_call (unsigned call_reference, const char *token) |
Call-back function to start PBX when OpenH323 ready to serve incoming call. | |
static struct oh323_alias * | build_alias (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
static struct oh323_peer * | build_peer (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
static struct oh323_user * | build_user (const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime) |
static void | chan_ringing (unsigned call_reference, const char *token) |
Call-back function to signal asterisk that the channel is ringing Returns nothing. | |
static void | cleanup_call_details (call_details_t *cd) |
static void | cleanup_connection (unsigned call_reference, const char *call_token) |
Call-back function to cleanup communication Returns nothing,. | |
static void | connection_made (unsigned call_reference, const char *token) |
Call-back function to signal asterisk that the channel has been answered Returns nothing. | |
static char * | convertcap (int cap) |
static int | create_addr (struct oh323_pvt *pvt, char *opeer) |
static void | delete_aliases (void) |
static void | delete_users (void) |
static void * | do_monitor (void *data) |
static struct rtp_info * | external_rtp_create (unsigned call_reference, const char *token) |
Callback function used to inform the H.323 stack of the local rtp ip/port details. | |
static struct oh323_alias * | find_alias (const char *source_aliases, int realtime) |
Find a call by alias. | |
static struct oh323_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_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, char *dest, int timeout) |
Make a call over the specified channel to the specified destination. Returns -1 on error, 0 on success. | |
static void | oh323_destroy (struct oh323_pvt *pvt) |
static void | oh323_destroy_alias (struct oh323_alias *alias) |
static void | oh323_destroy_peer (struct oh323_peer *peer) |
static void | oh323_destroy_user (struct oh323_user *user) |
static int | oh323_digit_begin (struct ast_channel *c, char digit) |
static int | oh323_digit_end (struct ast_channel *c, char digit, unsigned int duration) |
Send (play) the specified digit to the channel. | |
static int | oh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static enum ast_rtp_get_result | oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
static enum ast_rtp_get_result | oh323_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp) |
static int | oh323_hangup (struct ast_channel *c) |
static int | oh323_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen) |
static struct ast_frame * | oh323_read (struct ast_channel *c) |
static struct ast_channel * | oh323_request (const char *type, int format, void *data, 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 *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active) |
static int | oh323_simulate_dtmf_end (const void *data) |
static void | oh323_update_info (struct ast_channel *c) |
Only channel structure should be locked. | |
static int | oh323_write (struct ast_channel *c, struct ast_frame *frame) |
static int | progress (unsigned call_reference, const char *token, int inband) |
static void | prune_peers (void) |
static struct oh323_alias * | realtime_alias (const char *alias) |
static struct oh323_peer * | realtime_peer (const char *peername, struct sockaddr_in *sin) |
static struct oh323_user * | realtime_user (const call_details_t *cd) |
static int | receive_digit (unsigned call_reference, char digit, const char *token, int duration) |
Callback for sending digits from H.323 up to asterisk. | |
static const char * | redirectingreason2str (int redirectingreason) |
static int | reload (void) |
static int | reload_config (int is_reload) |
static void | remote_hold (unsigned call_reference, const char *token, int is_hold) |
static int | restart_monitor (void) |
static void | set_dtmf_payload (unsigned call_reference, const char *token, int payload, int is_cisco) |
static void | set_local_capabilities (unsigned call_reference, const char *token) |
static void | set_peer_capabilities (unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs) |
static call_options_t * | setup_incoming_call (call_details_t *cd) |
Call-back function for incoming calls. | |
static int | setup_outgoing_call (call_details_t *cd) |
Call-back function to establish an outgoing H.323 call. | |
static void | setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt) |
Call-back function passing remote ip/port information from H.323 to asterisk. | |
static int | unload_module (void) |
static int | update_common_options (struct ast_variable *v, struct call_options *options) |
static int | update_state (struct oh323_pvt *pvt, int state, int signal) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
static int | acceptAnonymous = 1 |
static struct h323_alias_list | aliasl |
H323 alias list. | |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct sockaddr_in | bindaddr |
static ast_mutex_t | caplock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. | |
static struct ast_cli_entry | cli_h323 [] |
static struct ast_cli_entry | cli_h323_reload |
static const char | config [] = "h323.conf" |
static unsigned int | cos = 0 |
static char | default_context [AST_MAX_CONTEXT] = "default" |
static struct ast_jb_conf | default_jbconf |
Global jitterbuffer configuration - by default, jb is disabled. | |
static char | gatekeeper [100] |
static int | gatekeeper_disable = 1 |
static int | gatekeeper_discover = 0 |
static int | gkroute = 0 |
static struct ast_jb_conf | global_jbconf |
static call_options_t | global_options |
static ast_mutex_t | h323_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
Protect the reload process. | |
static int | h323_reloading = 0 |
static int | h323_signalling_port = 1720 |
int | h323debug |
oh323_pvt * | iflist |
Private structure of a OpenH323 channel. | |
static ast_mutex_t | iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
static struct ast_rtp_protocol | oh323_rtp |
static struct ast_channel_tech | oh323_tech |
answer_call_cb | on_answer_call |
chan_ringing_cb | on_chan_ringing |
clear_con_cb | on_connection_cleared |
con_established_cb | on_connection_established |
on_rtp_cb | on_external_rtp_create |
hangup_cb | on_hangup |
onhold_cb | on_hold |
setup_incoming_cb | on_incoming_call |
setup_outbound_cb | on_outgoing_call |
progress_cb | on_progress |
receive_digit_cb | on_receive_digit |
rfc2833_cb | on_set_rfc2833_payload |
setcapabilities_cb | on_setcapabilities |
setpeercapabilities_cb | on_setpeercapabilities |
start_rtp_cb | on_start_rtp_channel |
static struct h323_peer_list | peerl |
H323 peer list. | |
static struct sched_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 |
H323 User list. |
Definition in file chan_h323.c.
#define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261) |
static void __oh323_destroy | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 440 of file chan_h323.c.
References ast_channel_lock, ast_channel_unlock, ast_debug, ast_dsp_free(), ast_free, ast_log(), ast_mutex_destroy(), ast_mutex_unlock(), ast_rtp_destroy(), AST_SCHED_DEL, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, iflist, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::next, dahdi_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, sched, ast_channel::tech_pvt, and oh323_pvt::vad.
Referenced by do_monitor(), and oh323_destroy().
00441 { 00442 struct oh323_pvt *cur, *prev = NULL; 00443 00444 AST_SCHED_DEL(sched, pvt->DTMFsched); 00445 00446 if (pvt->rtp) { 00447 ast_rtp_destroy(pvt->rtp); 00448 } 00449 00450 /* Free dsp used for in-band DTMF detection */ 00451 if (pvt->vad) { 00452 ast_dsp_free(pvt->vad); 00453 } 00454 cleanup_call_details(&pvt->cd); 00455 00456 /* Unlink us from the owner if we have one */ 00457 if (pvt->owner) { 00458 ast_channel_lock(pvt->owner); 00459 if (h323debug) 00460 ast_debug(1, "Detaching from %s\n", pvt->owner->name); 00461 pvt->owner->tech_pvt = NULL; 00462 ast_channel_unlock(pvt->owner); 00463 } 00464 cur = iflist; 00465 while(cur) { 00466 if (cur == pvt) { 00467 if (prev) 00468 prev->next = cur->next; 00469 else 00470 iflist = cur->next; 00471 break; 00472 } 00473 prev = cur; 00474 cur = cur->next; 00475 } 00476 if (!cur) { 00477 ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur); 00478 } else { 00479 ast_mutex_unlock(&pvt->lock); 00480 ast_mutex_destroy(&pvt->lock); 00481 ast_free(pvt); 00482 } 00483 }
static struct ast_channel* __oh323_new | ( | struct oh323_pvt * | pvt, | |
int | state, | |||
const char * | host | |||
) | [static] |
Private structure should be locked on a call.
Definition at line 995 of file chan_h323.c.
References __oh323_rtp_create(), accountcode, oh323_pvt::accountcode, ast_channel::amaflags, oh323_pvt::amaflags, ast_best_codec(), ast_channel_alloc(), ast_channel_set_fd(), ast_codec_choose(), ast_copy_string(), ast_dsp_new(), ast_dsp_set_features(), ast_hangup(), ast_log(), ast_module_ref(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_rtcp_fd(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_udptl_fd(), oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, cid_name, cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, ast_channel::context, oh323_pvt::context, DSP_FEATURE_DIGIT_DETECT, ast_channel::exten, oh323_pvt::exten, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_WARNING, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_tech, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, redirectingreason2str(), ast_channel::rings, oh323_pvt::rtp, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, and ast_channel::writeformat.
Referenced by answer_call(), and oh323_request().
00996 { 00997 struct ast_channel *ch; 00998 char *cid_num, *cid_name; 00999 int fmt; 01000 01001 if (!ast_strlen_zero(pvt->options.cid_num)) 01002 cid_num = pvt->options.cid_num; 01003 else 01004 cid_num = pvt->cd.call_source_e164; 01005 01006 if (!ast_strlen_zero(pvt->options.cid_name)) 01007 cid_name = pvt->options.cid_name; 01008 else 01009 cid_name = pvt->cd.call_source_name; 01010 01011 /* Don't hold a oh323_pvt lock while we allocate a chanel */ 01012 ast_mutex_unlock(&pvt->lock); 01013 ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, pvt->amaflags, "H323/%s", host); 01014 /* Update usage counter */ 01015 ast_module_ref(ast_module_info->self); 01016 ast_mutex_lock(&pvt->lock); 01017 if (ch) { 01018 ch->tech = &oh323_tech; 01019 if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability)) 01020 fmt = global_options.capability; 01021 ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/; 01022 pvt->nativeformats = ch->nativeformats; 01023 fmt = ast_best_codec(ch->nativeformats); 01024 ch->writeformat = fmt; 01025 ch->rawwriteformat = fmt; 01026 ch->readformat = fmt; 01027 ch->rawreadformat = fmt; 01028 if (!pvt->rtp) 01029 __oh323_rtp_create(pvt); 01030 #if 0 01031 ast_channel_set_fd(ch, 0, ast_rtp_fd(pvt->rtp)); 01032 ast_channel_set_fd(ch, 1, ast_rtcp_fd(pvt->rtp)); 01033 #endif 01034 #ifdef VIDEO_SUPPORT 01035 if (pvt->vrtp) { 01036 ast_channel_set_fd(ch, 2, ast_rtp_fd(pvt->vrtp)); 01037 ast_channel_set_fd(ch, 3, ast_rtcp_fd(pvt->vrtp)); 01038 } 01039 #endif 01040 #ifdef T38_SUPPORT 01041 if (pvt->udptl) { 01042 ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl)); 01043 } 01044 #endif 01045 if (state == AST_STATE_RING) { 01046 ch->rings = 1; 01047 } 01048 /* Allocate dsp for in-band DTMF support */ 01049 if (pvt->options.dtmfmode & H323_DTMF_INBAND) { 01050 pvt->vad = ast_dsp_new(); 01051 ast_dsp_set_features(pvt->vad, DSP_FEATURE_DIGIT_DETECT); 01052 } 01053 /* Register channel functions. */ 01054 ch->tech_pvt = pvt; 01055 /* Set the owner of this channel */ 01056 pvt->owner = ch; 01057 01058 ast_copy_string(ch->context, pvt->context, sizeof(ch->context)); 01059 ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten)); 01060 ch->priority = 1; 01061 if (!ast_strlen_zero(pvt->accountcode)) { 01062 ast_string_field_set(ch, accountcode, pvt->accountcode); 01063 } 01064 if (pvt->amaflags) { 01065 ch->amaflags = pvt->amaflags; 01066 } 01067 01068 /* Don't use ast_set_callerid() here because it will 01069 * generate a needless NewCallerID event */ 01070 ch->cid.cid_ani = ast_strdup(cid_num); 01071 01072 if (pvt->cd.redirect_reason >= 0) { 01073 ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number); 01074 pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason)); 01075 } 01076 ch->cid.cid_pres = pvt->cd.presentation; 01077 ch->cid.cid_ton = pvt->cd.type_of_number; 01078 01079 if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) { 01080 ch->cid.cid_dnid = ast_strdup(pvt->exten); 01081 } 01082 if (pvt->cd.transfer_capability >= 0) 01083 ch->transfercapability = pvt->cd.transfer_capability; 01084 if (state != AST_STATE_DOWN) { 01085 if (ast_pbx_start(ch)) { 01086 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name); 01087 ast_hangup(ch); 01088 ch = NULL; 01089 } 01090 } 01091 } else { 01092 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01093 } 01094 return ch; 01095 }
static int __oh323_rtp_create | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 947 of file chan_h323.c.
References ast_channel_set_fd(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_find_ourip(), ast_jb_configure(), ast_log(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_set_rtpmap_type(), ast_rtp_setnat(), ast_rtp_setqos(), oh323_pvt::dtmf_pt, errno, global_jbconf, io, oh323_pvt::lock, LOG_ERROR, LOG_WARNING, oh323_pvt::options, oh323_pvt::owner, oh323_pvt::peer_prefs, oh323_pvt::peercapability, oh323_pvt::rtp, sched, and oh323_pvt::update_rtp_info.
Referenced by __oh323_new(), external_rtp_create(), and setup_rtp_connection().
00948 { 00949 struct in_addr our_addr; 00950 00951 if (pvt->rtp) 00952 return 0; 00953 00954 if (ast_find_ourip(&our_addr, bindaddr)) { 00955 ast_mutex_unlock(&pvt->lock); 00956 ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n"); 00957 return -1; 00958 } 00959 pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, our_addr); 00960 if (!pvt->rtp) { 00961 ast_mutex_unlock(&pvt->lock); 00962 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); 00963 return -1; 00964 } 00965 if (h323debug) 00966 ast_debug(1, "Created RTP channel\n"); 00967 00968 ast_rtp_setqos(pvt->rtp, tos, cos, "H323 RTP"); 00969 00970 if (h323debug) 00971 ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat); 00972 ast_rtp_setnat(pvt->rtp, pvt->options.nat); 00973 00974 if (pvt->dtmf_pt[0] > 0) 00975 ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0); 00976 if (pvt->dtmf_pt[1] > 0) 00977 ast_rtp_set_rtpmap_type(pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0); 00978 00979 if (pvt->peercapability) 00980 ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs); 00981 00982 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 00983 ast_jb_configure(pvt->owner, &global_jbconf); 00984 ast_channel_set_fd(pvt->owner, 0, ast_rtp_fd(pvt->rtp)); 00985 ast_channel_set_fd(pvt->owner, 1, ast_rtcp_fd(pvt->rtp)); 00986 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */ 00987 ast_channel_unlock(pvt->owner); 00988 } else 00989 pvt->update_rtp_info = 1; 00990 00991 return 0; 00992 }
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 329 of file chan_h323.c.
References ast_channel::_softhangup, ast_channel_set_fd(), ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_jb_configure(), ast_log(), ast_null_frame, ast_queue_control(), ast_queue_frame(), ast_queue_hangup_with_cause(), ast_rtcp_fd(), ast_rtp_fd(), ast_sched_add(), AST_SCHED_DEL, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_SOFTHANGUP_DEV, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, f, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DTMF, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, sched, oh323_pvt::update_rtp_info, and ast_channel::writeformat.
Referenced by oh323_read(), oh323_update_info(), and oh323_write().
00330 { 00331 if (c->nativeformats != pvt->nativeformats) { 00332 if (h323debug) 00333 ast_debug(1, "Preparing %s for new native format\n", c->name); 00334 c->nativeformats = pvt->nativeformats; 00335 ast_set_read_format(c, c->readformat); 00336 ast_set_write_format(c, c->writeformat); 00337 } 00338 if (pvt->needhangup) { 00339 if (h323debug) 00340 ast_debug(1, "Process pending hangup for %s\n", c->name); 00341 c->_softhangup |= AST_SOFTHANGUP_DEV; 00342 c->hangupcause = pvt->hangupcause; 00343 ast_queue_hangup_with_cause(c, pvt->hangupcause); 00344 pvt->needhangup = 0; 00345 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->DTMFsched = -1; 00346 } 00347 if (pvt->newstate >= 0) { 00348 ast_setstate(c, pvt->newstate); 00349 pvt->newstate = -1; 00350 } 00351 if (pvt->newcontrol >= 0) { 00352 ast_queue_control(c, pvt->newcontrol); 00353 pvt->newcontrol = -1; 00354 } 00355 if (pvt->newdigit >= 0) { 00356 struct ast_frame f = { 00357 .frametype = AST_FRAME_DTMF_END, 00358 .subclass = pvt->newdigit, 00359 .samples = pvt->newduration * 8, 00360 .len = pvt->newduration, 00361 .src = "UPDATE_INFO", 00362 }; 00363 if (pvt->newdigit == ' ') { /* signalUpdate message */ 00364 f.subclass = pvt->curDTMF; 00365 if (pvt->DTMFsched >= 0) { 00366 AST_SCHED_DEL(sched, pvt->DTMFsched); 00367 } 00368 } else { /* Regular input or signal message */ 00369 if (pvt->newduration) { /* This is a signal, signalUpdate follows */ 00370 f.frametype = AST_FRAME_DTMF_BEGIN; 00371 AST_SCHED_DEL(sched, pvt->DTMFsched); 00372 pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt); 00373 if (h323debug) 00374 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched); 00375 } 00376 pvt->curDTMF = pvt->newdigit; 00377 } 00378 ast_queue_frame(c, &f); 00379 pvt->newdigit = -1; 00380 } 00381 if (pvt->update_rtp_info > 0) { 00382 if (pvt->rtp) { 00383 ast_jb_configure(c, &global_jbconf); 00384 ast_channel_set_fd(c, 0, ast_rtp_fd(pvt->rtp)); 00385 ast_channel_set_fd(c, 1, ast_rtcp_fd(pvt->rtp)); 00386 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */ 00387 } 00388 pvt->update_rtp_info = -1; 00389 } 00390 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 3373 of file chan_h323.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 3373 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 2223 of file chan_h323.c.
References __oh323_new(), AST_CAUSE_UNALLOCATED, ast_copy_string(), ast_debug, ast_exists_extension(), ast_log(), ast_mutex_unlock(), AST_STATE_RINGING, oh323_pvt::cd, oh323_pvt::context, oh323_pvt::exten, find_call_locked(), h323debug, oh323_pvt::lock, LOG_ERROR, and LOG_NOTICE.
Referenced by load_module().
02224 { 02225 struct oh323_pvt *pvt; 02226 struct ast_channel *c = NULL; 02227 enum {ext_original, ext_s, ext_i, ext_notexists} try_exten; 02228 char tmp_exten[sizeof(pvt->exten)]; 02229 02230 if (h323debug) 02231 ast_debug(1, "Preparing Asterisk to answer for %s\n", token); 02232 02233 /* Find the call or allocate a private structure if call not found */ 02234 pvt = find_call_locked(call_reference, token); 02235 if (!pvt) { 02236 ast_log(LOG_ERROR, "Something is wrong: answer_call\n"); 02237 return 0; 02238 } 02239 /* Check if requested extension@context pair exists in the dialplan */ 02240 ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten)); 02241 02242 /* Try to find best extension in specified context */ 02243 if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) { 02244 if (tmp_exten[0] == 's') 02245 try_exten = ext_s; 02246 else if (tmp_exten[0] == 'i') 02247 try_exten = ext_i; 02248 else 02249 try_exten = ext_original; 02250 } else 02251 try_exten = ext_original; 02252 do { 02253 if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL)) 02254 break; 02255 switch (try_exten) { 02256 case ext_original: 02257 tmp_exten[0] = 's'; 02258 tmp_exten[1] = '\0'; 02259 try_exten = ext_s; 02260 break; 02261 case ext_s: 02262 tmp_exten[0] = 'i'; 02263 try_exten = ext_i; 02264 break; 02265 case ext_i: 02266 try_exten = ext_notexists; 02267 break; 02268 default: 02269 break; 02270 } 02271 } while (try_exten != ext_notexists); 02272 02273 /* Drop the call if we don't have <exten>, s and i extensions */ 02274 if (try_exten == ext_notexists) { 02275 ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context); 02276 ast_mutex_unlock(&pvt->lock); 02277 h323_clear_call(token, AST_CAUSE_UNALLOCATED); 02278 return 0; 02279 } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) { 02280 if (h323debug) 02281 ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context); 02282 ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten)); 02283 } 02284 02285 /* allocate a channel and tell asterisk about it */ 02286 c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token); 02287 02288 /* And release when done */ 02289 ast_mutex_unlock(&pvt->lock); 02290 if (!c) { 02291 ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n"); 02292 return 0; 02293 } 02294 return 1; 02295 }
static struct oh323_alias* build_alias | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | realtime | |||
) | [static] |
Definition at line 1187 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.
01188 { 01189 struct oh323_alias *alias; 01190 int found = 0; 01191 01192 alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp); 01193 01194 if (alias) 01195 found++; 01196 else { 01197 if (!(alias = ast_calloc(1, sizeof(*alias)))) 01198 return NULL; 01199 ASTOBJ_INIT(alias); 01200 } 01201 if (!found && name) 01202 ast_copy_string(alias->name, name, sizeof(alias->name)); 01203 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { 01204 if (!strcasecmp(v->name, "e164")) { 01205 ast_copy_string(alias->e164, v->value, sizeof(alias->e164)); 01206 } else if (!strcasecmp(v->name, "prefix")) { 01207 ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix)); 01208 } else if (!strcasecmp(v->name, "context")) { 01209 ast_copy_string(alias->context, v->value, sizeof(alias->context)); 01210 } else if (!strcasecmp(v->name, "secret")) { 01211 ast_copy_string(alias->secret, v->value, sizeof(alias->secret)); 01212 } else { 01213 if (strcasecmp(v->value, "h323")) { 01214 ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name); 01215 } 01216 } 01217 } 01218 ASTOBJ_UNMARK(alias); 01219 return alias; 01220 }
static struct oh323_peer* build_peer | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | realtime | |||
) | [static] |
Definition at line 1472 of file chan_h323.c.
References ast_append_ha(), ast_calloc, ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_strlen_zero(), ast_true(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, global_options, h323_signalling_port, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, oh323_destroy_peer(), peerl, update_common_options(), and ast_variable::value.
Referenced by reload_config(), and set_config().
01473 { 01474 struct oh323_peer *peer; 01475 struct ast_ha *oldha; 01476 int found = 0; 01477 01478 peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp); 01479 01480 if (peer) 01481 found++; 01482 else { 01483 if (!(peer = ast_calloc(1, sizeof(*peer)))) 01484 return NULL; 01485 ASTOBJ_INIT(peer); 01486 } 01487 oldha = peer->ha; 01488 peer->ha = NULL; 01489 memcpy(&peer->options, &global_options, sizeof(peer->options)); 01490 peer->options.dtmfmode = 0; 01491 peer->options.holdHandling = 0; 01492 peer->addr.sin_port = htons(h323_signalling_port); 01493 peer->addr.sin_family = AF_INET; 01494 if (!found && name) 01495 ast_copy_string(peer->name, name, sizeof(peer->name)); 01496 01497 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */ 01498 if (peer->chanvars) { 01499 ast_variables_destroy(peer->chanvars); 01500 peer->chanvars = NULL; 01501 } 01502 #endif 01503 /* Default settings for mailbox */ 01504 peer->mailbox[0] = '\0'; 01505 01506 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { 01507 if (!update_common_options(v, &peer->options)) 01508 continue; 01509 if (!strcasecmp(v->name, "host")) { 01510 if (!strcasecmp(v->value, "dynamic")) { 01511 ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n"); 01512 ASTOBJ_UNREF(peer, oh323_destroy_peer); 01513 return NULL; 01514 } 01515 if (ast_get_ip(&peer->addr, v->value)) { 01516 ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value); 01517 ASTOBJ_UNREF(peer, oh323_destroy_peer); 01518 return NULL; 01519 } 01520 } else if (!strcasecmp(v->name, "port")) { 01521 peer->addr.sin_port = htons(atoi(v->value)); 01522 } else if (!strcasecmp(v->name, "permit") || 01523 !strcasecmp(v->name, "deny")) { 01524 int ha_error = 0; 01525 01526 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error); 01527 if (ha_error) 01528 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 01529 } else if (!strcasecmp(v->name, "mailbox")) { 01530 ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox)); 01531 } else if (!strcasecmp(v->name, "hasvoicemail")) { 01532 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) { 01533 ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox)); 01534 } 01535 } 01536 } 01537 if (!peer->options.dtmfmode) 01538 peer->options.dtmfmode = global_options.dtmfmode; 01539 if (peer->options.holdHandling == ~0) 01540 peer->options.holdHandling = 0; 01541 else if (!peer->options.holdHandling) 01542 peer->options.holdHandling = global_options.holdHandling; 01543 ASTOBJ_UNMARK(peer); 01544 ast_free_ha(oldha); 01545 return peer; 01546 }
static struct oh323_user* build_user | ( | const char * | name, | |
struct ast_variable * | v, | |||
struct ast_variable * | alt, | |||
int | realtime | |||
) | [static] |
Definition at line 1354 of file chan_h323.c.
References ast_append_ha(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, default_context, format, global_options, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_user(), update_common_options(), userl, and ast_variable::value.
Referenced by reload_config(), and set_config().
01355 { 01356 struct oh323_user *user; 01357 struct ast_ha *oldha; 01358 int found = 0; 01359 int format; 01360 01361 user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp); 01362 01363 if (user) 01364 found++; 01365 else { 01366 if (!(user = ast_calloc(1, sizeof(*user)))) 01367 return NULL; 01368 ASTOBJ_INIT(user); 01369 } 01370 oldha = user->ha; 01371 user->ha = (struct ast_ha *)NULL; 01372 memcpy(&user->options, &global_options, sizeof(user->options)); 01373 user->options.dtmfmode = 0; 01374 user->options.holdHandling = 0; 01375 /* Set default context */ 01376 ast_copy_string(user->context, default_context, sizeof(user->context)); 01377 if (user && !found) 01378 ast_copy_string(user->name, name, sizeof(user->name)); 01379 01380 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */ 01381 if (user->chanvars) { 01382 ast_variables_destroy(user->chanvars); 01383 user->chanvars = NULL; 01384 } 01385 #endif 01386 01387 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { 01388 if (!update_common_options(v, &user->options)) 01389 continue; 01390 if (!strcasecmp(v->name, "context")) { 01391 ast_copy_string(user->context, v->value, sizeof(user->context)); 01392 } else if (!strcasecmp(v->name, "secret")) { 01393 ast_copy_string(user->secret, v->value, sizeof(user->secret)); 01394 } else if (!strcasecmp(v->name, "accountcode")) { 01395 ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode)); 01396 } else if (!strcasecmp(v->name, "host")) { 01397 if (!strcasecmp(v->value, "dynamic")) { 01398 ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n"); 01399 ASTOBJ_UNREF(user, oh323_destroy_user); 01400 return NULL; 01401 } else if (ast_get_ip(&user->addr, v->value)) { 01402 ASTOBJ_UNREF(user, oh323_destroy_user); 01403 return NULL; 01404 } 01405 /* Let us know we need to use ip authentication */ 01406 user->host = 1; 01407 } else if (!strcasecmp(v->name, "amaflags")) { 01408 format = ast_cdr_amaflags2int(v->value); 01409 if (format < 0) { 01410 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 01411 } else { 01412 user->amaflags = format; 01413 } 01414 } else if (!strcasecmp(v->name, "permit") || 01415 !strcasecmp(v->name, "deny")) { 01416 int ha_error = 0; 01417 01418 user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error); 01419 if (ha_error) 01420 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 01421 } 01422 } 01423 if (!user->options.dtmfmode) 01424 user->options.dtmfmode = global_options.dtmfmode; 01425 if (user->options.holdHandling == ~0) 01426 user->options.holdHandling = 0; 01427 else if (!user->options.holdHandling) 01428 user->options.holdHandling = global_options.holdHandling; 01429 ASTOBJ_UNMARK(user); 01430 ast_free_ha(oldha); 01431 return user; 01432 }
static void chan_ringing | ( | unsigned | call_reference, | |
const char * | token | |||
) | [static] |
Call-back function to signal asterisk that the channel is ringing Returns nothing.
Definition at line 2314 of file chan_h323.c.
References AST_CONTROL_RINGING, ast_debug, ast_log(), ast_mutex_unlock(), AST_STATE_RINGING, find_call_locked(), h323debug, oh323_pvt::lock, LOG_ERROR, oh323_pvt::owner, and update_state().
Referenced by load_module().
02315 { 02316 struct oh323_pvt *pvt; 02317 02318 if (h323debug) 02319 ast_debug(1, "Ringing on %s\n", token); 02320 02321 pvt = find_call_locked(call_reference, token); 02322 if (!pvt) { 02323 ast_log(LOG_ERROR, "Something is wrong: ringing\n"); 02324 return; 02325 } 02326 if (!pvt->owner) { 02327 ast_mutex_unlock(&pvt->lock); 02328 ast_log(LOG_ERROR, "Channel has no owner\n"); 02329 return; 02330 } 02331 update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING); 02332 ast_mutex_unlock(&pvt->lock); 02333 return; 02334 }
static void cleanup_call_details | ( | call_details_t * | cd | ) | [static] |
Definition at line 404 of file chan_h323.c.
References ast_free.
Referenced by __oh323_destroy(), cleanup_connection(), setup_incoming_call(), and setup_outgoing_call().
00405 { 00406 if (cd->call_token) { 00407 ast_free(cd->call_token); 00408 cd->call_token = NULL; 00409 } 00410 if (cd->call_source_aliases) { 00411 ast_free(cd->call_source_aliases); 00412 cd->call_source_aliases = NULL; 00413 } 00414 if (cd->call_dest_alias) { 00415 ast_free(cd->call_dest_alias); 00416 cd->call_dest_alias = NULL; 00417 } 00418 if (cd->call_source_name) { 00419 ast_free(cd->call_source_name); 00420 cd->call_source_name = NULL; 00421 } 00422 if (cd->call_source_e164) { 00423 ast_free(cd->call_source_e164); 00424 cd->call_source_e164 = NULL; 00425 } 00426 if (cd->call_dest_e164) { 00427 ast_free(cd->call_dest_e164); 00428 cd->call_dest_e164 = NULL; 00429 } 00430 if (cd->sourceIp) { 00431 ast_free(cd->sourceIp); 00432 cd->sourceIp = NULL; 00433 } 00434 if (cd->redirect_number) { 00435 ast_free(cd->redirect_number); 00436 cd->redirect_number = NULL; 00437 } 00438 }
static void cleanup_connection | ( | unsigned | call_reference, | |
const char * | call_token | |||
) | [static] |
Call-back function to cleanup communication Returns nothing,.
Definition at line 2340 of file chan_h323.c.
References ast_channel::_softhangup, oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_dsp_free(), ast_log(), ast_mutex_unlock(), ast_queue_hangup(), ast_rtp_destroy(), AST_SOFTHANGUP_DEV, oh323_pvt::cd, cleanup_call_details(), find_call_locked(), h323debug, oh323_pvt::lock, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.
Referenced by load_module().
02341 { 02342 struct oh323_pvt *pvt; 02343 02344 if (h323debug) 02345 ast_debug(1, "Cleaning connection to %s\n", call_token); 02346 02347 while (1) { 02348 pvt = find_call_locked(call_reference, call_token); 02349 if (!pvt) { 02350 if (h323debug) 02351 ast_debug(1, "No connection for %s\n", call_token); 02352 return; 02353 } 02354 if (!pvt->owner || !ast_channel_trylock(pvt->owner)) 02355 break; 02356 #if 1 02357 ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token); 02358 #ifdef DEBUG_THREADS 02359 /* XXX to be completed 02360 * If we want to print more info on who is holding the lock, 02361 * implement the relevant code in lock.h and use the routines 02362 * supplied there. 02363 */ 02364 #endif 02365 #endif 02366 ast_mutex_unlock(&pvt->lock); 02367 usleep(1); 02368 } 02369 if (pvt->rtp) { 02370 /* Immediately stop RTP */ 02371 ast_rtp_destroy(pvt->rtp); 02372 pvt->rtp = NULL; 02373 } 02374 /* Free dsp used for in-band DTMF detection */ 02375 if (pvt->vad) { 02376 ast_dsp_free(pvt->vad); 02377 pvt->vad = NULL; 02378 } 02379 cleanup_call_details(&pvt->cd); 02380 pvt->alreadygone = 1; 02381 /* Send hangup */ 02382 if (pvt->owner) { 02383 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV; 02384 ast_queue_hangup(pvt->owner); 02385 ast_channel_unlock(pvt->owner); 02386 } 02387 ast_mutex_unlock(&pvt->lock); 02388 if (h323debug) 02389 ast_debug(1, "Connection to %s cleaned\n", call_token); 02390 return; 02391 }
static void connection_made | ( | unsigned | call_reference, | |
const char * | token | |||
) | [static] |
Call-back function to signal asterisk that the channel has been answered Returns nothing.
Definition at line 2048 of file chan_h323.c.
References AST_CONTROL_ANSWER, ast_debug, ast_log(), ast_mutex_unlock(), oh323_pvt::connection_established, find_call_locked(), h323debug, oh323_pvt::lock, LOG_ERROR, oh323_pvt::outgoing, and update_state().
Referenced by load_module().
02049 { 02050 struct oh323_pvt *pvt; 02051 02052 if (h323debug) 02053 ast_debug(1, "Call %s answered\n", token); 02054 02055 pvt = find_call_locked(call_reference, token); 02056 if (!pvt) { 02057 ast_log(LOG_ERROR, "Something is wrong: connection\n"); 02058 return; 02059 } 02060 02061 /* Inform asterisk about remote party connected only on outgoing calls */ 02062 if (!pvt->outgoing) { 02063 ast_mutex_unlock(&pvt->lock); 02064 return; 02065 } 02066 /* Do not send ANSWER message more than once */ 02067 if (!pvt->connection_established) { 02068 pvt->connection_established = 1; 02069 update_state(pvt, -1, AST_CONTROL_ANSWER); 02070 } 02071 ast_mutex_unlock(&pvt->lock); 02072 return; 02073 }
static char* convertcap | ( | int | cap | ) | [static] |
Definition at line 3132 of file chan_h323.c.
References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_ILBC, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, ast_log(), and LOG_NOTICE.
Referenced by oh323_set_rtp_peer().
03133 { 03134 switch (cap) { 03135 case AST_FORMAT_G723_1: 03136 return "G.723"; 03137 case AST_FORMAT_GSM: 03138 return "GSM"; 03139 case AST_FORMAT_ULAW: 03140 return "ULAW"; 03141 case AST_FORMAT_ALAW: 03142 return "ALAW"; 03143 case AST_FORMAT_G722: 03144 return "G.722"; 03145 case AST_FORMAT_ADPCM: 03146 return "G.728"; 03147 case AST_FORMAT_G729A: 03148 return "G.729"; 03149 case AST_FORMAT_SPEEX: 03150 return "SPEEX"; 03151 case AST_FORMAT_ILBC: 03152 return "ILBC"; 03153 default: 03154 ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap); 03155 return NULL; 03156 } 03157 }
static int create_addr | ( | struct oh323_pvt * | pvt, | |
char * | opeer | |||
) | [static] |
Definition at line 1644 of file chan_h323.c.
References ahp, ast_copy_string(), ast_gethostbyname(), ast_log(), AST_RTP_DTMF, ASTOBJ_UNREF, find_peer(), global_options, h323_signalling_port, hp, oh323_pvt::jointcapability, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_destroy_peer(), oh323_pvt::options, and oh323_pvt::sa.
Referenced by cache_get_callno_locked(), handle_request_invite(), iax2_call(), iax2_provision(), iax2_request(), manager_sipnotify(), oh323_request(), sip_cli_notify(), sip_request_call(), and transmit_register().
01645 { 01646 struct hostent *hp; 01647 struct ast_hostent ahp; 01648 struct oh323_peer *p; 01649 int portno; 01650 int found = 0; 01651 char *port; 01652 char *hostn; 01653 char peer[256] = ""; 01654 01655 ast_copy_string(peer, opeer, sizeof(peer)); 01656 port = strchr(peer, ':'); 01657 if (port) { 01658 *port = '\0'; 01659 port++; 01660 } 01661 pvt->sa.sin_family = AF_INET; 01662 p = find_peer(peer, NULL, 1); 01663 if (p) { 01664 found++; 01665 memcpy(&pvt->options, &p->options, sizeof(pvt->options)); 01666 pvt->jointcapability = pvt->options.capability; 01667 if (pvt->options.dtmfmode) { 01668 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { 01669 pvt->nonCodecCapability |= AST_RTP_DTMF; 01670 } else { 01671 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01672 } 01673 } 01674 if (p->addr.sin_addr.s_addr) { 01675 pvt->sa.sin_addr = p->addr.sin_addr; 01676 pvt->sa.sin_port = p->addr.sin_port; 01677 } 01678 ASTOBJ_UNREF(p, oh323_destroy_peer); 01679 } 01680 if (!p && !found) { 01681 hostn = peer; 01682 if (port) { 01683 portno = atoi(port); 01684 } else { 01685 portno = h323_signalling_port; 01686 } 01687 hp = ast_gethostbyname(hostn, &ahp); 01688 if (hp) { 01689 memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr)); 01690 pvt->sa.sin_port = htons(portno); 01691 /* Look peer by address */ 01692 p = find_peer(NULL, &pvt->sa, 1); 01693 memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options)); 01694 pvt->jointcapability = pvt->options.capability; 01695 if (p) { 01696 ASTOBJ_UNREF(p, oh323_destroy_peer); 01697 } 01698 if (pvt->options.dtmfmode) { 01699 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { 01700 pvt->nonCodecCapability |= AST_RTP_DTMF; 01701 } else { 01702 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01703 } 01704 } 01705 return 0; 01706 } else { 01707 ast_log(LOG_WARNING, "No such host: %s\n", peer); 01708 return -1; 01709 } 01710 } else if (!found) { 01711 return -1; 01712 } else { 01713 return 0; 01714 } 01715 }
static void delete_aliases | ( | void | ) | [static] |
Definition at line 2794 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().
02795 { 02796 int pruned = 0; 02797 02798 /* Delete all aliases */ 02799 ASTOBJ_CONTAINER_WRLOCK(&aliasl); 02800 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do { 02801 ASTOBJ_RDLOCK(iterator); 02802 ASTOBJ_MARK(iterator); 02803 ++pruned; 02804 ASTOBJ_UNLOCK(iterator); 02805 } while (0) ); 02806 if (pruned) { 02807 ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias); 02808 } 02809 ASTOBJ_CONTAINER_UNLOCK(&aliasl); 02810 }
static void delete_users | ( | void | ) | [static] |
Definition at line 2768 of file chan_h323.c.
References ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, oh323_destroy_user(), peerl, and userl.
Referenced by __unload_module(), reload(), reload_config(), set_config_destroy(), and unload_module().
02769 { 02770 int pruned = 0; 02771 02772 /* Delete all users */ 02773 ASTOBJ_CONTAINER_WRLOCK(&userl); 02774 ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do { 02775 ASTOBJ_RDLOCK(iterator); 02776 ASTOBJ_MARK(iterator); 02777 ++pruned; 02778 ASTOBJ_UNLOCK(iterator); 02779 } while (0) ); 02780 if (pruned) { 02781 ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user); 02782 } 02783 ASTOBJ_CONTAINER_UNLOCK(&userl); 02784 02785 ASTOBJ_CONTAINER_WRLOCK(&peerl); 02786 ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do { 02787 ASTOBJ_RDLOCK(iterator); 02788 ASTOBJ_MARK(iterator); 02789 ASTOBJ_UNLOCK(iterator); 02790 } while (0) ); 02791 ASTOBJ_CONTAINER_UNLOCK(&peerl); 02792 }
static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 2518 of file chan_h323.c.
References __oh323_destroy(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_verb, h323_do_reload(), h323_reload_lock, h323_reloading, iflist, iflock, oh323_pvt::lock, oh323_pvt::needdestroy, and oh323_pvt::next.
02519 { 02520 int res; 02521 int reloading; 02522 struct oh323_pvt *oh323 = NULL; 02523 02524 for(;;) { 02525 /* Check for a reload request */ 02526 ast_mutex_lock(&h323_reload_lock); 02527 reloading = h323_reloading; 02528 h323_reloading = 0; 02529 ast_mutex_unlock(&h323_reload_lock); 02530 if (reloading) { 02531 ast_verb(1, "Reloading H.323\n"); 02532 h323_do_reload(); 02533 } 02534 /* Check for interfaces needing to be killed */ 02535 if (!ast_mutex_trylock(&iflock)) { 02536 #if 1 02537 do { 02538 for (oh323 = iflist; oh323; oh323 = oh323->next) { 02539 if (!ast_mutex_trylock(&oh323->lock)) { 02540 if (oh323->needdestroy) { 02541 __oh323_destroy(oh323); 02542 break; 02543 } 02544 ast_mutex_unlock(&oh323->lock); 02545 } 02546 } 02547 } while (/*oh323*/ 0); 02548 #else 02549 restartsearch: 02550 oh323 = iflist; 02551 while(oh323) { 02552 if (!ast_mutex_trylock(&oh323->lock)) { 02553 if (oh323->needdestroy) { 02554 __oh323_destroy(oh323); 02555 goto restartsearch; 02556 } 02557 ast_mutex_unlock(&oh323->lock); 02558 oh323 = oh323->next; 02559 } 02560 } 02561 #endif 02562 ast_mutex_unlock(&iflock); 02563 } else 02564 oh323 = (struct oh323_pvt *)1; /* Force fast loop */ 02565 pthread_testcancel(); 02566 /* Wait for sched or io */ 02567 res = ast_sched_wait(sched); 02568 if ((res < 0) || (res > 1000)) { 02569 res = 1000; 02570 } 02571 /* Do not wait if some channel(s) is destroyed, probably, more available too */ 02572 if (oh323) 02573 res = 1; 02574 res = ast_io_wait(io, res); 02575 pthread_testcancel(); 02576 ast_mutex_lock(&monlock); 02577 if (res >= 0) { 02578 ast_sched_runq(sched); 02579 } 02580 ast_mutex_unlock(&monlock); 02581 } 02582 /* Never reached */ 02583 return NULL; 02584 }
static struct rtp_info* external_rtp_create | ( | unsigned | call_reference, | |
const char * | token | |||
) | [static] |
Callback function used to inform the H.323 stack of the local rtp ip/port details.
Definition at line 1889 of file chan_h323.c.
References __oh323_rtp_create(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_rtp_get_us(), find_call_locked(), h323debug, oh323_pvt::lock, LOG_ERROR, and oh323_pvt::rtp.
Referenced by load_module().
01890 { 01891 struct oh323_pvt *pvt; 01892 struct sockaddr_in us; 01893 struct rtp_info *info; 01894 01895 info = ast_calloc(1, sizeof(*info)); 01896 if (!info) { 01897 ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n"); 01898 return NULL; 01899 } 01900 pvt = find_call_locked(call_reference, token); 01901 if (!pvt) { 01902 ast_free(info); 01903 ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference); 01904 return NULL; 01905 } 01906 if (!pvt->rtp) 01907 __oh323_rtp_create(pvt); 01908 if (!pvt->rtp) { 01909 ast_mutex_unlock(&pvt->lock); 01910 ast_free(info); 01911 ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference); 01912 return NULL; 01913 } 01914 /* figure out our local RTP port and tell the H.323 stack about it */ 01915 ast_rtp_get_us(pvt->rtp, &us); 01916 ast_mutex_unlock(&pvt->lock); 01917 01918 ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr)); 01919 info->port = ntohs(us.sin_port); 01920 if (h323debug) 01921 ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port); 01922 return info; 01923 }
static struct oh323_alias* find_alias | ( | const char * | source_aliases, | |
int | realtime | |||
) | [static] |
Find a call by alias.
Definition at line 1805 of file chan_h323.c.
References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().
Referenced by __get_header(), add_header(), and setup_incoming_call().
01806 { 01807 struct oh323_alias *a; 01808 01809 a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases); 01810 01811 if (!a && realtime) 01812 a = realtime_alias(source_aliases); 01813 01814 return a; 01815 }
static struct oh323_pvt* find_call_locked | ( | int | call_reference, | |
const char * | token | |||
) | [static] |
Definition at line 1140 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().
01141 { 01142 struct oh323_pvt *pvt; 01143 01144 ast_mutex_lock(&iflock); 01145 pvt = iflist; 01146 while(pvt) { 01147 if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) { 01148 /* Found the call */ 01149 if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) { 01150 ast_mutex_lock(&pvt->lock); 01151 ast_mutex_unlock(&iflock); 01152 return pvt; 01153 } else if (token == NULL) { 01154 ast_log(LOG_WARNING, "Call Token is NULL\n"); 01155 ast_mutex_lock(&pvt->lock); 01156 ast_mutex_unlock(&iflock); 01157 return pvt; 01158 } 01159 } 01160 pvt = pvt->next; 01161 } 01162 ast_mutex_unlock(&iflock); 01163 return NULL; 01164 }
static struct oh323_peer* find_peer | ( | const char * | peer, | |
struct sockaddr_in * | sin, | |||
int | realtime | |||
) | [static] |
Definition at line 1626 of file chan_h323.c.
References ast_debug, ast_inet_ntoa(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, h323debug, oh323_addrcmp(), peerl, and realtime_peer().
Referenced by _sip_qualify_peer(), _sip_show_peer(), check_peer_ok(), create_addr(), dundi_encrypt(), function_iaxpeer(), function_sippeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), handle_command_response(), iax2_devicestate(), register_verify(), registry_authrequest(), set_config(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), sip_show_user(), sip_unregister(), st_get_mode(), st_get_refresher(), st_get_se(), update_call_counter(), and update_registry().
01627 { 01628 struct oh323_peer *p; 01629 01630 if (peer) 01631 p = ASTOBJ_CONTAINER_FIND(&peerl, peer); 01632 else 01633 p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp); 01634 01635 if (!p && realtime) 01636 p = realtime_peer(peer, sin); 01637 01638 if (!p && h323debug) 01639 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>")); 01640 01641 return p; 01642 }
static struct oh323_user* find_user | ( | const call_details_t * | cd, | |
int | realtime | |||
) | [static] |
Definition at line 1596 of file chan_h323.c.
References ast_debug, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, h323debug, oh323_addrcmp_str(), realtime_user(), userbyalias, and userl.
Referenced by acf_mailbox_exists(), admin_exec(), advanced_options(), forward_message(), handle_cli_iax2_prune_realtime(), leave_voicemail(), pp_each_extension_exec(), setup_incoming_call(), vm_authenticate(), vm_box_exists(), and vm_execmain().
01597 { 01598 struct oh323_user *u; 01599 01600 if (userbyalias) 01601 u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases); 01602 else 01603 u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str); 01604 01605 if (!u && realtime) 01606 u = realtime_user(cd); 01607 01608 if (!u && h323debug) 01609 ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp); 01610 01611 return u; 01612 }
static int h323_do_reload | ( | void | ) | [static] |
Definition at line 3089 of file chan_h323.c.
References reload_config().
Referenced by do_monitor().
03090 { 03091 reload_config(1); 03092 return 0; 03093 }
static int h323_reload | ( | void | ) | [static] |
Definition at line 3055 of file chan_h323.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose, h323_reload_lock, h323_reloading, and restart_monitor().
Referenced by handle_cli_h323_reload(), and reload().
03056 { 03057 ast_mutex_lock(&h323_reload_lock); 03058 if (h323_reloading) { 03059 ast_verbose("Previous H.323 reload not yet done\n"); 03060 } else { 03061 h323_reloading = 1; 03062 } 03063 ast_mutex_unlock(&h323_reload_lock); 03064 restart_monitor(); 03065 return 0; 03066 }
static char* handle_cli_h323_cycle_gk | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2667 of file chan_h323.c.
References ast_cli_args::argc, ast_log(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, gatekeeper, gatekeeper_disable, gatekeeper_discover, LOG_ERROR, secret, and ast_cli_entry::usage.
02668 { 02669 switch (cmd) { 02670 case CLI_INIT: 02671 e->command = "h323 cycle gk"; 02672 e->usage = 02673 "Usage: h323 cycle gk\n" 02674 " Manually re-register with the Gatekeper (Currently Disabled)\n"; 02675 return NULL; 02676 case CLI_GENERATE: 02677 return NULL; 02678 } 02679 02680 if (a->argc != 3) 02681 return CLI_SHOWUSAGE; 02682 02683 h323_gk_urq(); 02684 02685 /* Possibly register with a GK */ 02686 if (!gatekeeper_disable) { 02687 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { 02688 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); 02689 } 02690 } 02691 return CLI_SUCCESS; 02692 }
static char* handle_cli_h323_hangup | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2694 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.
02695 { 02696 switch (cmd) { 02697 case CLI_INIT: 02698 e->command = "h323 hangup"; 02699 e->usage = 02700 "Usage: h323 hangup <token>\n" 02701 " Manually try to hang up the call identified by <token>\n"; 02702 return NULL; 02703 case CLI_GENERATE: 02704 return NULL; 02705 } 02706 02707 if (a->argc != 3) 02708 return CLI_SHOWUSAGE; 02709 if (h323_soft_hangup(a->argv[2])) { 02710 ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]); 02711 } else { 02712 ast_verb(3, "Hangup failed for %s\n", a->argv[2]); 02713 } 02714 return CLI_SUCCESS; 02715 }
static char* handle_cli_h323_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 3068 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.
03069 { 03070 switch (cmd) { 03071 case CLI_INIT: 03072 e->command = "h323 reload"; 03073 e->usage = 03074 "Usage: h323 reload\n" 03075 " Reloads H.323 configuration from h323.conf\n"; 03076 return NULL; 03077 case CLI_GENERATE: 03078 return NULL; 03079 } 03080 03081 if (a->argc != 2) 03082 return CLI_SHOWUSAGE; 03083 03084 h323_reload(); 03085 03086 return CLI_SUCCESS; 03087 }
static char* handle_cli_h323_set_debug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2644 of file chan_h323.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, h323debug, and ast_cli_entry::usage.
02645 { 02646 switch (cmd) { 02647 case CLI_INIT: 02648 e->command = "h323 set debug [off]"; 02649 e->usage = 02650 "Usage: h323 set debug [off]\n" 02651 " Enable/Disable H.323 debugging output\n"; 02652 return NULL; 02653 case CLI_GENERATE: 02654 return NULL; 02655 } 02656 02657 if (a->argc < 3 || a->argc > 4) 02658 return CLI_SHOWUSAGE; 02659 if (a->argc == 4 && strcasecmp(a->argv[3], "off")) 02660 return CLI_SHOWUSAGE; 02661 02662 h323debug = (a->argc == 3) ? 1 : 0; 02663 ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled"); 02664 return CLI_SUCCESS; 02665 }
static char* handle_cli_h323_set_trace | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2618 of file chan_h323.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02619 { 02620 switch (cmd) { 02621 case CLI_INIT: 02622 e->command = "h323 set trace [off]"; 02623 e->usage = 02624 "Usage: h323 set trace (off|<trace level>)\n" 02625 " Enable/Disable H.323 stack tracing for debugging purposes\n"; 02626 return NULL; 02627 case CLI_GENERATE: 02628 return NULL; 02629 } 02630 02631 if (a->argc != 4) 02632 return CLI_SHOWUSAGE; 02633 if (!strcasecmp(a->argv[3], "off")) { 02634 h323_debug(0, 0); 02635 ast_cli(a->fd, "H.323 Trace Disabled\n"); 02636 } else { 02637 int tracelevel = atoi(a->argv[3]); 02638 h323_debug(1, tracelevel); 02639 ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel); 02640 } 02641 return CLI_SUCCESS; 02642 }
static char* handle_cli_h323_show_tokens | ( | 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, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, and ast_cli_entry::usage.
02718 { 02719 switch (cmd) { 02720 case CLI_INIT: 02721 e->command = "h323 show tokens"; 02722 e->usage = 02723 "Usage: h323 show tokens\n" 02724 " Print out all active call tokens\n"; 02725 return NULL; 02726 case CLI_GENERATE: 02727 return NULL; 02728 } 02729 02730 if (a->argc != 3) 02731 return CLI_SHOWUSAGE; 02732 02733 h323_show_tokens(); 02734 02735 return CLI_SUCCESS; 02736 }
static char* handle_cli_h323_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2738 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.
02739 { 02740 switch (cmd) { 02741 case CLI_INIT: 02742 e->command = "h323 show version"; 02743 e->usage = 02744 "Usage: h323 show version\n" 02745 " Show the version of the H.323 library in use\n"; 02746 return NULL; 02747 case CLI_GENERATE: 02748 return NULL; 02749 } 02750 02751 if (a->argc != 3) 02752 return CLI_SHOWUSAGE; 02753 02754 h323_show_version(); 02755 02756 return CLI_SUCCESS; 02757 }
static void hangup_connection | ( | unsigned int | call_reference, | |
const char * | token, | |||
int | cause | |||
) | [static] |
Definition at line 2393 of file chan_h323.c.
References ast_channel::_softhangup, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_mutex_unlock(), ast_queue_hangup_with_cause(), AST_SOFTHANGUP_DEV, find_call_locked(), h323debug, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, oh323_pvt::needhangup, and oh323_pvt::owner.
Referenced by load_module().
02394 { 02395 struct oh323_pvt *pvt; 02396 02397 if (h323debug) 02398 ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause); 02399 02400 pvt = find_call_locked(call_reference, token); 02401 if (!pvt) { 02402 if (h323debug) 02403 ast_debug(1, "Connection to %s already cleared\n", token); 02404 return; 02405 } 02406 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 02407 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV; 02408 pvt->owner->hangupcause = pvt->hangupcause = cause; 02409 ast_queue_hangup_with_cause(pvt->owner, cause); 02410 ast_channel_unlock(pvt->owner); 02411 } 02412 else { 02413 pvt->needhangup = 1; 02414 pvt->hangupcause = cause; 02415 if (h323debug) 02416 ast_debug(1, "Hangup for %s is pending\n", token); 02417 } 02418 ast_mutex_unlock(&pvt->lock); 02419 }
static enum ast_module_load_result load_module | ( | void | ) | [static] |
Definition at line 3192 of file chan_h323.c.
References aliasl, answer_call(), ast_channel_register(), ast_cli_register(), ast_cli_register_multiple(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), ast_rtp_proto_unregister(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, chan_ringing(), cleanup_connection(), cli_h323, cli_h323_reload, connection_made(), external_rtp_create(), gatekeeper, gatekeeper_disable, gatekeeper_discover, h323_signalling_port, h323debug, hangup_connection(), io, io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), sched_context_create(), sched_context_destroy(), secret, set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.
03193 { 03194 int res; 03195 03196 h323debug = 0; 03197 sched = sched_context_create(); 03198 if (!sched) { 03199 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 03200 return AST_MODULE_LOAD_FAILURE; 03201 } 03202 io = io_context_create(); 03203 if (!io) { 03204 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 03205 return AST_MODULE_LOAD_FAILURE; 03206 } 03207 ast_cli_register(&cli_h323_reload); 03208 ASTOBJ_CONTAINER_INIT(&userl); 03209 ASTOBJ_CONTAINER_INIT(&peerl); 03210 ASTOBJ_CONTAINER_INIT(&aliasl); 03211 res = reload_config(0); 03212 if (res) { 03213 /* No config entry */ 03214 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n"); 03215 ast_cli_unregister(&cli_h323_reload); 03216 io_context_destroy(io); 03217 io = NULL; 03218 sched_context_destroy(sched); 03219 sched = NULL; 03220 ASTOBJ_CONTAINER_DESTROY(&userl); 03221 ASTOBJ_CONTAINER_DESTROY(&peerl); 03222 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03223 return AST_MODULE_LOAD_DECLINE; 03224 } else { 03225 /* Make sure we can register our channel type */ 03226 if (ast_channel_register(&oh323_tech)) { 03227 ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n"); 03228 ast_cli_unregister(&cli_h323_reload); 03229 h323_end_process(); 03230 io_context_destroy(io); 03231 sched_context_destroy(sched); 03232 03233 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user); 03234 ASTOBJ_CONTAINER_DESTROY(&userl); 03235 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer); 03236 ASTOBJ_CONTAINER_DESTROY(&peerl); 03237 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias); 03238 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03239 03240 return AST_MODULE_LOAD_FAILURE; 03241 } 03242 ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry)); 03243 03244 ast_rtp_proto_register(&oh323_rtp); 03245 03246 /* Register our callback functions */ 03247 h323_callback_register(setup_incoming_call, 03248 setup_outgoing_call, 03249 external_rtp_create, 03250 setup_rtp_connection, 03251 cleanup_connection, 03252 chan_ringing, 03253 connection_made, 03254 receive_digit, 03255 answer_call, 03256 progress, 03257 set_dtmf_payload, 03258 hangup_connection, 03259 set_local_capabilities, 03260 set_peer_capabilities, 03261 remote_hold); 03262 /* start the h.323 listener */ 03263 if (h323_start_listener(h323_signalling_port, bindaddr)) { 03264 ast_log(LOG_ERROR, "Unable to create H323 listener.\n"); 03265 ast_rtp_proto_unregister(&oh323_rtp); 03266 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry)); 03267 ast_cli_unregister(&cli_h323_reload); 03268 h323_end_process(); 03269 io_context_destroy(io); 03270 sched_context_destroy(sched); 03271 03272 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user); 03273 ASTOBJ_CONTAINER_DESTROY(&userl); 03274 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer); 03275 ASTOBJ_CONTAINER_DESTROY(&peerl); 03276 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias); 03277 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03278 03279 return AST_MODULE_LOAD_FAILURE; 03280 } 03281 /* Possibly register with a GK */ 03282 if (!gatekeeper_disable) { 03283 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { 03284 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); 03285 gatekeeper_disable = 1; 03286 res = AST_MODULE_LOAD_SUCCESS; 03287 } 03288 } 03289 /* And start the monitor for the first time */ 03290 restart_monitor(); 03291 } 03292 return res; 03293 }
static int oh323_addrcmp | ( | struct sockaddr_in | addr, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 1614 of file chan_h323.c.
References inaddrcmp().
Referenced by find_peer().
01615 { 01616 int res; 01617 01618 if (!sin) 01619 res = -1; 01620 else 01621 res = inaddrcmp(&addr , sin); 01622 01623 return res; 01624 }
static int oh323_addrcmp_str | ( | struct in_addr | inaddr, | |
char * | addr | |||
) | [static] |
Definition at line 1591 of file chan_h323.c.
References ast_inet_ntoa().
Referenced by find_user().
01592 { 01593 return strcmp(ast_inet_ntoa(inaddr), addr); 01594 }
static struct oh323_pvt* oh323_alloc | ( | int | callid | ) | [static] |
Definition at line 1097 of file chan_h323.c.
References ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), AST_RTP_DTMF, iflist, iflock, and LOG_ERROR.
Referenced by oh323_request(), and setup_incoming_call().
01098 { 01099 struct oh323_pvt *pvt; 01100 01101 pvt = ast_calloc(1, sizeof(*pvt)); 01102 if (!pvt) { 01103 ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n"); 01104 return NULL; 01105 } 01106 pvt->cd.redirect_reason = -1; 01107 pvt->cd.transfer_capability = -1; 01108 /* Ensure the call token is allocated for outgoing call */ 01109 if (!callid) { 01110 if ((pvt->cd).call_token == NULL) { 01111 (pvt->cd).call_token = ast_calloc(1, 128); 01112 } 01113 if (!pvt->cd.call_token) { 01114 ast_log(LOG_ERROR, "Not enough memory to alocate call token\n"); 01115 ast_rtp_destroy(pvt->rtp); 01116 ast_free(pvt); 01117 return NULL; 01118 } 01119 memset((char *)(pvt->cd).call_token, 0, 128); 01120 pvt->cd.call_reference = callid; 01121 } 01122 memcpy(&pvt->options, &global_options, sizeof(pvt->options)); 01123 pvt->jointcapability = pvt->options.capability; 01124 if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) { 01125 pvt->nonCodecCapability |= AST_RTP_DTMF; 01126 } else { 01127 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01128 } 01129 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 01130 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1; 01131 ast_mutex_init(&pvt->lock); 01132 /* Add to interface list */ 01133 ast_mutex_lock(&iflock); 01134 pvt->next = iflist; 01135 iflist = pvt; 01136 ast_mutex_unlock(&iflock); 01137 return pvt; 01138 }
static int oh323_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 654 of file chan_h323.c.
References ast_channel::_state, ast_debug, ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::lock, ast_channel::name, oh323_update_info(), and ast_channel::tech_pvt.
00655 { 00656 int res; 00657 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00658 char *token; 00659 00660 if (h323debug) 00661 ast_debug(1, "Answering on %s\n", c->name); 00662 00663 ast_mutex_lock(&pvt->lock); 00664 token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL; 00665 ast_mutex_unlock(&pvt->lock); 00666 res = h323_answering_call(token, 0); 00667 if (token) 00668 ast_free(token); 00669 00670 oh323_update_info(c); 00671 if (c->_state != AST_STATE_UP) { 00672 ast_setstate(c, AST_STATE_UP); 00673 } 00674 return res; 00675 }
static int oh323_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Make a call over the specified channel to the specified destination. Returns -1 on error, 0 on success.
Definition at line 576 of file chan_h323.c.
References ast_channel::_state, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, AST_STATE_RESERVED, ast_strlen_zero(), ast_transfercapability2str(), ast_verb, oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, oh323_pvt::exten, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::outgoing, pbx_builtin_getvar_helper(), oh323_pvt::sa, ast_channel::tech_pvt, and ast_channel::transfercapability.
00577 { 00578 int res = 0; 00579 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt; 00580 const char *addr; 00581 char called_addr[1024]; 00582 00583 if (h323debug) { 00584 ast_debug(1, "Calling to %s on %s\n", dest, c->name); 00585 } 00586 if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) { 00587 ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name); 00588 return -1; 00589 } 00590 ast_mutex_lock(&pvt->lock); 00591 if (!gatekeeper_disable) { 00592 if (ast_strlen_zero(pvt->exten)) { 00593 ast_copy_string(called_addr, dest, sizeof(called_addr)); 00594 } else { 00595 snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest); 00596 } 00597 } else { 00598 res = htons(pvt->sa.sin_port); 00599 addr = ast_inet_ntoa(pvt->sa.sin_addr); 00600 if (ast_strlen_zero(pvt->exten)) { 00601 snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res); 00602 } else { 00603 snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res); 00604 } 00605 } 00606 /* make sure null terminated */ 00607 called_addr[sizeof(called_addr) - 1] = '\0'; 00608 00609 if (c->cid.cid_num) 00610 ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num)); 00611 00612 if (c->cid.cid_name) 00613 ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name)); 00614 00615 if (c->cid.cid_rdnis) { 00616 ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis)); 00617 } 00618 00619 pvt->options.presentation = c->cid.cid_pres; 00620 pvt->options.type_of_number = c->cid.cid_ton; 00621 00622 if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) { 00623 if (!strcasecmp(addr, "UNKNOWN")) 00624 pvt->options.redirect_reason = 0; 00625 else if (!strcasecmp(addr, "BUSY")) 00626 pvt->options.redirect_reason = 1; 00627 else if (!strcasecmp(addr, "NO_REPLY")) 00628 pvt->options.redirect_reason = 2; 00629 else if (!strcasecmp(addr, "UNCONDITIONAL")) 00630 pvt->options.redirect_reason = 15; 00631 else 00632 pvt->options.redirect_reason = -1; 00633 } else 00634 pvt->options.redirect_reason = -1; 00635 00636 pvt->options.transfer_capability = c->transfercapability; 00637 00638 /* indicate that this is an outgoing call */ 00639 pvt->outgoing = 1; 00640 00641 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability)); 00642 if (h323debug) 00643 ast_debug(1, "Placing outgoing call to %s, %d/%d\n", called_addr, pvt->options.dtmfcodec[0], pvt->options.dtmfcodec[1]); 00644 ast_mutex_unlock(&pvt->lock); 00645 res = h323_make_call(called_addr, &(pvt->cd), &pvt->options); 00646 if (res) { 00647 ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name); 00648 return -1; 00649 } 00650 oh323_update_info(c); 00651 return 0; 00652 }
static void oh323_destroy | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 485 of file chan_h323.c.
References __oh323_destroy(), ast_debug, ast_mutex_lock(), ast_mutex_unlock(), iflock, oh323_pvt::lock, ast_channel::name, and oh323_pvt::owner.
Referenced by oh323_request(), and setup_incoming_call().
00486 { 00487 if (h323debug) { 00488 ast_debug(1, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>")); 00489 } 00490 ast_mutex_lock(&iflock); 00491 ast_mutex_lock(&pvt->lock); 00492 __oh323_destroy(pvt); 00493 ast_mutex_unlock(&iflock); 00494 }
static void oh323_destroy_alias | ( | struct oh323_alias * | alias | ) | [static] |
Definition at line 276 of file chan_h323.c.
References ast_debug, and ast_free.
Referenced by delete_aliases(), load_module(), and unload_module().
00277 { 00278 if (h323debug) 00279 ast_debug(1, "Destroying alias '%s'\n", alias->name); 00280 ast_free(alias); 00281 }
static void oh323_destroy_peer | ( | struct oh323_peer * | peer | ) | [static] |
Definition at line 291 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().
00292 { 00293 if (h323debug) 00294 ast_debug(1, "Destroying peer '%s'\n", peer->name); 00295 ast_free_ha(peer->ha); 00296 ast_free(peer); 00297 }
static void oh323_destroy_user | ( | struct oh323_user * | user | ) | [static] |
Definition at line 283 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().
00284 { 00285 if (h323debug) 00286 ast_debug(1, "Destroying user '%s'\n", user->name); 00287 ast_free_ha(user->ha); 00288 ast_free(user); 00289 }
static int oh323_digit_begin | ( | struct ast_channel * | c, | |
char | digit | |||
) | [static] |
Definition at line 496 of file chan_h323.c.
References ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_begin(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.
00497 { 00498 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00499 char *token; 00500 00501 if (!pvt) { 00502 ast_log(LOG_ERROR, "No private structure?! This is bad\n"); 00503 return -1; 00504 } 00505 ast_mutex_lock(&pvt->lock); 00506 if (pvt->rtp && 00507 (((pvt->options.dtmfmode & H323_DTMF_RFC2833) && pvt->dtmf_pt[0]) 00508 /*|| ((pvt->options.dtmfmode & H323_DTMF_CISCO) && pvt->dtmf_pt[1]))*/)) { 00509 /* out-of-band DTMF */ 00510 if (h323debug) { 00511 ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name); 00512 } 00513 ast_rtp_senddigit_begin(pvt->rtp, digit); 00514 ast_mutex_unlock(&pvt->lock); 00515 } else if (pvt->txDtmfDigit != digit) { 00516 /* in-band DTMF */ 00517 if (h323debug) { 00518 ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, c->name); 00519 } 00520 pvt->txDtmfDigit = digit; 00521 token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL; 00522 ast_mutex_unlock(&pvt->lock); 00523 h323_send_tone(token, digit); 00524 if (token) { 00525 ast_free(token); 00526 } 00527 } else 00528 ast_mutex_unlock(&pvt->lock); 00529 oh323_update_info(c); 00530 return 0; 00531 }
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 537 of file chan_h323.c.
References ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_senddigit_end(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.
00538 { 00539 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00540 char *token; 00541 00542 if (!pvt) { 00543 ast_log(LOG_ERROR, "No private structure?! This is bad\n"); 00544 return -1; 00545 } 00546 ast_mutex_lock(&pvt->lock); 00547 if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && ((pvt->dtmf_pt[0] > 0) || (pvt->dtmf_pt[0] > 0))) { 00548 /* out-of-band DTMF */ 00549 if (h323debug) { 00550 ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration); 00551 } 00552 ast_rtp_senddigit_end(pvt->rtp, digit); 00553 ast_mutex_unlock(&pvt->lock); 00554 } else { 00555 /* in-band DTMF */ 00556 if (h323debug) { 00557 ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, c->name, duration); 00558 } 00559 pvt->txDtmfDigit = ' '; 00560 token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL; 00561 ast_mutex_unlock(&pvt->lock); 00562 h323_send_tone(token, ' '); 00563 if (token) { 00564 ast_free(token); 00565 } 00566 } 00567 oh323_update_info(c); 00568 return 0; 00569 }
static int oh323_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 933 of file chan_h323.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::lock, LOG_WARNING, oh323_pvt::owner, and ast_channel::tech_pvt.
00934 { 00935 struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt; 00936 00937 ast_mutex_lock(&pvt->lock); 00938 if (pvt->owner != oldchan) { 00939 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner); 00940 return -1; 00941 } 00942 pvt->owner = newchan; 00943 ast_mutex_unlock(&pvt->lock); 00944 return 0; 00945 }
static enum ast_rtp_get_result oh323_get_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp ** | rtp | |||
) | [static] |
Definition at line 3107 of file chan_h323.c.
References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, chan, oh323_pvt::lock, oh323_pvt::options, oh323_pvt::rtp, and ast_channel::tech_pvt.
03108 { 03109 struct oh323_pvt *pvt; 03110 enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL; 03111 03112 if (!(pvt = (struct oh323_pvt *)chan->tech_pvt)) 03113 return AST_RTP_GET_FAILED; 03114 03115 ast_mutex_lock(&pvt->lock); 03116 *rtp = pvt->rtp; 03117 #if 0 03118 if (pvt->options.bridge) { 03119 res = AST_RTP_TRY_NATIVE; 03120 } 03121 #endif 03122 ast_mutex_unlock(&pvt->lock); 03123 03124 return res; 03125 }
static enum ast_rtp_get_result oh323_get_vrtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp ** | rtp | |||
) | [static] |
Definition at line 3127 of file chan_h323.c.
References AST_RTP_GET_FAILED.
03128 { 03129 return AST_RTP_GET_FAILED; 03130 }
static int oh323_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 677 of file chan_h323.c.
References oh323_pvt::alreadygone, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_REQUESTED_CHAN_UNAVAIL, AST_CAUSE_USER_BUSY, ast_debug, ast_free, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, oh323_pvt::cd, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.
00678 { 00679 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00680 int q931cause = AST_CAUSE_NORMAL_CLEARING; 00681 char *call_token; 00682 00683 00684 if (h323debug) 00685 ast_debug(1, "Hanging up and scheduling destroy of call %s\n", c->name); 00686 00687 if (!c->tech_pvt) { 00688 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 00689 return 0; 00690 } 00691 ast_mutex_lock(&pvt->lock); 00692 /* Determine how to disconnect */ 00693 if (pvt->owner != c) { 00694 ast_log(LOG_WARNING, "Huh? We aren't the owner?\n"); 00695 ast_mutex_unlock(&pvt->lock); 00696 return 0; 00697 } 00698 00699 pvt->owner = NULL; 00700 c->tech_pvt = NULL; 00701 00702 if (c->hangupcause) { 00703 q931cause = c->hangupcause; 00704 } else { 00705 const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 00706 if (cause) { 00707 if (!strcmp(cause, "CONGESTION")) { 00708 q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION; 00709 } else if (!strcmp(cause, "BUSY")) { 00710 q931cause = AST_CAUSE_USER_BUSY; 00711 } else if (!strcmp(cause, "CHANISUNVAIL")) { 00712 q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL; 00713 } else if (!strcmp(cause, "NOANSWER")) { 00714 q931cause = AST_CAUSE_NO_ANSWER; 00715 } else if (!strcmp(cause, "CANCEL")) { 00716 q931cause = AST_CAUSE_CALL_REJECTED; 00717 } 00718 } 00719 } 00720 00721 /* Start the process if it's not already started */ 00722 if (!pvt->alreadygone && !pvt->hangupcause) { 00723 call_token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL; 00724 if (call_token) { 00725 /* Release lock to eliminate deadlock */ 00726 ast_mutex_unlock(&pvt->lock); 00727 if (h323_clear_call(call_token, q931cause)) { 00728 ast_log(LOG_WARNING, "ClearCall failed.\n"); 00729 } 00730 ast_free(call_token); 00731 ast_mutex_lock(&pvt->lock); 00732 } 00733 } 00734 pvt->needdestroy = 1; 00735 ast_mutex_unlock(&pvt->lock); 00736 00737 /* Update usage counter */ 00738 ast_module_unref(ast_module_info->self); 00739 00740 return 0; 00741 }
static int oh323_indicate | ( | struct ast_channel * | c, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 852 of file chan_h323.c.
References ast_channel::_state, oh323_pvt::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_free, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::got_progress, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_update_info(), oh323_pvt::rtp, and ast_channel::tech_pvt.
00853 { 00854 00855 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00856 char *token = (char *)NULL; 00857 int res = -1; 00858 int got_progress; 00859 00860 ast_mutex_lock(&pvt->lock); 00861 token = (pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL); 00862 got_progress = pvt->got_progress; 00863 if (condition == AST_CONTROL_PROGRESS) 00864 pvt->got_progress = 1; 00865 else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION)) 00866 pvt->alreadygone = 1; 00867 ast_mutex_unlock(&pvt->lock); 00868 00869 if (h323debug) 00870 ast_debug(1, "OH323: Indicating %d on %s (%s)\n", condition, token, c->name); 00871 00872 switch(condition) { 00873 case AST_CONTROL_RINGING: 00874 if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) { 00875 h323_send_alerting(token); 00876 res = (got_progress ? 0 : -1); /* Do not simulate any audio tones if we got PROGRESS message */ 00877 } 00878 break; 00879 case AST_CONTROL_PROGRESS: 00880 if (c->_state != AST_STATE_UP) { 00881 /* Do not send PROGRESS message more than once */ 00882 if (!got_progress) 00883 h323_send_progress(token); 00884 res = 0; 00885 } 00886 break; 00887 case AST_CONTROL_BUSY: 00888 if (c->_state != AST_STATE_UP) { 00889 h323_answering_call(token, 1); 00890 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV); 00891 res = 0; 00892 } 00893 break; 00894 case AST_CONTROL_CONGESTION: 00895 if (c->_state != AST_STATE_UP) { 00896 h323_answering_call(token, 1); 00897 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV); 00898 res = 0; 00899 } 00900 break; 00901 case AST_CONTROL_HOLD: 00902 h323_hold_call(token, 1); 00903 /* We should start MOH only if remote party isn't provide audio for us */ 00904 ast_moh_start(c, data, NULL); 00905 res = 0; 00906 break; 00907 case AST_CONTROL_UNHOLD: 00908 h323_hold_call(token, 0); 00909 ast_moh_stop(c); 00910 res = 0; 00911 break; 00912 case AST_CONTROL_SRCUPDATE: 00913 ast_rtp_new_source(pvt->rtp); 00914 res = 0; 00915 break; 00916 case AST_CONTROL_PROCEEDING: 00917 case -1: 00918 break; 00919 default: 00920 ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token); 00921 break; 00922 } 00923 00924 if (h323debug) 00925 ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res); 00926 if (token) 00927 ast_free(token); 00928 oh323_update_info(c); 00929 00930 return res; 00931 }
static struct ast_frame * oh323_read | ( | struct ast_channel * | c | ) | [static] |
Definition at line 799 of file chan_h323.c.
References __oh323_update_info(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_rtcp_read(), ast_channel::fdno, oh323_pvt::lock, LOG_ERROR, ast_channel::name, oh323_rtp_read(), oh323_pvt::rtp, and ast_channel::tech_pvt.
00800 { 00801 struct ast_frame *fr; 00802 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt; 00803 ast_mutex_lock(&pvt->lock); 00804 __oh323_update_info(c, pvt); 00805 switch(c->fdno) { 00806 case 0: 00807 fr = oh323_rtp_read(pvt); 00808 break; 00809 case 1: 00810 if (pvt->rtp) 00811 fr = ast_rtcp_read(pvt->rtp); 00812 else 00813 fr = &ast_null_frame; 00814 break; 00815 default: 00816 ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name); 00817 fr = &ast_null_frame; 00818 break; 00819 } 00820 ast_mutex_unlock(&pvt->lock); 00821 return fr; 00822 }
static struct ast_channel * oh323_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 1716 of file chan_h323.c.
References __oh323_new(), AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_INCOMPATIBLE_DESTINATION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, ast_copy_string(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_DTMF, AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), caplock, create_addr(), ext, oh323_pvt::exten, gatekeeper_disable, global_options, h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, restart_monitor(), and unique.
01717 { 01718 int oldformat; 01719 struct oh323_pvt *pvt; 01720 struct ast_channel *tmpc = NULL; 01721 char *dest = (char *)data; 01722 char *ext, *host; 01723 char *h323id = NULL; 01724 char tmp[256], tmp1[256]; 01725 01726 if (h323debug) 01727 ast_debug(1, "type=%s, format=%d, data=%s.\n", type, format, (char *)data); 01728 01729 pvt = oh323_alloc(0); 01730 if (!pvt) { 01731 ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data); 01732 return NULL; 01733 } 01734 oldformat = format; 01735 format &= AST_FORMAT_AUDIO_MASK; 01736 if (!format) { 01737 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format); 01738 oh323_destroy(pvt); 01739 if (cause) 01740 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION; 01741 return NULL; 01742 } 01743 ast_copy_string(tmp, dest, sizeof(tmp)); 01744 host = strchr(tmp, '@'); 01745 if (host) { 01746 *host = '\0'; 01747 host++; 01748 ext = tmp; 01749 } else { 01750 ext = strrchr(tmp, '/'); 01751 if (ext) 01752 *ext++ = '\0'; 01753 host = tmp; 01754 } 01755 strtok_r(host, "/", &(h323id)); 01756 if (!ast_strlen_zero(h323id)) { 01757 h323_set_id(h323id); 01758 } 01759 if (ext) { 01760 ast_copy_string(pvt->exten, ext, sizeof(pvt->exten)); 01761 } 01762 if (h323debug) 01763 ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host); 01764 01765 if (gatekeeper_disable) { 01766 if (create_addr(pvt, host)) { 01767 oh323_destroy(pvt); 01768 if (cause) 01769 *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 01770 return NULL; 01771 } 01772 } 01773 else { 01774 memcpy(&pvt->options, &global_options, sizeof(pvt->options)); 01775 pvt->jointcapability = pvt->options.capability; 01776 if (pvt->options.dtmfmode) { 01777 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { 01778 pvt->nonCodecCapability |= AST_RTP_DTMF; 01779 } else { 01780 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01781 } 01782 } 01783 } 01784 01785 ast_mutex_lock(&caplock); 01786 /* Generate unique channel identifier */ 01787 snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique); 01788 tmp1[sizeof(tmp1)-1] = '\0'; 01789 ast_mutex_unlock(&caplock); 01790 01791 ast_mutex_lock(&pvt->lock); 01792 tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1); 01793 ast_mutex_unlock(&pvt->lock); 01794 if (!tmpc) { 01795 oh323_destroy(pvt); 01796 if (cause) 01797 *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 01798 } 01799 ast_update_use_count(); 01800 restart_monitor(); 01801 return tmpc; 01802 }
Retrieve audio/etc from channel. Assumes pvt->lock is already held.
Definition at line 744 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, ast_debug, ast_dsp_process(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_read(), ast_rtp_setnat(), ast_set_read_format(), ast_set_write_format(), f, LOG_DTMF, LOG_NOTICE, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::noInbandDtmf, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, oh323_pvt::vad, and ast_channel::writeformat.
Referenced by oh323_read().
00745 { 00746 struct ast_frame *f; 00747 00748 /* Only apply it for the first packet, we just need the correct ip/port */ 00749 if (pvt->options.nat) { 00750 ast_rtp_setnat(pvt->rtp, pvt->options.nat); 00751 pvt->options.nat = 0; 00752 } 00753 00754 f = ast_rtp_read(pvt->rtp); 00755 /* Don't send RFC2833 if we're not supposed to */ 00756 if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) { 00757 return &ast_null_frame; 00758 } 00759 if (pvt->owner) { 00760 /* We already hold the channel lock */ 00761 if (f->frametype == AST_FRAME_VOICE) { 00762 if (f->subclass != pvt->owner->nativeformats) { 00763 /* Try to avoid deadlock */ 00764 if (ast_channel_trylock(pvt->owner)) { 00765 ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n"); 00766 return &ast_null_frame; 00767 } 00768 if (h323debug) 00769 ast_debug(1, "Oooh, format changed to %d\n", f->subclass); 00770 pvt->owner->nativeformats = f->subclass; 00771 pvt->nativeformats = f->subclass; 00772 ast_set_read_format(pvt->owner, pvt->owner->readformat); 00773 ast_set_write_format(pvt->owner, pvt->owner->writeformat); 00774 ast_channel_unlock(pvt->owner); 00775 } 00776 /* Do in-band DTMF detection */ 00777 if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) { 00778 if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) { 00779 if (!ast_channel_trylock(pvt->owner)) { 00780 f = ast_dsp_process(pvt->owner, pvt->vad, f); 00781 ast_channel_unlock(pvt->owner); 00782 } 00783 else 00784 ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n"); 00785 } else if (pvt->nativeformats && !pvt->noInbandDtmf) { 00786 ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass)); 00787 pvt->noInbandDtmf = 1; 00788 } 00789 if (f &&(f->frametype == AST_FRAME_DTMF)) { 00790 if (h323debug) 00791 ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass); 00792 } 00793 } 00794 } 00795 } 00796 return f; 00797 }
static int oh323_set_rtp_peer | ( | struct ast_channel * | chan, | |
struct ast_rtp * | rtp, | |||
struct ast_rtp * | vrtp, | |||
struct ast_rtp * | trtp, | |||
int | codecs, | |||
int | nat_active | |||
) | [static] |
Definition at line 3159 of file chan_h323.c.
References ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_rtp_get_us(), oh323_pvt::cd, chan, convertcap(), LOG_ERROR, oh323_pvt::rtp, ast_channel::tech_pvt, and ast_channel::writeformat.
03160 { 03161 /* XXX Deal with Video */ 03162 struct oh323_pvt *pvt; 03163 struct sockaddr_in them; 03164 struct sockaddr_in us; 03165 char *mode; 03166 03167 if (!rtp) { 03168 return 0; 03169 } 03170 03171 mode = convertcap(chan->writeformat); 03172 pvt = (struct oh323_pvt *) chan->tech_pvt; 03173 if (!pvt) { 03174 ast_log(LOG_ERROR, "No Private Structure, this is bad\n"); 03175 return -1; 03176 } 03177 ast_rtp_get_peer(rtp, &them); 03178 ast_rtp_get_us(rtp, &us); 03179 #if 0 /* Native bridge still isn't ready */ 03180 h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode); 03181 #endif 03182 return 0; 03183 }
static int oh323_simulate_dtmf_end | ( | const void * | data | ) | [static] |
Definition at line 299 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, AST_FRAME_DTMF_END, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.
Referenced by __oh323_update_info(), and receive_digit().
00300 { 00301 struct oh323_pvt *pvt = (struct oh323_pvt *)data; 00302 00303 if (pvt) { 00304 ast_mutex_lock(&pvt->lock); 00305 /* Don't hold pvt lock while trying to lock the channel */ 00306 while(pvt->owner && ast_channel_trylock(pvt->owner)) { 00307 DEADLOCK_AVOIDANCE(&pvt->lock); 00308 } 00309 00310 if (pvt->owner) { 00311 struct ast_frame f = { 00312 .frametype = AST_FRAME_DTMF_END, 00313 .subclass = pvt->curDTMF, 00314 .samples = 0, 00315 .src = "SIMULATE_DTMF_END", 00316 }; 00317 ast_queue_frame(pvt->owner, &f); 00318 ast_channel_unlock(pvt->owner); 00319 } 00320 00321 pvt->DTMFsched = -1; 00322 ast_mutex_unlock(&pvt->lock); 00323 } 00324 00325 return 0; 00326 }
static void oh323_update_info | ( | struct ast_channel * | c | ) | [static] |
Only channel structure should be locked.
Definition at line 393 of file chan_h323.c.
References __oh323_update_info(), ast_mutex_lock(), ast_mutex_unlock(), oh323_pvt::lock, and ast_channel::tech_pvt.
Referenced by oh323_answer(), oh323_call(), oh323_digit_begin(), oh323_digit_end(), and oh323_indicate().
00394 { 00395 struct oh323_pvt *pvt = c->tech_pvt; 00396 00397 if (pvt) { 00398 ast_mutex_lock(&pvt->lock); 00399 __oh323_update_info(c, pvt); 00400 ast_mutex_unlock(&pvt->lock); 00401 } 00402 }
static int oh323_write | ( | struct ast_channel * | c, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 824 of file chan_h323.c.
References __oh323_update_info(), AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_write(), ast_frame::frametype, oh323_pvt::lock, LOG_WARNING, ast_channel::nativeformats, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.
00825 { 00826 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00827 int res = 0; 00828 if (frame->frametype != AST_FRAME_VOICE) { 00829 if (frame->frametype == AST_FRAME_IMAGE) { 00830 return 0; 00831 } else { 00832 ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype); 00833 return 0; 00834 } 00835 } else { 00836 if (!(frame->subclass & c->nativeformats)) { 00837 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", 00838 frame->subclass, c->nativeformats, c->readformat, c->writeformat); 00839 return 0; 00840 } 00841 } 00842 if (pvt) { 00843 ast_mutex_lock(&pvt->lock); 00844 if (pvt->rtp && !pvt->recvonly) 00845 res = ast_rtp_write(pvt->rtp, frame); 00846 __oh323_update_info(c, pvt); 00847 ast_mutex_unlock(&pvt->lock); 00848 } 00849 return res; 00850 }
static int progress | ( | unsigned | call_reference, | |
const char * | token, | |||
int | inband | |||
) | [static] |
Definition at line 2075 of file chan_h323.c.
References AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_debug, ast_log(), ast_mutex_unlock(), find_call_locked(), h323debug, oh323_pvt::lock, LOG_ERROR, oh323_pvt::owner, and update_state().
02076 { 02077 struct oh323_pvt *pvt; 02078 02079 if (h323debug) 02080 ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated")); 02081 02082 pvt = find_call_locked(call_reference, token); 02083 if (!pvt) { 02084 ast_log(LOG_ERROR, "Private structure not found in progress.\n"); 02085 return -1; 02086 } 02087 if (!pvt->owner) { 02088 ast_mutex_unlock(&pvt->lock); 02089 ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n"); 02090 return -1; 02091 } 02092 update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING)); 02093 ast_mutex_unlock(&pvt->lock); 02094 02095 return 0; 02096 }
static void prune_peers | ( | void | ) | [static] |
Definition at line 2812 of file chan_h323.c.
References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.
Referenced by handle_cli_iax2_prune_realtime(), reload_config(), set_config(), and unload_module().
02813 { 02814 /* Prune peers who still are supposed to be deleted */ 02815 ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer); 02816 }
static struct oh323_alias* realtime_alias | ( | const char * | alias | ) | [static] |
Definition at line 1222 of file chan_h323.c.
References ast_load_realtime(), ast_variables_destroy(), ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
Referenced by find_alias().
01223 { 01224 struct ast_variable *var, *tmp; 01225 struct oh323_alias *a; 01226 01227 var = ast_load_realtime("h323", "name", alias, SENTINEL); 01228 01229 if (!var) 01230 return NULL; 01231 01232 for (tmp = var; tmp; tmp = tmp->next) { 01233 if (!strcasecmp(tmp->name, "type") && 01234 !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) { 01235 ast_variables_destroy(var); 01236 return NULL; 01237 } 01238 } 01239 01240 a = build_alias(alias, var, NULL, 1); 01241 01242 ast_variables_destroy(var); 01243 01244 return a; 01245 }
static struct oh323_peer* realtime_peer | ( | const char * | peername, | |
struct sockaddr_in * | sin | |||
) | [static] |
Definition at line 1548 of file chan_h323.c.
References ast_inet_ntoa(), ast_load_realtime(), ast_variables_destroy(), ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
Referenced by authenticate_reply(), find_peer(), and iax2_getpeername().
01549 { 01550 struct oh323_peer *peer; 01551 struct ast_variable *var; 01552 struct ast_variable *tmp; 01553 const char *addr = NULL; 01554 01555 /* First check on peer name */ 01556 if (peername) 01557 var = ast_load_realtime("h323", "name", peername, SENTINEL); 01558 else if (sin) /* Then check on IP address for dynamic peers */ 01559 var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL); 01560 else 01561 return NULL; 01562 01563 if (!var) 01564 return NULL; 01565 01566 for (tmp = var; tmp; tmp = tmp->next) { 01567 /* If this is type=user, then skip this object. */ 01568 if (!strcasecmp(tmp->name, "type") && 01569 !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) { 01570 ast_variables_destroy(var); 01571 return NULL; 01572 } else if (!peername && !strcasecmp(tmp->name, "name")) { 01573 peername = tmp->value; 01574 } 01575 } 01576 01577 if (!peername) { /* Did not find peer in realtime */ 01578 ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr); 01579 ast_variables_destroy(var); 01580 return NULL; 01581 } 01582 01583 /* Peer found in realtime, now build it in memory */ 01584 peer = build_peer(peername, var, NULL, 1); 01585 01586 ast_variables_destroy(var); 01587 01588 return peer; 01589 }
static struct oh323_user* realtime_user | ( | const call_details_t * | cd | ) | [static] |
Definition at line 1434 of file chan_h323.c.
References ast_load_realtime(), ast_variables_destroy(), ast_variable::name, ast_variable::next, SENTINEL, userbyalias, ast_variable::value, and var.
Referenced by check_access(), and find_user().
01435 { 01436 struct ast_variable *var, *tmp; 01437 struct oh323_user *user; 01438 const char *username; 01439 01440 if (userbyalias) 01441 var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL); 01442 else { 01443 username = (char *)NULL; 01444 var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL); 01445 } 01446 01447 if (!var) 01448 return NULL; 01449 01450 for (tmp = var; tmp; tmp = tmp->next) { 01451 if (!strcasecmp(tmp->name, "type") && 01452 !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) { 01453 ast_variables_destroy(var); 01454 return NULL; 01455 } else if (!username && !strcasecmp(tmp->name, "name")) 01456 username = tmp->value; 01457 } 01458 01459 if (!username) { 01460 ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp); 01461 ast_variables_destroy(var); 01462 return NULL; 01463 } 01464 01465 user = build_user(username, var, NULL, 1); 01466 01467 ast_variables_destroy(var); 01468 01469 return user; 01470 }
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 1821 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, AST_CONTROL_FLASH, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_mutex_unlock(), ast_queue_control(), ast_queue_frame(), ast_sched_add(), AST_SCHED_DEL, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, f, find_call_locked(), h323debug, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_simulate_dtmf_end(), and oh323_pvt::owner.
Referenced by load_module().
01822 { 01823 struct oh323_pvt *pvt; 01824 int res; 01825 01826 pvt = find_call_locked(call_reference, token); 01827 if (!pvt) { 01828 ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token); 01829 return -1; 01830 } 01831 if (h323debug) 01832 ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token); 01833 01834 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 01835 if (digit == '!') 01836 res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH); 01837 else { 01838 struct ast_frame f = { 01839 .frametype = AST_FRAME_DTMF_END, 01840 .subclass = digit, 01841 .samples = duration * 8, 01842 .len = duration, 01843 .src = "SEND_DIGIT", 01844 }; 01845 if (digit == ' ') { /* signalUpdate message */ 01846 f.subclass = pvt->curDTMF; 01847 AST_SCHED_DEL(sched, pvt->DTMFsched); 01848 } else { /* Regular input or signal message */ 01849 if (pvt->DTMFsched >= 0) { 01850 /* We still don't send DTMF END from previous event, send it now */ 01851 AST_SCHED_DEL(sched, pvt->DTMFsched); 01852 f.subclass = pvt->curDTMF; 01853 f.samples = f.len = 0; 01854 ast_queue_frame(pvt->owner, &f); 01855 /* Restore values */ 01856 f.subclass = digit; 01857 f.samples = duration * 8; 01858 f.len = duration; 01859 } 01860 if (duration) { /* This is a signal, signalUpdate follows */ 01861 f.frametype = AST_FRAME_DTMF_BEGIN; 01862 pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt); 01863 if (h323debug) 01864 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched); 01865 } 01866 pvt->curDTMF = digit; 01867 } 01868 res = ast_queue_frame(pvt->owner, &f); 01869 } 01870 ast_channel_unlock(pvt->owner); 01871 } else { 01872 if (digit == '!') 01873 pvt->newcontrol = AST_CONTROL_FLASH; 01874 else { 01875 pvt->newduration = duration; 01876 pvt->newdigit = digit; 01877 } 01878 res = 0; 01879 } 01880 ast_mutex_unlock(&pvt->lock); 01881 return res; 01882 }
static const char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 260 of file chan_h323.c.
00261 { 00262 switch (redirectingreason) { 00263 case 0: 00264 return "UNKNOWN"; 00265 case 1: 00266 return "BUSY"; 00267 case 2: 00268 return "NO_REPLY"; 00269 case 0xF: 00270 return "UNCONDITIONAL"; 00271 default: 00272 return "NOREDIRECT"; 00273 } 00274 }
static int reload | ( | void | ) | [static] |
Definition at line 3095 of file chan_h323.c.
References ast_log(), h323_reload(), io, and LOG_NOTICE.
03096 { 03097 if (!sched || !io) { 03098 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n"); 03099 return 0; 03100 } 03101 return h323_reload(); 03102 }
static int reload_config | ( | int | is_reload | ) | [static] |
Definition at line 2818 of file chan_h323.c.
References acceptAnonymous, ahp, ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ASTOBJ_CONTAINER_LINK, ASTOBJ_UNREF, bindaddr, build_peer(), build_user(), config, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, cos, default_context, default_jbconf, delete_aliases(), delete_users(), gatekeeper, gatekeeper_disable, gatekeeper_discover, gen, gkroute, GLOBAL_CAPABILITY, global_jbconf, global_options, h323_signalling_port, hp, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_peer(), oh323_destroy_user(), peerl, prune_peers(), tos, userbyalias, userl, and ast_variable::value.
Referenced by do_monitor(), h323_do_reload(), handle_cli_iax2_reload(), handle_cli_misdn_reload(), load_module(), reload(), and sip_do_reload().
02819 { 02820 struct ast_config *cfg, *ucfg; 02821 struct ast_variable *v; 02822 struct oh323_peer *peer = NULL; 02823 struct oh323_user *user = NULL; 02824 struct oh323_alias *alias = NULL; 02825 struct ast_hostent ahp; struct hostent *hp; 02826 char *cat; 02827 const char *utype; 02828 int is_user, is_peer, is_alias; 02829 char _gatekeeper[100]; 02830 int gk_discover, gk_disable, gk_changed; 02831 struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02832 02833 cfg = ast_config_load(config, config_flags); 02834 02835 /* We *must* have a config file otherwise stop immediately */ 02836 if (!cfg) { 02837 ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config); 02838 return 1; 02839 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 02840 ucfg = ast_config_load("users.conf", config_flags); 02841 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) 02842 return 0; 02843 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 02844 cfg = ast_config_load(config, config_flags); 02845 } else { 02846 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 02847 ucfg = ast_config_load("users.conf", config_flags); 02848 } 02849 02850 if (is_reload) { 02851 delete_users(); 02852 delete_aliases(); 02853 prune_peers(); 02854 } 02855 02856 /* fire up the H.323 Endpoint */ 02857 if (!h323_end_point_exist()) { 02858 h323_end_point_create(); 02859 } 02860 ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper)); 02861 gk_discover = gatekeeper_discover; 02862 gk_disable = gatekeeper_disable; 02863 memset(&bindaddr, 0, sizeof(bindaddr)); 02864 memset(&global_options, 0, sizeof(global_options)); 02865 global_options.fastStart = 1; 02866 global_options.h245Tunneling = 1; 02867 global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT; 02868 global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT; 02869 global_options.dtmfmode = 0; 02870 global_options.holdHandling = 0; 02871 global_options.capability = GLOBAL_CAPABILITY; 02872 global_options.bridge = 1; /* Do native bridging by default */ 02873 strcpy(default_context, "default"); 02874 h323_signalling_port = 1720; 02875 gatekeeper_disable = 1; 02876 gatekeeper_discover = 0; 02877 gkroute = 0; 02878 userbyalias = 1; 02879 acceptAnonymous = 1; 02880 tos = 0; 02881 cos = 0; 02882 02883 /* Copy the default jb config over global_jbconf */ 02884 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 02885 02886 if (ucfg) { 02887 struct ast_variable *gen; 02888 int genhas_h323; 02889 const char *has_h323; 02890 02891 genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323")); 02892 gen = ast_variable_browse(ucfg, "general"); 02893 for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) { 02894 if (strcasecmp(cat, "general")) { 02895 has_h323 = ast_variable_retrieve(ucfg, cat, "hash323"); 02896 if (ast_true(has_h323) || (!has_h323 && genhas_h323)) { 02897 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 02898 if (user) { 02899 ASTOBJ_CONTAINER_LINK(&userl, user); 02900 ASTOBJ_UNREF(user, oh323_destroy_user); 02901 } 02902 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 02903 if (peer) { 02904 ASTOBJ_CONTAINER_LINK(&peerl, peer); 02905 ASTOBJ_UNREF(peer, oh323_destroy_peer); 02906 } 02907 } 02908 } 02909 } 02910 ast_config_destroy(ucfg); 02911 } 02912 02913 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 02914 /* handle jb conf */ 02915 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 02916 continue; 02917 /* Create the interface list */ 02918 if (!strcasecmp(v->name, "port")) { 02919 h323_signalling_port = (int)strtol(v->value, NULL, 10); 02920 } else if (!strcasecmp(v->name, "bindaddr")) { 02921 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 02922 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 02923 } else { 02924 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 02925 } 02926 } else if (!strcasecmp(v->name, "tos")) { /* Needs to be removed in next release */ 02927 ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n"); 02928 if (ast_str2tos(v->value, &tos)) { 02929 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02930 } 02931 } else if (!strcasecmp(v->name, "tos_audio")) { 02932 if (ast_str2tos(v->value, &tos)) { 02933 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02934 } 02935 } else if (!strcasecmp(v->name, "cos")) { 02936 ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n"); 02937 if (ast_str2cos(v->value, &cos)) { 02938 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02939 } 02940 } else if (!strcasecmp(v->name, "cos_audio")) { 02941 if (ast_str2cos(v->value, &cos)) { 02942 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02943 } 02944 } else if (!strcasecmp(v->name, "gatekeeper")) { 02945 if (!strcasecmp(v->value, "DISABLE")) { 02946 gatekeeper_disable = 1; 02947 } else if (!strcasecmp(v->value, "DISCOVER")) { 02948 gatekeeper_disable = 0; 02949 gatekeeper_discover = 1; 02950 } else { 02951 gatekeeper_disable = 0; 02952 ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper)); 02953 } 02954 } else if (!strcasecmp(v->name, "secret")) { 02955 ast_copy_string(secret, v->value, sizeof(secret)); 02956 } else if (!strcasecmp(v->name, "AllowGKRouted")) { 02957 gkroute = ast_true(v->value); 02958 } else if (!strcasecmp(v->name, "context")) { 02959 ast_copy_string(default_context, v->value, sizeof(default_context)); 02960 ast_verb(2, "Setting default context to %s\n", default_context); 02961 } else if (!strcasecmp(v->name, "UserByAlias")) { 02962 userbyalias = ast_true(v->value); 02963 } else if (!strcasecmp(v->name, "AcceptAnonymous")) { 02964 acceptAnonymous = ast_true(v->value); 02965 } else if (!update_common_options(v, &global_options)) { 02966 /* dummy */ 02967 } 02968 } 02969 if (!global_options.dtmfmode) 02970 global_options.dtmfmode = H323_DTMF_RFC2833; 02971 if (global_options.holdHandling == ~0) 02972 global_options.holdHandling = 0; 02973 else if (!global_options.holdHandling) 02974 global_options.holdHandling = H323_HOLD_H450; 02975 02976 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) { 02977 if (strcasecmp(cat, "general")) { 02978 utype = ast_variable_retrieve(cfg, cat, "type"); 02979 if (utype) { 02980 is_user = is_peer = is_alias = 0; 02981 if (!strcasecmp(utype, "user")) 02982 is_user = 1; 02983 else if (!strcasecmp(utype, "peer")) 02984 is_peer = 1; 02985 else if (!strcasecmp(utype, "friend")) 02986 is_user = is_peer = 1; 02987 else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias")) 02988 is_alias = 1; 02989 else { 02990 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config); 02991 continue; 02992 } 02993 if (is_user) { 02994 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 02995 if (user) { 02996 ASTOBJ_CONTAINER_LINK(&userl, user); 02997 ASTOBJ_UNREF(user, oh323_destroy_user); 02998 } 02999 } 03000 if (is_peer) { 03001 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 03002 if (peer) { 03003 ASTOBJ_CONTAINER_LINK(&peerl, peer); 03004 ASTOBJ_UNREF(peer, oh323_destroy_peer); 03005 } 03006 } 03007 if (is_alias) { 03008 alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0); 03009 if (alias) { 03010 ASTOBJ_CONTAINER_LINK(&aliasl, alias); 03011 ASTOBJ_UNREF(alias, oh323_destroy_alias); 03012 } 03013 } 03014 } else { 03015 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 03016 } 03017 } 03018 } 03019 ast_config_destroy(cfg); 03020 03021 /* Register our H.323 aliases if any*/ 03022 ASTOBJ_CONTAINER_WRLOCK(&aliasl); 03023 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do { 03024 ASTOBJ_RDLOCK(iterator); 03025 if (h323_set_alias(iterator)) { 03026 ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name); 03027 ASTOBJ_UNLOCK(iterator); 03028 continue; 03029 } 03030 ASTOBJ_UNLOCK(iterator); 03031 } while (0) ); 03032 ASTOBJ_CONTAINER_UNLOCK(&aliasl); 03033 03034 /* Don't touch GK if nothing changed because URQ will drop all existing calls */ 03035 gk_changed = 0; 03036 if (gatekeeper_disable != gk_disable) 03037 gk_changed = is_reload; 03038 else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover)) 03039 gk_changed = is_reload; 03040 else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0)) 03041 gk_changed = is_reload; 03042 if (gk_changed) { 03043 if(!gk_disable) 03044 h323_gk_urq(); 03045 if (!gatekeeper_disable) { 03046 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { 03047 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); 03048 gatekeeper_disable = 1; 03049 } 03050 } 03051 } 03052 return 0; 03053 }
static void remote_hold | ( | unsigned | call_reference, | |
const char * | token, | |||
int | is_hold | |||
) | [static] |
Definition at line 2492 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_debug, ast_mutex_unlock(), ast_queue_control(), find_call_locked(), h323debug, oh323_pvt::lock, oh323_pvt::newcontrol, and oh323_pvt::owner.
Referenced by load_module().
02493 { 02494 struct oh323_pvt *pvt; 02495 02496 if (h323debug) 02497 ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token); 02498 02499 pvt = find_call_locked(call_reference, token); 02500 if (!pvt) 02501 return; 02502 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 02503 if (is_hold) 02504 ast_queue_control(pvt->owner, AST_CONTROL_HOLD); 02505 else 02506 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD); 02507 ast_channel_unlock(pvt->owner); 02508 } 02509 else { 02510 if (is_hold) 02511 pvt->newcontrol = AST_CONTROL_HOLD; 02512 else 02513 pvt->newcontrol = AST_CONTROL_UNHOLD; 02514 } 02515 ast_mutex_unlock(&pvt->lock); 02516 }
static int restart_monitor | ( | void | ) | [static] |
Definition at line 2586 of file chan_h323.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, monitor_thread, and monlock.
02587 { 02588 /* If we're supposed to be stopped -- stay stopped */ 02589 if (ast_mutex_lock(&monlock)) { 02590 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 02591 return -1; 02592 } 02593 if (monitor_thread == AST_PTHREADT_STOP) { 02594 ast_mutex_unlock(&monlock); 02595 return 0; 02596 } 02597 if (monitor_thread == pthread_self()) { 02598 ast_mutex_unlock(&monlock); 02599 ast_log(LOG_WARNING, "Cannot kill myself\n"); 02600 return -1; 02601 } 02602 if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) { 02603 /* Wake up the thread */ 02604 pthread_kill(monitor_thread, SIGURG); 02605 } else { 02606 /* Start a new monitor */ 02607 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 02608 monitor_thread = AST_PTHREADT_NULL; 02609 ast_mutex_unlock(&monlock); 02610 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 02611 return -1; 02612 } 02613 } 02614 ast_mutex_unlock(&monlock); 02615 return 0; 02616 }
static void set_dtmf_payload | ( | unsigned | call_reference, | |
const char * | token, | |||
int | payload, | |||
int | is_cisco | |||
) | [static] |
Definition at line 2421 of file chan_h323.c.
References ast_debug, ast_mutex_unlock(), ast_rtp_set_rtpmap_type(), oh323_pvt::dtmf_pt, find_call_locked(), h323debug, oh323_pvt::lock, and oh323_pvt::rtp.
Referenced by load_module().
02422 { 02423 struct oh323_pvt *pvt; 02424 02425 if (h323debug) 02426 ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token); 02427 02428 pvt = find_call_locked(call_reference, token); 02429 if (!pvt) { 02430 return; 02431 } 02432 if (pvt->rtp) { 02433 ast_rtp_set_rtpmap_type(pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0); 02434 } 02435 pvt->dtmf_pt[is_cisco ? 1 : 0] = payload; 02436 ast_mutex_unlock(&pvt->lock); 02437 if (h323debug) 02438 ast_debug(1, "DTMF payload on %s set to %d\n", token, payload); 02439 }
static void set_local_capabilities | ( | unsigned | call_reference, | |
const char * | token | |||
) | [static] |
Definition at line 2469 of file chan_h323.c.
References ast_debug, ast_mutex_unlock(), capability, dtmfmode, find_call_locked(), h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, oh323_pvt::options, oh323_pvt::pref_codec, and prefs.
Referenced by load_module().
02470 { 02471 struct oh323_pvt *pvt; 02472 int capability, dtmfmode, pref_codec; 02473 struct ast_codec_pref prefs; 02474 02475 if (h323debug) 02476 ast_debug(1, "Setting capabilities for connection %s\n", token); 02477 02478 pvt = find_call_locked(call_reference, token); 02479 if (!pvt) 02480 return; 02481 capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability; 02482 dtmfmode = pvt->options.dtmfmode; 02483 prefs = pvt->options.prefs; 02484 pref_codec = pvt->pref_codec; 02485 ast_mutex_unlock(&pvt->lock); 02486 h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec); 02487 02488 if (h323debug) 02489 ast_debug(1, "Capabilities for connection %s is set\n", token); 02490 }
static void set_peer_capabilities | ( | unsigned | call_reference, | |
const char * | token, | |||
int | capabilities, | |||
struct ast_codec_pref * | prefs | |||
) | [static] |
Definition at line 2441 of file chan_h323.c.
References ast_debug, ast_getformatname(), ast_mutex_unlock(), ast_rtp_codec_setpref(), find_call_locked(), ast_codec_pref::framing, h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, oh323_pvt::options, ast_codec_pref::order, oh323_pvt::peer_prefs, oh323_pvt::peercapability, prefs, and oh323_pvt::rtp.
Referenced by load_module().
02442 { 02443 struct oh323_pvt *pvt; 02444 02445 if (h323debug) 02446 ast_debug(1, "Got remote capabilities from connection %s\n", token); 02447 02448 pvt = find_call_locked(call_reference, token); 02449 if (!pvt) 02450 return; 02451 pvt->peercapability = capabilities; 02452 pvt->jointcapability = pvt->options.capability & capabilities; 02453 if (prefs) { 02454 memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs)); 02455 if (h323debug) { 02456 int i; 02457 for (i = 0; i < 32; ++i) { 02458 if (!prefs->order[i]) 02459 break; 02460 ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]); 02461 } 02462 } 02463 if (pvt->rtp) 02464 ast_rtp_codec_setpref(pvt->rtp, &pvt->peer_prefs); 02465 } 02466 ast_mutex_unlock(&pvt->lock); 02467 }
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 2103 of file chan_h323.c.
References acceptAnonymous, oh323_pvt::accountcode, oh323_pvt::amaflags, ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), ast_strlen_zero(), ast_verb, ASTOBJ_UNREF, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::context, default_context, oh323_pvt::exten, find_alias(), find_user(), gatekeeper, gatekeeper_disable, gkroute, global_options, h323debug, oh323_pvt::jointcapability, LOG_ERROR, LOG_NOTICE, oh323_alloc(), oh323_destroy(), oh323_destroy_user(), and oh323_pvt::options.
Referenced by load_module().
02104 { 02105 struct oh323_pvt *pvt; 02106 struct oh323_user *user = NULL; 02107 struct oh323_alias *alias = NULL; 02108 02109 if (h323debug) 02110 ast_debug(1, "Setting up incoming call for %s\n", cd->call_token); 02111 02112 /* allocate the call*/ 02113 pvt = oh323_alloc(cd->call_reference); 02114 02115 if (!pvt) { 02116 ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n"); 02117 cleanup_call_details(cd); 02118 return NULL; 02119 } 02120 02121 /* Populate the call details in the private structure */ 02122 memcpy(&pvt->cd, cd, sizeof(pvt->cd)); 02123 memcpy(&pvt->options, &global_options, sizeof(pvt->options)); 02124 pvt->jointcapability = pvt->options.capability; 02125 02126 if (h323debug) { 02127 ast_verb(3, "Setting up Call\n"); 02128 ast_verb(3, " \tCall token: [%s]\n", pvt->cd.call_token); 02129 ast_verb(3, " \tCalling party name: [%s]\n", pvt->cd.call_source_name); 02130 ast_verb(3, " \tCalling party number: [%s]\n", pvt->cd.call_source_e164); 02131 ast_verb(3, " \tCalled party name: [%s]\n", pvt->cd.call_dest_alias); 02132 ast_verb(3, " \tCalled party number: [%s]\n", pvt->cd.call_dest_e164); 02133 if (pvt->cd.redirect_reason >= 0) 02134 ast_verb(3, " \tRedirecting party number: [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason); 02135 ast_verb(3, " \tCalling party IP: [%s]\n", pvt->cd.sourceIp); 02136 } 02137 02138 /* Decide if we are allowing Gatekeeper routed calls*/ 02139 if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) { 02140 if (!ast_strlen_zero(cd->call_dest_e164)) { 02141 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten)); 02142 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 02143 } else { 02144 alias = find_alias(cd->call_dest_alias, 1); 02145 if (!alias) { 02146 ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias); 02147 oh323_destroy(pvt); 02148 return NULL; 02149 } 02150 ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten)); 02151 ast_copy_string(pvt->context, alias->context, sizeof(pvt->context)); 02152 } 02153 } else { 02154 /* Either this call is not from the Gatekeeper 02155 or we are not allowing gk routed calls */ 02156 user = find_user(cd, 1); 02157 if (!user) { 02158 if (!acceptAnonymous) { 02159 ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp); 02160 oh323_destroy(pvt); 02161 return NULL; 02162 } 02163 if (ast_strlen_zero(default_context)) { 02164 ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp); 02165 oh323_destroy(pvt); 02166 return NULL; 02167 } 02168 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 02169 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) { 02170 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten)); 02171 } else { 02172 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten)); 02173 } 02174 if (h323debug) 02175 ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten); 02176 } else { 02177 if (user->host) { 02178 if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) { 02179 if (ast_strlen_zero(user->context)) { 02180 if (ast_strlen_zero(default_context)) { 02181 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp); 02182 oh323_destroy(pvt); 02183 ASTOBJ_UNREF(user, oh323_destroy_user); 02184 return NULL; 02185 } 02186 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 02187 } else { 02188 ast_copy_string(pvt->context, user->context, sizeof(pvt->context)); 02189 } 02190 pvt->exten[0] = 'i'; 02191 pvt->exten[1] = '\0'; 02192 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp); 02193 oh323_destroy(pvt); 02194 ASTOBJ_UNREF(user, oh323_destroy_user); 02195 return NULL; /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */ 02196 } 02197 } 02198 ast_copy_string(pvt->context, user->context, sizeof(pvt->context)); 02199 memcpy(&pvt->options, &user->options, sizeof(pvt->options)); 02200 pvt->jointcapability = pvt->options.capability; 02201 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) { 02202 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten)); 02203 } else { 02204 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten)); 02205 } 02206 if (!ast_strlen_zero(user->accountcode)) { 02207 ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode)); 02208 } 02209 if (user->amaflags) { 02210 pvt->amaflags = user->amaflags; 02211 } 02212 ASTOBJ_UNREF(user, oh323_destroy_user); 02213 } 02214 } 02215 return &pvt->options; 02216 }
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 2302 of file chan_h323.c.
References cleanup_call_details().
Referenced by load_module().
02303 { 02304 /* Use argument here or free it immediately */ 02305 cleanup_call_details(cd); 02306 02307 return 1; 02308 }
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 1939 of file chan_h323.c.
References __oh323_rtp_create(), oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_debug, AST_FORMAT_G726_AAL2, ast_log(), ast_mutex_unlock(), ast_queue_control(), ast_rtp_lookup_pt(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp_set_peer(), ast_rtp_set_rtpmap_type(), ast_rtp_stop(), ast_set_read_format(), ast_set_write_format(), rtpPayloadType::code, find_call_locked(), h323debug, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, ast_channel::nativeformats, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_channel::writeformat.
Referenced by load_module().
01940 { 01941 struct oh323_pvt *pvt; 01942 struct sockaddr_in them; 01943 struct rtpPayloadType rtptype; 01944 int nativeformats_changed; 01945 enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE; 01946 01947 if (h323debug) 01948 ast_debug(1, "Setting up RTP connection for %s\n", token); 01949 01950 /* Find the call or allocate a private structure if call not found */ 01951 pvt = find_call_locked(call_reference, token); 01952 if (!pvt) { 01953 ast_log(LOG_ERROR, "Something is wrong: rtp\n"); 01954 return; 01955 } 01956 if (pvt->alreadygone) { 01957 ast_mutex_unlock(&pvt->lock); 01958 return; 01959 } 01960 01961 if (!pvt->rtp) 01962 __oh323_rtp_create(pvt); 01963 01964 if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) { 01965 ast_rtp_set_rtpmap_type(pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD); 01966 } 01967 01968 them.sin_family = AF_INET; 01969 /* only works for IPv4 */ 01970 them.sin_addr.s_addr = inet_addr(remoteIp); 01971 them.sin_port = htons(remotePort); 01972 01973 if (them.sin_addr.s_addr) { 01974 ast_rtp_set_peer(pvt->rtp, &them); 01975 if (pvt->recvonly) { 01976 pvt->recvonly = 0; 01977 rtp_change = NEED_UNHOLD; 01978 } 01979 } else { 01980 ast_rtp_stop(pvt->rtp); 01981 if (!pvt->recvonly) { 01982 pvt->recvonly = 1; 01983 rtp_change = NEED_HOLD; 01984 } 01985 } 01986 01987 /* Change native format to reflect information taken from OLC/OLCAck */ 01988 nativeformats_changed = 0; 01989 if (pt != 128 && pvt->rtp) { /* Payload type is invalid, so try to use previously decided */ 01990 rtptype = ast_rtp_lookup_pt(pvt->rtp, pt); 01991 if (h323debug) 01992 ast_debug(1, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt); 01993 if (pvt->nativeformats != rtptype.code) { 01994 pvt->nativeformats = rtptype.code; 01995 nativeformats_changed = 1; 01996 } 01997 } else if (h323debug) 01998 ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n"); 01999 02000 /* Don't try to lock the channel if nothing changed */ 02001 if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) { 02002 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 02003 /* Re-build translation path only if native format(s) has been changed */ 02004 if (pvt->owner->nativeformats != pvt->nativeformats) { 02005 if (h323debug) 02006 ast_debug(1, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat); 02007 pvt->owner->nativeformats = pvt->nativeformats; 02008 ast_set_read_format(pvt->owner, pvt->owner->readformat); 02009 ast_set_write_format(pvt->owner, pvt->owner->writeformat); 02010 } 02011 if (pvt->options.progress_audio) 02012 ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS); 02013 switch (rtp_change) { 02014 case NEED_HOLD: 02015 ast_queue_control(pvt->owner, AST_CONTROL_HOLD); 02016 break; 02017 case NEED_UNHOLD: 02018 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD); 02019 break; 02020 default: 02021 break; 02022 } 02023 ast_channel_unlock(pvt->owner); 02024 } 02025 else { 02026 if (pvt->options.progress_audio) 02027 pvt->newcontrol = AST_CONTROL_PROGRESS; 02028 else if (rtp_change == NEED_HOLD) 02029 pvt->newcontrol = AST_CONTROL_HOLD; 02030 else if (rtp_change == NEED_UNHOLD) 02031 pvt->newcontrol = AST_CONTROL_UNHOLD; 02032 if (h323debug) 02033 ast_debug(1, "RTP connection preparation for %s is pending...\n", token); 02034 } 02035 } 02036 ast_mutex_unlock(&pvt->lock); 02037 02038 if (h323debug) 02039 ast_debug(1, "RTP connection prepared for %s\n", token); 02040 02041 return; 02042 }
static int unload_module | ( | void | ) | [static] |
Definition at line 3295 of file chan_h323.c.
References aliasl, ast_channel_unregister(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_free, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, cli_h323, cli_h323_reload, gatekeeper_disable, iflist, iflock, io, io_context_destroy(), oh323_pvt::lock, LOG_WARNING, monitor_thread, monlock, oh323_pvt::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), oh323_rtp, oh323_tech, oh323_pvt::owner, peerl, sched_context_destroy(), and userl.
03296 { 03297 struct oh323_pvt *p, *pl; 03298 03299 /* unregister commands */ 03300 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry)); 03301 ast_cli_unregister(&cli_h323_reload); 03302 03303 ast_channel_unregister(&oh323_tech); 03304 ast_rtp_proto_unregister(&oh323_rtp); 03305 03306 if (!ast_mutex_lock(&iflock)) { 03307 /* hangup all interfaces if they have an owner */ 03308 p = iflist; 03309 while(p) { 03310 if (p->owner) { 03311 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 03312 } 03313 p = p->next; 03314 } 03315 iflist = NULL; 03316 ast_mutex_unlock(&iflock); 03317 } else { 03318 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 03319 return -1; 03320 } 03321 if (!ast_mutex_lock(&monlock)) { 03322 if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 03323 if (monitor_thread != pthread_self()) { 03324 pthread_cancel(monitor_thread); 03325 } 03326 pthread_kill(monitor_thread, SIGURG); 03327 pthread_join(monitor_thread, NULL); 03328 } 03329 monitor_thread = AST_PTHREADT_STOP; 03330 ast_mutex_unlock(&monlock); 03331 } else { 03332 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 03333 return -1; 03334 } 03335 if (!ast_mutex_lock(&iflock)) { 03336 /* destroy all the interfaces and free their memory */ 03337 p = iflist; 03338 while(p) { 03339 pl = p; 03340 p = p->next; 03341 /* free associated memory */ 03342 ast_mutex_destroy(&pl->lock); 03343 ast_free(pl); 03344 } 03345 iflist = NULL; 03346 ast_mutex_unlock(&iflock); 03347 } else { 03348 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 03349 return -1; 03350 } 03351 if (!gatekeeper_disable) 03352 h323_gk_urq(); 03353 h323_end_process(); 03354 if (io) 03355 io_context_destroy(io); 03356 if (sched) 03357 sched_context_destroy(sched); 03358 03359 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user); 03360 ASTOBJ_CONTAINER_DESTROY(&userl); 03361 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer); 03362 ASTOBJ_CONTAINER_DESTROY(&peerl); 03363 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias); 03364 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03365 03366 return 0; 03367 }
static int update_common_options | ( | struct ast_variable * | v, | |
struct call_options * | options | |||
) | [static] |
Definition at line 1247 of file chan_h323.c.
References ast_callerid_split(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ast_strdupa, ast_true(), ast_variable::lineno, LOG_NOTICE, LOG_WARNING, ast_variable::name, and ast_variable::value.
Referenced by build_peer(), and build_user().
01248 { 01249 int tmp = 0; 01250 char *val, *opt; 01251 01252 if (!strcasecmp(v->name, "allow")) { 01253 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1); 01254 } else if (!strcasecmp(v->name, "disallow")) { 01255 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0); 01256 } else if (!strcasecmp(v->name, "dtmfmode")) { 01257 val = ast_strdupa(v->value); 01258 if ((opt = strchr(val, ':')) != (char *)NULL) { 01259 *opt++ = '\0'; 01260 tmp = atoi(opt); 01261 } 01262 if (!strcasecmp(v->value, "inband")) { 01263 options->dtmfmode |= H323_DTMF_INBAND; 01264 } else if (!strcasecmp(val, "rfc2833")) { 01265 options->dtmfmode |= H323_DTMF_RFC2833; 01266 if (!opt) { 01267 options->dtmfcodec[0] = H323_DTMF_RFC2833_PT; 01268 } else if ((tmp >= 96) && (tmp < 128)) { 01269 options->dtmfcodec[0] = tmp; 01270 } else { 01271 options->dtmfcodec[0] = H323_DTMF_RFC2833_PT; 01272 ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]); 01273 } 01274 } else if (!strcasecmp(val, "cisco")) { 01275 options->dtmfmode |= H323_DTMF_CISCO; 01276 if (!opt) { 01277 options->dtmfcodec[1] = H323_DTMF_CISCO_PT; 01278 } else if ((tmp >= 96) && (tmp < 128)) { 01279 options->dtmfcodec[1] = tmp; 01280 } else { 01281 options->dtmfcodec[1] = H323_DTMF_CISCO_PT; 01282 ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]); 01283 } 01284 } else if (!strcasecmp(v->value, "h245-signal")) { 01285 options->dtmfmode |= H323_DTMF_SIGNAL; 01286 } else { 01287 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno); 01288 } 01289 } else if (!strcasecmp(v->name, "dtmfcodec")) { 01290 ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno); 01291 tmp = atoi(v->value); 01292 if (tmp < 96) 01293 ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno); 01294 else 01295 options->dtmfcodec[0] = tmp; 01296 } else if (!strcasecmp(v->name, "bridge")) { 01297 options->bridge = ast_true(v->value); 01298 } else if (!strcasecmp(v->name, "nat")) { 01299 options->nat = ast_true(v->value); 01300 } else if (!strcasecmp(v->name, "fastStart")) { 01301 options->fastStart = ast_true(v->value); 01302 } else if (!strcasecmp(v->name, "h245Tunneling")) { 01303 options->h245Tunneling = ast_true(v->value); 01304 } else if (!strcasecmp(v->name, "silenceSuppression")) { 01305 options->silenceSuppression = ast_true(v->value); 01306 } else if (!strcasecmp(v->name, "progress_setup")) { 01307 tmp = atoi(v->value); 01308 if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) { 01309 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno); 01310 tmp = 0; 01311 } 01312 options->progress_setup = tmp; 01313 } else if (!strcasecmp(v->name, "progress_alert")) { 01314 tmp = atoi(v->value); 01315 if ((tmp != 0) && (tmp != 1) && (tmp != 8)) { 01316 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno); 01317 tmp = 0; 01318 } 01319 options->progress_alert = tmp; 01320 } else if (!strcasecmp(v->name, "progress_audio")) { 01321 options->progress_audio = ast_true(v->value); 01322 } else if (!strcasecmp(v->name, "callerid")) { 01323 ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num)); 01324 } else if (!strcasecmp(v->name, "fullname")) { 01325 ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name)); 01326 } else if (!strcasecmp(v->name, "cid_number")) { 01327 ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num)); 01328 } else if (!strcasecmp(v->name, "tunneling")) { 01329 if (!strcasecmp(v->value, "none")) 01330 options->tunnelOptions = 0; 01331 else if (!strcasecmp(v->value, "cisco")) 01332 options->tunnelOptions |= H323_TUNNEL_CISCO; 01333 else if (!strcasecmp(v->value, "qsig")) 01334 options->tunnelOptions |= H323_TUNNEL_QSIG; 01335 else 01336 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno); 01337 } else if (!strcasecmp(v->name, "hold")) { 01338 if (!strcasecmp(v->value, "none")) 01339 options->holdHandling = ~0; 01340 else if (!strcasecmp(v->value, "notify")) 01341 options->holdHandling |= H323_HOLD_NOTIFY; 01342 else if (!strcasecmp(v->value, "q931only")) 01343 options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY; 01344 else if (!strcasecmp(v->value, "h450")) 01345 options->holdHandling |= H323_HOLD_H450; 01346 else 01347 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno); 01348 } else 01349 return 1; 01350 01351 return 0; 01352 }
static int update_state | ( | struct oh323_pvt * | pvt, | |
int | state, | |||
int | signal | |||
) | [static] |
Definition at line 1166 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, ast_queue_control(), ast_setstate(), oh323_pvt::newcontrol, oh323_pvt::newstate, and oh323_pvt::owner.
Referenced by chan_ringing(), connection_made(), and progress().
01167 { 01168 if (!pvt) 01169 return 0; 01170 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 01171 if (state >= 0) 01172 ast_setstate(pvt->owner, state); 01173 if (signal >= 0) 01174 ast_queue_control(pvt->owner, signal); 01175 ast_channel_unlock(pvt->owner); 01176 return 1; 01177 } 01178 else { 01179 if (state >= 0) 01180 pvt->newstate = state; 01181 if (signal >= 0) 01182 pvt->newcontrol = signal; 01183 return 0; 01184 } 01185 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3373 of file chan_h323.c.
int acceptAnonymous = 1 [static] |
Definition at line 139 of file chan_h323.c.
Referenced by reload_config(), and setup_incoming_call().
struct h323_alias_list aliasl [static] |
H323 alias list.
Referenced by build_alias(), delete_aliases(), find_alias(), load_module(), and unload_module().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 3373 of file chan_h323.c.
struct sockaddr_in bindaddr [static] |
Definition at line 127 of file chan_h323.c.
ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
Definition at line 215 of file chan_h323.c.
Referenced by oh323_request().
struct ast_cli_entry cli_h323[] [static] |
struct ast_cli_entry cli_h323_reload [static] |
Initial value:
{ .handler = handle_cli_h323_reload , .summary = "Reload H.323 configuration" ,__VA_ARGS__ }
Definition at line 3104 of file chan_h323.c.
Referenced by load_module(), and unload_module().
const char config[] = "h323.conf" [static] |
Definition at line 125 of file chan_h323.c.
unsigned int cos = 0 [static] |
Definition at line 141 of file chan_h323.c.
Referenced by ast_playtones_start(), callerid_init(), goertzel_init(), reload_config(), tdd_init(), and tonepair_alloc().
char default_context[AST_MAX_CONTEXT] = "default" [static] |
Definition at line 126 of file chan_h323.c.
Referenced by build_user(), reload_config(), and setup_incoming_call().
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled.
Definition at line 114 of file chan_h323.c.
char gatekeeper[100] [static] |
Definition at line 133 of file chan_h323.c.
Referenced by handle_cli_h323_cycle_gk(), load_module(), reload_config(), and setup_incoming_call().
int gatekeeper_disable = 1 [static] |
Definition at line 134 of file chan_h323.c.
Referenced by handle_cli_h323_cycle_gk(), load_module(), oh323_request(), reload_config(), setup_incoming_call(), and unload_module().
int gatekeeper_discover = 0 [static] |
Definition at line 135 of file chan_h323.c.
Referenced by handle_cli_h323_cycle_gk(), load_module(), and reload_config().
int gkroute = 0 [static] |
Definition at line 136 of file chan_h323.c.
Referenced by reload_config(), and setup_incoming_call().
struct ast_jb_conf global_jbconf [static] |
Definition at line 121 of file chan_h323.c.
call_options_t global_options [static] |
Definition at line 145 of file chan_h323.c.
Referenced by build_peer(), build_user(), create_addr(), oh323_request(), reload_config(), and setup_incoming_call().
ast_mutex_t h323_reload_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the reload process.
Definition at line 218 of file chan_h323.c.
Referenced by do_monitor(), and h323_reload().
int h323_reloading = 0 [static] |
int h323_signalling_port = 1720 [static] |
H.323 configuration values
Definition at line 132 of file chan_h323.c.
Referenced by build_peer(), create_addr(), load_module(), and reload_config().
int h323debug |
global debug flag
Definition at line 111 of file chan_h323.c.
Referenced by answer_call(), chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), find_peer(), find_user(), handle_cli_h323_set_debug(), hangup_connection(), load_module(), oh323_request(), progress(), receive_digit(), remote_hold(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), and setup_rtp_connection().
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the interface list (oh323_pvt)
Definition at line 208 of file chan_h323.c.
struct io_context* io [static] |
Definition at line 206 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 223 of file chan_h323.c.
ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 212 of file chan_h323.c.
struct ast_rtp_protocol oh323_rtp [static] |
struct ast_channel_tech oh323_tech [static] |
Definition at line 242 of file chan_h323.c.
Referenced by __oh323_new(), load_module(), and unload_module().
answer_call_cb on_answer_call |
Definition at line 103 of file chan_h323.c.
chan_ringing_cb on_chan_ringing |
Definition at line 100 of file chan_h323.c.
clear_con_cb on_connection_cleared |
Definition at line 102 of file chan_h323.c.
con_established_cb on_connection_established |
Definition at line 101 of file chan_h323.c.
on_rtp_cb on_external_rtp_create |
Definition at line 96 of file chan_h323.c.
hangup_cb on_hangup |
Definition at line 106 of file chan_h323.c.
onhold_cb on_hold |
Definition at line 109 of file chan_h323.c.
setup_incoming_cb on_incoming_call |
Definition at line 98 of file chan_h323.c.
setup_outbound_cb on_outgoing_call |
Definition at line 99 of file chan_h323.c.
progress_cb on_progress |
Definition at line 104 of file chan_h323.c.
receive_digit_cb on_receive_digit |
Definition at line 95 of file chan_h323.c.
rfc2833_cb on_set_rfc2833_payload |
Definition at line 105 of file chan_h323.c.
setcapabilities_cb on_setcapabilities |
Definition at line 107 of file chan_h323.c.
setpeercapabilities_cb on_setpeercapabilities |
Definition at line 108 of file chan_h323.c.
start_rtp_cb on_start_rtp_channel |
Definition at line 97 of file chan_h323.c.
struct h323_peer_list peerl [static] |
H323 peer list.
Referenced by build_peer(), delete_users(), find_peer(), load_module(), prune_peers(), reload_config(), and unload_module().
struct sched_context* sched [static] |
Definition at line 205 of file chan_h323.c.
char secret[50] [static] |
Definition at line 142 of file chan_h323.c.
Referenced by add_realm_authentication(), aji_act_hook(), authenticate_verify(), build_peer(), build_reply_digest(), build_user(), cache_get_callno_locked(), check_access(), decrypt_frame(), handle_cli_h323_cycle_gk(), iax2_call(), iax2_register(), load_module(), read_agent_config(), register_verify(), set_config(), sip_register(), and sip_request_call().
const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver" [static] |
Variables required by Asterisk
Definition at line 124 of file chan_h323.c.
unsigned int tos = 0 [static] |
unsigned int unique = 0 [static] |
int userbyalias = 1 [static] |
Definition at line 138 of file chan_h323.c.
Referenced by find_user(), realtime_user(), and reload_config().
struct h323_user_list userl [static] |
H323 User list.
Referenced by build_user(), delete_users(), find_user(), load_module(), reload_config(), and unload_module().