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