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