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