#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netdb.h>
#include <fcntl.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/musiconhold.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/astobj.h"
#include "h323/chan_h323.h"

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