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