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

Go to the source code of this file.
Data Structures | |
| struct | h323_alias_list |
| H323 alias list. More... | |
| struct | h323_peer_list |
| H323 peer list. More... | |
| struct | h323_user_list |
| H323 User list. More... | |
| struct | oh323_pvt |
| Private structure of a OpenH323 channel. More... | |
Defines | |
| #define | GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261) |
Functions | |
| static void | __oh323_destroy (struct oh323_pvt *pvt) |
| static struct ast_channel * | __oh323_new (struct oh323_pvt *pvt, int state, const char *host, const char *linkedid) |
| Private structure should be locked on a call. | |
| static int | __oh323_rtp_create (struct oh323_pvt *pvt) |
| static void | __oh323_update_info (struct ast_channel *c, struct oh323_pvt *pvt) |
| Channel and private structures should be already locked. | |
| static 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_glue_result | oh323_get_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance **instance) |
| static int | oh323_hangup (struct ast_channel *c) |
| static int | oh323_indicate (struct ast_channel *c, int condition, const void *data, size_t datalen) |
| static struct ast_frame * | oh323_read (struct ast_channel *c) |
| static struct ast_channel * | oh323_request (const char *type, int format, const struct ast_channel *requestor, void *data, int *cause) |
| static struct ast_frame * | oh323_rtp_read (struct oh323_pvt *pvt) |
| Retrieve audio/etc from channel. Assumes pvt->lock is already held. | |
| static int | oh323_set_rtp_peer (struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active) |
| static int | oh323_simulate_dtmf_end (const void *data) |
| static void | oh323_update_info (struct ast_channel *c) |
| Only channel structure should be locked. | |
| static int | oh323_write (struct ast_channel *c, struct ast_frame *frame) |
| static int | progress (unsigned call_reference, const char *token, int inband) |
| static void | prune_peers (void) |
| static struct oh323_alias * | realtime_alias (const char *alias) |
| static struct oh323_peer * | realtime_peer (const char *peername, struct sockaddr_in *sin) |
| static struct oh323_user * | realtime_user (const call_details_t *cd) |
| static int | receive_digit (unsigned call_reference, char digit, const char *token, int duration) |
| Callback for sending digits from H.323 up to asterisk. | |
| static const char * | redirectingreason2str (int redirectingreason) |
| static int | reload (void) |
| static int | reload_config (int is_reload) |
| static void | remote_hold (unsigned call_reference, const char *token, int is_hold) |
| static int | restart_monitor (void) |
| static void | set_dtmf_payload (unsigned call_reference, const char *token, int payload, int is_cisco) |
| static void | set_local_capabilities (unsigned call_reference, const char *token) |
| static void | set_peer_capabilities (unsigned call_reference, const char *token, int capabilities, struct ast_codec_pref *prefs) |
| static call_options_t * | setup_incoming_call (call_details_t *cd) |
| Call-back function for incoming calls. | |
| static int | setup_outgoing_call (call_details_t *cd) |
| Call-back function to establish an outgoing H.323 call. | |
| static void | setup_rtp_connection (unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt) |
| Call-back function passing remote ip/port information from H.323 to asterisk. | |
| static int | unload_module (void) |
| static int | update_common_options (struct ast_variable *v, struct call_options *options) |
| static int | update_state (struct oh323_pvt *pvt, int state, int signal) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } |
| static int | acceptAnonymous = 1 |
| static struct h323_alias_list | aliasl |
| H323 alias list. | |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct sockaddr_in | bindaddr |
| static ast_mutex_t | caplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. | |
| static struct ast_cli_entry | cli_h323 [] |
| static struct ast_cli_entry | cli_h323_reload |
| static const char | config [] = "h323.conf" |
| static unsigned int | cos = 0 |
| static char | default_context [AST_MAX_CONTEXT] = "default" |
| static struct ast_jb_conf | default_jbconf |
| Global jitterbuffer configuration - by default, jb is disabled. | |
| static char | gatekeeper [100] |
| static int | gatekeeper_disable = 1 |
| static int | gatekeeper_discover = 0 |
| static int | gkroute = 0 |
| static struct ast_jb_conf | global_jbconf |
| static call_options_t | global_options |
| static ast_mutex_t | h323_reload_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| Protect the reload process. | |
| static int | h323_reloading = 0 |
| static int | h323_signalling_port = 1720 |
| int | h323debug |
| static struct oh323_pvt * | iflist |
| Private structure of a OpenH323 channel. | |
| static ast_mutex_t | iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| static struct io_context * | io |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
| static ast_mutex_t | monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| static struct ast_rtp_glue | oh323_rtp_glue |
| static struct ast_channel_tech | oh323_tech |
| answer_call_cb | on_answer_call |
| chan_ringing_cb | on_chan_ringing |
| clear_con_cb | on_connection_cleared |
| con_established_cb | on_connection_established |
| on_rtp_cb | on_external_rtp_create |
| hangup_cb | on_hangup |
| onhold_cb | on_hold |
| setup_incoming_cb | on_incoming_call |
| setup_outbound_cb | on_outgoing_call |
| progress_cb | on_progress |
| receive_digit_cb | on_receive_digit |
| rfc2833_cb | on_set_rfc2833_payload |
| setcapabilities_cb | on_setcapabilities |
| setpeercapabilities_cb | on_setpeercapabilities |
| start_rtp_cb | on_start_rtp_channel |
| static struct h323_peer_list | peerl |
| H323 peer list. | |
| static struct sched_context * | sched |
| static char | secret [50] |
| static const char | tdesc [] = "The NuFone Network's Open H.323 Channel Driver" |
| static unsigned int | tos = 0 |
| static unsigned int | unique = 0 |
| static int | userbyalias = 1 |
| static struct h323_user_list | userl |
| H323 User list. | |
Definition in file chan_h323.c.
| #define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261) |
| static void __oh323_destroy | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 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_instance_destroy(), AST_SCHED_DEL, oh323_pvt::cd, cleanup_call_details(), oh323_pvt::DTMFsched, iflist, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::next, oh323_pvt::owner, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::vad.
Referenced by do_monitor(), and oh323_destroy().
00443 { 00444 struct oh323_pvt *cur, *prev = NULL; 00445 00446 AST_SCHED_DEL(sched, pvt->DTMFsched); 00447 00448 if (pvt->rtp) { 00449 ast_rtp_instance_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, | |||
| const char * | linkedid | |||
| ) | [static, read] |
Private structure should be locked on a call.
Definition at line 997 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_rtp_instance_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_udptl_fd(), oh323_pvt::cd, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, cid_name, cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, ast_callerid::cid_ton, ast_channel::context, oh323_pvt::context, DSP_FEATURE_DIGIT_DETECT, ast_channel::exten, oh323_pvt::exten, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::options, oh323_pvt::owner, pbx_builtin_setvar_helper(), ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, redirectingreason2str(), ast_channel::rings, oh323_pvt::rtp, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, oh323_pvt::vad, and ast_channel::writeformat.
Referenced by answer_call(), and oh323_request().
00998 { 00999 struct ast_channel *ch; 01000 char *cid_num, *cid_name; 01001 int fmt; 01002 01003 if (!ast_strlen_zero(pvt->options.cid_num)) 01004 cid_num = pvt->options.cid_num; 01005 else 01006 cid_num = pvt->cd.call_source_e164; 01007 01008 if (!ast_strlen_zero(pvt->options.cid_name)) 01009 cid_name = pvt->options.cid_name; 01010 else 01011 cid_name = pvt->cd.call_source_name; 01012 01013 /* Don't hold a oh323_pvt lock while we allocate a chanel */ 01014 ast_mutex_unlock(&pvt->lock); 01015 ch = ast_channel_alloc(1, state, cid_num, cid_name, pvt->accountcode, pvt->exten, pvt->context, linkedid, pvt->amaflags, "H323/%s", host); 01016 /* Update usage counter */ 01017 ast_module_ref(ast_module_info->self); 01018 ast_mutex_lock(&pvt->lock); 01019 if (ch) { 01020 ch->tech = &oh323_tech; 01021 if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability)) 01022 fmt = global_options.capability; 01023 ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/; 01024 pvt->nativeformats = ch->nativeformats; 01025 fmt = ast_best_codec(ch->nativeformats); 01026 ch->writeformat = fmt; 01027 ch->rawwriteformat = fmt; 01028 ch->readformat = fmt; 01029 ch->rawreadformat = fmt; 01030 if (!pvt->rtp) 01031 __oh323_rtp_create(pvt); 01032 #if 0 01033 ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(pvt->rtp, 0)); 01034 ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(pvt->rtp, 1)); 01035 #endif 01036 #ifdef VIDEO_SUPPORT 01037 if (pvt->vrtp) { 01038 ast_channel_set_fd(ch, 2, ast_rtp_instance_fd(pvt->vrtp, 0)); 01039 ast_channel_set_fd(ch, 3, ast_rtp_instance_fd(pvt->vrtp, 1)); 01040 } 01041 #endif 01042 #ifdef T38_SUPPORT 01043 if (pvt->udptl) { 01044 ast_channel_set_fd(ch, 4, ast_udptl_fd(pvt->udptl)); 01045 } 01046 #endif 01047 if (state == AST_STATE_RING) { 01048 ch->rings = 1; 01049 } 01050 /* Allocate dsp for in-band DTMF support */ 01051 if (pvt->options.dtmfmode & H323_DTMF_INBAND) { 01052 pvt->vad = ast_dsp_new(); 01053 ast_dsp_set_features(pvt->vad, DSP_FEATURE_DIGIT_DETECT); 01054 } 01055 /* Register channel functions. */ 01056 ch->tech_pvt = pvt; 01057 /* Set the owner of this channel */ 01058 pvt->owner = ch; 01059 01060 ast_copy_string(ch->context, pvt->context, sizeof(ch->context)); 01061 ast_copy_string(ch->exten, pvt->exten, sizeof(ch->exten)); 01062 ch->priority = 1; 01063 if (!ast_strlen_zero(pvt->accountcode)) { 01064 ast_string_field_set(ch, accountcode, pvt->accountcode); 01065 } 01066 if (pvt->amaflags) { 01067 ch->amaflags = pvt->amaflags; 01068 } 01069 01070 /* Don't use ast_set_callerid() here because it will 01071 * generate a needless NewCallerID event */ 01072 ch->cid.cid_ani = ast_strdup(cid_num); 01073 01074 if (pvt->cd.redirect_reason >= 0) { 01075 ch->cid.cid_rdnis = ast_strdup(pvt->cd.redirect_number); 01076 pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason)); 01077 } 01078 ch->cid.cid_pres = pvt->cd.presentation; 01079 ch->cid.cid_ton = pvt->cd.type_of_number; 01080 01081 if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) { 01082 ch->cid.cid_dnid = ast_strdup(pvt->exten); 01083 } 01084 if (pvt->cd.transfer_capability >= 0) 01085 ch->transfercapability = pvt->cd.transfer_capability; 01086 if (state != AST_STATE_DOWN) { 01087 if (ast_pbx_start(ch)) { 01088 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name); 01089 ast_hangup(ch); 01090 ch = NULL; 01091 } 01092 } 01093 } else { 01094 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 01095 } 01096 return ch; 01097 }
| static int __oh323_rtp_create | ( | struct oh323_pvt * | pvt | ) | [static] |
Definition at line 949 of file chan_h323.c.
References ast_channel_set_fd(), ast_channel_trylock, ast_channel_unlock, ast_debug, ast_find_ourip(), ast_jb_configure(), ast_log(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), ast_rtp_codecs_packetization_set(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_fd(), ast_rtp_instance_get_codecs(), ast_rtp_instance_new(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_qos(), AST_RTP_PROPERTY_NAT, 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().
00950 { 00951 struct sockaddr_in our_addr; 00952 00953 if (pvt->rtp) 00954 return 0; 00955 00956 if (ast_find_ourip(&our_addr.sin_addr, bindaddr)) { 00957 ast_mutex_unlock(&pvt->lock); 00958 ast_log(LOG_ERROR, "Unable to locate local IP address for RTP stream\n"); 00959 return -1; 00960 } 00961 pvt->rtp = ast_rtp_instance_new("asterisk", sched, &our_addr, NULL); 00962 if (!pvt->rtp) { 00963 ast_mutex_unlock(&pvt->lock); 00964 ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); 00965 return -1; 00966 } 00967 if (h323debug) 00968 ast_debug(1, "Created RTP channel\n"); 00969 00970 ast_rtp_instance_set_qos(pvt->rtp, tos, cos, "H323 RTP"); 00971 00972 if (h323debug) 00973 ast_debug(1, "Setting NAT on RTP to %d\n", pvt->options.nat); 00974 ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat); 00975 00976 if (pvt->dtmf_pt[0] > 0) 00977 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[0], "audio", "telephone-event", 0); 00978 if (pvt->dtmf_pt[1] > 0) 00979 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pvt->dtmf_pt[1], "audio", "cisco-telephone-event", 0); 00980 00981 if (pvt->peercapability) 00982 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs); 00983 00984 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 00985 ast_jb_configure(pvt->owner, &global_jbconf); 00986 ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0)); 00987 ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1)); 00988 ast_queue_frame(pvt->owner, &ast_null_frame); /* Tell Asterisk to apply changes */ 00989 ast_channel_unlock(pvt->owner); 00990 } else 00991 pvt->update_rtp_info = 1; 00992 00993 return 0; 00994 }
| 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_rtp_instance_fd(), ast_sched_add(), AST_SCHED_DEL, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_SOFTHANGUP_DEV, oh323_pvt::curDTMF, oh323_pvt::DTMFsched, ast_frame::frametype, global_jbconf, oh323_pvt::hangupcause, ast_channel::hangupcause, LOG_DTMF, ast_channel::name, oh323_pvt::nativeformats, ast_channel::nativeformats, oh323_pvt::needhangup, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newduration, oh323_pvt::newstate, oh323_simulate_dtmf_end(), oh323_pvt::owner, ast_channel::readformat, oh323_pvt::rtp, ast_frame::subclass, oh323_pvt::update_rtp_info, and ast_channel::writeformat.
Referenced by oh323_read(), oh323_update_info(), and oh323_write().
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_instance_fd(pvt->rtp, 0)); 00387 ast_channel_set_fd(c, 1, ast_rtp_instance_fd(pvt->rtp, 1)); 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 3394 of file chan_h323.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 3394 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 2217 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().
02218 { 02219 struct oh323_pvt *pvt; 02220 struct ast_channel *c = NULL; 02221 enum {ext_original, ext_s, ext_i, ext_notexists} try_exten; 02222 char tmp_exten[sizeof(pvt->exten)]; 02223 02224 if (h323debug) 02225 ast_debug(1, "Preparing Asterisk to answer for %s\n", token); 02226 02227 /* Find the call or allocate a private structure if call not found */ 02228 pvt = find_call_locked(call_reference, token); 02229 if (!pvt) { 02230 ast_log(LOG_ERROR, "Something is wrong: answer_call\n"); 02231 return 0; 02232 } 02233 /* Check if requested extension@context pair exists in the dialplan */ 02234 ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten)); 02235 02236 /* Try to find best extension in specified context */ 02237 if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) { 02238 if (tmp_exten[0] == 's') 02239 try_exten = ext_s; 02240 else if (tmp_exten[0] == 'i') 02241 try_exten = ext_i; 02242 else 02243 try_exten = ext_original; 02244 } else 02245 try_exten = ext_original; 02246 do { 02247 if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL)) 02248 break; 02249 switch (try_exten) { 02250 case ext_original: 02251 tmp_exten[0] = 's'; 02252 tmp_exten[1] = '\0'; 02253 try_exten = ext_s; 02254 break; 02255 case ext_s: 02256 tmp_exten[0] = 'i'; 02257 try_exten = ext_i; 02258 break; 02259 case ext_i: 02260 try_exten = ext_notexists; 02261 break; 02262 default: 02263 break; 02264 } 02265 } while (try_exten != ext_notexists); 02266 02267 /* Drop the call if we don't have <exten>, s and i extensions */ 02268 if (try_exten == ext_notexists) { 02269 ast_log(LOG_NOTICE, "Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s]\n", pvt->exten, pvt->context); 02270 ast_mutex_unlock(&pvt->lock); 02271 h323_clear_call(token, AST_CAUSE_UNALLOCATED); 02272 return 0; 02273 } else if ((try_exten != ext_original) && (strcmp(pvt->exten, tmp_exten) != 0)) { 02274 if (h323debug) 02275 ast_debug(1, "Going to extension %s@%s because %s@%s isn't exists\n", tmp_exten, pvt->context, pvt->exten, pvt->context); 02276 ast_copy_string(pvt->exten, tmp_exten, sizeof(pvt->exten)); 02277 } 02278 02279 /* allocate a channel and tell asterisk about it */ 02280 c = __oh323_new(pvt, AST_STATE_RINGING, pvt->cd.call_token, NULL); 02281 02282 /* And release when done */ 02283 ast_mutex_unlock(&pvt->lock); 02284 if (!c) { 02285 ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n"); 02286 return 0; 02287 } 02288 return 1; 02289 }
| static struct oh323_alias* build_alias | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | realtime | |||
| ) | [static, read] |
Definition at line 1189 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().
01190 { 01191 struct oh323_alias *alias; 01192 int found = 0; 01193 01194 alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&aliasl, name, name, 0, 0, strcasecmp); 01195 01196 if (alias) 01197 found++; 01198 else { 01199 if (!(alias = ast_calloc(1, sizeof(*alias)))) 01200 return NULL; 01201 ASTOBJ_INIT(alias); 01202 } 01203 if (!found && name) 01204 ast_copy_string(alias->name, name, sizeof(alias->name)); 01205 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { 01206 if (!strcasecmp(v->name, "e164")) { 01207 ast_copy_string(alias->e164, v->value, sizeof(alias->e164)); 01208 } else if (!strcasecmp(v->name, "prefix")) { 01209 ast_copy_string(alias->prefix, v->value, sizeof(alias->prefix)); 01210 } else if (!strcasecmp(v->name, "context")) { 01211 ast_copy_string(alias->context, v->value, sizeof(alias->context)); 01212 } else if (!strcasecmp(v->name, "secret")) { 01213 ast_copy_string(alias->secret, v->value, sizeof(alias->secret)); 01214 } else { 01215 if (strcasecmp(v->value, "h323")) { 01216 ast_log(LOG_WARNING, "Keyword %s does not make sense in type=h323\n", v->name); 01217 } 01218 } 01219 } 01220 ASTOBJ_UNMARK(alias); 01221 return alias; 01222 }
| static struct oh323_peer* build_peer | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | realtime | |||
| ) | [static, read] |
Definition at line 1476 of file chan_h323.c.
References ast_append_ha(), ast_calloc, ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_strlen_zero(), ast_true(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, oh323_destroy_peer(), peerl, update_common_options(), and ast_variable::value.
Referenced by realtime_peer(), reload_config(), and set_config().
01477 { 01478 struct oh323_peer *peer; 01479 struct ast_ha *oldha; 01480 int found = 0; 01481 01482 peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp); 01483 01484 if (peer) 01485 found++; 01486 else { 01487 if (!(peer = ast_calloc(1, sizeof(*peer)))) 01488 return NULL; 01489 ASTOBJ_INIT(peer); 01490 } 01491 oldha = peer->ha; 01492 peer->ha = NULL; 01493 memcpy(&peer->options, &global_options, sizeof(peer->options)); 01494 peer->options.dtmfmode = 0; 01495 peer->options.holdHandling = 0; 01496 peer->addr.sin_port = htons(h323_signalling_port); 01497 peer->addr.sin_family = AF_INET; 01498 if (!found && name) 01499 ast_copy_string(peer->name, name, sizeof(peer->name)); 01500 01501 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */ 01502 if (peer->chanvars) { 01503 ast_variables_destroy(peer->chanvars); 01504 peer->chanvars = NULL; 01505 } 01506 #endif 01507 /* Default settings for mailbox */ 01508 peer->mailbox[0] = '\0'; 01509 01510 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { 01511 if (!update_common_options(v, &peer->options)) 01512 continue; 01513 if (!strcasecmp(v->name, "host")) { 01514 if (!strcasecmp(v->value, "dynamic")) { 01515 ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n"); 01516 ASTOBJ_UNREF(peer, oh323_destroy_peer); 01517 return NULL; 01518 } 01519 if (ast_get_ip(&peer->addr, v->value)) { 01520 ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value); 01521 ASTOBJ_UNREF(peer, oh323_destroy_peer); 01522 return NULL; 01523 } 01524 } else if (!strcasecmp(v->name, "port")) { 01525 peer->addr.sin_port = htons(atoi(v->value)); 01526 } else if (!strcasecmp(v->name, "permit") || 01527 !strcasecmp(v->name, "deny")) { 01528 int ha_error = 0; 01529 01530 peer->ha = ast_append_ha(v->name, v->value, peer->ha, &ha_error); 01531 if (ha_error) 01532 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 01533 } else if (!strcasecmp(v->name, "mailbox")) { 01534 ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox)); 01535 } else if (!strcasecmp(v->name, "hasvoicemail")) { 01536 if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) { 01537 ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox)); 01538 } 01539 } 01540 } 01541 if (!peer->options.dtmfmode) 01542 peer->options.dtmfmode = global_options.dtmfmode; 01543 if (peer->options.holdHandling == ~0) 01544 peer->options.holdHandling = 0; 01545 else if (!peer->options.holdHandling) 01546 peer->options.holdHandling = global_options.holdHandling; 01547 ASTOBJ_UNMARK(peer); 01548 ast_free_ha(oldha); 01549 return peer; 01550 }
| static struct oh323_user* build_user | ( | const char * | name, | |
| struct ast_variable * | v, | |||
| struct ast_variable * | alt, | |||
| int | realtime | |||
| ) | [static, read] |
Definition at line 1358 of file chan_h323.c.
References ast_append_ha(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), ast_free_ha(), ast_get_ip(), ast_log(), ast_variables_destroy(), ASTOBJ_CONTAINER_FIND_UNLINK_FULL, ASTOBJ_INIT, ASTOBJ_UNMARK, ASTOBJ_UNREF, format, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_user(), update_common_options(), userl, and ast_variable::value.
Referenced by realtime_user(), reload_config(), and set_config().
01359 { 01360 struct oh323_user *user; 01361 struct ast_ha *oldha; 01362 int found = 0; 01363 int format; 01364 01365 user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp); 01366 01367 if (user) 01368 found++; 01369 else { 01370 if (!(user = ast_calloc(1, sizeof(*user)))) 01371 return NULL; 01372 ASTOBJ_INIT(user); 01373 } 01374 oldha = user->ha; 01375 user->ha = (struct ast_ha *)NULL; 01376 memcpy(&user->options, &global_options, sizeof(user->options)); 01377 user->options.dtmfmode = 0; 01378 user->options.holdHandling = 0; 01379 /* Set default context */ 01380 ast_copy_string(user->context, default_context, sizeof(user->context)); 01381 if (user && !found) 01382 ast_copy_string(user->name, name, sizeof(user->name)); 01383 01384 #if 0 /* XXX Port channel variables functionality from chan_sip XXX */ 01385 if (user->chanvars) { 01386 ast_variables_destroy(user->chanvars); 01387 user->chanvars = NULL; 01388 } 01389 #endif 01390 01391 for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { 01392 if (!update_common_options(v, &user->options)) 01393 continue; 01394 if (!strcasecmp(v->name, "context")) { 01395 ast_copy_string(user->context, v->value, sizeof(user->context)); 01396 } else if (!strcasecmp(v->name, "secret")) { 01397 ast_copy_string(user->secret, v->value, sizeof(user->secret)); 01398 } else if (!strcasecmp(v->name, "accountcode")) { 01399 ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode)); 01400 } else if (!strcasecmp(v->name, "host")) { 01401 if (!strcasecmp(v->value, "dynamic")) { 01402 ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n"); 01403 ASTOBJ_UNREF(user, oh323_destroy_user); 01404 return NULL; 01405 } else if (ast_get_ip(&user->addr, v->value)) { 01406 ASTOBJ_UNREF(user, oh323_destroy_user); 01407 return NULL; 01408 } 01409 /* Let us know we need to use ip authentication */ 01410 user->host = 1; 01411 } else if (!strcasecmp(v->name, "amaflags")) { 01412 format = ast_cdr_amaflags2int(v->value); 01413 if (format < 0) { 01414 ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); 01415 } else { 01416 user->amaflags = format; 01417 } 01418 } else if (!strcasecmp(v->name, "permit") || 01419 !strcasecmp(v->name, "deny")) { 01420 int ha_error = 0; 01421 01422 user->ha = ast_append_ha(v->name, v->value, user->ha, &ha_error); 01423 if (ha_error) 01424 ast_log(LOG_ERROR, "Bad ACL entry in configuration line %d : %s\n", v->lineno, v->value); 01425 } 01426 } 01427 if (!user->options.dtmfmode) 01428 user->options.dtmfmode = global_options.dtmfmode; 01429 if (user->options.holdHandling == ~0) 01430 user->options.holdHandling = 0; 01431 else if (!user->options.holdHandling) 01432 user->options.holdHandling = global_options.holdHandling; 01433 ASTOBJ_UNMARK(user); 01434 ast_free_ha(oldha); 01435 return user; 01436 }
| 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 2308 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().
02309 { 02310 struct oh323_pvt *pvt; 02311 02312 if (h323debug) 02313 ast_debug(1, "Ringing on %s\n", token); 02314 02315 pvt = find_call_locked(call_reference, token); 02316 if (!pvt) { 02317 ast_log(LOG_ERROR, "Something is wrong: ringing\n"); 02318 return; 02319 } 02320 if (!pvt->owner) { 02321 ast_mutex_unlock(&pvt->lock); 02322 ast_log(LOG_ERROR, "Channel has no owner\n"); 02323 return; 02324 } 02325 update_state(pvt, AST_STATE_RINGING, AST_CONTROL_RINGING); 02326 ast_mutex_unlock(&pvt->lock); 02327 return; 02328 }
| 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 2334 of file chan_h323.c.
References ast_channel::_softhangup, oh323_pvt::alreadygone, ast_channel_trylock, ast_channel_unlock, ast_debug, ast_dsp_free(), ast_log(), ast_mutex_unlock(), ast_queue_hangup(), ast_rtp_instance_destroy(), AST_SOFTHANGUP_DEV, oh323_pvt::cd, cleanup_call_details(), find_call_locked(), oh323_pvt::lock, LOG_NOTICE, oh323_pvt::owner, oh323_pvt::rtp, and oh323_pvt::vad.
Referenced by load_module().
02335 { 02336 struct oh323_pvt *pvt; 02337 02338 if (h323debug) 02339 ast_debug(1, "Cleaning connection to %s\n", call_token); 02340 02341 while (1) { 02342 pvt = find_call_locked(call_reference, call_token); 02343 if (!pvt) { 02344 if (h323debug) 02345 ast_debug(1, "No connection for %s\n", call_token); 02346 return; 02347 } 02348 if (!pvt->owner || !ast_channel_trylock(pvt->owner)) 02349 break; 02350 #if 1 02351 ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token); 02352 #ifdef DEBUG_THREADS 02353 /* XXX to be completed 02354 * If we want to print more info on who is holding the lock, 02355 * implement the relevant code in lock.h and use the routines 02356 * supplied there. 02357 */ 02358 #endif 02359 #endif 02360 ast_mutex_unlock(&pvt->lock); 02361 usleep(1); 02362 } 02363 if (pvt->rtp) { 02364 /* Immediately stop RTP */ 02365 ast_rtp_instance_destroy(pvt->rtp); 02366 pvt->rtp = NULL; 02367 } 02368 /* Free dsp used for in-band DTMF detection */ 02369 if (pvt->vad) { 02370 ast_dsp_free(pvt->vad); 02371 pvt->vad = NULL; 02372 } 02373 cleanup_call_details(&pvt->cd); 02374 pvt->alreadygone = 1; 02375 /* Send hangup */ 02376 if (pvt->owner) { 02377 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV; 02378 ast_queue_hangup(pvt->owner); 02379 ast_channel_unlock(pvt->owner); 02380 } 02381 ast_mutex_unlock(&pvt->lock); 02382 if (h323debug) 02383 ast_debug(1, "Connection to %s cleaned\n", call_token); 02384 return; 02385 }
| 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 2042 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().
02043 { 02044 struct oh323_pvt *pvt; 02045 02046 if (h323debug) 02047 ast_debug(1, "Call %s answered\n", token); 02048 02049 pvt = find_call_locked(call_reference, token); 02050 if (!pvt) { 02051 ast_log(LOG_ERROR, "Something is wrong: connection\n"); 02052 return; 02053 } 02054 02055 /* Inform asterisk about remote party connected only on outgoing calls */ 02056 if (!pvt->outgoing) { 02057 ast_mutex_unlock(&pvt->lock); 02058 return; 02059 } 02060 /* Do not send ANSWER message more than once */ 02061 if (!pvt->connection_established) { 02062 pvt->connection_established = 1; 02063 update_state(pvt, -1, AST_CONTROL_ANSWER); 02064 } 02065 ast_mutex_unlock(&pvt->lock); 02066 return; 02067 }
| static char* convertcap | ( | int | cap | ) | [static] |
Definition at line 3154 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().
03155 { 03156 switch (cap) { 03157 case AST_FORMAT_G723_1: 03158 return "G.723"; 03159 case AST_FORMAT_GSM: 03160 return "GSM"; 03161 case AST_FORMAT_ULAW: 03162 return "ULAW"; 03163 case AST_FORMAT_ALAW: 03164 return "ALAW"; 03165 case AST_FORMAT_G722: 03166 return "G.722"; 03167 case AST_FORMAT_ADPCM: 03168 return "G.728"; 03169 case AST_FORMAT_G729A: 03170 return "G.729"; 03171 case AST_FORMAT_SPEEX: 03172 return "SPEEX"; 03173 case AST_FORMAT_ILBC: 03174 return "ILBC"; 03175 default: 03176 ast_log(LOG_NOTICE, "Don't know how to deal with mode %d\n", cap); 03177 return NULL; 03178 } 03179 }
| static int create_addr | ( | struct oh323_pvt * | pvt, | |
| char * | opeer | |||
| ) | [static] |
Definition at line 1648 of file chan_h323.c.
References ast_copy_string(), ast_gethostbyname(), ast_log(), AST_RTP_DTMF, ASTOBJ_UNREF, find_peer(), hp, oh323_pvt::jointcapability, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_destroy_peer(), oh323_pvt::options, and oh323_pvt::sa.
Referenced by __sip_subscribe_mwi_do(), cache_get_callno_locked(), iax2_call(), iax2_provision(), iax2_request(), manager_sipnotify(), oh323_request(), sip_cli_notify(), sip_request_call(), and transmit_register().
01649 { 01650 struct hostent *hp; 01651 struct ast_hostent ahp; 01652 struct oh323_peer *p; 01653 int portno; 01654 int found = 0; 01655 char *port; 01656 char *hostn; 01657 char peer[256] = ""; 01658 01659 ast_copy_string(peer, opeer, sizeof(peer)); 01660 port = strchr(peer, ':'); 01661 if (port) { 01662 *port = '\0'; 01663 port++; 01664 } 01665 pvt->sa.sin_family = AF_INET; 01666 p = find_peer(peer, NULL, 1); 01667 if (p) { 01668 found++; 01669 memcpy(&pvt->options, &p->options, sizeof(pvt->options)); 01670 pvt->jointcapability = pvt->options.capability; 01671 if (pvt->options.dtmfmode) { 01672 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { 01673 pvt->nonCodecCapability |= AST_RTP_DTMF; 01674 } else { 01675 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01676 } 01677 } 01678 if (p->addr.sin_addr.s_addr) { 01679 pvt->sa.sin_addr = p->addr.sin_addr; 01680 pvt->sa.sin_port = p->addr.sin_port; 01681 } 01682 ASTOBJ_UNREF(p, oh323_destroy_peer); 01683 } 01684 if (!p && !found) { 01685 hostn = peer; 01686 if (port) { 01687 portno = atoi(port); 01688 } else { 01689 portno = h323_signalling_port; 01690 } 01691 hp = ast_gethostbyname(hostn, &ahp); 01692 if (hp) { 01693 memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr)); 01694 pvt->sa.sin_port = htons(portno); 01695 /* Look peer by address */ 01696 p = find_peer(NULL, &pvt->sa, 1); 01697 memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options)); 01698 pvt->jointcapability = pvt->options.capability; 01699 if (p) { 01700 ASTOBJ_UNREF(p, oh323_destroy_peer); 01701 } 01702 if (pvt->options.dtmfmode) { 01703 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { 01704 pvt->nonCodecCapability |= AST_RTP_DTMF; 01705 } else { 01706 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01707 } 01708 } 01709 return 0; 01710 } else { 01711 ast_log(LOG_WARNING, "No such host: %s\n", peer); 01712 return -1; 01713 } 01714 } else if (!found) { 01715 return -1; 01716 } else { 01717 return 0; 01718 } 01719 }
| static void delete_aliases | ( | void | ) | [static] |
Definition at line 2805 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().
02806 { 02807 int pruned = 0; 02808 02809 /* Delete all aliases */ 02810 ASTOBJ_CONTAINER_WRLOCK(&aliasl); 02811 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do { 02812 ASTOBJ_RDLOCK(iterator); 02813 ASTOBJ_MARK(iterator); 02814 ++pruned; 02815 ASTOBJ_UNLOCK(iterator); 02816 } while (0) ); 02817 if (pruned) { 02818 ASTOBJ_CONTAINER_PRUNE_MARKED(&aliasl, oh323_destroy_alias); 02819 } 02820 ASTOBJ_CONTAINER_UNLOCK(&aliasl); 02821 }
| static void delete_users | ( | void | ) | [static] |
Definition at line 2779 of file chan_h323.c.
References ASTOBJ_CONTAINER_PRUNE_MARKED, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_MARK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, oh323_destroy_user(), peerl, and userl.
Referenced by __unload_module(), reload(), reload_config(), set_config_destroy(), and unload_module().
02780 { 02781 int pruned = 0; 02782 02783 /* Delete all users */ 02784 ASTOBJ_CONTAINER_WRLOCK(&userl); 02785 ASTOBJ_CONTAINER_TRAVERSE(&userl, 1, do { 02786 ASTOBJ_RDLOCK(iterator); 02787 ASTOBJ_MARK(iterator); 02788 ++pruned; 02789 ASTOBJ_UNLOCK(iterator); 02790 } while (0) ); 02791 if (pruned) { 02792 ASTOBJ_CONTAINER_PRUNE_MARKED(&userl, oh323_destroy_user); 02793 } 02794 ASTOBJ_CONTAINER_UNLOCK(&userl); 02795 02796 ASTOBJ_CONTAINER_WRLOCK(&peerl); 02797 ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do { 02798 ASTOBJ_RDLOCK(iterator); 02799 ASTOBJ_MARK(iterator); 02800 ASTOBJ_UNLOCK(iterator); 02801 } while (0) ); 02802 ASTOBJ_CONTAINER_UNLOCK(&peerl); 02803 }
| static void* do_monitor | ( | void * | data | ) | [static] |
Definition at line 2526 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.
02527 { 02528 int res; 02529 int reloading; 02530 struct oh323_pvt *oh323 = NULL; 02531 02532 for(;;) { 02533 /* Check for a reload request */ 02534 ast_mutex_lock(&h323_reload_lock); 02535 reloading = h323_reloading; 02536 h323_reloading = 0; 02537 ast_mutex_unlock(&h323_reload_lock); 02538 if (reloading) { 02539 ast_verb(1, "Reloading H.323\n"); 02540 h323_do_reload(); 02541 } 02542 /* Check for interfaces needing to be killed */ 02543 if (!ast_mutex_trylock(&iflock)) { 02544 #if 1 02545 do { 02546 for (oh323 = iflist; oh323; oh323 = oh323->next) { 02547 if (!ast_mutex_trylock(&oh323->lock)) { 02548 if (oh323->needdestroy) { 02549 __oh323_destroy(oh323); 02550 break; 02551 } 02552 ast_mutex_unlock(&oh323->lock); 02553 } 02554 } 02555 } while (/*oh323*/ 0); 02556 #else 02557 restartsearch: 02558 oh323 = iflist; 02559 while(oh323) { 02560 if (!ast_mutex_trylock(&oh323->lock)) { 02561 if (oh323->needdestroy) { 02562 __oh323_destroy(oh323); 02563 goto restartsearch; 02564 } 02565 ast_mutex_unlock(&oh323->lock); 02566 oh323 = oh323->next; 02567 } 02568 } 02569 #endif 02570 ast_mutex_unlock(&iflock); 02571 } else 02572 oh323 = (struct oh323_pvt *)1; /* Force fast loop */ 02573 pthread_testcancel(); 02574 /* Wait for sched or io */ 02575 res = ast_sched_wait(sched); 02576 if ((res < 0) || (res > 1000)) { 02577 res = 1000; 02578 } 02579 /* Do not wait if some channel(s) is destroyed, probably, more available too */ 02580 if (oh323) 02581 res = 1; 02582 res = ast_io_wait(io, res); 02583 pthread_testcancel(); 02584 ast_mutex_lock(&monlock); 02585 if (res >= 0) { 02586 ast_sched_runq(sched); 02587 } 02588 ast_mutex_unlock(&monlock); 02589 } 02590 /* Never reached */ 02591 return NULL; 02592 }
| 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 1893 of file chan_h323.c.
References __oh323_rtp_create(), ast_calloc, ast_copy_string(), ast_debug, ast_free, ast_inet_ntoa(), ast_log(), ast_mutex_unlock(), ast_rtp_instance_get_local_address(), find_call_locked(), oh323_pvt::lock, LOG_ERROR, and oh323_pvt::rtp.
Referenced by load_module().
01894 { 01895 struct oh323_pvt *pvt; 01896 struct sockaddr_in us; 01897 struct rtp_info *info; 01898 01899 info = ast_calloc(1, sizeof(*info)); 01900 if (!info) { 01901 ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n"); 01902 return NULL; 01903 } 01904 pvt = find_call_locked(call_reference, token); 01905 if (!pvt) { 01906 ast_free(info); 01907 ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference); 01908 return NULL; 01909 } 01910 if (!pvt->rtp) 01911 __oh323_rtp_create(pvt); 01912 if (!pvt->rtp) { 01913 ast_mutex_unlock(&pvt->lock); 01914 ast_free(info); 01915 ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference); 01916 return NULL; 01917 } 01918 /* figure out our local RTP port and tell the H.323 stack about it */ 01919 ast_rtp_instance_get_local_address(pvt->rtp, &us); 01920 ast_mutex_unlock(&pvt->lock); 01921 01922 ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr)); 01923 info->port = ntohs(us.sin_port); 01924 if (h323debug) 01925 ast_debug(1, "Sending RTP 'US' %s:%d\n", info->addr, info->port); 01926 return info; 01927 }
| static struct oh323_alias* find_alias | ( | const char * | source_aliases, | |
| int | realtime | |||
| ) | [static, read] |
Find a call by alias.
Definition at line 1809 of file chan_h323.c.
References aliasl, ASTOBJ_CONTAINER_FIND, and realtime_alias().
Referenced by __get_header(), add_header(), and setup_incoming_call().
01810 { 01811 struct oh323_alias *a; 01812 01813 a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases); 01814 01815 if (!a && realtime) 01816 a = realtime_alias(source_aliases); 01817 01818 return a; 01819 }
| static struct oh323_pvt* find_call_locked | ( | int | call_reference, | |
| const char * | token | |||
| ) | [static, read] |
Definition at line 1142 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().
01143 { 01144 struct oh323_pvt *pvt; 01145 01146 ast_mutex_lock(&iflock); 01147 pvt = iflist; 01148 while(pvt) { 01149 if (!pvt->needdestroy && ((signed int)pvt->cd.call_reference == call_reference)) { 01150 /* Found the call */ 01151 if ((token != NULL) && (pvt->cd.call_token != NULL) && (!strcmp(pvt->cd.call_token, token))) { 01152 ast_mutex_lock(&pvt->lock); 01153 ast_mutex_unlock(&iflock); 01154 return pvt; 01155 } else if (token == NULL) { 01156 ast_log(LOG_WARNING, "Call Token is NULL\n"); 01157 ast_mutex_lock(&pvt->lock); 01158 ast_mutex_unlock(&iflock); 01159 return pvt; 01160 } 01161 } 01162 pvt = pvt->next; 01163 } 01164 ast_mutex_unlock(&iflock); 01165 return NULL; 01166 }
| static struct oh323_peer* find_peer | ( | const char * | peer, | |
| struct sockaddr_in * | sin, | |||
| int | realtime | |||
| ) | [static, read] |
Definition at line 1630 of file chan_h323.c.
References ast_debug, ast_inet_ntoa(), ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, oh323_addrcmp(), peerl, and realtime_peer().
Referenced by _sip_qualify_peer(), _sip_show_peer(), calltoken_required(), check_peer_ok(), create_addr(), dundi_encrypt(), function_iaxpeer(), function_sippeer(), handle_cli_iax2_prune_realtime(), handle_cli_iax2_set_debug(), handle_cli_iax2_show_peer(), handle_cli_iax2_unregister(), handle_command_response(), handle_request_notify(), handle_response(), iax2_devicestate(), register_verify(), registry_authrequest(), requirecalltoken_mark_auto(), set_config(), sip_devicestate(), sip_do_debug_peer(), sip_peer_hold(), sip_show_user(), sip_unregister(), st_get_mode(), st_get_refresher(), st_get_se(), transmit_register(), update_call_counter(), and update_registry().
01631 { 01632 struct oh323_peer *p; 01633 01634 if (peer) 01635 p = ASTOBJ_CONTAINER_FIND(&peerl, peer); 01636 else 01637 p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp); 01638 01639 if (!p && realtime) 01640 p = realtime_peer(peer, sin); 01641 01642 if (!p && h323debug) 01643 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>")); 01644 01645 return p; 01646 }
| static struct oh323_user* find_user | ( | const call_details_t * | cd, | |
| int | realtime | |||
| ) | [static, read] |
Definition at line 1600 of file chan_h323.c.
References ast_debug, ASTOBJ_CONTAINER_FIND, ASTOBJ_CONTAINER_FIND_FULL, oh323_addrcmp_str(), realtime_user(), and userl.
01601 { 01602 struct oh323_user *u; 01603 01604 if (userbyalias) 01605 u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases); 01606 else 01607 u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str); 01608 01609 if (!u && realtime) 01610 u = realtime_user(cd); 01611 01612 if (!u && h323debug) 01613 ast_debug(1, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp); 01614 01615 return u; 01616 }
| static int h323_do_reload | ( | void | ) | [static] |
Definition at line 3116 of file chan_h323.c.
References reload_config().
Referenced by do_monitor().
03117 { 03118 reload_config(1); 03119 return 0; 03120 }
| static int h323_reload | ( | void | ) | [static] |
Definition at line 3082 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().
03083 { 03084 ast_mutex_lock(&h323_reload_lock); 03085 if (h323_reloading) { 03086 ast_verbose("Previous H.323 reload not yet done\n"); 03087 } else { 03088 h323_reloading = 1; 03089 } 03090 ast_mutex_unlock(&h323_reload_lock); 03091 restart_monitor(); 03092 return 0; 03093 }
| static char* handle_cli_h323_cycle_gk | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2678 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.
02679 { 02680 switch (cmd) { 02681 case CLI_INIT: 02682 e->command = "h323 cycle gk"; 02683 e->usage = 02684 "Usage: h323 cycle gk\n" 02685 " Manually re-register with the Gatekeper (Currently Disabled)\n"; 02686 return NULL; 02687 case CLI_GENERATE: 02688 return NULL; 02689 } 02690 02691 if (a->argc != 3) 02692 return CLI_SHOWUSAGE; 02693 02694 h323_gk_urq(); 02695 02696 /* Possibly register with a GK */ 02697 if (!gatekeeper_disable) { 02698 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { 02699 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); 02700 } 02701 } 02702 return CLI_SUCCESS; 02703 }
| static char* handle_cli_h323_hangup | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2705 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.
02706 { 02707 switch (cmd) { 02708 case CLI_INIT: 02709 e->command = "h323 hangup"; 02710 e->usage = 02711 "Usage: h323 hangup <token>\n" 02712 " Manually try to hang up the call identified by <token>\n"; 02713 return NULL; 02714 case CLI_GENERATE: 02715 return NULL; 02716 } 02717 02718 if (a->argc != 3) 02719 return CLI_SHOWUSAGE; 02720 if (h323_soft_hangup(a->argv[2])) { 02721 ast_verb(3, "Hangup succeeded on %s\n", a->argv[2]); 02722 } else { 02723 ast_verb(3, "Hangup failed for %s\n", a->argv[2]); 02724 } 02725 return CLI_SUCCESS; 02726 }
| static char* handle_cli_h323_reload | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 3095 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.
03096 { 03097 switch (cmd) { 03098 case CLI_INIT: 03099 e->command = "h323 reload"; 03100 e->usage = 03101 "Usage: h323 reload\n" 03102 " Reloads H.323 configuration from h323.conf\n"; 03103 return NULL; 03104 case CLI_GENERATE: 03105 return NULL; 03106 } 03107 03108 if (a->argc != 2) 03109 return CLI_SHOWUSAGE; 03110 03111 h323_reload(); 03112 03113 return CLI_SUCCESS; 03114 }
| static char* handle_cli_h323_set_debug | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2655 of file chan_h323.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02656 { 02657 switch (cmd) { 02658 case CLI_INIT: 02659 e->command = "h323 set debug [on|off]"; 02660 e->usage = 02661 "Usage: h323 set debug [on|off]\n" 02662 " Enable/Disable H.323 debugging output\n"; 02663 return NULL; 02664 case CLI_GENERATE: 02665 return NULL; 02666 } 02667 02668 if (a->argc != e->args) 02669 return CLI_SHOWUSAGE; 02670 if (strcasecmp(a->argv[3], "on") && strcasecmp(a->argv[3], "off")) 02671 return CLI_SHOWUSAGE; 02672 02673 h323debug = (strcasecmp(a->argv[3], "on")) ? 0 : 1; 02674 ast_cli(a->fd, "H.323 Debugging %s\n", h323debug ? "Enabled" : "Disabled"); 02675 return CLI_SUCCESS; 02676 }
| static char* handle_cli_h323_set_trace | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2626 of file chan_h323.c.
References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
02627 { 02628 switch (cmd) { 02629 case CLI_INIT: 02630 e->command = "h323 set trace [on|off]"; 02631 e->usage = 02632 "Usage: h323 set trace (on|off|<trace level>)\n" 02633 " Enable/Disable H.323 stack tracing for debugging purposes\n"; 02634 return NULL; 02635 case CLI_GENERATE: 02636 return NULL; 02637 } 02638 02639 if (a->argc != e->args) 02640 return CLI_SHOWUSAGE; 02641 if (!strcasecmp(a->argv[3], "off")) { 02642 h323_debug(0, 0); 02643 ast_cli(a->fd, "H.323 Trace Disabled\n"); 02644 } else if (!strcasecmp(a->argv[3], "on")) { 02645 h323_debug(1, 1); 02646 ast_cli(a->fd, "H.323 Trace Enabled\n"); 02647 } else { 02648 int tracelevel = atoi(a->argv[3]); 02649 h323_debug(1, tracelevel); 02650 ast_cli(a->fd, "H.323 Trace Enabled (Trace Level: %d)\n", tracelevel); 02651 } 02652 return CLI_SUCCESS; 02653 }
| static char* handle_cli_h323_show_tokens | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2728 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.
02729 { 02730 switch (cmd) { 02731 case CLI_INIT: 02732 e->command = "h323 show tokens"; 02733 e->usage = 02734 "Usage: h323 show tokens\n" 02735 " Print out all active call tokens\n"; 02736 return NULL; 02737 case CLI_GENERATE: 02738 return NULL; 02739 } 02740 02741 if (a->argc != 3) 02742 return CLI_SHOWUSAGE; 02743 02744 h323_show_tokens(); 02745 02746 return CLI_SUCCESS; 02747 }
| static char* handle_cli_h323_show_version | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2749 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.
02750 { 02751 switch (cmd) { 02752 case CLI_INIT: 02753 e->command = "h323 show version"; 02754 e->usage = 02755 "Usage: h323 show version\n" 02756 " Show the version of the H.323 library in use\n"; 02757 return NULL; 02758 case CLI_GENERATE: 02759 return NULL; 02760 } 02761 02762 if (a->argc != 3) 02763 return CLI_SHOWUSAGE; 02764 02765 h323_show_version(); 02766 02767 return CLI_SUCCESS; 02768 }
| static void hangup_connection | ( | unsigned int | call_reference, | |
| const char * | token, | |||
| int | cause | |||
| ) | [static] |
Definition at line 2387 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().
02388 { 02389 struct oh323_pvt *pvt; 02390 02391 if (h323debug) 02392 ast_debug(1, "Hanging up connection to %s with cause %d\n", token, cause); 02393 02394 pvt = find_call_locked(call_reference, token); 02395 if (!pvt) { 02396 if (h323debug) 02397 ast_debug(1, "Connection to %s already cleared\n", token); 02398 return; 02399 } 02400 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 02401 pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV; 02402 pvt->owner->hangupcause = pvt->hangupcause = cause; 02403 ast_queue_hangup_with_cause(pvt->owner, cause); 02404 ast_channel_unlock(pvt->owner); 02405 } 02406 else { 02407 pvt->needhangup = 1; 02408 pvt->hangupcause = cause; 02409 if (h323debug) 02410 ast_debug(1, "Hangup for %s is pending\n", token); 02411 } 02412 ast_mutex_unlock(&pvt->lock); 02413 }
| static enum ast_module_load_result load_module | ( | void | ) | [static] |
Definition at line 3213 of file chan_h323.c.
References aliasl, answer_call(), ast_channel_register(), ast_cli_register(), ast_cli_register_multiple(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, ast_rtp_glue_unregister(), ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, ASTOBJ_CONTAINER_INIT, bindaddr, chan_ringing(), cleanup_connection(), connection_made(), external_rtp_create(), hangup_connection(), io_context_create(), io_context_destroy(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, receive_digit(), reload_config(), remote_hold(), restart_monitor(), sched_context_create(), sched_context_destroy(), set_dtmf_payload(), set_local_capabilities(), set_peer_capabilities(), setup_incoming_call(), setup_outgoing_call(), setup_rtp_connection(), and userl.
03214 { 03215 int res; 03216 03217 h323debug = 0; 03218 sched = sched_context_create(); 03219 if (!sched) { 03220 ast_log(LOG_WARNING, "Unable to create schedule context\n"); 03221 return AST_MODULE_LOAD_FAILURE; 03222 } 03223 io = io_context_create(); 03224 if (!io) { 03225 ast_log(LOG_WARNING, "Unable to create I/O context\n"); 03226 return AST_MODULE_LOAD_FAILURE; 03227 } 03228 ast_cli_register(&cli_h323_reload); 03229 ASTOBJ_CONTAINER_INIT(&userl); 03230 ASTOBJ_CONTAINER_INIT(&peerl); 03231 ASTOBJ_CONTAINER_INIT(&aliasl); 03232 res = reload_config(0); 03233 if (res) { 03234 /* No config entry */ 03235 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n"); 03236 ast_cli_unregister(&cli_h323_reload); 03237 io_context_destroy(io); 03238 io = NULL; 03239 sched_context_destroy(sched); 03240 sched = NULL; 03241 ASTOBJ_CONTAINER_DESTROY(&userl); 03242 ASTOBJ_CONTAINER_DESTROY(&peerl); 03243 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03244 return AST_MODULE_LOAD_DECLINE; 03245 } else { 03246 /* Make sure we can register our channel type */ 03247 if (ast_channel_register(&oh323_tech)) { 03248 ast_log(LOG_ERROR, "Unable to register channel class 'H323'\n"); 03249 ast_cli_unregister(&cli_h323_reload); 03250 h323_end_process(); 03251 io_context_destroy(io); 03252 sched_context_destroy(sched); 03253 03254 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user); 03255 ASTOBJ_CONTAINER_DESTROY(&userl); 03256 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer); 03257 ASTOBJ_CONTAINER_DESTROY(&peerl); 03258 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias); 03259 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03260 03261 return AST_MODULE_LOAD_FAILURE; 03262 } 03263 ast_cli_register_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry)); 03264 03265 ast_rtp_glue_register(&oh323_rtp_glue); 03266 03267 /* Register our callback functions */ 03268 h323_callback_register(setup_incoming_call, 03269 setup_outgoing_call, 03270 external_rtp_create, 03271 setup_rtp_connection, 03272 cleanup_connection, 03273 chan_ringing, 03274 connection_made, 03275 receive_digit, 03276 answer_call, 03277 progress, 03278 set_dtmf_payload, 03279 hangup_connection, 03280 set_local_capabilities, 03281 set_peer_capabilities, 03282 remote_hold); 03283 /* start the h.323 listener */ 03284 if (h323_start_listener(h323_signalling_port, bindaddr)) { 03285 ast_log(LOG_ERROR, "Unable to create H323 listener.\n"); 03286 ast_rtp_glue_unregister(&oh323_rtp_glue); 03287 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry)); 03288 ast_cli_unregister(&cli_h323_reload); 03289 h323_end_process(); 03290 io_context_destroy(io); 03291 sched_context_destroy(sched); 03292 03293 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user); 03294 ASTOBJ_CONTAINER_DESTROY(&userl); 03295 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer); 03296 ASTOBJ_CONTAINER_DESTROY(&peerl); 03297 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias); 03298 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03299 03300 return AST_MODULE_LOAD_FAILURE; 03301 } 03302 /* Possibly register with a GK */ 03303 if (!gatekeeper_disable) { 03304 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { 03305 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); 03306 gatekeeper_disable = 1; 03307 res = AST_MODULE_LOAD_SUCCESS; 03308 } 03309 } 03310 /* And start the monitor for the first time */ 03311 restart_monitor(); 03312 } 03313 return res; 03314 }
| static int oh323_addrcmp | ( | struct sockaddr_in | addr, | |
| struct sockaddr_in * | sin | |||
| ) | [static] |
Definition at line 1618 of file chan_h323.c.
References inaddrcmp().
Referenced by find_peer().
01619 { 01620 int res; 01621 01622 if (!sin) 01623 res = -1; 01624 else 01625 res = inaddrcmp(&addr , sin); 01626 01627 return res; 01628 }
| static int oh323_addrcmp_str | ( | struct in_addr | inaddr, | |
| char * | addr | |||
| ) | [static] |
Definition at line 1595 of file chan_h323.c.
References ast_inet_ntoa().
Referenced by find_user().
01596 { 01597 return strcmp(ast_inet_ntoa(inaddr), addr); 01598 }
| static struct oh323_pvt* oh323_alloc | ( | int | callid | ) | [static, read] |
Definition at line 1099 of file chan_h323.c.
References ast_calloc, ast_copy_string(), ast_free, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_DTMF, ast_rtp_instance_destroy(), oh323_pvt::cd, oh323_pvt::context, oh323_pvt::DTMFsched, iflist, iflock, oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, oh323_pvt::newcontrol, oh323_pvt::newdigit, oh323_pvt::newstate, oh323_pvt::next, oh323_pvt::nonCodecCapability, oh323_pvt::options, oh323_pvt::rtp, and oh323_pvt::update_rtp_info.
Referenced by oh323_request(), and setup_incoming_call().
01100 { 01101 struct oh323_pvt *pvt; 01102 01103 pvt = ast_calloc(1, sizeof(*pvt)); 01104 if (!pvt) { 01105 ast_log(LOG_ERROR, "Couldn't allocate private structure. This is bad\n"); 01106 return NULL; 01107 } 01108 pvt->cd.redirect_reason = -1; 01109 pvt->cd.transfer_capability = -1; 01110 /* Ensure the call token is allocated for outgoing call */ 01111 if (!callid) { 01112 if ((pvt->cd).call_token == NULL) { 01113 (pvt->cd).call_token = ast_calloc(1, 128); 01114 } 01115 if (!pvt->cd.call_token) { 01116 ast_log(LOG_ERROR, "Not enough memory to alocate call token\n"); 01117 ast_rtp_instance_destroy(pvt->rtp); 01118 ast_free(pvt); 01119 return NULL; 01120 } 01121 memset((char *)(pvt->cd).call_token, 0, 128); 01122 pvt->cd.call_reference = callid; 01123 } 01124 memcpy(&pvt->options, &global_options, sizeof(pvt->options)); 01125 pvt->jointcapability = pvt->options.capability; 01126 if (pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO)) { 01127 pvt->nonCodecCapability |= AST_RTP_DTMF; 01128 } else { 01129 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01130 } 01131 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 01132 pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->update_rtp_info = pvt->DTMFsched = -1; 01133 ast_mutex_init(&pvt->lock); 01134 /* Add to interface list */ 01135 ast_mutex_lock(&iflock); 01136 pvt->next = iflist; 01137 iflist = pvt; 01138 ast_mutex_unlock(&iflock); 01139 return pvt; 01140 }
| static int oh323_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 656 of file chan_h323.c.
References ast_channel::_state, ast_debug, ast_free, ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::lock, ast_channel::name, oh323_update_info(), and ast_channel::tech_pvt.
00657 { 00658 int res; 00659 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00660 char *token; 00661 00662 if (h323debug) 00663 ast_debug(1, "Answering on %s\n", c->name); 00664 00665 ast_mutex_lock(&pvt->lock); 00666 token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL; 00667 ast_mutex_unlock(&pvt->lock); 00668 res = h323_answering_call(token, 0); 00669 if (token) 00670 ast_free(token); 00671 00672 oh323_update_info(c); 00673 if (c->_state != AST_STATE_UP) { 00674 ast_setstate(c, AST_STATE_UP); 00675 } 00676 return res; 00677 }
| 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_rdnis, ast_channel::connected, oh323_pvt::exten, ast_party_connected_line::id, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_party_id::name, ast_channel::name, ast_party_id::number, ast_party_id::number_presentation, ast_party_id::number_type, 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->connected.id.number) 00612 ast_copy_string(pvt->options.cid_num, c->connected.id.number, sizeof(pvt->options.cid_num)); 00613 00614 if (c->connected.id.name) 00615 ast_copy_string(pvt->options.cid_name, c->connected.id.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->connected.id.number_presentation; 00622 pvt->options.type_of_number = c->connected.id.number_type; 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")) 00630 pvt->options.redirect_reason = 2; 00631 else if (!strcasecmp(addr, "UNCONDITIONAL")) 00632 pvt->options.redirect_reason = 15; 00633 else 00634 pvt->options.redirect_reason = -1; 00635 } else 00636 pvt->options.redirect_reason = -1; 00637 00638 pvt->options.transfer_capability = c->transfercapability; 00639 00640 /* indicate that this is an outgoing call */ 00641 pvt->outgoing = 1; 00642 00643 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability)); 00644 if (h323debug) 00645 ast_debug(1, "Placing outgoing call to %s, %d/%d\n", called_addr, pvt->options.dtmfcodec[0], pvt->options.dtmfcodec[1]); 00646 ast_mutex_unlock(&pvt->lock); 00647 res = h323_make_call(called_addr, &(pvt->cd), &pvt->options); 00648 if (res) { 00649 ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name); 00650 return -1; 00651 } 00652 oh323_update_info(c); 00653 return 0; 00654 }
| 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, ast_channel::name, 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().
00279 { 00280 if (h323debug) 00281 ast_debug(1, "Destroying alias '%s'\n", alias->name); 00282 ast_free(alias); 00283 }
| 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().
00286 { 00287 if (h323debug) 00288 ast_debug(1, "Destroying user '%s'\n", user->name); 00289 ast_free_ha(user->ha); 00290 ast_free(user); 00291 }
| 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_instance_dtmf_begin(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.
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_instance_dtmf_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_instance_dtmf_end(), ast_strdup, oh323_pvt::cd, oh323_pvt::dtmf_pt, oh323_pvt::lock, LOG_DTMF, LOG_ERROR, ast_channel::name, oh323_update_info(), oh323_pvt::options, oh323_pvt::rtp, ast_channel::tech_pvt, and oh323_pvt::txDtmfDigit.
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_instance_dtmf_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 935 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.
00936 { 00937 struct oh323_pvt *pvt = (struct oh323_pvt *) newchan->tech_pvt; 00938 00939 ast_mutex_lock(&pvt->lock); 00940 if (pvt->owner != oldchan) { 00941 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, pvt->owner); 00942 return -1; 00943 } 00944 pvt->owner = newchan; 00945 ast_mutex_unlock(&pvt->lock); 00946 return 0; 00947 }
| static enum ast_rtp_glue_result oh323_get_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp_instance ** | instance | |||
| ) | [static] |
Definition at line 3134 of file chan_h323.c.
References ao2_ref, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, oh323_pvt::lock, oh323_pvt::options, oh323_pvt::rtp, and ast_channel::tech_pvt.
03135 { 03136 struct oh323_pvt *pvt; 03137 enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL; 03138 03139 if (!(pvt = (struct oh323_pvt *)chan->tech_pvt)) 03140 return AST_RTP_GLUE_RESULT_FORBID; 03141 03142 ast_mutex_lock(&pvt->lock); 03143 *instance = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL; 03144 #if 0 03145 if (pvt->options.bridge) { 03146 res = AST_RTP_GLUE_RESULT_REMOTE; 03147 } 03148 #endif 03149 ast_mutex_unlock(&pvt->lock); 03150 03151 return res; 03152 }
| static int oh323_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 679 of file chan_h323.c.
References oh323_pvt::alreadygone, AST_CAUSE_CALL_REJECTED, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_CLEARING, AST_CAUSE_REQUESTED_CHAN_UNAVAIL, AST_CAUSE_USER_BUSY, ast_debug, ast_free, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, cause, oh323_pvt::cd, oh323_pvt::hangupcause, ast_channel::hangupcause, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_pvt::needdestroy, oh323_pvt::owner, pbx_builtin_getvar_helper(), and ast_channel::tech_pvt.
00680 { 00681 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00682 int q931cause = AST_CAUSE_NORMAL_CLEARING; 00683 char *call_token; 00684 00685 00686 if (h323debug) 00687 ast_debug(1, "Hanging up and scheduling destroy of call %s\n", c->name); 00688 00689 if (!c->tech_pvt) { 00690 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 00691 return 0; 00692 } 00693 ast_mutex_lock(&pvt->lock); 00694 /* Determine how to disconnect */ 00695 if (pvt->owner != c) { 00696 ast_log(LOG_WARNING, "Huh? We aren't the owner?\n"); 00697 ast_mutex_unlock(&pvt->lock); 00698 return 0; 00699 } 00700 00701 pvt->owner = NULL; 00702 c->tech_pvt = NULL; 00703 00704 if (c->hangupcause) { 00705 q931cause = c->hangupcause; 00706 } else { 00707 const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS"); 00708 if (cause) { 00709 if (!strcmp(cause, "CONGESTION")) { 00710 q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION; 00711 } else if (!strcmp(cause, "BUSY")) { 00712 q931cause = AST_CAUSE_USER_BUSY; 00713 } else if (!strcmp(cause, "CHANISUNVAIL")) { 00714 q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL; 00715 } else if (!strcmp(cause, "NOANSWER")) { 00716 q931cause = AST_CAUSE_NO_ANSWER; 00717 } else if (!strcmp(cause, "CANCEL")) { 00718 q931cause = AST_CAUSE_CALL_REJECTED; 00719 } 00720 } 00721 } 00722 00723 /* Start the process if it's not already started */ 00724 if (!pvt->alreadygone && !pvt->hangupcause) { 00725 call_token = pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL; 00726 if (call_token) { 00727 /* Release lock to eliminate deadlock */ 00728 ast_mutex_unlock(&pvt->lock); 00729 if (h323_clear_call(call_token, q931cause)) { 00730 ast_log(LOG_WARNING, "ClearCall failed.\n"); 00731 } 00732 ast_free(call_token); 00733 ast_mutex_lock(&pvt->lock); 00734 } 00735 } 00736 pvt->needdestroy = 1; 00737 ast_mutex_unlock(&pvt->lock); 00738 00739 /* Update usage counter */ 00740 ast_module_unref(ast_module_info->self); 00741 00742 return 0; 00743 }
| static int oh323_indicate | ( | struct ast_channel * | c, | |
| int | condition, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 854 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_instance_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, oh323_pvt::cd, oh323_pvt::got_progress, oh323_pvt::lock, LOG_WARNING, ast_channel::name, oh323_update_info(), oh323_pvt::rtp, and ast_channel::tech_pvt.
00855 { 00856 00857 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00858 char *token = (char *)NULL; 00859 int res = -1; 00860 int got_progress; 00861 00862 ast_mutex_lock(&pvt->lock); 00863 token = (pvt->cd.call_token ? ast_strdup(pvt->cd.call_token) : NULL); 00864 got_progress = pvt->got_progress; 00865 if (condition == AST_CONTROL_PROGRESS) 00866 pvt->got_progress = 1; 00867 else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION)) 00868 pvt->alreadygone = 1; 00869 ast_mutex_unlock(&pvt->lock); 00870 00871 if (h323debug) 00872 ast_debug(1, "OH323: Indicating %d on %s (%s)\n", condition, token, c->name); 00873 00874 switch(condition) { 00875 case AST_CONTROL_RINGING: 00876 if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) { 00877 h323_send_alerting(token); 00878 res = (got_progress ? 0 : -1); /* Do not simulate any audio tones if we got PROGRESS message */ 00879 } 00880 break; 00881 case AST_CONTROL_PROGRESS: 00882 if (c->_state != AST_STATE_UP) { 00883 /* Do not send PROGRESS message more than once */ 00884 if (!got_progress) 00885 h323_send_progress(token); 00886 res = 0; 00887 } 00888 break; 00889 case AST_CONTROL_BUSY: 00890 if (c->_state != AST_STATE_UP) { 00891 h323_answering_call(token, 1); 00892 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV); 00893 res = 0; 00894 } 00895 break; 00896 case AST_CONTROL_CONGESTION: 00897 if (c->_state != AST_STATE_UP) { 00898 h323_answering_call(token, 1); 00899 ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV); 00900 res = 0; 00901 } 00902 break; 00903 case AST_CONTROL_HOLD: 00904 h323_hold_call(token, 1); 00905 /* We should start MOH only if remote party isn't provide audio for us */ 00906 ast_moh_start(c, data, NULL); 00907 res = 0; 00908 break; 00909 case AST_CONTROL_UNHOLD: 00910 h323_hold_call(token, 0); 00911 ast_moh_stop(c); 00912 res = 0; 00913 break; 00914 case AST_CONTROL_SRCUPDATE: 00915 ast_rtp_instance_new_source(pvt->rtp); 00916 res = 0; 00917 break; 00918 case AST_CONTROL_PROCEEDING: 00919 case -1: 00920 break; 00921 default: 00922 ast_log(LOG_WARNING, "OH323: Don't know how to indicate condition %d on %s\n", condition, token); 00923 break; 00924 } 00925 00926 if (h323debug) 00927 ast_debug(1, "OH323: Indicated %d on %s, res=%d\n", condition, token, res); 00928 if (token) 00929 ast_free(token); 00930 oh323_update_info(c); 00931 00932 return res; 00933 }
| static struct ast_frame * oh323_read | ( | struct ast_channel * | c | ) | [static, read] |
Definition at line 801 of file chan_h323.c.
References __oh323_update_info(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_rtp_instance_read(), ast_channel::fdno, oh323_pvt::lock, LOG_ERROR, ast_channel::name, oh323_rtp_read(), oh323_pvt::rtp, and ast_channel::tech_pvt.
00802 { 00803 struct ast_frame *fr; 00804 struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt; 00805 ast_mutex_lock(&pvt->lock); 00806 __oh323_update_info(c, pvt); 00807 switch(c->fdno) { 00808 case 0: 00809 fr = oh323_rtp_read(pvt); 00810 break; 00811 case 1: 00812 if (pvt->rtp) 00813 fr = ast_rtp_instance_read(pvt->rtp, 1); 00814 else 00815 fr = &ast_null_frame; 00816 break; 00817 default: 00818 ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name); 00819 fr = &ast_null_frame; 00820 break; 00821 } 00822 ast_mutex_unlock(&pvt->lock); 00823 return fr; 00824 }
| static struct ast_channel * oh323_request | ( | const char * | type, | |
| int | format, | |||
| const struct ast_channel * | requestor, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 1720 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, ast_channel::linkedid, oh323_pvt::lock, LOG_NOTICE, LOG_WARNING, oh323_pvt::nonCodecCapability, oh323_alloc(), oh323_destroy(), oh323_pvt::options, and restart_monitor().
01721 { 01722 int oldformat; 01723 struct oh323_pvt *pvt; 01724 struct ast_channel *tmpc = NULL; 01725 char *dest = (char *)data; 01726 char *ext, *host; 01727 char *h323id = NULL; 01728 char tmp[256], tmp1[256]; 01729 01730 if (h323debug) 01731 ast_debug(1, "type=%s, format=%d, data=%s.\n", type, format, (char *)data); 01732 01733 pvt = oh323_alloc(0); 01734 if (!pvt) { 01735 ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data); 01736 return NULL; 01737 } 01738 oldformat = format; 01739 format &= AST_FORMAT_AUDIO_MASK; 01740 if (!format) { 01741 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format); 01742 oh323_destroy(pvt); 01743 if (cause) 01744 *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION; 01745 return NULL; 01746 } 01747 ast_copy_string(tmp, dest, sizeof(tmp)); 01748 host = strchr(tmp, '@'); 01749 if (host) { 01750 *host = '\0'; 01751 host++; 01752 ext = tmp; 01753 } else { 01754 ext = strrchr(tmp, '/'); 01755 if (ext) 01756 *ext++ = '\0'; 01757 host = tmp; 01758 } 01759 strtok_r(host, "/", &(h323id)); 01760 if (!ast_strlen_zero(h323id)) { 01761 h323_set_id(h323id); 01762 } 01763 if (ext) { 01764 ast_copy_string(pvt->exten, ext, sizeof(pvt->exten)); 01765 } 01766 if (h323debug) 01767 ast_debug(1, "Extension: %s Host: %s\n", pvt->exten, host); 01768 01769 if (gatekeeper_disable) { 01770 if (create_addr(pvt, host)) { 01771 oh323_destroy(pvt); 01772 if (cause) 01773 *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; 01774 return NULL; 01775 } 01776 } 01777 else { 01778 memcpy(&pvt->options, &global_options, sizeof(pvt->options)); 01779 pvt->jointcapability = pvt->options.capability; 01780 if (pvt->options.dtmfmode) { 01781 if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { 01782 pvt->nonCodecCapability |= AST_RTP_DTMF; 01783 } else { 01784 pvt->nonCodecCapability &= ~AST_RTP_DTMF; 01785 } 01786 } 01787 } 01788 01789 ast_mutex_lock(&caplock); 01790 /* Generate unique channel identifier */ 01791 snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique); 01792 tmp1[sizeof(tmp1)-1] = '\0'; 01793 ast_mutex_unlock(&caplock); 01794 01795 ast_mutex_lock(&pvt->lock); 01796 tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1, requestor ? requestor->linkedid : NULL); 01797 ast_mutex_unlock(&pvt->lock); 01798 if (!tmpc) { 01799 oh323_destroy(pvt); 01800 if (cause) 01801 *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE; 01802 } 01803 ast_update_use_count(); 01804 restart_monitor(); 01805 return tmpc; 01806 }
Retrieve audio/etc from channel. Assumes pvt->lock is already held.
Definition at line 746 of file chan_h323.c.
References ast_channel_trylock, ast_channel_unlock, ast_debug, ast_dsp_process(), AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_null_frame, ast_rtp_instance_read(), ast_rtp_instance_set_prop(), AST_RTP_PROPERTY_NAT, ast_set_read_format(), ast_set_write_format(), 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().
00747 { 00748 struct ast_frame *f; 00749 00750 /* Only apply it for the first packet, we just need the correct ip/port */ 00751 if (pvt->options.nat) { 00752 ast_rtp_instance_set_prop(pvt->rtp, AST_RTP_PROPERTY_NAT, pvt->options.nat); 00753 pvt->options.nat = 0; 00754 } 00755 00756 f = ast_rtp_instance_read(pvt->rtp, 0); 00757 /* Don't send RFC2833 if we're not supposed to */ 00758 if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & (H323_DTMF_RFC2833 | H323_DTMF_CISCO))) { 00759 return &ast_null_frame; 00760 } 00761 if (pvt->owner) { 00762 /* We already hold the channel lock */ 00763 if (f->frametype == AST_FRAME_VOICE) { 00764 if (f->subclass != pvt->owner->nativeformats) { 00765 /* Try to avoid deadlock */ 00766 if (ast_channel_trylock(pvt->owner)) { 00767 ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n"); 00768 return &ast_null_frame; 00769 } 00770 if (h323debug) 00771 ast_debug(1, "Oooh, format changed to %d\n", f->subclass); 00772 pvt->owner->nativeformats = f->subclass; 00773 pvt->nativeformats = f->subclass; 00774 ast_set_read_format(pvt->owner, pvt->owner->readformat); 00775 ast_set_write_format(pvt->owner, pvt->owner->writeformat); 00776 ast_channel_unlock(pvt->owner); 00777 } 00778 /* Do in-band DTMF detection */ 00779 if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) { 00780 if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) { 00781 if (!ast_channel_trylock(pvt->owner)) { 00782 f = ast_dsp_process(pvt->owner, pvt->vad, f); 00783 ast_channel_unlock(pvt->owner); 00784 } 00785 else 00786 ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n"); 00787 } else if (pvt->nativeformats && !pvt->noInbandDtmf) { 00788 ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass)); 00789 pvt->noInbandDtmf = 1; 00790 } 00791 if (f &&(f->frametype == AST_FRAME_DTMF)) { 00792 if (h323debug) 00793 ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass); 00794 } 00795 } 00796 } 00797 } 00798 return f; 00799 }
| static int oh323_set_rtp_peer | ( | struct ast_channel * | chan, | |
| struct ast_rtp_instance * | rtp, | |||
| struct ast_rtp_instance * | vrtp, | |||
| struct ast_rtp_instance * | trtp, | |||
| int | codecs, | |||
| int | nat_active | |||
| ) | [static] |
Definition at line 3181 of file chan_h323.c.
References ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), oh323_pvt::cd, convertcap(), LOG_ERROR, ast_channel::tech_pvt, and ast_channel::writeformat.
03182 { 03183 /* XXX Deal with Video */ 03184 struct oh323_pvt *pvt; 03185 struct sockaddr_in them = { 0, }; 03186 struct sockaddr_in us = { 0, }; 03187 char *mode; 03188 03189 if (!rtp) { 03190 return 0; 03191 } 03192 03193 mode = convertcap(chan->writeformat); 03194 pvt = (struct oh323_pvt *) chan->tech_pvt; 03195 if (!pvt) { 03196 ast_log(LOG_ERROR, "No Private Structure, this is bad\n"); 03197 return -1; 03198 } 03199 ast_rtp_instance_get_remote_address(rtp, &them); 03200 ast_rtp_instance_get_local_address(rtp, &us); 03201 #if 0 /* Native bridge still isn't ready */ 03202 h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(them.sin_addr), mode); 03203 #endif 03204 return 0; 03205 }
| 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 826 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_instance_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.
00827 { 00828 struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt; 00829 int res = 0; 00830 if (frame->frametype != AST_FRAME_VOICE) { 00831 if (frame->frametype == AST_FRAME_IMAGE) { 00832 return 0; 00833 } else { 00834 ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype); 00835 return 0; 00836 } 00837 } else { 00838 if (!(frame->subclass & c->nativeformats)) { 00839 ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", 00840 frame->subclass, c->nativeformats, c->readformat, c->writeformat); 00841 return 0; 00842 } 00843 } 00844 if (pvt) { 00845 ast_mutex_lock(&pvt->lock); 00846 if (pvt->rtp && !pvt->recvonly) 00847 res = ast_rtp_instance_write(pvt->rtp, frame); 00848 __oh323_update_info(c, pvt); 00849 ast_mutex_unlock(&pvt->lock); 00850 } 00851 return res; 00852 }
| static int progress | ( | unsigned | call_reference, | |
| const char * | token, | |||
| int | inband | |||
| ) | [static] |
Definition at line 2069 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().
02070 { 02071 struct oh323_pvt *pvt; 02072 02073 if (h323debug) 02074 ast_debug(1, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated")); 02075 02076 pvt = find_call_locked(call_reference, token); 02077 if (!pvt) { 02078 ast_log(LOG_ERROR, "Private structure not found in progress.\n"); 02079 return -1; 02080 } 02081 if (!pvt->owner) { 02082 ast_mutex_unlock(&pvt->lock); 02083 ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n"); 02084 return -1; 02085 } 02086 update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING)); 02087 ast_mutex_unlock(&pvt->lock); 02088 02089 return 0; 02090 }
| static void prune_peers | ( | void | ) | [static] |
Definition at line 2823 of file chan_h323.c.
References ASTOBJ_CONTAINER_PRUNE_MARKED, oh323_destroy_peer(), and peerl.
Referenced by handle_cli_iax2_prune_realtime(), reload_config(), set_config(), and unload_module().
02824 { 02825 /* Prune peers who still are supposed to be deleted */ 02826 ASTOBJ_CONTAINER_PRUNE_MARKED(&peerl, oh323_destroy_peer); 02827 }
| static struct oh323_alias* realtime_alias | ( | const char * | alias | ) | [static, read] |
Definition at line 1224 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().
01225 { 01226 struct ast_variable *var, *tmp; 01227 struct oh323_alias *a; 01228 01229 var = ast_load_realtime("h323", "name", alias, SENTINEL); 01230 01231 if (!var) 01232 return NULL; 01233 01234 for (tmp = var; tmp; tmp = tmp->next) { 01235 if (!strcasecmp(tmp->name, "type") && 01236 !(!strcasecmp(tmp->value, "alias") || !strcasecmp(tmp->value, "h323"))) { 01237 ast_variables_destroy(var); 01238 return NULL; 01239 } 01240 } 01241 01242 a = build_alias(alias, var, NULL, 1); 01243 01244 ast_variables_destroy(var); 01245 01246 return a; 01247 }
| static struct oh323_peer* realtime_peer | ( | const char * | peername, | |
| struct sockaddr_in * | sin | |||
| ) | [static, read] |
Definition at line 1552 of file chan_h323.c.
References ast_inet_ntoa(), ast_load_realtime(), ast_log(), ast_variables_destroy(), build_peer(), LOG_WARNING, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
Referenced by authenticate_reply(), calltoken_required(), find_peer(), and iax2_getpeername().
01553 { 01554 struct oh323_peer *peer; 01555 struct ast_variable *var; 01556 struct ast_variable *tmp; 01557 const char *addr = NULL; 01558 01559 /* First check on peer name */ 01560 if (peername) 01561 var = ast_load_realtime("h323", "name", peername, SENTINEL); 01562 else if (sin) /* Then check on IP address for dynamic peers */ 01563 var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), SENTINEL); 01564 else 01565 return NULL; 01566 01567 if (!var) 01568 return NULL; 01569 01570 for (tmp = var; tmp; tmp = tmp->next) { 01571 /* If this is type=user, then skip this object. */ 01572 if (!strcasecmp(tmp->name, "type") && 01573 !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) { 01574 ast_variables_destroy(var); 01575 return NULL; 01576 } else if (!peername && !strcasecmp(tmp->name, "name")) { 01577 peername = tmp->value; 01578 } 01579 } 01580 01581 if (!peername) { /* Did not find peer in realtime */ 01582 ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr); 01583 ast_variables_destroy(var); 01584 return NULL; 01585 } 01586 01587 /* Peer found in realtime, now build it in memory */ 01588 peer = build_peer(peername, var, NULL, 1); 01589 01590 ast_variables_destroy(var); 01591 01592 return peer; 01593 }
| static struct oh323_user* realtime_user | ( | const call_details_t * | cd | ) | [static, read] |
Definition at line 1438 of file chan_h323.c.
References ast_load_realtime(), ast_log(), ast_variables_destroy(), build_user(), LOG_WARNING, ast_variable::name, ast_variable::next, SENTINEL, ast_variable::value, and var.
Referenced by calltoken_required(), check_access(), and find_user().
01439 { 01440 struct ast_variable *var, *tmp; 01441 struct oh323_user *user; 01442 const char *username; 01443 01444 if (userbyalias) 01445 var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, SENTINEL); 01446 else { 01447 username = (char *)NULL; 01448 var = ast_load_realtime("h323", "host", cd->sourceIp, SENTINEL); 01449 } 01450 01451 if (!var) 01452 return NULL; 01453 01454 for (tmp = var; tmp; tmp = tmp->next) { 01455 if (!strcasecmp(tmp->name, "type") && 01456 !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) { 01457 ast_variables_destroy(var); 01458 return NULL; 01459 } else if (!username && !strcasecmp(tmp->name, "name")) 01460 username = tmp->value; 01461 } 01462 01463 if (!username) { 01464 ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp); 01465 ast_variables_destroy(var); 01466 return NULL; 01467 } 01468 01469 user = build_user(username, var, NULL, 1); 01470 01471 ast_variables_destroy(var); 01472 01473 return user; 01474 }
| 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 1825 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().
01826 { 01827 struct oh323_pvt *pvt; 01828 int res; 01829 01830 pvt = find_call_locked(call_reference, token); 01831 if (!pvt) { 01832 ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token); 01833 return -1; 01834 } 01835 if (h323debug) 01836 ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token); 01837 01838 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 01839 if (digit == '!') 01840 res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH); 01841 else { 01842 struct ast_frame f = { 01843 .frametype = AST_FRAME_DTMF_END, 01844 .subclass = digit, 01845 .samples = duration * 8, 01846 .len = duration, 01847 .src = "SEND_DIGIT", 01848 }; 01849 if (digit == ' ') { /* signalUpdate message */ 01850 f.subclass = pvt->curDTMF; 01851 AST_SCHED_DEL(sched, pvt->DTMFsched); 01852 } else { /* Regular input or signal message */ 01853 if (pvt->DTMFsched >= 0) { 01854 /* We still don't send DTMF END from previous event, send it now */ 01855 AST_SCHED_DEL(sched, pvt->DTMFsched); 01856 f.subclass = pvt->curDTMF; 01857 f.samples = f.len = 0; 01858 ast_queue_frame(pvt->owner, &f); 01859 /* Restore values */ 01860 f.subclass = digit; 01861 f.samples = duration * 8; 01862 f.len = duration; 01863 } 01864 if (duration) { /* This is a signal, signalUpdate follows */ 01865 f.frametype = AST_FRAME_DTMF_BEGIN; 01866 pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt); 01867 if (h323debug) 01868 ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched); 01869 } 01870 pvt->curDTMF = digit; 01871 } 01872 res = ast_queue_frame(pvt->owner, &f); 01873 } 01874 ast_channel_unlock(pvt->owner); 01875 } else { 01876 if (digit == '!') 01877 pvt->newcontrol = AST_CONTROL_FLASH; 01878 else { 01879 pvt->newduration = duration; 01880 pvt->newdigit = digit; 01881 } 01882 res = 0; 01883 } 01884 ast_mutex_unlock(&pvt->lock); 01885 return res; 01886 }
| static const char* redirectingreason2str | ( | int | redirectingreason | ) | [static] |
Definition at line 262 of file chan_h323.c.
Referenced by __oh323_new().
00263 { 00264 switch (redirectingreason) { 00265 case 0: 00266 return "UNKNOWN"; 00267 case 1: 00268 return "BUSY"; 00269 case 2: 00270 return "NO_REPLY"; 00271 case 0xF: 00272 return "UNCONDITIONAL"; 00273 default: 00274 return "NOREDIRECT"; 00275 } 00276 }
| static int reload | ( | void | ) | [static] |
Definition at line 3122 of file chan_h323.c.
References ast_log(), h323_reload(), and LOG_NOTICE.
03123 { 03124 if (!sched || !io) { 03125 ast_log(LOG_NOTICE, "Unload and load chan_h323.so again in order to receive configuration changes.\n"); 03126 return 0; 03127 } 03128 return h323_reload(); 03129 }
| static int reload_config | ( | int | is_reload | ) | [static] |
Definition at line 2829 of file chan_h323.c.
References aliasl, ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_copy_string(), ast_gethostbyname(), ast_jb_read_conf(), ast_log(), ast_str2cos(), ast_str2tos(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, ASTOBJ_CONTAINER_LINK, ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_CONTAINER_UNLOCK, ASTOBJ_CONTAINER_WRLOCK, ASTOBJ_RDLOCK, ASTOBJ_UNLOCK, ASTOBJ_UNREF, bindaddr, build_alias(), build_peer(), build_user(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, delete_aliases(), delete_users(), gen, GLOBAL_CAPABILITY, global_jbconf, hp, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, oh323_destroy_alias(), oh323_destroy_peer(), oh323_destroy_user(), peerl, prune_peers(), update_common_options(), userl, and ast_variable::value.
Referenced by do_monitor(), h323_do_reload(), handle_cli_iax2_reload(), handle_cli_misdn_reload(), load_module(), reload(), and sip_do_reload().
02830 { 02831 struct ast_config *cfg, *ucfg; 02832 struct ast_variable *v; 02833 struct oh323_peer *peer = NULL; 02834 struct oh323_user *user = NULL; 02835 struct oh323_alias *alias = NULL; 02836 struct ast_hostent ahp; struct hostent *hp; 02837 char *cat; 02838 const char *utype; 02839 int is_user, is_peer, is_alias; 02840 char _gatekeeper[100]; 02841 int gk_discover, gk_disable, gk_changed; 02842 struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02843 02844 cfg = ast_config_load(config, config_flags); 02845 02846 /* We *must* have a config file otherwise stop immediately */ 02847 if (!cfg) { 02848 ast_log(LOG_NOTICE, "Unable to load config %s, H.323 disabled\n", config); 02849 return 1; 02850 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 02851 ucfg = ast_config_load("users.conf", config_flags); 02852 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) { 02853 return 0; 02854 } else if (ucfg == CONFIG_STATUS_FILEINVALID) { 02855 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n"); 02856 return 0; 02857 } 02858 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 02859 if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) { 02860 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 02861 ast_config_destroy(ucfg); 02862 return 0; 02863 } 02864 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02865 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config); 02866 return 0; 02867 } else { 02868 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 02869 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) { 02870 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n"); 02871 ast_config_destroy(cfg); 02872 return 0; 02873 } 02874 } 02875 02876 if (is_reload) { 02877 delete_users(); 02878 delete_aliases(); 02879 prune_peers(); 02880 } 02881 02882 /* fire up the H.323 Endpoint */ 02883 if (!h323_end_point_exist()) { 02884 h323_end_point_create(); 02885 } 02886 ast_copy_string(_gatekeeper, gatekeeper, sizeof(_gatekeeper)); 02887 gk_discover = gatekeeper_discover; 02888 gk_disable = gatekeeper_disable; 02889 memset(&bindaddr, 0, sizeof(bindaddr)); 02890 memset(&global_options, 0, sizeof(global_options)); 02891 global_options.fastStart = 1; 02892 global_options.h245Tunneling = 1; 02893 global_options.dtmfcodec[0] = H323_DTMF_RFC2833_PT; 02894 global_options.dtmfcodec[1] = H323_DTMF_CISCO_PT; 02895 global_options.dtmfmode = 0; 02896 global_options.holdHandling = 0; 02897 global_options.capability = GLOBAL_CAPABILITY; 02898 global_options.bridge = 1; /* Do native bridging by default */ 02899 global_options.autoframing = 0; 02900 strcpy(default_context, "default"); 02901 h323_signalling_port = 1720; 02902 gatekeeper_disable = 1; 02903 gatekeeper_discover = 0; 02904 gkroute = 0; 02905 userbyalias = 1; 02906 acceptAnonymous = 1; 02907 tos = 0; 02908 cos = 0; 02909 02910 /* Copy the default jb config over global_jbconf */ 02911 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 02912 02913 if (ucfg) { 02914 struct ast_variable *gen; 02915 int genhas_h323; 02916 const char *has_h323; 02917 02918 genhas_h323 = ast_true(ast_variable_retrieve(ucfg, "general", "hash323")); 02919 gen = ast_variable_browse(ucfg, "general"); 02920 for (cat = ast_category_browse(ucfg, NULL); cat; cat = ast_category_browse(ucfg, cat)) { 02921 if (strcasecmp(cat, "general")) { 02922 has_h323 = ast_variable_retrieve(ucfg, cat, "hash323"); 02923 if (ast_true(has_h323) || (!has_h323 && genhas_h323)) { 02924 user = build_user(cat, gen, ast_variable_browse(ucfg, cat), 0); 02925 if (user) { 02926 ASTOBJ_CONTAINER_LINK(&userl, user); 02927 ASTOBJ_UNREF(user, oh323_destroy_user); 02928 } 02929 peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0); 02930 if (peer) { 02931 ASTOBJ_CONTAINER_LINK(&peerl, peer); 02932 ASTOBJ_UNREF(peer, oh323_destroy_peer); 02933 } 02934 } 02935 } 02936 } 02937 ast_config_destroy(ucfg); 02938 } 02939 02940 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 02941 /* handle jb conf */ 02942 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 02943 continue; 02944 /* Create the interface list */ 02945 if (!strcasecmp(v->name, "port")) { 02946 h323_signalling_port = (int)strtol(v->value, NULL, 10); 02947 } else if (!strcasecmp(v->name, "bindaddr")) { 02948 if (!(hp = ast_gethostbyname(v->value, &ahp))) { 02949 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); 02950 } else { 02951 memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr)); 02952 } 02953 } else if (!strcasecmp(v->name, "tos")) { /* Needs to be removed in next release */ 02954 ast_log(LOG_WARNING, "The \"tos\" setting is deprecated in this version of Asterisk. Please change to \"tos_audio\".\n"); 02955 if (ast_str2tos(v->value, &tos)) { 02956 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02957 } 02958 } else if (!strcasecmp(v->name, "tos_audio")) { 02959 if (ast_str2tos(v->value, &tos)) { 02960 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02961 } 02962 } else if (!strcasecmp(v->name, "cos")) { 02963 ast_log(LOG_WARNING, "The \"cos\" setting is deprecated in this version of Asterisk. Please change to \"cos_audio\".\n"); 02964 if (ast_str2cos(v->value, &cos)) { 02965 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02966 } 02967 } else if (!strcasecmp(v->name, "cos_audio")) { 02968 if (ast_str2cos(v->value, &cos)) { 02969 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno); 02970 } 02971 } else if (!strcasecmp(v->name, "gatekeeper")) { 02972 if (!strcasecmp(v->value, "DISABLE")) { 02973 gatekeeper_disable = 1; 02974 } else if (!strcasecmp(v->value, "DISCOVER")) { 02975 gatekeeper_disable = 0; 02976 gatekeeper_discover = 1; 02977 } else { 02978 gatekeeper_disable = 0; 02979 ast_copy_string(gatekeeper, v->value, sizeof(gatekeeper)); 02980 } 02981 } else if (!strcasecmp(v->name, "secret")) { 02982 ast_copy_string(secret, v->value, sizeof(secret)); 02983 } else if (!strcasecmp(v->name, "AllowGKRouted")) { 02984 gkroute = ast_true(v->value); 02985 } else if (!strcasecmp(v->name, "context")) { 02986 ast_copy_string(default_context, v->value, sizeof(default_context)); 02987 ast_verb(2, "Setting default context to %s\n", default_context); 02988 } else if (!strcasecmp(v->name, "UserByAlias")) { 02989 userbyalias = ast_true(v->value); 02990 } else if (!strcasecmp(v->name, "AcceptAnonymous")) { 02991 acceptAnonymous = ast_true(v->value); 02992 } else if (!update_common_options(v, &global_options)) { 02993 /* dummy */ 02994 } 02995 } 02996 if (!global_options.dtmfmode) 02997 global_options.dtmfmode = H323_DTMF_RFC2833; 02998 if (global_options.holdHandling == ~0) 02999 global_options.holdHandling = 0; 03000 else if (!global_options.holdHandling) 03001 global_options.holdHandling = H323_HOLD_H450; 03002 03003 for (cat = ast_category_browse(cfg, NULL); cat; cat = ast_category_browse(cfg, cat)) { 03004 if (strcasecmp(cat, "general")) { 03005 utype = ast_variable_retrieve(cfg, cat, "type"); 03006 if (utype) { 03007 is_user = is_peer = is_alias = 0; 03008 if (!strcasecmp(utype, "user")) 03009 is_user = 1; 03010 else if (!strcasecmp(utype, "peer")) 03011 is_peer = 1; 03012 else if (!strcasecmp(utype, "friend")) 03013 is_user = is_peer = 1; 03014 else if (!strcasecmp(utype, "h323") || !strcasecmp(utype, "alias")) 03015 is_alias = 1; 03016 else { 03017 ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config); 03018 continue; 03019 } 03020 if (is_user) { 03021 user = build_user(cat, ast_variable_browse(cfg, cat), NULL, 0); 03022 if (user) { 03023 ASTOBJ_CONTAINER_LINK(&userl, user); 03024 ASTOBJ_UNREF(user, oh323_destroy_user); 03025 } 03026 } 03027 if (is_peer) { 03028 peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0); 03029 if (peer) { 03030 ASTOBJ_CONTAINER_LINK(&peerl, peer); 03031 ASTOBJ_UNREF(peer, oh323_destroy_peer); 03032 } 03033 } 03034 if (is_alias) { 03035 alias = build_alias(cat, ast_variable_browse(cfg, cat), NULL, 0); 03036 if (alias) { 03037 ASTOBJ_CONTAINER_LINK(&aliasl, alias); 03038 ASTOBJ_UNREF(alias, oh323_destroy_alias); 03039 } 03040 } 03041 } else { 03042 ast_log(LOG_WARNING, "Section '%s' lacks type\n", cat); 03043 } 03044 } 03045 } 03046 ast_config_destroy(cfg); 03047 03048 /* Register our H.323 aliases if any*/ 03049 ASTOBJ_CONTAINER_WRLOCK(&aliasl); 03050 ASTOBJ_CONTAINER_TRAVERSE(&aliasl, 1, do { 03051 ASTOBJ_RDLOCK(iterator); 03052 if (h323_set_alias(iterator)) { 03053 ast_log(LOG_ERROR, "Alias %s rejected by endpoint\n", alias->name); 03054 ASTOBJ_UNLOCK(iterator); 03055 continue; 03056 } 03057 ASTOBJ_UNLOCK(iterator); 03058 } while (0) ); 03059 ASTOBJ_CONTAINER_UNLOCK(&aliasl); 03060 03061 /* Don't touch GK if nothing changed because URQ will drop all existing calls */ 03062 gk_changed = 0; 03063 if (gatekeeper_disable != gk_disable) 03064 gk_changed = is_reload; 03065 else if(!gatekeeper_disable && (gatekeeper_discover != gk_discover)) 03066 gk_changed = is_reload; 03067 else if(!gatekeeper_disable && (strncmp(_gatekeeper, gatekeeper, sizeof(_gatekeeper)) != 0)) 03068 gk_changed = is_reload; 03069 if (gk_changed) { 03070 if(!gk_disable) 03071 h323_gk_urq(); 03072 if (!gatekeeper_disable) { 03073 if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { 03074 ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); 03075 gatekeeper_disable = 1; 03076 } 03077 } 03078 } 03079 return 0; 03080 }
| static void remote_hold | ( | unsigned | call_reference, | |
| const char * | token, | |||
| int | is_hold | |||
| ) | [static] |
Definition at line 2500 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().
02501 { 02502 struct oh323_pvt *pvt; 02503 02504 if (h323debug) 02505 ast_debug(1, "Setting %shold status for connection %s\n", (is_hold ? "" : "un"), token); 02506 02507 pvt = find_call_locked(call_reference, token); 02508 if (!pvt) 02509 return; 02510 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 02511 if (is_hold) 02512 ast_queue_control(pvt->owner, AST_CONTROL_HOLD); 02513 else 02514 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD); 02515 ast_channel_unlock(pvt->owner); 02516 } 02517 else { 02518 if (is_hold) 02519 pvt->newcontrol = AST_CONTROL_HOLD; 02520 else 02521 pvt->newcontrol = AST_CONTROL_UNHOLD; 02522 } 02523 ast_mutex_unlock(&pvt->lock); 02524 }
| static int restart_monitor | ( | void | ) | [static] |
Definition at line 2594 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.
02595 { 02596 /* If we're supposed to be stopped -- stay stopped */ 02597 if (ast_mutex_lock(&monlock)) { 02598 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 02599 return -1; 02600 } 02601 if (monitor_thread == AST_PTHREADT_STOP) { 02602 ast_mutex_unlock(&monlock); 02603 return 0; 02604 } 02605 if (monitor_thread == pthread_self()) { 02606 ast_mutex_unlock(&monlock); 02607 ast_log(LOG_WARNING, "Cannot kill myself\n"); 02608 return -1; 02609 } 02610 if (monitor_thread && (monitor_thread != AST_PTHREADT_NULL)) { 02611 /* Wake up the thread */ 02612 pthread_kill(monitor_thread, SIGURG); 02613 } else { 02614 /* Start a new monitor */ 02615 if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) { 02616 monitor_thread = AST_PTHREADT_NULL; 02617 ast_mutex_unlock(&monlock); 02618 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 02619 return -1; 02620 } 02621 } 02622 ast_mutex_unlock(&monlock); 02623 return 0; 02624 }
| static void set_dtmf_payload | ( | unsigned | call_reference, | |
| const char * | token, | |||
| int | payload, | |||
| int | is_cisco | |||
| ) | [static] |
Definition at line 2415 of file chan_h323.c.
References ast_debug, ast_mutex_unlock(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), oh323_pvt::dtmf_pt, find_call_locked(), oh323_pvt::lock, and oh323_pvt::rtp.
Referenced by load_module().
02416 { 02417 struct oh323_pvt *pvt; 02418 02419 if (h323debug) 02420 ast_debug(1, "Setting %s DTMF payload to %d on %s\n", (is_cisco ? "Cisco" : "RFC2833"), payload, token); 02421 02422 pvt = find_call_locked(call_reference, token); 02423 if (!pvt) { 02424 return; 02425 } 02426 if (pvt->rtp) { 02427 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, payload, "audio", (is_cisco ? "cisco-telephone-event" : "telephone-event"), 0); 02428 } 02429 pvt->dtmf_pt[is_cisco ? 1 : 0] = payload; 02430 ast_mutex_unlock(&pvt->lock); 02431 if (h323debug) 02432 ast_debug(1, "DTMF payload on %s set to %d\n", token, payload); 02433 }
| static void set_local_capabilities | ( | unsigned | call_reference, | |
| const char * | token | |||
| ) | [static] |
Definition at line 2470 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().
02471 { 02472 struct oh323_pvt *pvt; 02473 int capability, dtmfmode, pref_codec; 02474 struct ast_codec_pref prefs; 02475 02476 if (h323debug) 02477 ast_debug(1, "Setting capabilities for connection %s\n", token); 02478 02479 pvt = find_call_locked(call_reference, token); 02480 if (!pvt) 02481 return; 02482 capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability; 02483 dtmfmode = pvt->options.dtmfmode; 02484 prefs = pvt->options.prefs; 02485 pref_codec = pvt->pref_codec; 02486 ast_mutex_unlock(&pvt->lock); 02487 h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec); 02488 02489 if (h323debug) { 02490 int i; 02491 for (i = 0; i < 32; i++) { 02492 if (!prefs.order[i]) 02493 break; 02494 ast_debug(1, "local prefs[%d]=%s:%d\n", i, (prefs.order[i] ? ast_getformatname(1 << (prefs.order[i]-1)) : "<none>"), prefs.framing[i]); 02495 } 02496 ast_debug(1, "Capabilities for connection %s is set\n", token); 02497 } 02498 }
| static void set_peer_capabilities | ( | unsigned | call_reference, | |
| const char * | token, | |||
| int | capabilities, | |||
| struct ast_codec_pref * | prefs | |||
| ) | [static] |
Definition at line 2435 of file chan_h323.c.
References ast_debug, ast_getformatname(), ast_mutex_unlock(), ast_rtp_codecs_packetization_set(), ast_rtp_instance_get_codecs(), find_call_locked(), ast_codec_pref::framing, oh323_pvt::jointcapability, oh323_pvt::lock, oh323_pvt::options, ast_codec_pref::order, oh323_pvt::peer_prefs, oh323_pvt::peercapability, and oh323_pvt::rtp.
Referenced by load_module().
02436 { 02437 struct oh323_pvt *pvt; 02438 02439 if (h323debug) 02440 ast_debug(1, "Got remote capabilities from connection %s\n", token); 02441 02442 pvt = find_call_locked(call_reference, token); 02443 if (!pvt) 02444 return; 02445 pvt->peercapability = capabilities; 02446 pvt->jointcapability = pvt->options.capability & capabilities; 02447 if (prefs) { 02448 memcpy(&pvt->peer_prefs, prefs, sizeof(pvt->peer_prefs)); 02449 if (h323debug) { 02450 int i; 02451 for (i = 0; i < 32; ++i) { 02452 if (!prefs->order[i]) 02453 break; 02454 ast_debug(1, "prefs[%d]=%s:%d\n", i, (prefs->order[i] ? ast_getformatname(1 << (prefs->order[i]-1)) : "<none>"), prefs->framing[i]); 02455 } 02456 } 02457 if (pvt->rtp) { 02458 if (pvt->options.autoframing) { 02459 ast_debug(2, "Autoframing option set, using peer's packetization settings\n"); 02460 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->peer_prefs); 02461 } else { 02462 ast_debug(2, "Autoframing option not set, ignoring peer's packetization settings\n"); 02463 ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, &pvt->options.prefs); 02464 } 02465 } 02466 } 02467 ast_mutex_unlock(&pvt->lock); 02468 }
| 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 2097 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().
02098 { 02099 struct oh323_pvt *pvt; 02100 struct oh323_user *user = NULL; 02101 struct oh323_alias *alias = NULL; 02102 02103 if (h323debug) 02104 ast_debug(1, "Setting up incoming call for %s\n", cd->call_token); 02105 02106 /* allocate the call*/ 02107 pvt = oh323_alloc(cd->call_reference); 02108 02109 if (!pvt) { 02110 ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n"); 02111 cleanup_call_details(cd); 02112 return NULL; 02113 } 02114 02115 /* Populate the call details in the private structure */ 02116 memcpy(&pvt->cd, cd, sizeof(pvt->cd)); 02117 memcpy(&pvt->options, &global_options, sizeof(pvt->options)); 02118 pvt->jointcapability = pvt->options.capability; 02119 02120 if (h323debug) { 02121 ast_verb(3, "Setting up Call\n"); 02122 ast_verb(3, " \tCall token: [%s]\n", pvt->cd.call_token); 02123 ast_verb(3, " \tCalling party name: [%s]\n", pvt->cd.call_source_name); 02124 ast_verb(3, " \tCalling party number: [%s]\n", pvt->cd.call_source_e164); 02125 ast_verb(3, " \tCalled party name: [%s]\n", pvt->cd.call_dest_alias); 02126 ast_verb(3, " \tCalled party number: [%s]\n", pvt->cd.call_dest_e164); 02127 if (pvt->cd.redirect_reason >= 0) 02128 ast_verb(3, " \tRedirecting party number: [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason); 02129 ast_verb(3, " \tCalling party IP: [%s]\n", pvt->cd.sourceIp); 02130 } 02131 02132 /* Decide if we are allowing Gatekeeper routed calls*/ 02133 if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) { 02134 if (!ast_strlen_zero(cd->call_dest_e164)) { 02135 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten)); 02136 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 02137 } else { 02138 alias = find_alias(cd->call_dest_alias, 1); 02139 if (!alias) { 02140 ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias); 02141 oh323_destroy(pvt); 02142 return NULL; 02143 } 02144 ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten)); 02145 ast_copy_string(pvt->context, alias->context, sizeof(pvt->context)); 02146 } 02147 } else { 02148 /* Either this call is not from the Gatekeeper 02149 or we are not allowing gk routed calls */ 02150 user = find_user(cd, 1); 02151 if (!user) { 02152 if (!acceptAnonymous) { 02153 ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp); 02154 oh323_destroy(pvt); 02155 return NULL; 02156 } 02157 if (ast_strlen_zero(default_context)) { 02158 ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp); 02159 oh323_destroy(pvt); 02160 return NULL; 02161 } 02162 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 02163 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) { 02164 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten)); 02165 } else { 02166 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten)); 02167 } 02168 if (h323debug) 02169 ast_debug(1, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten); 02170 } else { 02171 if (user->host) { 02172 if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) { 02173 if (ast_strlen_zero(user->context)) { 02174 if (ast_strlen_zero(default_context)) { 02175 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp); 02176 oh323_destroy(pvt); 02177 ASTOBJ_UNREF(user, oh323_destroy_user); 02178 return NULL; 02179 } 02180 ast_copy_string(pvt->context, default_context, sizeof(pvt->context)); 02181 } else { 02182 ast_copy_string(pvt->context, user->context, sizeof(pvt->context)); 02183 } 02184 pvt->exten[0] = 'i'; 02185 pvt->exten[1] = '\0'; 02186 ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp); 02187 oh323_destroy(pvt); 02188 ASTOBJ_UNREF(user, oh323_destroy_user); 02189 return NULL; /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */ 02190 } 02191 } 02192 ast_copy_string(pvt->context, user->context, sizeof(pvt->context)); 02193 memcpy(&pvt->options, &user->options, sizeof(pvt->options)); 02194 pvt->jointcapability = pvt->options.capability; 02195 if (!ast_strlen_zero(pvt->cd.call_dest_e164)) { 02196 ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten)); 02197 } else { 02198 ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten)); 02199 } 02200 if (!ast_strlen_zero(user->accountcode)) { 02201 ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode)); 02202 } 02203 if (user->amaflags) { 02204 pvt->amaflags = user->amaflags; 02205 } 02206 ASTOBJ_UNREF(user, oh323_destroy_user); 02207 } 02208 } 02209 return &pvt->options; 02210 }
| 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 2296 of file chan_h323.c.
References cleanup_call_details().
Referenced by load_module().
02297 { 02298 /* Use argument here or free it immediately */ 02299 cleanup_call_details(cd); 02300 02301 return 1; 02302 }
| 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 1934 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_codecs_payload_lookup(), ast_rtp_codecs_payloads_set_rtpmap_type(), ast_rtp_instance_get_codecs(), ast_rtp_instance_set_remote_address(), ast_rtp_instance_stop(), AST_RTP_OPT_G726_NONSTANDARD, ast_set_read_format(), ast_set_write_format(), ast_rtp_payload_type::code, find_call_locked(), oh323_pvt::jointcapability, oh323_pvt::lock, LOG_ERROR, LOG_NOTICE, ast_channel::nativeformats, oh323_pvt::nativeformats, oh323_pvt::newcontrol, oh323_pvt::options, oh323_pvt::owner, ast_channel::readformat, oh323_pvt::recvonly, oh323_pvt::rtp, and ast_channel::writeformat.
Referenced by load_module().
01935 { 01936 struct oh323_pvt *pvt; 01937 struct sockaddr_in them; 01938 int nativeformats_changed; 01939 enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE; 01940 01941 if (h323debug) 01942 ast_debug(1, "Setting up RTP connection for %s\n", token); 01943 01944 /* Find the call or allocate a private structure if call not found */ 01945 pvt = find_call_locked(call_reference, token); 01946 if (!pvt) { 01947 ast_log(LOG_ERROR, "Something is wrong: rtp\n"); 01948 return; 01949 } 01950 if (pvt->alreadygone) { 01951 ast_mutex_unlock(&pvt->lock); 01952 return; 01953 } 01954 01955 if (!pvt->rtp) 01956 __oh323_rtp_create(pvt); 01957 01958 if ((pt == 2) && (pvt->jointcapability & AST_FORMAT_G726_AAL2)) { 01959 ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(pvt->rtp), pvt->rtp, pt, "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD); 01960 } 01961 01962 them.sin_family = AF_INET; 01963 /* only works for IPv4 */ 01964 them.sin_addr.s_addr = inet_addr(remoteIp); 01965 them.sin_port = htons(remotePort); 01966 01967 if (them.sin_addr.s_addr) { 01968 ast_rtp_instance_set_remote_address(pvt->rtp, &them); 01969 if (pvt->recvonly) { 01970 pvt->recvonly = 0; 01971 rtp_change = NEED_UNHOLD; 01972 } 01973 } else { 01974 ast_rtp_instance_stop(pvt->rtp); 01975 if (!pvt->recvonly) { 01976 pvt->recvonly = 1; 01977 rtp_change = NEED_HOLD; 01978 } 01979 } 01980 01981 /* Change native format to reflect information taken from OLC/OLCAck */ 01982 nativeformats_changed = 0; 01983 if (pt != 128 && pvt->rtp) { /* Payload type is invalid, so try to use previously decided */ 01984 struct ast_rtp_payload_type rtptype = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(pvt->rtp), pt); 01985 if (h323debug) 01986 ast_debug(1, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt); 01987 if (pvt->nativeformats != rtptype.code) { 01988 pvt->nativeformats = rtptype.code; 01989 nativeformats_changed = 1; 01990 } 01991 } else if (h323debug) 01992 ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n"); 01993 01994 /* Don't try to lock the channel if nothing changed */ 01995 if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) { 01996 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 01997 /* Re-build translation path only if native format(s) has been changed */ 01998 if (pvt->owner->nativeformats != pvt->nativeformats) { 01999 if (h323debug) 02000 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); 02001 pvt->owner->nativeformats = pvt->nativeformats; 02002 ast_set_read_format(pvt->owner, pvt->owner->readformat); 02003 ast_set_write_format(pvt->owner, pvt->owner->writeformat); 02004 } 02005 if (pvt->options.progress_audio) 02006 ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS); 02007 switch (rtp_change) { 02008 case NEED_HOLD: 02009 ast_queue_control(pvt->owner, AST_CONTROL_HOLD); 02010 break; 02011 case NEED_UNHOLD: 02012 ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD); 02013 break; 02014 default: 02015 break; 02016 } 02017 ast_channel_unlock(pvt->owner); 02018 } 02019 else { 02020 if (pvt->options.progress_audio) 02021 pvt->newcontrol = AST_CONTROL_PROGRESS; 02022 else if (rtp_change == NEED_HOLD) 02023 pvt->newcontrol = AST_CONTROL_HOLD; 02024 else if (rtp_change == NEED_UNHOLD) 02025 pvt->newcontrol = AST_CONTROL_UNHOLD; 02026 if (h323debug) 02027 ast_debug(1, "RTP connection preparation for %s is pending...\n", token); 02028 } 02029 } 02030 ast_mutex_unlock(&pvt->lock); 02031 02032 if (h323debug) 02033 ast_debug(1, "RTP connection prepared for %s\n", token); 02034 02035 return; 02036 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 3316 of file chan_h323.c.
References aliasl, ast_channel_unregister(), ast_cli_unregister(), ast_cli_unregister_multiple(), ast_free, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_glue_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ASTOBJ_CONTAINER_DESTROY, ASTOBJ_CONTAINER_DESTROYALL, iflist, 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.
03317 { 03318 struct oh323_pvt *p, *pl; 03319 03320 /* unregister commands */ 03321 ast_cli_unregister_multiple(cli_h323, sizeof(cli_h323) / sizeof(struct ast_cli_entry)); 03322 ast_cli_unregister(&cli_h323_reload); 03323 03324 ast_channel_unregister(&oh323_tech); 03325 ast_rtp_glue_unregister(&oh323_rtp_glue); 03326 03327 if (!ast_mutex_lock(&iflock)) { 03328 /* hangup all interfaces if they have an owner */ 03329 p = iflist; 03330 while(p) { 03331 if (p->owner) { 03332 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 03333 } 03334 p = p->next; 03335 } 03336 iflist = NULL; 03337 ast_mutex_unlock(&iflock); 03338 } else { 03339 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 03340 return -1; 03341 } 03342 if (!ast_mutex_lock(&monlock)) { 03343 if ((monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) { 03344 if (monitor_thread != pthread_self()) { 03345 pthread_cancel(monitor_thread); 03346 } 03347 pthread_kill(monitor_thread, SIGURG); 03348 pthread_join(monitor_thread, NULL); 03349 } 03350 monitor_thread = AST_PTHREADT_STOP; 03351 ast_mutex_unlock(&monlock); 03352 } else { 03353 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 03354 return -1; 03355 } 03356 if (!ast_mutex_lock(&iflock)) { 03357 /* destroy all the interfaces and free their memory */ 03358 p = iflist; 03359 while(p) { 03360 pl = p; 03361 p = p->next; 03362 /* free associated memory */ 03363 ast_mutex_destroy(&pl->lock); 03364 ast_free(pl); 03365 } 03366 iflist = NULL; 03367 ast_mutex_unlock(&iflock); 03368 } else { 03369 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 03370 return -1; 03371 } 03372 if (!gatekeeper_disable) 03373 h323_gk_urq(); 03374 h323_end_process(); 03375 if (io) 03376 io_context_destroy(io); 03377 if (sched) 03378 sched_context_destroy(sched); 03379 03380 ASTOBJ_CONTAINER_DESTROYALL(&userl, oh323_destroy_user); 03381 ASTOBJ_CONTAINER_DESTROY(&userl); 03382 ASTOBJ_CONTAINER_DESTROYALL(&peerl, oh323_destroy_peer); 03383 ASTOBJ_CONTAINER_DESTROY(&peerl); 03384 ASTOBJ_CONTAINER_DESTROYALL(&aliasl, oh323_destroy_alias); 03385 ASTOBJ_CONTAINER_DESTROY(&aliasl); 03386 03387 return 0; 03388 }
| static int update_common_options | ( | struct ast_variable * | v, | |
| struct call_options * | options | |||
| ) | [static] |
Definition at line 1249 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().
01250 { 01251 int tmp = 0; 01252 char *val, *opt; 01253 01254 if (!strcasecmp(v->name, "allow")) { 01255 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1); 01256 } else if (!strcasecmp(v->name, "autoframing")) { 01257 options->autoframing = ast_true(v->value); 01258 } else if (!strcasecmp(v->name, "disallow")) { 01259 ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0); 01260 } else if (!strcasecmp(v->name, "dtmfmode")) { 01261 val = ast_strdupa(v->value); 01262 if ((opt = strchr(val, ':')) != (char *)NULL) { 01263 *opt++ = '\0'; 01264 tmp = atoi(opt); 01265 } 01266 if (!strcasecmp(v->value, "inband")) { 01267 options->dtmfmode |= H323_DTMF_INBAND; 01268 } else if (!strcasecmp(val, "rfc2833")) { 01269 options->dtmfmode |= H323_DTMF_RFC2833; 01270 if (!opt) { 01271 options->dtmfcodec[0] = H323_DTMF_RFC2833_PT; 01272 } else if ((tmp >= 96) && (tmp < 128)) { 01273 options->dtmfcodec[0] = tmp; 01274 } else { 01275 options->dtmfcodec[0] = H323_DTMF_RFC2833_PT; 01276 ast_log(LOG_WARNING, "Unknown rfc2833 payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[0]); 01277 } 01278 } else if (!strcasecmp(val, "cisco")) { 01279 options->dtmfmode |= H323_DTMF_CISCO; 01280 if (!opt) { 01281 options->dtmfcodec[1] = H323_DTMF_CISCO_PT; 01282 } else if ((tmp >= 96) && (tmp < 128)) { 01283 options->dtmfcodec[1] = tmp; 01284 } else { 01285 options->dtmfcodec[1] = H323_DTMF_CISCO_PT; 01286 ast_log(LOG_WARNING, "Unknown Cisco DTMF payload %s specified at line %d, using default %d\n", opt, v->lineno, options->dtmfcodec[1]); 01287 } 01288 } else if (!strcasecmp(v->value, "h245-signal")) { 01289 options->dtmfmode |= H323_DTMF_SIGNAL; 01290 } else { 01291 ast_log(LOG_WARNING, "Unknown dtmf mode '%s' at line %d\n", v->value, v->lineno); 01292 } 01293 } else if (!strcasecmp(v->name, "dtmfcodec")) { 01294 ast_log(LOG_NOTICE, "Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead.\n", v->name, v->lineno); 01295 tmp = atoi(v->value); 01296 if (tmp < 96) 01297 ast_log(LOG_WARNING, "Invalid %s value %s at line %d\n", v->name, v->value, v->lineno); 01298 else 01299 options->dtmfcodec[0] = tmp; 01300 } else if (!strcasecmp(v->name, "bridge")) { 01301 options->bridge = ast_true(v->value); 01302 } else if (!strcasecmp(v->name, "nat")) { 01303 options->nat = ast_true(v->value); 01304 } else if (!strcasecmp(v->name, "fastStart")) { 01305 options->fastStart = ast_true(v->value); 01306 } else if (!strcasecmp(v->name, "h245Tunneling")) { 01307 options->h245Tunneling = ast_true(v->value); 01308 } else if (!strcasecmp(v->name, "silenceSuppression")) { 01309 options->silenceSuppression = ast_true(v->value); 01310 } else if (!strcasecmp(v->name, "progress_setup")) { 01311 tmp = atoi(v->value); 01312 if ((tmp != 0) && (tmp != 1) && (tmp != 3) && (tmp != 8)) { 01313 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno); 01314 tmp = 0; 01315 } 01316 options->progress_setup = tmp; 01317 } else if (!strcasecmp(v->name, "progress_alert")) { 01318 tmp = atoi(v->value); 01319 if ((tmp != 0) && (tmp != 1) && (tmp != 8)) { 01320 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d, assuming 0\n", v->value, v->name, v->lineno); 01321 tmp = 0; 01322 } 01323 options->progress_alert = tmp; 01324 } else if (!strcasecmp(v->name, "progress_audio")) { 01325 options->progress_audio = ast_true(v->value); 01326 } else if (!strcasecmp(v->name, "callerid")) { 01327 ast_callerid_split(v->value, options->cid_name, sizeof(options->cid_name), options->cid_num, sizeof(options->cid_num)); 01328 } else if (!strcasecmp(v->name, "fullname")) { 01329 ast_copy_string(options->cid_name, v->value, sizeof(options->cid_name)); 01330 } else if (!strcasecmp(v->name, "cid_number")) { 01331 ast_copy_string(options->cid_num, v->value, sizeof(options->cid_num)); 01332 } else if (!strcasecmp(v->name, "tunneling")) { 01333 if (!strcasecmp(v->value, "none")) 01334 options->tunnelOptions = 0; 01335 else if (!strcasecmp(v->value, "cisco")) 01336 options->tunnelOptions |= H323_TUNNEL_CISCO; 01337 else if (!strcasecmp(v->value, "qsig")) 01338 options->tunnelOptions |= H323_TUNNEL_QSIG; 01339 else 01340 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno); 01341 } else if (!strcasecmp(v->name, "hold")) { 01342 if (!strcasecmp(v->value, "none")) 01343 options->holdHandling = ~0; 01344 else if (!strcasecmp(v->value, "notify")) 01345 options->holdHandling |= H323_HOLD_NOTIFY; 01346 else if (!strcasecmp(v->value, "q931only")) 01347 options->holdHandling |= H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY; 01348 else if (!strcasecmp(v->value, "h450")) 01349 options->holdHandling |= H323_HOLD_H450; 01350 else 01351 ast_log(LOG_WARNING, "Invalid value %s for %s at line %d\n", v->value, v->name, v->lineno); 01352 } else 01353 return 1; 01354 01355 return 0; 01356 }
| static int update_state | ( | struct oh323_pvt * | pvt, | |
| int | state, | |||
| int | signal | |||
| ) | [static] |
Definition at line 1168 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().
01169 { 01170 if (!pvt) 01171 return 0; 01172 if (pvt->owner && !ast_channel_trylock(pvt->owner)) { 01173 if (state >= 0) 01174 ast_setstate(pvt->owner, state); 01175 if (signal >= 0) 01176 ast_queue_control(pvt->owner, signal); 01177 ast_channel_unlock(pvt->owner); 01178 return 1; 01179 } 01180 else { 01181 if (state >= 0) 01182 pvt->newstate = state; 01183 if (signal >= 0) 01184 pvt->newcontrol = signal; 01185 return 0; 01186 } 01187 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "The NuFone Network's OpenH323 Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 3394 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 3394 of file chan_h323.c.
struct sockaddr_in bindaddr [static] |
Definition at line 129 of file chan_h323.c.
ast_mutex_t caplock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack.
Definition at line 217 of file chan_h323.c.
Referenced by oh323_request().
struct ast_cli_entry cli_h323[] [static] |
Definition at line 2770 of file chan_h323.c.
struct ast_cli_entry cli_h323_reload [static] |
Initial value:
AST_CLI_DEFINE(handle_cli_h323_reload, "Reload H.323 configuration")
Definition at line 3131 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.
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_MUTEX_INITIALIZER ) [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.
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Protect the interface list (oh323_pvt)
Definition at line 210 of file chan_h323.c.
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_MUTEX_INITIALIZER ) [static] |
Protect the H.323 monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
Definition at line 214 of file chan_h323.c.
struct ast_rtp_glue oh323_rtp_glue [static] |
Initial value:
{
.type = "H323",
.get_rtp_info = oh323_get_rtp_peer,
.update_peer = oh323_set_rtp_peer,
}
Definition at line 3207 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(), caldav_load_calendar(), check_access(), decrypt_frame(), exchangecal_load_calendar(), iax2_call(), iax2_register(), ical_load_calendar(), read_agent_config(), register_verify(), reload_config(), set_config(), set_peer_defaults(), sip_register(), sip_request_call(), and sip_subscribe_mwi().
const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver" [static] |
Variables required by Asterisk
Definition at line 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.5.6