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