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