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