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

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