10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7298SMark.J.Nelson@Sun.COM * Common Development and Distribution License (the "License"). 6*7298SMark.J.Nelson@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 220Sstevel@tonic-gate * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate // SLPConfig.java 280Sstevel@tonic-gate // 290Sstevel@tonic-gate 300Sstevel@tonic-gate /** 310Sstevel@tonic-gate * This class is a singleton - it has the configuration which 320Sstevel@tonic-gate * is the default. It reads from a configuration file and 330Sstevel@tonic-gate * this overrides the default. If the config file does not 340Sstevel@tonic-gate * expressly forbid it, the ServiceLocationManager interface 350Sstevel@tonic-gate * allows some of these configuration options to be modified. 360Sstevel@tonic-gate * This configuration is refered to by many points of the 370Sstevel@tonic-gate * implementation. Note that the class itself is abstract, 380Sstevel@tonic-gate * and is extended by two classes, one that allows slpd to 390Sstevel@tonic-gate * run as an SA server only, the other allows it to run 400Sstevel@tonic-gate * as a DA as well. 410Sstevel@tonic-gate * 420Sstevel@tonic-gate * @see com.sun.slp.ServiceLocationManager 430Sstevel@tonic-gate */ 440Sstevel@tonic-gate 450Sstevel@tonic-gate package com.sun.slp; 460Sstevel@tonic-gate 470Sstevel@tonic-gate import java.net.*; 480Sstevel@tonic-gate import java.util.*; 490Sstevel@tonic-gate import java.text.*; 500Sstevel@tonic-gate import java.io.*; 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * This class contains all configuration information. It 540Sstevel@tonic-gate * is hard coded to know the defaults, and will read a config 550Sstevel@tonic-gate * file if it is present. The config file will override the 560Sstevel@tonic-gate * default values and policy. If the config file allows it 570Sstevel@tonic-gate * the user may reset some of these values using the 580Sstevel@tonic-gate * ServiceLocationManager interface. 590Sstevel@tonic-gate * 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate class SLPConfig { 620Sstevel@tonic-gate 630Sstevel@tonic-gate /** 640Sstevel@tonic-gate * A Java properties file defines `\' as an escape character, which 650Sstevel@tonic-gate * conflicts with the SLP API escape convention. Therefore, we need 660Sstevel@tonic-gate * to subclass properties so we can parse in the file ourselves. 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate 690Sstevel@tonic-gate public static class SLPProperties extends Properties { 700Sstevel@tonic-gate SLPProperties(Properties p)710Sstevel@tonic-gate SLPProperties(Properties p) { 720Sstevel@tonic-gate super(p); 730Sstevel@tonic-gate 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate // Parse the SLP properties file ourselves. Groan! We don't recognize 770Sstevel@tonic-gate // backslash as an escape. 780Sstevel@tonic-gate load(InputStream in)790Sstevel@tonic-gate public synchronized void load(InputStream in) throws IOException { 800Sstevel@tonic-gate 810Sstevel@tonic-gate BufferedReader rd = new BufferedReader(new InputStreamReader(in)); 820Sstevel@tonic-gate 830Sstevel@tonic-gate while (rd.ready()) { 840Sstevel@tonic-gate String ln = rd.readLine(); 850Sstevel@tonic-gate 860Sstevel@tonic-gate // Throw out anything that begins with '#' or ';'. 870Sstevel@tonic-gate 880Sstevel@tonic-gate if (ln.startsWith("#") || 890Sstevel@tonic-gate ln.startsWith(";") || 900Sstevel@tonic-gate ln.length() <= 0) { 910Sstevel@tonic-gate continue; 920Sstevel@tonic-gate 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 950Sstevel@tonic-gate // Parse out equals sign, if any. Note that we trim any 960Sstevel@tonic-gate // white space preceding or following data strings. 970Sstevel@tonic-gate // Although the grammar doesn't allow it, users may 980Sstevel@tonic-gate // enter blanks in their configuration files. 990Sstevel@tonic-gate // NOTE: White space is not allowed in the data of 1000Sstevel@tonic-gate // property tag or values. If included, according 1010Sstevel@tonic-gate // to RFC 2614, Section 2.1 these MUST be escaped, 1020Sstevel@tonic-gate // ie. space would be represented with '\20'. 1030Sstevel@tonic-gate // Therefore, it is *completely* safe to perform 1040Sstevel@tonic-gate // these trim()s. They will catch errors resulting 1050Sstevel@tonic-gate // from sloppy data entry in slp.conf files and 1060Sstevel@tonic-gate // never corrupt or alter correctly formatted 1070Sstevel@tonic-gate // properties. 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate SLPTokenizer tk = new SLPTokenizer(ln, "="); 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate if (!tk.hasMoreTokens()) {// empty line... 1120Sstevel@tonic-gate continue; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate String prop = tk.nextToken().trim(); 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate if (prop.trim().length() <= 0) {// line has just spaces... 1190Sstevel@tonic-gate continue; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate } 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (!tk.hasMoreTokens()) {// line has no definition... 1240Sstevel@tonic-gate continue; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate // Register the property. 1290Sstevel@tonic-gate String def = tk.nextToken().trim(); 1300Sstevel@tonic-gate this.setProperty(prop, def); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate SLPConfig()1360Sstevel@tonic-gate protected SLPConfig() { 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate // Create a temporary, default log to report any errors during 1390Sstevel@tonic-gate // configuration. 1400Sstevel@tonic-gate log = new StderrLog(); 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate // Initialize properties. Properties on command line override config 1430Sstevel@tonic-gate // file properties, and both override defaults. 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate Properties sysProps = (Properties)(System.getProperties().clone()); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate // Load Defalts. 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate try { 1500Sstevel@tonic-gate Class.forName("com.sun.slp.Defaults"); 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate } catch (ClassNotFoundException ex) { 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate Assert.printMessageAndDie(this, 1550Sstevel@tonic-gate "no_class", 1560Sstevel@tonic-gate new Object[] {"com.sun.slp.Defaults"}); 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate // System properties now contain Defaults 1600Sstevel@tonic-gate Properties defaultProps = System.getProperties(); 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate // Load config file. 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate SLPProperties slpProps = new SLPProperties(new Properties()); 1650Sstevel@tonic-gate try { 1660Sstevel@tonic-gate InputStream fis = getConfigURLStream(); 1670Sstevel@tonic-gate if (fis != null) { 1680Sstevel@tonic-gate slpProps.load(fis); 1690Sstevel@tonic-gate System.setProperties(slpProps); 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate } catch (IOException ex) { 1730Sstevel@tonic-gate writeLog("unparsable_config_file", 1740Sstevel@tonic-gate new Object[] {ex.getMessage()}); 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate // Add config properties to Defaults, overwritting any pre-existing 1780Sstevel@tonic-gate // entries 1790Sstevel@tonic-gate defaultProps.putAll(slpProps); 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate // Now add in system props, overwritting any pre-existing entries 1820Sstevel@tonic-gate defaultProps.putAll(sysProps); 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate System.setProperties(defaultProps); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate // Initialize useScopes property. This is read-only after the file 1880Sstevel@tonic-gate // has been loaded. 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate configuredScopes = initializeScopes("net.slp.useScopes"); 1910Sstevel@tonic-gate saConfiguredScopes = (Vector)configuredScopes.clone(); 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate // Add default scope to scopes for SA. 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate if (saConfiguredScopes.size() <= 0) { 1960Sstevel@tonic-gate saConfiguredScopes.addElement(Defaults.DEFAULT_SCOPE); 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate // Initialize SA scopes. This uses a Sun specific property for 2010Sstevel@tonic-gate // scopes only used by the SA and adds in the DA scopes. 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate saOnlyScopes = initializeScopes(DATable.SA_ONLY_SCOPES_PROP); 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate // Initialized preconfigured DAs. 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate preconfiguredDAs = initializePreconfiguredDAs(); 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate // Initialize broadcast flag. 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate broadcastOnly = Boolean.getBoolean("net.slp.isBroadcastOnly"); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate // Initialize logging. Default is stderr, first check for alternate. 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate String failed = null; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate try { 2180Sstevel@tonic-gate String loggerClassName = 2190Sstevel@tonic-gate System.getProperty("sun.net.slp.loggerClass"); 2200Sstevel@tonic-gate if (loggerClassName != null) { 2210Sstevel@tonic-gate Class loggerClass = Class.forName(loggerClassName); 2220Sstevel@tonic-gate // Protect against disastrous pilot error, such as trying 2230Sstevel@tonic-gate // to use com.sun.slp.SLPConfig as the log class 2240Sstevel@tonic-gate // (causes stack recursion) 2250Sstevel@tonic-gate if (Class.forName("java.io.Writer").isAssignableFrom( 2260Sstevel@tonic-gate loggerClass)) { 2270Sstevel@tonic-gate Object logger = loggerClass.newInstance(); 2280Sstevel@tonic-gate log = (Writer) logger; 2290Sstevel@tonic-gate } else { 2300Sstevel@tonic-gate failed = formatMessage( 2310Sstevel@tonic-gate "bad_log_class", 2320Sstevel@tonic-gate new Object[] { 2330Sstevel@tonic-gate loggerClass.toString()}) + "\n"; 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate } catch (Throwable ex) { 2380Sstevel@tonic-gate log = null; 2390Sstevel@tonic-gate failed = formatMessage( 2400Sstevel@tonic-gate "bad_log", 2410Sstevel@tonic-gate new Object[] { 2420Sstevel@tonic-gate ex.toString()}) + "\n"; 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate // If no alternate log, revert to minimal default 2460Sstevel@tonic-gate if (log == null) { 2470Sstevel@tonic-gate log = new StderrLog(); 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate // If the alternate log failed, log it through the default log 2500Sstevel@tonic-gate if (failed != null) { 2510Sstevel@tonic-gate try { 2520Sstevel@tonic-gate synchronized (log) { 2530Sstevel@tonic-gate log.write(failed); 2540Sstevel@tonic-gate log.flush(); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate } catch (IOException giveUp) {} 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate getConfigURLStream()2620Sstevel@tonic-gate private InputStream getConfigURLStream() { 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate // Open a URL onto the configuration file. 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate String conf = System.getProperty("sun.net.slp.configURL"); 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate if (conf == null) { 2690Sstevel@tonic-gate conf = Defaults.SOLARIS_CONF; 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate InputStream str = null; 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate try { 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate URL confURL = new URL(conf); 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate str = confURL.openStream(); 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate } catch (MalformedURLException ex) { 2820Sstevel@tonic-gate writeLog("url_malformed", 2830Sstevel@tonic-gate new Object[] {conf}); 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate } catch (IOException ex) { 2860Sstevel@tonic-gate if (conf != Defaults.SOLARIS_CONF) { 2870Sstevel@tonic-gate // don't complain if we can't find our own default 2880Sstevel@tonic-gate writeLog("unparsable_config_file", 2890Sstevel@tonic-gate new Object[] {ex.getMessage()}); 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate return str; 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate // ------------------------------------------------------------ 2980Sstevel@tonic-gate // Property manipulation functions 2990Sstevel@tonic-gate // 3000Sstevel@tonic-gate OKBound(int i, int lb, int ub)3010Sstevel@tonic-gate private boolean OKBound(int i, int lb, int ub) { 3020Sstevel@tonic-gate if (i < lb || i > ub) 3030Sstevel@tonic-gate return false; 3040Sstevel@tonic-gate else 3050Sstevel@tonic-gate return true; 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate getIntProperty(String prop, int df, int lb, int ub)3080Sstevel@tonic-gate int getIntProperty(String prop, int df, int lb, int ub) { 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate int i = Integer.getInteger(prop, df).intValue(); 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate if (OKBound(i, lb, ub)) { 3130Sstevel@tonic-gate return i; 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate } else { 3160Sstevel@tonic-gate writeLog("bad_prop_tag", new Object[] {prop}); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate return df; 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate // ------------------------------------------------------------ 3230Sstevel@tonic-gate // Multicast radius 3240Sstevel@tonic-gate // 3250Sstevel@tonic-gate private int iMinMCRadius = 1; // link local scope 3260Sstevel@tonic-gate private int iMaxMCRadius = 255; // universal scope 3270Sstevel@tonic-gate getMCRadius()3280Sstevel@tonic-gate int getMCRadius() { 3290Sstevel@tonic-gate return getIntProperty("net.slp.multicastTTL", 3300Sstevel@tonic-gate Defaults.iMulticastRadius, 3310Sstevel@tonic-gate iMinMCRadius, 3320Sstevel@tonic-gate iMaxMCRadius); 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate // ------------------------------------------------------------ 3360Sstevel@tonic-gate // Heartbeat interval, seconds. 3370Sstevel@tonic-gate // 3380Sstevel@tonic-gate private final int iMinHeart = 2000; // 10 minutes 3390Sstevel@tonic-gate private final int iMaxHeart = 259200000; // 3 days 3400Sstevel@tonic-gate getAdvertHeartbeatTime()3410Sstevel@tonic-gate int getAdvertHeartbeatTime() { 3420Sstevel@tonic-gate return getIntProperty("net.slp.DAHeartBeat", 3430Sstevel@tonic-gate Defaults.iHeartbeat, 3440Sstevel@tonic-gate iMinHeart, 3450Sstevel@tonic-gate iMaxHeart); 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate // ------------------------------------------------------------ 3490Sstevel@tonic-gate // Active discovery interval, seconds. 3500Sstevel@tonic-gate // 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate private final int iMinDisc = 300; // 5 minutes 3530Sstevel@tonic-gate private final int iMaxDisc = 10800; // 3 hours 3540Sstevel@tonic-gate getActiveDiscoveryInterval()3550Sstevel@tonic-gate int getActiveDiscoveryInterval() { 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate // We allow zero in order to turn active discovery off, but 3580Sstevel@tonic-gate // if 5 minutes is the smallest actual time. 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate int prop = getIntProperty("net.slp.DAActiveDiscoveryInterval", 3610Sstevel@tonic-gate Defaults.iActiveDiscoveryInterval, 3620Sstevel@tonic-gate 0, 3630Sstevel@tonic-gate iMaxDisc); 3640Sstevel@tonic-gate if (prop > 0 && prop < iMinDisc) { 3650Sstevel@tonic-gate writeLog("bad_prop_tag", 3660Sstevel@tonic-gate new Object[] {"net.slp.DAActiveDiscoveryInterval"}); 3670Sstevel@tonic-gate return iMinDisc; 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate return prop; 3720Sstevel@tonic-gate } 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate // ------------------------------------------------------------ 3760Sstevel@tonic-gate // Active discovery granularity, seconds. 3770Sstevel@tonic-gate // 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate private int iMaxDiscGran = iMaxDisc * 2; 3800Sstevel@tonic-gate getActiveDiscoveryGranularity()3810Sstevel@tonic-gate int getActiveDiscoveryGranularity() { 3820Sstevel@tonic-gate return getIntProperty("sun.net.slp.DAActiveDiscoveryGranularity", 3830Sstevel@tonic-gate Defaults.iActiveDiscoveryGranularity, 3840Sstevel@tonic-gate 0, 3850Sstevel@tonic-gate iMaxDiscGran); 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate // ------------------------------------------------------------ 3890Sstevel@tonic-gate // Bound for random wait, milliseconds. 3900Sstevel@tonic-gate // 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate private final int iMinWait = 1000; // 1 sec. 3930Sstevel@tonic-gate private final int iMaxWait = 3000; // 3 sec. 3940Sstevel@tonic-gate getRandomWaitBound()3950Sstevel@tonic-gate int getRandomWaitBound() { 3960Sstevel@tonic-gate return getIntProperty("net.slp.randomWaitBound", 3970Sstevel@tonic-gate Defaults.iRandomWaitBound, 3980Sstevel@tonic-gate iMinWait, 3990Sstevel@tonic-gate iMaxWait); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate private static Random randomWait = null; 4030Sstevel@tonic-gate getRandomWait()4040Sstevel@tonic-gate long getRandomWait() { 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate if (randomWait == null) { 4070Sstevel@tonic-gate randomWait = new Random(); 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate double r = randomWait.nextDouble(); 4110Sstevel@tonic-gate double max = (double)getRandomWaitBound(); 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate return (long)(max * r); 4140Sstevel@tonic-gate } 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate // ------------------------------------------------------------ 4170Sstevel@tonic-gate // TCP timeout, milliseconds. 4180Sstevel@tonic-gate // 4190Sstevel@tonic-gate final static private int iMinTimeout = 100; 4200Sstevel@tonic-gate final static private int iMaxTimeout = 360000; 4210Sstevel@tonic-gate getTCPTimeout()4220Sstevel@tonic-gate int getTCPTimeout() { 4230Sstevel@tonic-gate return getIntProperty("sun.net.slp.TCPTimeout", 4240Sstevel@tonic-gate Defaults.iTCPTimeout, 4250Sstevel@tonic-gate iMinTimeout, 4260Sstevel@tonic-gate iMaxTimeout); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate // ------------------------------------------------------------ 4300Sstevel@tonic-gate // Path MTU 4310Sstevel@tonic-gate // 4320Sstevel@tonic-gate private final int iMinMTU = 128; // used for some ppp connections 4330Sstevel@tonic-gate private final int iMaxMTU = 8192; // used on some LANs 4340Sstevel@tonic-gate getMTU()4350Sstevel@tonic-gate int getMTU() { 4360Sstevel@tonic-gate return getIntProperty("net.slp.MTU", 4370Sstevel@tonic-gate Defaults.iMTU, 4380Sstevel@tonic-gate iMinMTU, 4390Sstevel@tonic-gate iMaxMTU); 4400Sstevel@tonic-gate } 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate // ------------------------------------------------------------ 4440Sstevel@tonic-gate // Serialized registrations. 4450Sstevel@tonic-gate // 4460Sstevel@tonic-gate getSerializedRegURL()4470Sstevel@tonic-gate String getSerializedRegURL() { 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate return System.getProperty("net.slp.serializedRegURL", null); 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate // ------------------------------------------------------------ 4540Sstevel@tonic-gate // Are we running as a DA or SA server? 4550Sstevel@tonic-gate // 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate protected static boolean isSA = false; 4580Sstevel@tonic-gate isDA()4590Sstevel@tonic-gate boolean isDA() { 4600Sstevel@tonic-gate return false; 4610Sstevel@tonic-gate } 4620Sstevel@tonic-gate isSA()4630Sstevel@tonic-gate boolean isSA() { 4640Sstevel@tonic-gate return isSA; 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate // ------------------------------------------------------------ 4680Sstevel@tonic-gate // DA and SA attributes 4690Sstevel@tonic-gate // 4700Sstevel@tonic-gate getDAAttributes()4710Sstevel@tonic-gate Vector getDAAttributes() { 4720Sstevel@tonic-gate return getAttributes("net.slp.DAAttributes", 4730Sstevel@tonic-gate Defaults.defaultDAAttributes, 4740Sstevel@tonic-gate true); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate getSAAttributes()4770Sstevel@tonic-gate Vector getSAAttributes() { 4780Sstevel@tonic-gate return getAttributes("net.slp.SAAttributes", 4790Sstevel@tonic-gate Defaults.defaultSAAttributes, 4800Sstevel@tonic-gate false); 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate getAttributes(String prop, Vector defaults, boolean daAttrs)4830Sstevel@tonic-gate private Vector getAttributes(String prop, 4840Sstevel@tonic-gate Vector defaults, 4850Sstevel@tonic-gate boolean daAttrs) { 4860Sstevel@tonic-gate String attrList = 4870Sstevel@tonic-gate System.getProperty(prop); 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate if (attrList == null || attrList.length() <= 0) { 4900Sstevel@tonic-gate return (Vector)defaults.clone(); 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate try { 4950Sstevel@tonic-gate Vector sAttrs = 4960Sstevel@tonic-gate SrvLocHeader.parseCommaSeparatedListIn(attrList, false); 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate Vector attrs = new Vector(); 4990Sstevel@tonic-gate int i, n = sAttrs.size(); 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate // Create attribute objects. 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate for (i = 0; i < n; i++) { 5040Sstevel@tonic-gate String attrExp = (String)sAttrs.elementAt(i); 5050Sstevel@tonic-gate ServiceLocationAttribute attr = 5060Sstevel@tonic-gate new ServiceLocationAttribute(attrExp, false); 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate // If this is the min-refresh-interval, then check the value. 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate if (daAttrs && 5110Sstevel@tonic-gate attr.getId().equals( 5120Sstevel@tonic-gate Defaults.MIN_REFRESH_INTERVAL_ATTR_ID)) { 5130Sstevel@tonic-gate Vector values = attr.getValues(); 5140Sstevel@tonic-gate boolean errorp = true; 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate if (values != null && values.size() == 1) { 5170Sstevel@tonic-gate Object val = values.elementAt(0); 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate if (val instanceof Integer) { 5200Sstevel@tonic-gate int ival = ((Integer)val).intValue(); 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate if (ival >= 0 && 5230Sstevel@tonic-gate ival <= ServiceURL.LIFETIME_MAXIMUM) { 5240Sstevel@tonic-gate errorp = false; 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate } 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate // Throw exception if it didn't work. 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate if (errorp) { 5330Sstevel@tonic-gate throw new ServiceLocationException( 5340Sstevel@tonic-gate ServiceLocationException.PARSE_ERROR, 5350Sstevel@tonic-gate "syntax_error_prop", 5360Sstevel@tonic-gate new Object[] {prop, attrs}); 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate // Add attribute to vector. 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate attrs.addElement(attr); 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate 5470Sstevel@tonic-gate return attrs; 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate } catch (Exception ex) { 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate writeLog("syntax_error_prop", 5520Sstevel@tonic-gate new Object[] {prop, attrList}); 5530Sstevel@tonic-gate return (Vector)defaults.clone(); 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate } 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate // ------------------------------------------------------------- 5590Sstevel@tonic-gate // Do we support V1? 5600Sstevel@tonic-gate // 5610Sstevel@tonic-gate isV1Supported()5620Sstevel@tonic-gate boolean isV1Supported() { 5630Sstevel@tonic-gate return false; 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate // ------------------------------------------------------------- 5670Sstevel@tonic-gate // Queue length for server socket. 5680Sstevel@tonic-gate // 5690Sstevel@tonic-gate getServerSocketQueueLength()5700Sstevel@tonic-gate int getServerSocketQueueLength() { 5710Sstevel@tonic-gate return getIntProperty("sun.net.slp.serverSocketQueueLength", 5720Sstevel@tonic-gate Defaults.iSocketQueueLength, 5730Sstevel@tonic-gate 0, 5740Sstevel@tonic-gate Integer.MAX_VALUE); 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate // ------------------------------------------------------------ 5780Sstevel@tonic-gate // Testing options 5790Sstevel@tonic-gate // 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate traceAll()5820Sstevel@tonic-gate boolean traceAll() {// not official! 5830Sstevel@tonic-gate return Boolean.getBoolean("sun.net.slp.traceALL"); 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate regTest()5860Sstevel@tonic-gate boolean regTest() { 5870Sstevel@tonic-gate if (Boolean.getBoolean("sun.net.slp.traceALL") || 5880Sstevel@tonic-gate Boolean.getBoolean("net.slp.traceReg")) 5890Sstevel@tonic-gate return true; 5900Sstevel@tonic-gate else 5910Sstevel@tonic-gate return false; 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate traceMsg()5940Sstevel@tonic-gate boolean traceMsg() { 5950Sstevel@tonic-gate if (Boolean.getBoolean("sun.net.slp.traceALL") || 5960Sstevel@tonic-gate Boolean.getBoolean("net.slp.traceMsg")) 5970Sstevel@tonic-gate return true; 5980Sstevel@tonic-gate else 5990Sstevel@tonic-gate return false; 6000Sstevel@tonic-gate } 6010Sstevel@tonic-gate traceDrop()6020Sstevel@tonic-gate boolean traceDrop() { 6030Sstevel@tonic-gate if (Boolean.getBoolean("sun.net.slp.traceALL") || 6040Sstevel@tonic-gate Boolean.getBoolean("net.slp.traceDrop")) 6050Sstevel@tonic-gate return true; 6060Sstevel@tonic-gate else 6070Sstevel@tonic-gate return false; 6080Sstevel@tonic-gate } 6090Sstevel@tonic-gate traceDATraffic()6100Sstevel@tonic-gate boolean traceDATraffic() { 6110Sstevel@tonic-gate if (Boolean.getBoolean("sun.net.slp.traceALL") || 6120Sstevel@tonic-gate Boolean.getBoolean("net.slp.traceDATraffic")) 6130Sstevel@tonic-gate return true; 6140Sstevel@tonic-gate else 6150Sstevel@tonic-gate return false; 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate // cannot use Boolean.getBoolean as the default is 'true' 6190Sstevel@tonic-gate // using that mechanism, absense would be considered 'false' 6200Sstevel@tonic-gate passiveDADetection()6210Sstevel@tonic-gate boolean passiveDADetection() { 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate String sPassive = 6240Sstevel@tonic-gate System.getProperty("net.slp.passiveDADetection", "true"); 6250Sstevel@tonic-gate if (sPassive.equalsIgnoreCase("true")) 6260Sstevel@tonic-gate return true; 6270Sstevel@tonic-gate else 6280Sstevel@tonic-gate return false; 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate // Initialized when the SLPConfig object is created to avoid changing 6330Sstevel@tonic-gate // during the program. 6340Sstevel@tonic-gate private boolean broadcastOnly = false; 6350Sstevel@tonic-gate isBroadcastOnly()6360Sstevel@tonic-gate boolean isBroadcastOnly() { 6370Sstevel@tonic-gate return broadcastOnly; 6380Sstevel@tonic-gate } 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate // ------------------------------------------------------------ 6420Sstevel@tonic-gate // Multicast/broadcast socket mangement. 6430Sstevel@tonic-gate // 6440Sstevel@tonic-gate DatagramSocket broadSocket = null; // cached broadcast socket. 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate // Reopen the multicast/broadcast socket bound to the 6480Sstevel@tonic-gate // interface. If groups is not null, then join all 6490Sstevel@tonic-gate // the groups. Otherwise, this is send only. 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate DatagramSocket refreshMulticastSocketOnInterface(InetAddress interfac, Vector groups)6520Sstevel@tonic-gate refreshMulticastSocketOnInterface(InetAddress interfac, 6530Sstevel@tonic-gate Vector groups) { 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate try { 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate // Reopen it. 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate DatagramSocket dss = 6600Sstevel@tonic-gate getMulticastSocketOnInterface(interfac, 6610Sstevel@tonic-gate (groups == null ? true:false)); 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate if ((groups != null) && (dss instanceof MulticastSocket)) { 6640Sstevel@tonic-gate int i, n = groups.size(); 6650Sstevel@tonic-gate MulticastSocket mss = (MulticastSocket)dss; 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate for (i = 0; i < n; i++) { 6680Sstevel@tonic-gate InetAddress maddr = (InetAddress)groups.elementAt(i); 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate mss.joinGroup(maddr); 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate } 6730Sstevel@tonic-gate } 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate return dss; 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate } catch (Exception ex) { 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate // Any exception in error recovery causes program to die. 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate Assert.slpassert(false, 6820Sstevel@tonic-gate "cast_socket_failure", 6830Sstevel@tonic-gate new Object[] {ex, ex.getMessage()}); 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate } 6860Sstevel@tonic-gate 6870Sstevel@tonic-gate return null; 6880Sstevel@tonic-gate } 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate // Open a multicast/broadcast socket on the interface. Note that if 6910Sstevel@tonic-gate // the socket is broadcast, the network interface is not specified in the 6920Sstevel@tonic-gate // creation message. Is it bound to all interfaces? The isSend parameter 6930Sstevel@tonic-gate // specifies whether the socket is for send only. 6940Sstevel@tonic-gate 6950Sstevel@tonic-gate DatagramSocket getMulticastSocketOnInterface(InetAddress interfac, boolean isSend)6960Sstevel@tonic-gate getMulticastSocketOnInterface(InetAddress interfac, boolean isSend) 6970Sstevel@tonic-gate throws ServiceLocationException { 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate DatagramSocket castSocket = null; 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate // Substitute broadcast if we are configured for it. 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate if (isBroadcastOnly()) { 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate try { 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate // If transmit, then simply return a new socket. 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate if (isSend) { 7100Sstevel@tonic-gate castSocket = new DatagramSocket(); 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate } else { 7130Sstevel@tonic-gate 7140Sstevel@tonic-gate // Return cached socket if there. 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate if (broadSocket != null) { 7170Sstevel@tonic-gate castSocket = broadSocket; 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate } else { 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate // Make a new broadcast socket. 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate castSocket = 7240Sstevel@tonic-gate new DatagramSocket(Defaults.iSLPPort, 7250Sstevel@tonic-gate getBroadcastAddress()); 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate // Cache for future reference. 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate broadSocket = castSocket; 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate } catch (SocketException ex) { 7340Sstevel@tonic-gate throw 7350Sstevel@tonic-gate new ServiceLocationException( 7360Sstevel@tonic-gate ServiceLocationException.NETWORK_INIT_FAILED, 7370Sstevel@tonic-gate "socket_creation_failure", 7380Sstevel@tonic-gate new Object[] { 7390Sstevel@tonic-gate getBroadcastAddress(), ex.getMessage()}); 7400Sstevel@tonic-gate } 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate } else { 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate // Create a multicast socket. 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate MulticastSocket ms; 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate try { 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate if (isSend) { 7510Sstevel@tonic-gate ms = new MulticastSocket(); 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate } else { 7540Sstevel@tonic-gate ms = new MulticastSocket(Defaults.iSLPPort); 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate } 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate } catch (IOException ex) { 7590Sstevel@tonic-gate throw 7600Sstevel@tonic-gate new ServiceLocationException( 7610Sstevel@tonic-gate ServiceLocationException.NETWORK_INIT_FAILED, 7620Sstevel@tonic-gate "socket_creation_failure", 7630Sstevel@tonic-gate new Object[] {interfac, ex.getMessage()}); 7640Sstevel@tonic-gate } 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate 7670Sstevel@tonic-gate try { 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate // Set the TTL and the interface on the multicast socket. 7700Sstevel@tonic-gate // Client is responsible for joining group. 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate ms.setTimeToLive(getMCRadius()); 7730Sstevel@tonic-gate ms.setInterface(interfac); 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate } catch (IOException ex) { 7760Sstevel@tonic-gate throw 7770Sstevel@tonic-gate new ServiceLocationException( 7780Sstevel@tonic-gate ServiceLocationException.NETWORK_INIT_FAILED, 7790Sstevel@tonic-gate "socket_initializtion_failure", 7800Sstevel@tonic-gate new Object[] {interfac, ex.getMessage()}); 7810Sstevel@tonic-gate } 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate castSocket = ms; 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate } 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate return castSocket; 7880Sstevel@tonic-gate } 7890Sstevel@tonic-gate 7900Sstevel@tonic-gate // ------------------------------------------------------------ 7910Sstevel@tonic-gate // Type hint 7920Sstevel@tonic-gate // 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate // Return a vector of ServiceType objects for the type hint. 7950Sstevel@tonic-gate getTypeHint()7960Sstevel@tonic-gate Vector getTypeHint() { 7970Sstevel@tonic-gate Vector hint = new Vector(); 7980Sstevel@tonic-gate String sTypeList = System.getProperty("net.slp.typeHint", ""); 7990Sstevel@tonic-gate 8000Sstevel@tonic-gate if (sTypeList.length() <= 0) { 8010Sstevel@tonic-gate return hint; 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate // Create a vector of ServiceType objects for the type hint. 8060Sstevel@tonic-gate 8070Sstevel@tonic-gate try { 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate hint = SrvLocHeader.parseCommaSeparatedListIn(sTypeList, true); 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate int i, n = hint.size(); 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate for (i = 0; i < n; i++) { 8140Sstevel@tonic-gate String type = (String)hint.elementAt(i); 8150Sstevel@tonic-gate 8160Sstevel@tonic-gate hint.setElementAt(new ServiceType(type), i); 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate } catch (ServiceLocationException ex) { 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate writeLog("syntax_error_prop", 8220Sstevel@tonic-gate new Object[] {"net.slp.typeHint", sTypeList}); 8230Sstevel@tonic-gate 8240Sstevel@tonic-gate hint.removeAllElements(); 8250Sstevel@tonic-gate 8260Sstevel@tonic-gate } 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate return hint; 8290Sstevel@tonic-gate 8300Sstevel@tonic-gate } 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate // ------------------------------------------------------------ 8330Sstevel@tonic-gate // Configured scope handling 8340Sstevel@tonic-gate // 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate // Vector of configured scopes. 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate private Vector configuredScopes = null; 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate // Vector of configures scopes for SA. 8410Sstevel@tonic-gate 8420Sstevel@tonic-gate private Vector saConfiguredScopes = null; 8430Sstevel@tonic-gate 8440Sstevel@tonic-gate // Vector of scopes only in the sa server. 8450Sstevel@tonic-gate 8460Sstevel@tonic-gate private Vector saOnlyScopes = null; 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate // Return the configured scopes. 8490Sstevel@tonic-gate getConfiguredScopes()8500Sstevel@tonic-gate Vector getConfiguredScopes() { 8510Sstevel@tonic-gate return (Vector)configuredScopes.clone(); 8520Sstevel@tonic-gate } 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate // Return SA scopes. 8550Sstevel@tonic-gate getSAOnlyScopes()8560Sstevel@tonic-gate Vector getSAOnlyScopes() { 8570Sstevel@tonic-gate return (Vector)saOnlyScopes.clone(); 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate } 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate // Return the configured scopes for the SA. 8620Sstevel@tonic-gate getSAConfiguredScopes()8630Sstevel@tonic-gate Vector getSAConfiguredScopes() { 8640Sstevel@tonic-gate return (Vector)saConfiguredScopes.clone(); 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate } 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate // Add scopes discovered during preconfigured DA contact. 8690Sstevel@tonic-gate // These count as configured scopes. 8700Sstevel@tonic-gate addPreconfiguredDAScopes(Vector scopes)8710Sstevel@tonic-gate void addPreconfiguredDAScopes(Vector scopes) { 8720Sstevel@tonic-gate 8730Sstevel@tonic-gate int i, n = scopes.size(); 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate for (i = 0; i < n; i++) { 8760Sstevel@tonic-gate Object scope = scopes.elementAt(i); 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate if (!configuredScopes.contains(scope)) { 8790Sstevel@tonic-gate configuredScopes.addElement(scope); 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate } 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate // There better be none extra here for the SA server/DA. 8840Sstevel@tonic-gate 8850Sstevel@tonic-gate if (isSA() || isDA()) { 8860Sstevel@tonic-gate Assert.slpassert(saConfiguredScopes.contains(scope), 8870Sstevel@tonic-gate "sa_new_scope", 8880Sstevel@tonic-gate new Object[] {scope, saConfiguredScopes}); 8890Sstevel@tonic-gate 8900Sstevel@tonic-gate } 8910Sstevel@tonic-gate } 8920Sstevel@tonic-gate } 8930Sstevel@tonic-gate 8940Sstevel@tonic-gate // Initialize the scopes list on property. 8950Sstevel@tonic-gate initializeScopes(String prop)8960Sstevel@tonic-gate private Vector initializeScopes(String prop) { 8970Sstevel@tonic-gate 8980Sstevel@tonic-gate String sScopes = System.getProperty(prop); 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate if (sScopes == null || sScopes.length() <= 0) { 9010Sstevel@tonic-gate return new Vector(); 9020Sstevel@tonic-gate } 9030Sstevel@tonic-gate 9040Sstevel@tonic-gate try { 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate Vector vv = 9070Sstevel@tonic-gate SrvLocHeader.parseCommaSeparatedListIn(sScopes, true); 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate // Unescape scope strings. 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate SLPHeaderV2.unescapeScopeStrings(vv); 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate // Validate, lower case scope names. 9140Sstevel@tonic-gate 9150Sstevel@tonic-gate DATable.validateScopes(vv, getLocale()); 9160Sstevel@tonic-gate 9170Sstevel@tonic-gate if (vv.size() > 0) { 9180Sstevel@tonic-gate return vv; 9190Sstevel@tonic-gate } 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate } catch (ServiceLocationException ex) { 9220Sstevel@tonic-gate writeLog("syntax_error_prop", 9230Sstevel@tonic-gate new Object[] { 9240Sstevel@tonic-gate prop, 9250Sstevel@tonic-gate sScopes}); 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate } 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate return new Vector(); 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate // Vector of preconfigured DAs. Read only after initialized. 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate private Vector preconfiguredDAs = null; 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate // Return a vector of DA addresses. 9380Sstevel@tonic-gate getPreconfiguredDAs()9390Sstevel@tonic-gate Vector getPreconfiguredDAs() { 9400Sstevel@tonic-gate return (Vector)preconfiguredDAs.clone(); 9410Sstevel@tonic-gate 9420Sstevel@tonic-gate } 9430Sstevel@tonic-gate 9440Sstevel@tonic-gate // Initialize preconfigured DA list. 9450Sstevel@tonic-gate initializePreconfiguredDAs()9460Sstevel@tonic-gate private Vector initializePreconfiguredDAs() { 9470Sstevel@tonic-gate String sDAList = System.getProperty("net.slp.DAAddresses", ""); 9480Sstevel@tonic-gate Vector ret = new Vector(); 9490Sstevel@tonic-gate 9500Sstevel@tonic-gate sDAList.trim(); 9510Sstevel@tonic-gate 9520Sstevel@tonic-gate if (sDAList.length() <= 0) { 9530Sstevel@tonic-gate return ret; 9540Sstevel@tonic-gate 9550Sstevel@tonic-gate } 9560Sstevel@tonic-gate 9570Sstevel@tonic-gate try { 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate ret = SrvLocHeader.parseCommaSeparatedListIn(sDAList, true); 9600Sstevel@tonic-gate 9610Sstevel@tonic-gate } catch (ServiceLocationException ex) { 9620Sstevel@tonic-gate 9630Sstevel@tonic-gate writeLog("syntax_error_prop", 9640Sstevel@tonic-gate new Object[] {"net.slp.DAAddress", sDAList}); 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate return ret; 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate } 9690Sstevel@tonic-gate 9700Sstevel@tonic-gate // Convert to InetAddress objects. 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate int i; 9730Sstevel@tonic-gate 9740Sstevel@tonic-gate for (i = 0; i < ret.size(); i++) { 9750Sstevel@tonic-gate String da = ""; 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate try { 9780Sstevel@tonic-gate da = ((String)ret.elementAt(i)).trim(); 9790Sstevel@tonic-gate InetAddress daAddr = InetAddress.getByName(da); 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate ret.setElementAt(daAddr, i); 9820Sstevel@tonic-gate 9830Sstevel@tonic-gate } catch (UnknownHostException ex) { 9840Sstevel@tonic-gate 9850Sstevel@tonic-gate writeLog("resolve_failed", 9860Sstevel@tonic-gate new Object[] {da}); 9870Sstevel@tonic-gate 9880Sstevel@tonic-gate /* 9890Sstevel@tonic-gate * Must decrement the index 'i' otherwise the next iteration 9900Sstevel@tonic-gate * around the loop will miss the element immediately after 9910Sstevel@tonic-gate * the element removed. 9920Sstevel@tonic-gate * 9930Sstevel@tonic-gate * WARNING: Do not use 'i' again until the loop has 9940Sstevel@tonic-gate * iterated as it may, after decrementing, 9950Sstevel@tonic-gate * be negative. 9960Sstevel@tonic-gate */ 9970Sstevel@tonic-gate ret.removeElementAt(i); 9980Sstevel@tonic-gate i--; 9990Sstevel@tonic-gate continue; 10000Sstevel@tonic-gate } 10010Sstevel@tonic-gate } 10020Sstevel@tonic-gate 10030Sstevel@tonic-gate 10040Sstevel@tonic-gate return ret; 10050Sstevel@tonic-gate } 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate // ------------------------------------------------------------ 10080Sstevel@tonic-gate // SLPv1 Support Switches 10090Sstevel@tonic-gate // 10100Sstevel@tonic-gate getSLPv1NotSupported()10110Sstevel@tonic-gate boolean getSLPv1NotSupported() {// not official! 10120Sstevel@tonic-gate return Boolean.getBoolean("sun.net.slp.SLPv1NotSupported"); 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate } 10150Sstevel@tonic-gate getAcceptSLPv1UnscopedRegs()10160Sstevel@tonic-gate boolean getAcceptSLPv1UnscopedRegs() {// not official! 10170Sstevel@tonic-gate 10180Sstevel@tonic-gate if (!getSLPv1NotSupported()) { 10190Sstevel@tonic-gate return Boolean.getBoolean("sun.net.slp.acceptSLPv1UnscopedRegs"); 10200Sstevel@tonic-gate 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate return false; 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate // ------------------------------------------------------------ 10270Sstevel@tonic-gate // Accessor for SLPConfig object 10280Sstevel@tonic-gate // 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate protected static SLPConfig theSLPConfig = null; 10310Sstevel@tonic-gate getSLPConfig()10320Sstevel@tonic-gate static SLPConfig getSLPConfig() { 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate if (theSLPConfig == null) { 10350Sstevel@tonic-gate theSLPConfig = new SLPConfig(); 10360Sstevel@tonic-gate } 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate return theSLPConfig; 10390Sstevel@tonic-gate 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate 10420Sstevel@tonic-gate /** 10430Sstevel@tonic-gate * @return Maximum number of messages/objects to return. 10440Sstevel@tonic-gate */ 10450Sstevel@tonic-gate getMaximumResults()10460Sstevel@tonic-gate int getMaximumResults() { 10470Sstevel@tonic-gate int i = Integer.getInteger("net.slp.maxResults", 10480Sstevel@tonic-gate Defaults.iMaximumResults).intValue(); 10490Sstevel@tonic-gate if (i == -1) { 10500Sstevel@tonic-gate i = Integer.MAX_VALUE; 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate } 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate if (OKBound(i, 1, Integer.MAX_VALUE)) { 10550Sstevel@tonic-gate return i; 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate } else { 10580Sstevel@tonic-gate 10590Sstevel@tonic-gate writeLog("bad_prop_tag", 10600Sstevel@tonic-gate new Object[] { 10610Sstevel@tonic-gate "net.slp.maxResults"}); 10620Sstevel@tonic-gate 10630Sstevel@tonic-gate return Defaults.iMaximumResults; 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate } 10660Sstevel@tonic-gate } 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate /** 10690Sstevel@tonic-gate * Convert a language tag into a locale. 10700Sstevel@tonic-gate */ 10710Sstevel@tonic-gate langTagToLocale(String ltag)10720Sstevel@tonic-gate static Locale langTagToLocale(String ltag) { 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate // We treat the first part as the ISO 639 language and the 10750Sstevel@tonic-gate // second part as the ISO 3166 country tag, even though RFC 10760Sstevel@tonic-gate // 1766 doesn't necessarily require that. We should probably 10770Sstevel@tonic-gate // use a lookup table here to determine if they are correct. 10780Sstevel@tonic-gate 10790Sstevel@tonic-gate StringTokenizer tk = new StringTokenizer(ltag, "-"); 10800Sstevel@tonic-gate String lang = ""; 10810Sstevel@tonic-gate String country = ""; 10820Sstevel@tonic-gate 10830Sstevel@tonic-gate if (tk.hasMoreTokens()) { 10840Sstevel@tonic-gate lang = tk.nextToken(); 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate if (tk.hasMoreTokens()) { 10870Sstevel@tonic-gate country = tk.nextToken(""); 10880Sstevel@tonic-gate // country name may have "-" in it... 10890Sstevel@tonic-gate 10900Sstevel@tonic-gate } 10910Sstevel@tonic-gate } 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate return new Locale(lang, country); 10940Sstevel@tonic-gate } 10950Sstevel@tonic-gate 10960Sstevel@tonic-gate /** 10970Sstevel@tonic-gate * Convert a Locale object into a language tag for output. 10980Sstevel@tonic-gate * 10990Sstevel@tonic-gate * @param locale The Locale. 11000Sstevel@tonic-gate * @return String with the language tag encoded. 11010Sstevel@tonic-gate */ 11020Sstevel@tonic-gate localeToLangTag(Locale locale)11030Sstevel@tonic-gate static String localeToLangTag(Locale locale) { 11040Sstevel@tonic-gate 11050Sstevel@tonic-gate // Construct the language tag. 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate String ltag = locale.getCountry(); 11080Sstevel@tonic-gate ltag = locale.getLanguage() + (ltag.length() <= 0 ? "" : ("-" + ltag)); 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate return ltag; 11110Sstevel@tonic-gate 11120Sstevel@tonic-gate } 11130Sstevel@tonic-gate 11140Sstevel@tonic-gate /** 11150Sstevel@tonic-gate * @return the language requests will be made in. 11160Sstevel@tonic-gate */ getLocale()11170Sstevel@tonic-gate static Locale getLocale() { 11180Sstevel@tonic-gate String s = System.getProperty("net.slp.locale"); 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate if (s != null && s.length() > 0) { 11210Sstevel@tonic-gate return langTagToLocale(s); 11220Sstevel@tonic-gate 11230Sstevel@tonic-gate } else { 11240Sstevel@tonic-gate 11250Sstevel@tonic-gate // Return the Java default if the SLP property is not set. 11260Sstevel@tonic-gate 11270Sstevel@tonic-gate return Locale.getDefault(); 11280Sstevel@tonic-gate 11290Sstevel@tonic-gate } 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate /** 11330Sstevel@tonic-gate * @return the InetAddress of the broadcast interface. 11340Sstevel@tonic-gate */ 11350Sstevel@tonic-gate 11360Sstevel@tonic-gate static private InetAddress broadcastAddress; 11370Sstevel@tonic-gate getBroadcastAddress()11380Sstevel@tonic-gate static InetAddress getBroadcastAddress() { 11390Sstevel@tonic-gate if (broadcastAddress == null) { 11400Sstevel@tonic-gate 11410Sstevel@tonic-gate try { 11420Sstevel@tonic-gate broadcastAddress = 11430Sstevel@tonic-gate InetAddress.getByName(Defaults.sBroadcast); 11440Sstevel@tonic-gate } catch (UnknownHostException uhe) { 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate Assert.slpassert(false, 11470Sstevel@tonic-gate "cast_address_failure", 11480Sstevel@tonic-gate new Object[] {Defaults.sBroadcast}); 11490Sstevel@tonic-gate 11500Sstevel@tonic-gate } 11510Sstevel@tonic-gate } 11520Sstevel@tonic-gate return broadcastAddress; 11530Sstevel@tonic-gate } 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate /** 11570Sstevel@tonic-gate * @return the InetAddress of the multicast group. 11580Sstevel@tonic-gate */ 11590Sstevel@tonic-gate 11600Sstevel@tonic-gate static private InetAddress multicastAddress; 11610Sstevel@tonic-gate getMulticastAddress()11620Sstevel@tonic-gate static InetAddress getMulticastAddress() { 11630Sstevel@tonic-gate if (multicastAddress == null) { 11640Sstevel@tonic-gate 11650Sstevel@tonic-gate try { 11660Sstevel@tonic-gate multicastAddress = 11670Sstevel@tonic-gate InetAddress.getByName(Defaults.sGeneralSLPMCAddress); 11680Sstevel@tonic-gate } catch (UnknownHostException uhe) { 11690Sstevel@tonic-gate Assert.slpassert(false, 11700Sstevel@tonic-gate "cast_address_failure", 11710Sstevel@tonic-gate new Object[] {Defaults.sGeneralSLPMCAddress}); 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate } 11740Sstevel@tonic-gate } 11750Sstevel@tonic-gate return multicastAddress; 11760Sstevel@tonic-gate } 11770Sstevel@tonic-gate 11780Sstevel@tonic-gate /** 11790Sstevel@tonic-gate * @return the interfaces on which SLP should listen and transmit. 11800Sstevel@tonic-gate */ 11810Sstevel@tonic-gate 11820Sstevel@tonic-gate private static Vector interfaces = null; 11830Sstevel@tonic-gate getInterfaces()11840Sstevel@tonic-gate Vector getInterfaces() { 11850Sstevel@tonic-gate 11860Sstevel@tonic-gate if (interfaces == null) { 11870Sstevel@tonic-gate InetAddress iaLocal = null; 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate // Get local host. 11900Sstevel@tonic-gate 11910Sstevel@tonic-gate try { 11920Sstevel@tonic-gate iaLocal = InetAddress.getLocalHost(); 11930Sstevel@tonic-gate 11940Sstevel@tonic-gate } catch (UnknownHostException ex) { 11950Sstevel@tonic-gate Assert.slpassert(false, 11960Sstevel@tonic-gate "resolve_failed", 11970Sstevel@tonic-gate new Object[] {"localhost"}); 11980Sstevel@tonic-gate } 11990Sstevel@tonic-gate 12000Sstevel@tonic-gate String mcastI = System.getProperty("net.slp.interfaces"); 12010Sstevel@tonic-gate interfaces = new Vector(); 12020Sstevel@tonic-gate 12030Sstevel@tonic-gate // Only add local host if nothing else is given. 12040Sstevel@tonic-gate 12050Sstevel@tonic-gate if (mcastI == null || mcastI.length() <= 0) { 12060Sstevel@tonic-gate interfaces.addElement(iaLocal); 12070Sstevel@tonic-gate return interfaces; 12080Sstevel@tonic-gate 12090Sstevel@tonic-gate } 12100Sstevel@tonic-gate 12110Sstevel@tonic-gate Vector nintr; 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate try { 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate nintr = SrvLocHeader.parseCommaSeparatedListIn(mcastI, true); 12160Sstevel@tonic-gate 12170Sstevel@tonic-gate } catch (ServiceLocationException ex) { 12180Sstevel@tonic-gate writeLog("syntax_error_prop", 12190Sstevel@tonic-gate new Object[] { 12200Sstevel@tonic-gate "net.slp.multicastInterfaces", 12210Sstevel@tonic-gate mcastI}); 12220Sstevel@tonic-gate 12230Sstevel@tonic-gate // Add local host. 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate interfaces.addElement(iaLocal); 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate return interfaces; 12280Sstevel@tonic-gate 12290Sstevel@tonic-gate } 12300Sstevel@tonic-gate 12310Sstevel@tonic-gate // See if they are really there. 12320Sstevel@tonic-gate 12330Sstevel@tonic-gate int i, n = nintr.size(); 12340Sstevel@tonic-gate 12350Sstevel@tonic-gate for (i = 0; i < n; i++) { 12360Sstevel@tonic-gate InetAddress ia; 12370Sstevel@tonic-gate String host = (String)nintr.elementAt(i); 12380Sstevel@tonic-gate 12390Sstevel@tonic-gate try { 12400Sstevel@tonic-gate 12410Sstevel@tonic-gate ia = InetAddress.getByName(host); 12420Sstevel@tonic-gate 12430Sstevel@tonic-gate } catch (UnknownHostException ex) { 12440Sstevel@tonic-gate writeLog("unknown_interface", 12450Sstevel@tonic-gate new Object[] {host, 12460Sstevel@tonic-gate "net.slp.multicastInterfaces"}); 12470Sstevel@tonic-gate continue; 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate } 12500Sstevel@tonic-gate 12510Sstevel@tonic-gate if (!interfaces.contains(ia)) { 12520Sstevel@tonic-gate 12530Sstevel@tonic-gate // Add default at beginning. 12540Sstevel@tonic-gate 12550Sstevel@tonic-gate if (ia.equals(iaLocal)) { 12560Sstevel@tonic-gate interfaces.insertElementAt(ia, 0); 12570Sstevel@tonic-gate 12580Sstevel@tonic-gate } else { 12590Sstevel@tonic-gate interfaces.addElement(ia); 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate } 12620Sstevel@tonic-gate } 12630Sstevel@tonic-gate } 12640Sstevel@tonic-gate } 12650Sstevel@tonic-gate 12660Sstevel@tonic-gate return interfaces; 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate } 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate /** 12710Sstevel@tonic-gate * @return An InetAddress object representing 127.0.0.1 12720Sstevel@tonic-gate */ getLoopback()12730Sstevel@tonic-gate InetAddress getLoopback() { 12740Sstevel@tonic-gate InetAddress iaLoopback = null; 12750Sstevel@tonic-gate 12760Sstevel@tonic-gate try { 12770Sstevel@tonic-gate iaLoopback = InetAddress.getByName(Defaults.LOOPBACK_ADDRESS); 12780Sstevel@tonic-gate 12790Sstevel@tonic-gate } catch (UnknownHostException ex) { 12800Sstevel@tonic-gate Assert.slpassert(false, 12810Sstevel@tonic-gate "resolve_failed", 12820Sstevel@tonic-gate new Object[] {"localhost loopback"}); 12830Sstevel@tonic-gate } 12840Sstevel@tonic-gate 12850Sstevel@tonic-gate return iaLoopback; 12860Sstevel@tonic-gate } 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate /** 12890Sstevel@tonic-gate * @return The default interface, which should be the first in the 12900Sstevel@tonic-gate * interfaces vector Vector. 12910Sstevel@tonic-gate */ 12920Sstevel@tonic-gate getLocalHost()12930Sstevel@tonic-gate InetAddress getLocalHost() { 12940Sstevel@tonic-gate Vector inter = getInterfaces(); 12950Sstevel@tonic-gate return (InetAddress)inter.elementAt(0); 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate } 12980Sstevel@tonic-gate 12990Sstevel@tonic-gate // Return true if the address is one of the local interfaces. 13000Sstevel@tonic-gate isLocalHostSource(InetAddress addr)13010Sstevel@tonic-gate boolean isLocalHostSource(InetAddress addr) { 13020Sstevel@tonic-gate 13030Sstevel@tonic-gate // First check loopback 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate if (addr.equals(getLoopback())) { 13060Sstevel@tonic-gate return true; 13070Sstevel@tonic-gate 13080Sstevel@tonic-gate } 13090Sstevel@tonic-gate 13100Sstevel@tonic-gate return interfaces.contains(addr); 13110Sstevel@tonic-gate 13120Sstevel@tonic-gate } 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate // ----------------- 13150Sstevel@tonic-gate // Timeouts 13160Sstevel@tonic-gate // 13170Sstevel@tonic-gate 13180Sstevel@tonic-gate // Return the maximum wait for multicast convergence. 13190Sstevel@tonic-gate 13200Sstevel@tonic-gate final static private int iMultiMin = 1000; // one second 13210Sstevel@tonic-gate final static private int iMultiMax = 60000; // one minute 13220Sstevel@tonic-gate getMulticastMaximumWait()13230Sstevel@tonic-gate int getMulticastMaximumWait() { 13240Sstevel@tonic-gate 13250Sstevel@tonic-gate return getIntProperty("net.slp.multicastMaximumWait", 13260Sstevel@tonic-gate Defaults.iMulticastMaxWait, 13270Sstevel@tonic-gate iMultiMin, 13280Sstevel@tonic-gate iMultiMax); 13290Sstevel@tonic-gate } 13300Sstevel@tonic-gate 13310Sstevel@tonic-gate /* 13320Sstevel@tonic-gate * @return Vector of timeouts for multicast convergence. 13330Sstevel@tonic-gate */ 13340Sstevel@tonic-gate getMulticastTimeouts()13350Sstevel@tonic-gate int[] getMulticastTimeouts() { 13360Sstevel@tonic-gate int[] timeouts = parseTimeouts("net.slp.multicastTimeouts", 13370Sstevel@tonic-gate Defaults.a_iConvergeTimeout); 13380Sstevel@tonic-gate 13390Sstevel@tonic-gate timeouts = capTimeouts("net.slp.multicastTimeouts", 13400Sstevel@tonic-gate timeouts, 13410Sstevel@tonic-gate false, 13420Sstevel@tonic-gate 0, 13430Sstevel@tonic-gate 0); 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate return timeouts; 13460Sstevel@tonic-gate } 13470Sstevel@tonic-gate 13480Sstevel@tonic-gate /** 13490Sstevel@tonic-gate * @return Vector of timeouts to try for datagram transmission. 13500Sstevel@tonic-gate */ 13510Sstevel@tonic-gate getDatagramTimeouts()13520Sstevel@tonic-gate int[] getDatagramTimeouts() { 13530Sstevel@tonic-gate int[] timeouts = parseTimeouts("net.slp.datagramTimeouts", 13540Sstevel@tonic-gate Defaults.a_iDatagramTimeout); 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate timeouts = capTimeouts("net.slp.datagramTimeouts", 13570Sstevel@tonic-gate timeouts, 13580Sstevel@tonic-gate true, 13590Sstevel@tonic-gate iMultiMin, 13600Sstevel@tonic-gate iMultiMax); 13610Sstevel@tonic-gate 13620Sstevel@tonic-gate return timeouts; 13630Sstevel@tonic-gate } 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate /** 13660Sstevel@tonic-gate * @return Vector of timeouts for DA discovery multicast. 13670Sstevel@tonic-gate */ 13680Sstevel@tonic-gate getDADiscoveryTimeouts()13690Sstevel@tonic-gate int[] getDADiscoveryTimeouts() { 13700Sstevel@tonic-gate int[] timeouts = parseTimeouts("net.slp.DADiscoveryTimeouts", 13710Sstevel@tonic-gate Defaults.a_iDADiscoveryTimeout); 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate timeouts = capTimeouts("net.slp.DADiscoveryTimeouts", 13740Sstevel@tonic-gate timeouts, 13750Sstevel@tonic-gate false, 13760Sstevel@tonic-gate 0, 13770Sstevel@tonic-gate 0); 13780Sstevel@tonic-gate 13790Sstevel@tonic-gate return timeouts; 13800Sstevel@tonic-gate } 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate /** 13830Sstevel@tonic-gate * This method ensures that all the timeouts are within valid ranges. 13840Sstevel@tonic-gate * The sum of all timeouts for the given property name must not 13850Sstevel@tonic-gate * exceed the value returned by <i>getMulticastMaximumWait()</i>. If 13860Sstevel@tonic-gate * the sum of all timeouts does exceed the maximum wait period the 13870Sstevel@tonic-gate * timeouts are averaged out so that the sum equals the maximum wait 13880Sstevel@tonic-gate * period. 13890Sstevel@tonic-gate * <br> 13900Sstevel@tonic-gate * Additional range checking is also performed when <i>rangeCheck</i> 13910Sstevel@tonic-gate * is true. Then the sum of all timeouts must also be between <i>min</i> 13920Sstevel@tonic-gate * and <i>max</i>. If the sum of all timeouts is not within the range 13930Sstevel@tonic-gate * the average is taken from the closest range boundary. 13940Sstevel@tonic-gate * 13950Sstevel@tonic-gate * @param property 13960Sstevel@tonic-gate * Name of timeout property being capped. This is only present for 13970Sstevel@tonic-gate * reporting purposes and no actual manipulation of the property 13980Sstevel@tonic-gate * is made within this method. 13990Sstevel@tonic-gate * @param timeouts 14000Sstevel@tonic-gate * Array of timeout values. 14010Sstevel@tonic-gate * @param rangeCheck 14020Sstevel@tonic-gate * Indicator of whether additional range checking is required. When 14030Sstevel@tonic-gate * false <i>min</i> and <i>max</i> are ignored. 14040Sstevel@tonic-gate * @param min 14050Sstevel@tonic-gate * Additional range checking lower boundary. 14060Sstevel@tonic-gate * @param max 14070Sstevel@tonic-gate * Additional range checking upper boundary. 14080Sstevel@tonic-gate * @return 14090Sstevel@tonic-gate * Array of capped timeouts. Note this may be the same array as 14100Sstevel@tonic-gate * passed in (<i>timeouts</i>). 14110Sstevel@tonic-gate */ capTimeouts(String property, int[] timeouts, boolean rangeCheck, int min, int max)14120Sstevel@tonic-gate private int[] capTimeouts(String property, 14130Sstevel@tonic-gate int[] timeouts, 14140Sstevel@tonic-gate boolean rangeCheck, 14150Sstevel@tonic-gate int min, 14160Sstevel@tonic-gate int max) { 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate int averagedTimeout; 14190Sstevel@tonic-gate int totalWait = 0; 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate for (int index = 0; index < timeouts.length; index++) { 14220Sstevel@tonic-gate totalWait += timeouts[index]; 14230Sstevel@tonic-gate } 14240Sstevel@tonic-gate 14250Sstevel@tonic-gate if (rangeCheck) { 14260Sstevel@tonic-gate // If sum of timeouts within limits then finished. 14270Sstevel@tonic-gate if (totalWait >= min && totalWait <= max) { 14280Sstevel@tonic-gate return timeouts; 14290Sstevel@tonic-gate } 14300Sstevel@tonic-gate 14310Sstevel@tonic-gate // Average out the timeouts so the sum is equal to the closest 14320Sstevel@tonic-gate // range boundary. 14330Sstevel@tonic-gate if (totalWait < min) { 14340Sstevel@tonic-gate averagedTimeout = min / timeouts.length; 14350Sstevel@tonic-gate } else { 14360Sstevel@tonic-gate averagedTimeout = max / timeouts.length; 14370Sstevel@tonic-gate } 14380Sstevel@tonic-gate 14390Sstevel@tonic-gate writeLog("capped_range_timeout_prop", 14400Sstevel@tonic-gate new Object[] {property, 14410Sstevel@tonic-gate String.valueOf(totalWait), 14420Sstevel@tonic-gate String.valueOf(min), 14430Sstevel@tonic-gate String.valueOf(max), 14440Sstevel@tonic-gate String.valueOf(timeouts.length), 14450Sstevel@tonic-gate String.valueOf(averagedTimeout)}); 14460Sstevel@tonic-gate } else { 14470Sstevel@tonic-gate // Sum of all timeouts must not exceed this value. 14480Sstevel@tonic-gate int maximumWait = getMulticastMaximumWait(); 14490Sstevel@tonic-gate 14500Sstevel@tonic-gate // If sum of timeouts within limits then finished. 14510Sstevel@tonic-gate if (totalWait <= maximumWait) { 14520Sstevel@tonic-gate return timeouts; 14530Sstevel@tonic-gate } 14540Sstevel@tonic-gate 14550Sstevel@tonic-gate // Average out the timeouts so the sum is equal to the maximum 14560Sstevel@tonic-gate // timeout. 14570Sstevel@tonic-gate averagedTimeout = maximumWait / timeouts.length; 14580Sstevel@tonic-gate 14590Sstevel@tonic-gate writeLog("capped_timeout_prop", 14600Sstevel@tonic-gate new Object[] {property, 14610Sstevel@tonic-gate String.valueOf(totalWait), 14620Sstevel@tonic-gate String.valueOf(maximumWait), 14630Sstevel@tonic-gate String.valueOf(timeouts.length), 14640Sstevel@tonic-gate String.valueOf(averagedTimeout)}); 14650Sstevel@tonic-gate } 14660Sstevel@tonic-gate 14670Sstevel@tonic-gate for (int index = 0; index < timeouts.length; index++) { 14680Sstevel@tonic-gate timeouts[index] = averagedTimeout; 14690Sstevel@tonic-gate } 14700Sstevel@tonic-gate 14710Sstevel@tonic-gate return timeouts; 14720Sstevel@tonic-gate } 14730Sstevel@tonic-gate parseTimeouts(String property, int[] defaults)14740Sstevel@tonic-gate private int[] parseTimeouts(String property, int[] defaults) { 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate String sTimeouts = System.getProperty(property); 14770Sstevel@tonic-gate 14780Sstevel@tonic-gate if (sTimeouts == null || sTimeouts.length() <= 0) { 14790Sstevel@tonic-gate return defaults; 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate } 14820Sstevel@tonic-gate 14830Sstevel@tonic-gate Vector timeouts = null; 14840Sstevel@tonic-gate 14850Sstevel@tonic-gate try { 14860Sstevel@tonic-gate timeouts = SrvLocHeader.parseCommaSeparatedListIn(sTimeouts, true); 14870Sstevel@tonic-gate 14880Sstevel@tonic-gate } catch (ServiceLocationException ex) { 14890Sstevel@tonic-gate writeLog("syntax_error_prop", 14900Sstevel@tonic-gate new Object[] {property, sTimeouts}); 14910Sstevel@tonic-gate return defaults; 14920Sstevel@tonic-gate 14930Sstevel@tonic-gate } 14940Sstevel@tonic-gate 14950Sstevel@tonic-gate int iCount = 0; 14960Sstevel@tonic-gate int[] iTOs = new int[timeouts.size()]; 14970Sstevel@tonic-gate 14980Sstevel@tonic-gate for (Enumeration en = timeouts.elements(); en.hasMoreElements(); ) { 14990Sstevel@tonic-gate String s1 = (String)en.nextElement(); 15000Sstevel@tonic-gate 15010Sstevel@tonic-gate try { 15020Sstevel@tonic-gate iTOs[iCount] = Integer.parseInt(s1); 15030Sstevel@tonic-gate 15040Sstevel@tonic-gate } catch (NumberFormatException nfe) { 15050Sstevel@tonic-gate writeLog("syntax_error_prop", 15060Sstevel@tonic-gate new Object[] {property, sTimeouts}); 15070Sstevel@tonic-gate return defaults; 15080Sstevel@tonic-gate 15090Sstevel@tonic-gate } 15100Sstevel@tonic-gate 15110Sstevel@tonic-gate if (iTOs[iCount] < 0) { 15120Sstevel@tonic-gate writeLog("invalid_timeout_prop", 15130Sstevel@tonic-gate new Object[] {property, String.valueOf(iTOs[iCount])}); 15140Sstevel@tonic-gate return defaults; 15150Sstevel@tonic-gate } 15160Sstevel@tonic-gate 15170Sstevel@tonic-gate iCount++; 15180Sstevel@tonic-gate } 15190Sstevel@tonic-gate 15200Sstevel@tonic-gate return iTOs; 15210Sstevel@tonic-gate } 15220Sstevel@tonic-gate 15230Sstevel@tonic-gate // ----------------------------- 15240Sstevel@tonic-gate // SLP Time Calculation 15250Sstevel@tonic-gate // 15260Sstevel@tonic-gate 15270Sstevel@tonic-gate /** 15280Sstevel@tonic-gate * Returns the number of seconds since 00:00 Universal Coordinated 15290Sstevel@tonic-gate * Time, January 1, 1970. 15300Sstevel@tonic-gate * 15310Sstevel@tonic-gate * Java returns the number of milliseconds, so all the method does is 15320Sstevel@tonic-gate * divide by 1000. 15330Sstevel@tonic-gate * 15340Sstevel@tonic-gate * This implementation still will have a problem when the Java time 15350Sstevel@tonic-gate * values wraps, but there isn't much we can do now. 15360Sstevel@tonic-gate */ currentSLPTime()15370Sstevel@tonic-gate static long currentSLPTime() { 15380Sstevel@tonic-gate return (System.currentTimeMillis() / 1000); 15390Sstevel@tonic-gate } 15400Sstevel@tonic-gate 15410Sstevel@tonic-gate /* security */ 15420Sstevel@tonic-gate 15430Sstevel@tonic-gate // Indicates whether security class is available. 15440Sstevel@tonic-gate getSecurityEnabled()15450Sstevel@tonic-gate boolean getSecurityEnabled() { 15460Sstevel@tonic-gate return securityEnabled; 15470Sstevel@tonic-gate 15480Sstevel@tonic-gate } 15490Sstevel@tonic-gate 15500Sstevel@tonic-gate private static boolean securityEnabled; 15510Sstevel@tonic-gate 15520Sstevel@tonic-gate // Indicates whether the securityEnabled property is true 15530Sstevel@tonic-gate getHasSecurity()15540Sstevel@tonic-gate boolean getHasSecurity() { 15550Sstevel@tonic-gate return securityEnabled && 15560Sstevel@tonic-gate (new Boolean(System.getProperty("net.slp.securityEnabled", 15570Sstevel@tonic-gate "false")).booleanValue()); 15580Sstevel@tonic-gate } 15590Sstevel@tonic-gate 15600Sstevel@tonic-gate // I18N Support. 15610Sstevel@tonic-gate 15620Sstevel@tonic-gate private static final String BASE_BUNDLE_NAME = "com/sun/slp/ClientLib"; 15630Sstevel@tonic-gate getMessageBundle(Locale locale)15640Sstevel@tonic-gate ResourceBundle getMessageBundle(Locale locale) { 15650Sstevel@tonic-gate 15660Sstevel@tonic-gate ResourceBundle msgBundle = null; 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate // First try the Solaris Java locale area 15690Sstevel@tonic-gate 15700Sstevel@tonic-gate try { 15710Sstevel@tonic-gate URL[] urls = new URL[] {new URL("file:/usr/share/lib/locale/")}; 15720Sstevel@tonic-gate 15730Sstevel@tonic-gate URLClassLoader ld = new URLClassLoader(urls); 15740Sstevel@tonic-gate 15750Sstevel@tonic-gate msgBundle = ResourceBundle.getBundle(BASE_BUNDLE_NAME, locale, ld); 15760Sstevel@tonic-gate 15770Sstevel@tonic-gate return msgBundle; 15780Sstevel@tonic-gate } catch (MalformedURLException e) { // shouldn't get here 15790Sstevel@tonic-gate } catch (MissingResourceException ex) { 15800Sstevel@tonic-gate System.err.println("Missing resource bundle ``"+ 15810Sstevel@tonic-gate "/usr/share/lib/locale/" + BASE_BUNDLE_NAME + 15820Sstevel@tonic-gate "'' for locale ``" + 15830Sstevel@tonic-gate locale + "''; trying default..."); 15840Sstevel@tonic-gate } 15850Sstevel@tonic-gate 15860Sstevel@tonic-gate try { 15870Sstevel@tonic-gate msgBundle = ResourceBundle.getBundle(BASE_BUNDLE_NAME, locale); 15880Sstevel@tonic-gate 15890Sstevel@tonic-gate } catch (MissingResourceException ex) { // can't localize this one! 15900Sstevel@tonic-gate 15910Sstevel@tonic-gate // We can't print out to the log, because we may be in the 15920Sstevel@tonic-gate // process of trying to. 15930Sstevel@tonic-gate 15940Sstevel@tonic-gate System.err.println("Missing resource bundle ``"+ 15950Sstevel@tonic-gate BASE_BUNDLE_NAME+ 15960Sstevel@tonic-gate "'' for locale ``"+ 15970Sstevel@tonic-gate locale+ 15980Sstevel@tonic-gate "''"); 15990Sstevel@tonic-gate // Hosed if the default locale is missing. 16000Sstevel@tonic-gate 16010Sstevel@tonic-gate if (locale.equals(Defaults.locale)) { 16020Sstevel@tonic-gate 16030Sstevel@tonic-gate System.err.println("Exiting..."); 16040Sstevel@tonic-gate System.exit(1); 16050Sstevel@tonic-gate } 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate // Otherwise, return the default locale. 16080Sstevel@tonic-gate 16090Sstevel@tonic-gate System.err.println("Using SLP default locale ``" + 16100Sstevel@tonic-gate Defaults.locale + 16110Sstevel@tonic-gate "''"); 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate msgBundle = getMessageBundle(Defaults.locale); 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate } 16160Sstevel@tonic-gate 16170Sstevel@tonic-gate return msgBundle; 16180Sstevel@tonic-gate } 16190Sstevel@tonic-gate formatMessage(String msgTag, Object[] params)16200Sstevel@tonic-gate String formatMessage(String msgTag, Object[] params) { 16210Sstevel@tonic-gate ResourceBundle bundle = getMessageBundle(getLocale()); 16220Sstevel@tonic-gate return formatMessageInternal(msgTag, params, bundle); 16230Sstevel@tonic-gate 16240Sstevel@tonic-gate } 16250Sstevel@tonic-gate 16260Sstevel@tonic-gate // MessageFormat is picky about types. Convert the params into strings. 16270Sstevel@tonic-gate convertToString(Object[] params)16280Sstevel@tonic-gate static void convertToString(Object[] params) { 16290Sstevel@tonic-gate int i, n = params.length; 16300Sstevel@tonic-gate 16310Sstevel@tonic-gate for (i = 0; i < n; i++) { 16320Sstevel@tonic-gate 16330Sstevel@tonic-gate if (params[i] != null) { 16340Sstevel@tonic-gate params[i] = params[i].toString(); 16350Sstevel@tonic-gate 16360Sstevel@tonic-gate } else { 16370Sstevel@tonic-gate params[i] = "<null>"; 16380Sstevel@tonic-gate 16390Sstevel@tonic-gate } 16400Sstevel@tonic-gate } 16410Sstevel@tonic-gate } 16420Sstevel@tonic-gate 16430Sstevel@tonic-gate static String formatMessageInternal(String msgTag, Object[] params, ResourceBundle bundle)16440Sstevel@tonic-gate formatMessageInternal(String msgTag, 16450Sstevel@tonic-gate Object[] params, 16460Sstevel@tonic-gate ResourceBundle bundle) { 16470Sstevel@tonic-gate String pattern = ""; 16480Sstevel@tonic-gate 16490Sstevel@tonic-gate try { 16500Sstevel@tonic-gate pattern = bundle.getString(msgTag); 16510Sstevel@tonic-gate 16520Sstevel@tonic-gate } catch (MissingResourceException ex) { 16530Sstevel@tonic-gate 16540Sstevel@tonic-gate // Attempt to report error. Can't use Assert here because it 16550Sstevel@tonic-gate // calls back into SLPConfig. 16560Sstevel@tonic-gate String msg = "Can''t find message ``{0}''''."; 16570Sstevel@tonic-gate 16580Sstevel@tonic-gate try { 16590Sstevel@tonic-gate pattern = bundle.getString("cant_find_resource"); 16600Sstevel@tonic-gate msg = MessageFormat.format(pattern, new Object[] {msgTag}); 16610Sstevel@tonic-gate 16620Sstevel@tonic-gate } catch (MissingResourceException exx) { 16630Sstevel@tonic-gate 16640Sstevel@tonic-gate } 16650Sstevel@tonic-gate 16660Sstevel@tonic-gate System.err.println(msg); 16670Sstevel@tonic-gate System.exit(-1); 16680Sstevel@tonic-gate } 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate convertToString(params); 16710Sstevel@tonic-gate 16720Sstevel@tonic-gate return MessageFormat.format(pattern, params); 16730Sstevel@tonic-gate } 16740Sstevel@tonic-gate 16750Sstevel@tonic-gate // logging. 16760Sstevel@tonic-gate 16770Sstevel@tonic-gate // Protected so slpd can replace it. 16780Sstevel@tonic-gate 16790Sstevel@tonic-gate protected Writer log; 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate // Synchronized so writes from multiple threads don't get interleaved. 16820Sstevel@tonic-gate writeLog(String msgTag, Object[] params)16830Sstevel@tonic-gate void writeLog(String msgTag, Object[] params) { 16840Sstevel@tonic-gate 16850Sstevel@tonic-gate // MessageFormat is picky about types. Convert the params into strings. 16860Sstevel@tonic-gate 16870Sstevel@tonic-gate convertToString(params); 16880Sstevel@tonic-gate 16890Sstevel@tonic-gate try { 16900Sstevel@tonic-gate synchronized (log) { 16910Sstevel@tonic-gate log.write(formatMessage(msgTag, params)); 16920Sstevel@tonic-gate log.flush(); 16930Sstevel@tonic-gate } 16940Sstevel@tonic-gate } catch (IOException ex) {} 16950Sstevel@tonic-gate } 16960Sstevel@tonic-gate writeLogLine(String msgTag, Object[] params)16970Sstevel@tonic-gate void writeLogLine(String msgTag, Object[] params) { 16980Sstevel@tonic-gate 16990Sstevel@tonic-gate try { 17000Sstevel@tonic-gate String pattern = getMessageBundle(getLocale()).getString(msgTag); 17010Sstevel@tonic-gate 17020Sstevel@tonic-gate synchronized (log) { 17030Sstevel@tonic-gate log.write(formatMessage(msgTag, params)); 17040Sstevel@tonic-gate log.write("\n"); 17050Sstevel@tonic-gate log.flush(); 17060Sstevel@tonic-gate } 17070Sstevel@tonic-gate } catch (IOException ex) {} 17080Sstevel@tonic-gate 17090Sstevel@tonic-gate } 17100Sstevel@tonic-gate getDateString()17110Sstevel@tonic-gate static String getDateString() { 17120Sstevel@tonic-gate 17130Sstevel@tonic-gate DateFormat df = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, 17140Sstevel@tonic-gate DateFormat.DEFAULT, 17150Sstevel@tonic-gate getLocale()); 17160Sstevel@tonic-gate Calendar calendar = Calendar.getInstance(getLocale()); 17170Sstevel@tonic-gate return df.format(calendar.getTime()); 17180Sstevel@tonic-gate 17190Sstevel@tonic-gate } 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate 17220Sstevel@tonic-gate // On load, check whether the signature class is available, and turn 17230Sstevel@tonic-gate // security off if not. 17240Sstevel@tonic-gate 17250Sstevel@tonic-gate static { 17260Sstevel@tonic-gate 17270Sstevel@tonic-gate securityEnabled = true; 17280Sstevel@tonic-gate try { 17290Sstevel@tonic-gate Class c = Class.forName("com.sun.slp.AuthBlock"); 17300Sstevel@tonic-gate 17310Sstevel@tonic-gate } catch (ClassNotFoundException e) { 17320Sstevel@tonic-gate securityEnabled = false; 17330Sstevel@tonic-gate } 17340Sstevel@tonic-gate } 17350Sstevel@tonic-gate 17360Sstevel@tonic-gate } 1737