/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
*/
//
/**
* This class is a singleton - it has the configuration which
* is the default. It reads from a configuration file and
* this overrides the default. If the config file does not
* expressly forbid it, the ServiceLocationManager interface
* allows some of these configuration options to be modified.
* This configuration is refered to by many points of the
* implementation. Note that the class itself is abstract,
* and is extended by two classes, one that allows slpd to
* run as an SA server only, the other allows it to run
* as a DA as well.
*
* @see com.sun.slp.ServiceLocationManager
*/
/*
* This class contains all configuration information. It
* is hard coded to know the defaults, and will read a config
* file if it is present. The config file will override the
* default values and policy. If the config file allows it
* the user may reset some of these values using the
* ServiceLocationManager interface.
*
*/
class SLPConfig {
/**
* A Java properties file defines `\' as an escape character, which
* conflicts with the SLP API escape convention. Therefore, we need
* to subclass properties so we can parse in the file ourselves.
*/
super(p);
}
// Parse the SLP properties file ourselves. Groan! We don't recognize
// backslash as an escape.
// Throw out anything that begins with '#' or ';'.
continue;
}
// Parse out equals sign, if any. Note that we trim any
// white space preceding or following data strings.
// Although the grammar doesn't allow it, users may
// enter blanks in their configuration files.
// NOTE: White space is not allowed in the data of
// property tag or values. If included, according
// to RFC 2614, Section 2.1 these MUST be escaped,
// ie. space would be represented with '\20'.
// Therefore, it is *completely* safe to perform
// these trim()s. They will catch errors resulting
// from sloppy data entry in slp.conf files and
// never corrupt or alter correctly formatted
// properties.
continue;
}
continue;
}
continue;
}
// Register the property.
}
}
}
protected SLPConfig() {
// Create a temporary, default log to report any errors during
// configuration.
// Initialize properties. Properties on command line override config
// file properties, and both override defaults.
// Load Defalts.
try {
} catch (ClassNotFoundException ex) {
Assert.printMessageAndDie(this,
"no_class",
new Object[] {"com.sun.slp.Defaults"});
}
// System properties now contain Defaults
// Load config file.
try {
}
} catch (IOException ex) {
writeLog("unparsable_config_file",
}
// Add config properties to Defaults, overwritting any pre-existing
// entries
// Now add in system props, overwritting any pre-existing entries
// Initialize useScopes property. This is read-only after the file
// has been loaded.
// Add default scope to scopes for SA.
}
// Initialize SA scopes. This uses a Sun specific property for
// scopes only used by the SA and adds in the DA scopes.
// Initialized preconfigured DAs.
// Initialize broadcast flag.
// Initialize logging. Default is stderr, first check for alternate.
try {
if (loggerClassName != null) {
// Protect against disastrous pilot error, such as trying
// to use com.sun.slp.SLPConfig as the log class
// (causes stack recursion)
loggerClass)) {
} else {
"bad_log_class",
new Object[] {
}
}
"bad_log",
new Object[] {
}
// If no alternate log, revert to minimal default
// If the alternate log failed, log it through the default log
try {
synchronized (log) {
}
} catch (IOException giveUp) {}
}
}
}
// Open a URL onto the configuration file.
}
try {
} catch (MalformedURLException ex) {
writeLog("url_malformed",
} catch (IOException ex) {
// don't complain if we can't find our own default
writeLog("unparsable_config_file",
}
}
return str;
}
// ------------------------------------------------------------
// Property manipulation functions
//
return false;
else
return true;
}
return i;
} else {
return df;
}
}
// ------------------------------------------------------------
// Multicast radius
//
int getMCRadius() {
return getIntProperty("net.slp.multicastTTL",
}
// ------------------------------------------------------------
// Heartbeat interval, seconds.
//
int getAdvertHeartbeatTime() {
return getIntProperty("net.slp.DAHeartBeat",
}
// ------------------------------------------------------------
// Active discovery interval, seconds.
//
int getActiveDiscoveryInterval() {
// We allow zero in order to turn active discovery off, but
// if 5 minutes is the smallest actual time.
0,
iMaxDisc);
writeLog("bad_prop_tag",
new Object[] {"net.slp.DAActiveDiscoveryInterval"});
return iMinDisc;
}
return prop;
}
// ------------------------------------------------------------
// Active discovery granularity, seconds.
//
int getActiveDiscoveryGranularity() {
return getIntProperty("sun.net.slp.DAActiveDiscoveryGranularity",
0,
}
// ------------------------------------------------------------
// Bound for random wait, milliseconds.
//
int getRandomWaitBound() {
return getIntProperty("net.slp.randomWaitBound",
iMaxWait);
}
long getRandomWait() {
if (randomWait == null) {
randomWait = new Random();
}
double r = randomWait.nextDouble();
double max = (double)getRandomWaitBound();
return (long)(max * r);
}
// ------------------------------------------------------------
// TCP timeout, milliseconds.
//
int getTCPTimeout() {
return getIntProperty("sun.net.slp.TCPTimeout",
}
// ------------------------------------------------------------
// Path MTU
//
int getMTU() {
return getIntProperty("net.slp.MTU",
iMaxMTU);
}
// ------------------------------------------------------------
// Serialized registrations.
//
}
// ------------------------------------------------------------
// Are we running as a DA or SA server?
//
protected static boolean isSA = false;
boolean isDA() {
return false;
}
boolean isSA() {
return isSA;
}
// ------------------------------------------------------------
// DA and SA attributes
//
return getAttributes("net.slp.DAAttributes",
true);
}
return getAttributes("net.slp.SAAttributes",
false);
}
boolean daAttrs) {
}
try {
// Create attribute objects.
for (i = 0; i < n; i++) {
new ServiceLocationAttribute(attrExp, false);
// If this is the min-refresh-interval, then check the value.
if (daAttrs &&
boolean errorp = true;
if (ival >= 0 &&
errorp = false;
}
}
}
// Throw exception if it didn't work.
if (errorp) {
throw new ServiceLocationException(
"syntax_error_prop",
}
}
// Add attribute to vector.
}
return attrs;
writeLog("syntax_error_prop",
}
}
// -------------------------------------------------------------
// Do we support V1?
//
boolean isV1Supported() {
return false;
}
// -------------------------------------------------------------
// Queue length for server socket.
//
int getServerSocketQueueLength() {
return getIntProperty("sun.net.slp.serverSocketQueueLength",
0,
}
// ------------------------------------------------------------
// Testing options
//
}
boolean regTest() {
return true;
else
return false;
}
boolean traceMsg() {
return true;
else
return false;
}
boolean traceDrop() {
return true;
else
return false;
}
boolean traceDATraffic() {
return true;
else
return false;
}
// cannot use Boolean.getBoolean as the default is 'true'
// using that mechanism, absense would be considered 'false'
boolean passiveDADetection() {
return true;
else
return false;
}
// Initialized when the SLPConfig object is created to avoid changing
// during the program.
private boolean broadcastOnly = false;
boolean isBroadcastOnly() {
return broadcastOnly;
}
// ------------------------------------------------------------
//
// interface. If groups is not null, then join all
// the groups. Otherwise, this is send only.
try {
// Reopen it.
for (i = 0; i < n; i++) {
}
}
return dss;
// Any exception in error recovery causes program to die.
"cast_socket_failure",
}
return null;
}
// the socket is broadcast, the network interface is not specified in the
// creation message. Is it bound to all interfaces? The isSend parameter
// specifies whether the socket is for send only.
throws ServiceLocationException {
// Substitute broadcast if we are configured for it.
if (isBroadcastOnly()) {
try {
// If transmit, then simply return a new socket.
if (isSend) {
castSocket = new DatagramSocket();
} else {
// Return cached socket if there.
if (broadSocket != null) {
} else {
// Make a new broadcast socket.
}
// Cache for future reference.
}
} catch (SocketException ex) {
throw
"socket_creation_failure",
new Object[] {
}
} else {
// Create a multicast socket.
try {
if (isSend) {
ms = new MulticastSocket();
} else {
}
} catch (IOException ex) {
throw
"socket_creation_failure",
}
try {
// Set the TTL and the interface on the multicast socket.
// Client is responsible for joining group.
} catch (IOException ex) {
throw
"socket_initializtion_failure",
}
castSocket = ms;
}
return castSocket;
}
// ------------------------------------------------------------
// Type hint
//
// Return a vector of ServiceType objects for the type hint.
return hint;
}
// Create a vector of ServiceType objects for the type hint.
try {
for (i = 0; i < n; i++) {
}
} catch (ServiceLocationException ex) {
writeLog("syntax_error_prop",
}
return hint;
}
// ------------------------------------------------------------
// Configured scope handling
//
// Vector of configured scopes.
// Vector of configures scopes for SA.
// Vector of scopes only in the sa server.
// Return the configured scopes.
}
// Return SA scopes.
}
// Return the configured scopes for the SA.
}
// Add scopes discovered during preconfigured DA contact.
// These count as configured scopes.
for (i = 0; i < n; i++) {
}
"sa_new_scope",
}
}
}
// Initialize the scopes list on property.
return new Vector();
}
try {
// Unescape scope strings.
// Validate, lower case scope names.
return vv;
}
} catch (ServiceLocationException ex) {
writeLog("syntax_error_prop",
new Object[] {
prop,
sScopes});
}
return new Vector();
}
// Vector of preconfigured DAs. Read only after initialized.
// Return a vector of DA addresses.
}
// Initialize preconfigured DA list.
return ret;
}
try {
} catch (ServiceLocationException ex) {
writeLog("syntax_error_prop",
return ret;
}
// Convert to InetAddress objects.
int i;
try {
} catch (UnknownHostException ex) {
writeLog("resolve_failed",
/*
* Must decrement the index 'i' otherwise the next iteration
* around the loop will miss the element immediately after
* the element removed.
*
* WARNING: Do not use 'i' again until the loop has
* iterated as it may, after decrementing,
* be negative.
*/
ret.removeElementAt(i);
i--;
continue;
}
}
return ret;
}
// ------------------------------------------------------------
// SLPv1 Support Switches
//
}
if (!getSLPv1NotSupported()) {
}
return false;
}
// ------------------------------------------------------------
// Accessor for SLPConfig object
//
if (theSLPConfig == null) {
theSLPConfig = new SLPConfig();
}
return theSLPConfig;
}
/**
*/
int getMaximumResults() {
if (i == -1) {
}
return i;
} else {
writeLog("bad_prop_tag",
new Object[] {
"net.slp.maxResults"});
return Defaults.iMaximumResults;
}
}
/**
* Convert a language tag into a locale.
*/
// We treat the first part as the ISO 639 language and the
// second part as the ISO 3166 country tag, even though RFC
// 1766 doesn't necessarily require that. We should probably
// use a lookup table here to determine if they are correct.
if (tk.hasMoreTokens()) {
if (tk.hasMoreTokens()) {
// country name may have "-" in it...
}
}
}
/**
* Convert a Locale object into a language tag for output.
*
* @param locale The Locale.
* @return String with the language tag encoded.
*/
// Construct the language tag.
return ltag;
}
/**
* @return the language requests will be made in.
*/
return langTagToLocale(s);
} else {
// Return the Java default if the SLP property is not set.
return Locale.getDefault();
}
}
/**
* @return the InetAddress of the broadcast interface.
*/
if (broadcastAddress == null) {
try {
} catch (UnknownHostException uhe) {
"cast_address_failure",
}
}
return broadcastAddress;
}
/**
* @return the InetAddress of the multicast group.
*/
if (multicastAddress == null) {
try {
} catch (UnknownHostException uhe) {
"cast_address_failure",
}
}
return multicastAddress;
}
/**
* @return the interfaces on which SLP should listen and transmit.
*/
if (interfaces == null) {
// Get local host.
try {
} catch (UnknownHostException ex) {
"resolve_failed",
new Object[] {"localhost"});
}
interfaces = new Vector();
// Only add local host if nothing else is given.
return interfaces;
}
try {
} catch (ServiceLocationException ex) {
writeLog("syntax_error_prop",
new Object[] {
"net.slp.multicastInterfaces",
mcastI});
// Add local host.
return interfaces;
}
// See if they are really there.
for (i = 0; i < n; i++) {
try {
} catch (UnknownHostException ex) {
writeLog("unknown_interface",
"net.slp.multicastInterfaces"});
continue;
}
// Add default at beginning.
} else {
}
}
}
}
return interfaces;
}
/**
* @return An InetAddress object representing 127.0.0.1
*/
try {
} catch (UnknownHostException ex) {
"resolve_failed",
new Object[] {"localhost loopback"});
}
return iaLoopback;
}
/**
* @return The default interface, which should be the first in the
* interfaces vector Vector.
*/
}
// Return true if the address is one of the local interfaces.
// First check loopback
return true;
}
}
// -----------------
// Timeouts
//
// Return the maximum wait for multicast convergence.
int getMulticastMaximumWait() {
return getIntProperty("net.slp.multicastMaximumWait",
}
/*
* @return Vector of timeouts for multicast convergence.
*/
int[] getMulticastTimeouts() {
false,
0,
0);
return timeouts;
}
/**
* @return Vector of timeouts to try for datagram transmission.
*/
int[] getDatagramTimeouts() {
true,
return timeouts;
}
/**
* @return Vector of timeouts for DA discovery multicast.
*/
int[] getDADiscoveryTimeouts() {
false,
0,
0);
return timeouts;
}
/**
* This method ensures that all the timeouts are within valid ranges.
* The sum of all timeouts for the given property name must not
* exceed the value returned by <i>getMulticastMaximumWait()</i>. If
* the sum of all timeouts does exceed the maximum wait period the
* timeouts are averaged out so that the sum equals the maximum wait
* period.
* <br>
* Additional range checking is also performed when <i>rangeCheck</i>
* is true. Then the sum of all timeouts must also be between <i>min</i>
* and <i>max</i>. If the sum of all timeouts is not within the range
* the average is taken from the closest range boundary.
*
* @param property
* Name of timeout property being capped. This is only present for
* reporting purposes and no actual manipulation of the property
* is made within this method.
* @param timeouts
* Array of timeout values.
* @param rangeCheck
* Indicator of whether additional range checking is required. When
* false <i>min</i> and <i>max</i> are ignored.
* @param min
* Additional range checking lower boundary.
* @param max
* Additional range checking upper boundary.
* @return
* Array of capped timeouts. Note this may be the same array as
* passed in (<i>timeouts</i>).
*/
int[] timeouts,
boolean rangeCheck,
int min,
int max) {
int averagedTimeout;
int totalWait = 0;
}
if (rangeCheck) {
// If sum of timeouts within limits then finished.
return timeouts;
}
// Average out the timeouts so the sum is equal to the closest
// range boundary.
} else {
}
writeLog("capped_range_timeout_prop",
} else {
// Sum of all timeouts must not exceed this value.
int maximumWait = getMulticastMaximumWait();
// If sum of timeouts within limits then finished.
if (totalWait <= maximumWait) {
return timeouts;
}
// Average out the timeouts so the sum is equal to the maximum
// timeout.
writeLog("capped_timeout_prop",
}
}
return timeouts;
}
return defaults;
}
try {
} catch (ServiceLocationException ex) {
writeLog("syntax_error_prop",
return defaults;
}
int iCount = 0;
try {
} catch (NumberFormatException nfe) {
writeLog("syntax_error_prop",
return defaults;
}
writeLog("invalid_timeout_prop",
return defaults;
}
iCount++;
}
return iTOs;
}
// -----------------------------
// SLP Time Calculation
//
/**
* Returns the number of seconds since 00:00 Universal Coordinated
* Time, January 1, 1970.
*
* Java returns the number of milliseconds, so all the method does is
* divide by 1000.
*
* This implementation still will have a problem when the Java time
* values wraps, but there isn't much we can do now.
*/
static long currentSLPTime() {
}
/* security */
// Indicates whether security class is available.
boolean getSecurityEnabled() {
return securityEnabled;
}
private static boolean securityEnabled;
// Indicates whether the securityEnabled property is true
boolean getHasSecurity() {
return securityEnabled &&
"false")).booleanValue());
}
// I18N Support.
// First try the Solaris Java locale area
try {
return msgBundle;
} catch (MalformedURLException e) { // shouldn't get here
} catch (MissingResourceException ex) {
"/usr/share/lib/locale/" + BASE_BUNDLE_NAME +
"'' for locale ``" +
locale + "''; trying default...");
}
try {
// We can't print out to the log, because we may be in the
// process of trying to.
"'' for locale ``"+
"''");
// Hosed if the default locale is missing.
}
// Otherwise, return the default locale.
"''");
}
return msgBundle;
}
}
// MessageFormat is picky about types. Convert the params into strings.
for (i = 0; i < n; i++) {
} else {
params[i] = "<null>";
}
}
}
static String
try {
} catch (MissingResourceException ex) {
// Attempt to report error. Can't use Assert here because it
// calls back into SLPConfig.
try {
} catch (MissingResourceException exx) {
}
}
}
// logging.
// Protected so slpd can replace it.
// Synchronized so writes from multiple threads don't get interleaved.
// MessageFormat is picky about types. Convert the params into strings.
try {
synchronized (log) {
}
} catch (IOException ex) {}
}
try {
synchronized (log) {
}
} catch (IOException ex) {}
}
getLocale());
}
// On load, check whether the signature class is available, and turn
// security off if not.
static {
securityEnabled = true;
try {
} catch (ClassNotFoundException e) {
securityEnabled = false;
}
}
}