xref: /onnv-gate/usr/src/lib/libslp/javalib/com/sun/slp/slpd.java (revision 7298:b69e27387f74)
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 2004 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
27*7298SMark.J.Nelson@Sun.COM //  sldp.java : The service location daemon.
280Sstevel@tonic-gate //  Author:           Erik Guttman
290Sstevel@tonic-gate //
300Sstevel@tonic-gate 
310Sstevel@tonic-gate package com.sun.slp;
320Sstevel@tonic-gate 
330Sstevel@tonic-gate import java.io.*;
340Sstevel@tonic-gate import java.util.*;
350Sstevel@tonic-gate import java.net.*;
360Sstevel@tonic-gate import java.lang.reflect.*;
370Sstevel@tonic-gate import java.awt.*;
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /**
400Sstevel@tonic-gate  * The slpd class is the main class for the slpd directory agent/
410Sstevel@tonic-gate  * service agent server of SLP. Slpd can run in two possible modes,
420Sstevel@tonic-gate  * depending on the configuration of the classes with which it was shipped
430Sstevel@tonic-gate  * and information read from the optional configuration file argument:
440Sstevel@tonic-gate  *
450Sstevel@tonic-gate  *   <ol>
460Sstevel@tonic-gate  *     <li> <b> Service Agent server </b>
470Sstevel@tonic-gate  *          In this mode, slpd functions as a service agent server only.
480Sstevel@tonic-gate  *	    Directory agent functionality is disabled. Service agent
490Sstevel@tonic-gate  *	    clients on the local machine register and deregister services
500Sstevel@tonic-gate  *	    with slpd, and slpd responds to multicast requests for
510Sstevel@tonic-gate  *	    services. It passively and actively listens for directory agent
520Sstevel@tonic-gate  *	    advertisements, caches them, and forwards them to both
530Sstevel@tonic-gate  *	    user agent and service agent clients. A file of serialized
540Sstevel@tonic-gate  *	    proxy registrations can be read at startup.
550Sstevel@tonic-gate  *	    This mode is normally default.
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  *     <li> <b> Directory Agent/Service Agent server </b>
580Sstevel@tonic-gate  *          In this mode, slpd functions  as a directory agent
590Sstevel@tonic-gate  *	    for port 427 on the local machine. The directory agent
600Sstevel@tonic-gate  *	    caches service advertisements, makes directory agent
610Sstevel@tonic-gate  *	    advertisements of its services, and responds to requests
620Sstevel@tonic-gate  *          for TCP connections with service agents and user agents.
630Sstevel@tonic-gate  *	    In addition, slpd functions in the first mode, as a
640Sstevel@tonic-gate  *	    service agent server, for SAs and UAs on the local host.
650Sstevel@tonic-gate  *
660Sstevel@tonic-gate  *   </ol>
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * The slpd is invoked as follows:<br>
690Sstevel@tonic-gate  *<blockquote>
700Sstevel@tonic-gate  *
710Sstevel@tonic-gate  *	java com.sun.slpd [monitor] [stop] [-f <config file name>]
720Sstevel@tonic-gate  *
730Sstevel@tonic-gate  *</blockquote>
740Sstevel@tonic-gate  *
750Sstevel@tonic-gate  * The optional monitor argument specifies that a GUI monitor should be
760Sstevel@tonic-gate  * brought up. The optional stop argument indicates that slpd should
770Sstevel@tonic-gate  * signal a running slpd to stop. The optional <config file name> argument
780Sstevel@tonic-gate  * specifies that the named file should be used as the configuration file.
790Sstevel@tonic-gate  * <p>
800Sstevel@tonic-gate  * See <a href="slpd.conf.html">slpd.conf</a> for more information on
810Sstevel@tonic-gate  * configuration file syntax and <a href="slpd.reg.html">slpd.reg</a>
820Sstevel@tonic-gate  * for more information on proxy registration file syntax.
830Sstevel@tonic-gate  *
840Sstevel@tonic-gate  * @author Erik Guttman, James Kempf
850Sstevel@tonic-gate  */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate // Note that the inheritance is *only* so slpd can initialize the
880Sstevel@tonic-gate // internals of SLP config.
890Sstevel@tonic-gate 
900Sstevel@tonic-gate public class slpd extends SLPConfig {
910Sstevel@tonic-gate 
920Sstevel@tonic-gate     private static final String SERVER_BUNDLE_NAME = "com/sun/slp/Server";
930Sstevel@tonic-gate 
940Sstevel@tonic-gate     // Server bundle. Set the parent.
950Sstevel@tonic-gate 
960Sstevel@tonic-gate     static class ServerBundle extends ResourceBundle {
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	private ResourceBundle bundle = null;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	static ResourceBundle
getBundle(ResourceBundle parent, Locale locale)1010Sstevel@tonic-gate 	    getBundle(ResourceBundle parent, Locale locale)
1020Sstevel@tonic-gate 	    throws MissingResourceException {
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	    return new ServerBundle(parent, locale);
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	}
1070Sstevel@tonic-gate 
ServerBundle(ResourceBundle parent, Locale locale)1080Sstevel@tonic-gate 	private ServerBundle(ResourceBundle parent, Locale locale)
1090Sstevel@tonic-gate 	    throws MissingResourceException {
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate 	    if (parent != null) {
1120Sstevel@tonic-gate 		this.parent = parent;
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	    }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	    try {
1170Sstevel@tonic-gate 		URL[] urls = null;
1180Sstevel@tonic-gate 		urls = new URL[] {new URL("file:/usr/share/lib/locale/")};
1190Sstevel@tonic-gate 		URLClassLoader ld = new URLClassLoader(urls);
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 		bundle =
1220Sstevel@tonic-gate 		    ResourceBundle.getBundle(SERVER_BUNDLE_NAME, locale, ld);
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	    } catch (MalformedURLException e) {
1250Sstevel@tonic-gate 		// fallthru to default location
1260Sstevel@tonic-gate 	    }	// No locales in slpd.jar, so propagate the
1270Sstevel@tonic-gate 		// MissingResourceException
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	    bundle = bundle != null ?
1300Sstevel@tonic-gate 		bundle :
1310Sstevel@tonic-gate 		ResourceBundle.getBundle(SERVER_BUNDLE_NAME, locale);
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 
handleGetObject(String key)1350Sstevel@tonic-gate 	protected Object handleGetObject(String key)
1360Sstevel@tonic-gate 	    throws MissingResourceException {
1370Sstevel@tonic-gate 	    Object ret = null;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	    try {
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 		ret = bundle.getObject(key);
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	    } catch (MissingResourceException ex) {
1440Sstevel@tonic-gate 		ret = parent.getObject(key);
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	    }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	    return ret;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	}
1510Sstevel@tonic-gate 
getKeys()1520Sstevel@tonic-gate 	public Enumeration getKeys() {
1530Sstevel@tonic-gate 	    return bundle.getKeys();
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate     }
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate     /**
1600Sstevel@tonic-gate      * Log object for SLP to write to GUI. This class follows the
1610Sstevel@tonic-gate      * semantics of the other SLP logging classes:
1620Sstevel@tonic-gate      *
1630Sstevel@tonic-gate      * This class does not actually write anything until the flush() method
1640Sstevel@tonic-gate      * in invoked; this will write the concatenation of all messages
1650Sstevel@tonic-gate      * passed to the write() method since the last invocation of flush().
1660Sstevel@tonic-gate      *
1670Sstevel@tonic-gate      * The actual logging class used can be controlled via the
1680Sstevel@tonic-gate      * sun.net.slp.loggerClass property.
1690Sstevel@tonic-gate      *
1700Sstevel@tonic-gate      * See also the StderrLog and Syslog classes.
1710Sstevel@tonic-gate      */
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate     static class SLPLog extends Writer {
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	private TextArea taLog = null;
1760Sstevel@tonic-gate 	private StringBuffer buf;
1770Sstevel@tonic-gate 
SLPLog(TextArea nta)1780Sstevel@tonic-gate 	SLPLog(TextArea nta) {
1790Sstevel@tonic-gate 	    taLog = nta;
1800Sstevel@tonic-gate 	    buf = new StringBuffer();
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	}
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	// Write to the StringBuffer
1850Sstevel@tonic-gate 
write(char[] cbuf, int off, int len)1860Sstevel@tonic-gate 	public void write(char[] cbuf, int off, int len)
1870Sstevel@tonic-gate 	    throws IOException {
1880Sstevel@tonic-gate 	    buf.append(cbuf, off, len);
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	}
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	// Write to the Frame.
1930Sstevel@tonic-gate 
flush()1940Sstevel@tonic-gate 	public void flush() throws IOException {
1950Sstevel@tonic-gate 	    String date = SLPConfig.getDateString();
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	    taLog.append(
1980Sstevel@tonic-gate 			 "********" +
1990Sstevel@tonic-gate 			 date + "\n" +
2000Sstevel@tonic-gate 			 buf.toString() + "\n" +
2010Sstevel@tonic-gate 			 "********\n");
2020Sstevel@tonic-gate 	    buf = new StringBuffer();
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	}
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	// These is a no-op
2070Sstevel@tonic-gate 
close()2080Sstevel@tonic-gate 	public void close() throws IOException {}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate     }
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate     //
2130Sstevel@tonic-gate     // slpd definition.
2140Sstevel@tonic-gate     //
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate     private static String  configFile;		// name of configuration file
2170Sstevel@tonic-gate     private static SLPDgui slpdgui;		// GUI monitor, if desired
2180Sstevel@tonic-gate     private static SLPConfig config;		// handles system properties
2190Sstevel@tonic-gate     private static ServerDATable daTable;	// handle recording of DAs
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate     // Called by the slpd and subclasses only.
2220Sstevel@tonic-gate 
slpd()2230Sstevel@tonic-gate     protected slpd() {
2240Sstevel@tonic-gate 	super();
2250Sstevel@tonic-gate     }
2260Sstevel@tonic-gate 
usage()2270Sstevel@tonic-gate     private static void usage() {
2280Sstevel@tonic-gate 	ResourceBundle bundle =
2290Sstevel@tonic-gate 	    getMessageBundleInternal(Locale.getDefault(), null);
2300Sstevel@tonic-gate 	System.err.println(formatMessageInternal("slpd_usage",
2310Sstevel@tonic-gate 						 new Object[0],
2320Sstevel@tonic-gate 						 bundle));
2330Sstevel@tonic-gate 	System.exit(1);
2340Sstevel@tonic-gate     }
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate     /**
2370Sstevel@tonic-gate      * Usage: slpd [monitor] [stop] [-f config-file name]<br>
2380Sstevel@tonic-gate      * <br>
2390Sstevel@tonic-gate      * String arguments are:
2400Sstevel@tonic-gate      * <br>
2410Sstevel@tonic-gate      * <b> monitor </b> Puts up a rudimentary GUI for the slpd.<br>
2420Sstevel@tonic-gate      * <b>stop <b> Bring down a running slpd and exit.
2430Sstevel@tonic-gate      * <b> config-file name </b> Reads the specified configuration file.<br>
2440Sstevel@tonic-gate      *
2450Sstevel@tonic-gate      * The default running mode is to have no GUI and to use SLP
2460Sstevel@tonic-gate      * defined configuration.
2470Sstevel@tonic-gate      */
2480Sstevel@tonic-gate 
main(String args[])2490Sstevel@tonic-gate     public static void main(String args[]) {
2500Sstevel@tonic-gate 	boolean bMon  = false;
2510Sstevel@tonic-gate 	boolean bStop = false;
2520Sstevel@tonic-gate 	configFile    = null;
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	Thread.currentThread().setName("slpd");
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	// Process args.
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	if (args.length > 3) {
2590Sstevel@tonic-gate 	    usage();
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	int i, n = args.length;
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	    // Argument is a config file.
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	    if (args[i].equals("-f")) {
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 		if (configFile != null) {
2720Sstevel@tonic-gate 		    usage();
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 		}
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 		// Make sure we can open it.
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 		try {
2790Sstevel@tonic-gate 		    File f = new File(args[++i]);
2800Sstevel@tonic-gate 		    configFile = args[i];
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 		} catch (Exception ex) {
2830Sstevel@tonic-gate 		    usage();
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 		}
2860Sstevel@tonic-gate 	    } else if (args[i].equals("monitor")) {
2870Sstevel@tonic-gate 		bMon = true;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	    } else if (args[i].equals("stop")) {
2900Sstevel@tonic-gate 		bStop = true;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	    } else {
2930Sstevel@tonic-gate 		usage();
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	    }
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	// Read message bundle file, load config file into properties.
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	ResourceBundle bundle =
3010Sstevel@tonic-gate 	    getMessageBundleInternal(Locale.getDefault(), null);
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	try {
3040Sstevel@tonic-gate 	    if (configFile != null) {
3050Sstevel@tonic-gate 		Properties props = System.getProperties();
3060Sstevel@tonic-gate 		props.setProperty("sun.net.slp.configURL",
3070Sstevel@tonic-gate 				  "file:" + configFile);
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	    }
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	    // Create a new SLP Config object from the config file.
3120Sstevel@tonic-gate 	    config = initializeSLPConfig();
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	    // Create a GUI if the user asked for one.
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	    if (bMon) {
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 		try {
3190Sstevel@tonic-gate 		    slpdgui = new SLPDgui(configFile);
3200Sstevel@tonic-gate 		    SLPLog log = new SLPLog(slpdgui.getTALog());
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 		    synchronized (config) {
3230Sstevel@tonic-gate 			config.log = log;
3240Sstevel@tonic-gate 		    }
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		    slpdgui.setVisible(true);
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 		} catch (Exception ex) {
3290Sstevel@tonic-gate 		    System.err.println(formatMessageInternal("slpd_no_gui",
3300Sstevel@tonic-gate 							     new Object[0],
3310Sstevel@tonic-gate 							     bundle));
3320Sstevel@tonic-gate 		}
3330Sstevel@tonic-gate 	    }
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	    // Either start or stop the server, depending on what was
3360Sstevel@tonic-gate 	    //  requested.
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	    if (!bStop) {
3390Sstevel@tonic-gate 		start();
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	    } else {
3420Sstevel@tonic-gate 		stop();
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	    }
3450Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	    errorExit(bundle, ex);
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	}
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate     }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate     /**
3540Sstevel@tonic-gate      * Start the slpd.
3550Sstevel@tonic-gate      *
3560Sstevel@tonic-gate      * @param bMon	True if initializing with GUI monitor.
3570Sstevel@tonic-gate      * @exception ServiceLocationException Internal error or network
3580Sstevel@tonic-gate      *			initialization error or
3590Sstevel@tonic-gate      *			internal networking error.
3600Sstevel@tonic-gate      *
3610Sstevel@tonic-gate      */
3620Sstevel@tonic-gate 
start()3630Sstevel@tonic-gate     static void start() throws ServiceLocationException {
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	// Initialize the service table.
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	ServiceTable table = ServiceTable.getServiceTable();
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	// Initialize the class name for the DA table to the Sun-specific
3700Sstevel@tonic-gate 	//  DA table.
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	Properties props = System.getProperties();
3730Sstevel@tonic-gate 	props.put(DATable.DA_TABLE_CLASS_PROP, "com.sun.slp.SunServerDATable");
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	// If there is a request on stdin, process it now
3760Sstevel@tonic-gate 	try {
3770Sstevel@tonic-gate 	    if (System.in.available() > 0) {
3780Sstevel@tonic-gate 		RequestHandler rh =
3790Sstevel@tonic-gate 		    new RequestHandler(System.in, System.out, config);
3800Sstevel@tonic-gate 		rh.start();
3810Sstevel@tonic-gate 	    }
3820Sstevel@tonic-gate 	} catch (IOException e) {}
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	// Start a StreamListener on loopback to start accepting locals regs
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	StreamListener.initializeStreamListenerOnInterface(
3870Sstevel@tonic-gate 							config.getLoopback());
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	// Create a ServerDATable from the class. This will initialize
3900Sstevel@tonic-gate 	//  active discovery. Note that we need to record our own presence
3910Sstevel@tonic-gate 	//  in the DA table because we are not yet listening for requests.
3920Sstevel@tonic-gate 	//  We do this after deserialization so that if we discover any
3930Sstevel@tonic-gate 	//  DAs, we can perform registrations of the serialized advertisements.
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 	daTable = ServerDATable.getServerDATable();
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	// Deserialize any serialized advertisements and do them now.
3980Sstevel@tonic-gate 	//  Waiting until here allows any error messages to appear in
3990Sstevel@tonic-gate 	//  the GUI log, if any, and at this point the DA table is ready.
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	table.deserializeTable();
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	// Need to create datagram and stream listeners, and a
4040Sstevel@tonic-gate 	//  DAAdvertiser on all network interfaces.
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	Vector interfaces = config.getInterfaces();
4070Sstevel@tonic-gate 	int i, n = interfaces.size();
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
4100Sstevel@tonic-gate 	    InetAddress interfac = (InetAddress)interfaces.elementAt(i);
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	    // Initialize the complex of listener/sender objects on the
4130Sstevel@tonic-gate 	    // interface. This includes a datagram listener, a DAAdvertiser
4140Sstevel@tonic-gate 	    // (which shares the same socket as the datagram listener), and
4150Sstevel@tonic-gate 	    // a stream listener.
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	    Listener.initializeInterfaceManagers(interfac);
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	}
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	// If we've been configured as a DA, then create a DA advertiser to
4220Sstevel@tonic-gate 	//  periodically advertise our presence on this interface. This
4230Sstevel@tonic-gate 	//  is only done on the default interface.
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	if (config.isDA()) {
4260Sstevel@tonic-gate 	    DAAdvertiser.initializeDAAdvertiserOnInterface(
4270Sstevel@tonic-gate 							config.getLocalHost());
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	// Report scopes and whether DA or SA.
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	Vector discoveredScopes = daTable.findScopes();
4340Sstevel@tonic-gate 	Vector serverScopes = config.getSAConfiguredScopes();
4350Sstevel@tonic-gate 	Vector daAttributes = config.getDAAttributes();
4360Sstevel@tonic-gate 	Vector saAttributes = config.getSAAttributes();
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	// Report that we are running if tracing is on
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	if (config.regTest() ||
4410Sstevel@tonic-gate 	    config.traceMsg() ||
4420Sstevel@tonic-gate 	    config.traceDrop() ||
4430Sstevel@tonic-gate 	    config.traceDATraffic()) {
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	    config.writeLog((config.isDA() ? "hello_da":"hello"),
4460Sstevel@tonic-gate 			    new Object[] {interfaces,
4470Sstevel@tonic-gate 					      serverScopes,
4480Sstevel@tonic-gate 					      discoveredScopes,
4490Sstevel@tonic-gate 					      (config.isDA() ?
4500Sstevel@tonic-gate 					       daAttributes:saAttributes)});
4510Sstevel@tonic-gate 	}
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	// If V1 is supported, crank up V1 support as well.
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	if (config.isV1Supported()) {
4560Sstevel@tonic-gate 	    SLPV1Manager.start(config, daTable, table);
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate     }
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate     // Stop a running server by sending a DAAdvert or SAAdvert.
4620Sstevel@tonic-gate 
stop()4630Sstevel@tonic-gate     static void stop() throws ServiceLocationException {
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	if (daemonIsDA()) {
4660Sstevel@tonic-gate 	    stopDA();
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	} else {
4690Sstevel@tonic-gate 	    stopSA();
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	}
4720Sstevel@tonic-gate     }
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate     // Determine whether the daemon running on this machine is a DA
4750Sstevel@tonic-gate     //  or not.
4760Sstevel@tonic-gate 
daemonIsDA()4770Sstevel@tonic-gate     static boolean daemonIsDA() throws ServiceLocationException {
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	// Get a DA table with available DAs.
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	DATable table =
4820Sstevel@tonic-gate 	    DATable.getDATable();
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	// Get DAs.
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	Hashtable das =
4870Sstevel@tonic-gate 	    table.findDAScopes(config.getSAConfiguredScopes());
4880Sstevel@tonic-gate 	Vector daRecs = (Vector)das.get(DATable.UNICAST_KEY);
4890Sstevel@tonic-gate 	Vector interfaces = config.getInterfaces();
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	// If no DAs, then simply return.
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	if (daRecs == null) {
4940Sstevel@tonic-gate 	    return false;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	}
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	// Find our address in the list, if it exists.
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 	int i, n = daRecs.size();
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
5030Sstevel@tonic-gate 	    DATable.DARecord rec =
5040Sstevel@tonic-gate 		(DATable.DARecord)daRecs.elementAt(i);
5050Sstevel@tonic-gate 	    Vector daAddresses = rec.daAddresses;
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	    int j, m = interfaces.size();
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	    for (j = 0; j < m; j++) {
5100Sstevel@tonic-gate 		if (daAddresses.contains(interfaces.elementAt(i))) {
5110Sstevel@tonic-gate 		    return true;
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 		}
5140Sstevel@tonic-gate 	    }
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	return false;
5180Sstevel@tonic-gate     }
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate     // Stop a DA by multicasting the DAAdvert with boot timestamp 0.
5210Sstevel@tonic-gate 
stopDA()5220Sstevel@tonic-gate     private static void stopDA() throws ServiceLocationException {
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	// Make the DA URL and the DAAdvert. Note that we only need signal
5250Sstevel@tonic-gate 	//  on the default local host interface because that is the only
5260Sstevel@tonic-gate 	//  one on which the server is listening.
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 	ServiceURL url =
5290Sstevel@tonic-gate 	    new ServiceURL(Defaults.DA_SERVICE_TYPE +
5300Sstevel@tonic-gate 			   "://" +
5310Sstevel@tonic-gate 			   config.getLocalHost().getHostAddress(),
5320Sstevel@tonic-gate 			   ServiceURL.LIFETIME_DEFAULT);
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	SDAAdvert advert =
5350Sstevel@tonic-gate 	    new SDAAdvert(new SLPServerHeaderV2(),
5360Sstevel@tonic-gate 			  (short)0x0,  // sez we're unsolicited...
5370Sstevel@tonic-gate 			  0L,    // sez we're going down...
5380Sstevel@tonic-gate 			  url,
5390Sstevel@tonic-gate 			  config.getSAConfiguredScopes(),
5400Sstevel@tonic-gate 			  new Vector()); // no attributes needed to go down...
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	// Make the DAAdvertiser.
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	DAAdvertiser daadv = new DAAdvertiser(config.getLocalHost(),
5450Sstevel@tonic-gate 					      advert.getHeader());
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	// Send out unsolicted "going down" message.
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	daadv.sendAdvert();
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	// That's it! No need for any messages here.
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	System.exit(0);
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate     }
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate     // Stop an SA server by unicasting an SA advert with xid 0.
5580Sstevel@tonic-gate 
stopSA()5590Sstevel@tonic-gate     private static void stopSA() throws ServiceLocationException {
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	// We signal for stop on the local host, which is guaranteed
5620Sstevel@tonic-gate 	//  to have an SA listener.
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	ServiceURL url =
5650Sstevel@tonic-gate 	    new ServiceURL(Defaults.SA_SERVICE_TYPE + "://" +
5660Sstevel@tonic-gate 			   config.getLocalHost().getHostAddress(),
5670Sstevel@tonic-gate 			   ServiceURL.LIFETIME_DEFAULT);
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	SSAAdvert advert = new SSAAdvert(Defaults.version,
5700Sstevel@tonic-gate 					 (short)0x0, // sez we're going down...
5710Sstevel@tonic-gate 					 config.getLocale(),
5720Sstevel@tonic-gate 					 url,
5730Sstevel@tonic-gate 					 config.getSAConfiguredScopes(),
5740Sstevel@tonic-gate 					 new Vector());
5750Sstevel@tonic-gate 						// don't care about attrs..,
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	// Send it TCP. We ignore NETWORK_ERROR because it only means
5780Sstevel@tonic-gate 	//  that the daemon didn't send us a reply, which is expected.
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	try {
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	    SrvLocMsg msg =
5830Sstevel@tonic-gate 		Transact.transactTCPMsg(config.getLoopback(), advert, false);
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	    if (msg.getErrorCode() != ServiceLocationException.OK) {
5860Sstevel@tonic-gate 		config.writeLog("slpd_sa_stop_failure",
5870Sstevel@tonic-gate 				new Object[] {
5880Sstevel@tonic-gate 		    new Integer(msg.getErrorCode())});
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 	    }
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	    if (ex.getErrorCode() != ServiceLocationException.NETWORK_ERROR) {
5950Sstevel@tonic-gate 		config.writeLog("slpd_sa_stop_failure",
5960Sstevel@tonic-gate 				new Object[] {new Integer(ex.getErrorCode())});
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 	    }
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	// That's it!
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	System.exit(0);
6050Sstevel@tonic-gate     }
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate     // Print error message, exit.
6080Sstevel@tonic-gate 
errorExit(ResourceBundle bundle, ServiceLocationException ex)6090Sstevel@tonic-gate     static void errorExit(ResourceBundle bundle, ServiceLocationException ex) {
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 	switch (ex.getErrorCode()) {
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	case ServiceLocationException.INTERNAL_SYSTEM_ERROR:
6140Sstevel@tonic-gate 	    System.err.println(formatMessageInternal("slpd_int_err",
6150Sstevel@tonic-gate 						     new Object[] {
6160Sstevel@tonic-gate 		ex.getMessage()},
6170Sstevel@tonic-gate 		bundle));
6180Sstevel@tonic-gate 	    break;
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	case ServiceLocationException.NETWORK_INIT_FAILED:
6210Sstevel@tonic-gate 	    System.err.println(formatMessageInternal("slpd_intnet_err",
6220Sstevel@tonic-gate 						     new Object[] {
6230Sstevel@tonic-gate 		ex.getMessage()},
6240Sstevel@tonic-gate 		bundle));
6250Sstevel@tonic-gate 	    break;
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	case ServiceLocationException.NETWORK_ERROR:
6280Sstevel@tonic-gate 	    System.err.println(formatMessageInternal("slpd_net_err",
6290Sstevel@tonic-gate 						     new Object[] {
6300Sstevel@tonic-gate 		ex.getMessage()},
6310Sstevel@tonic-gate 		bundle));
6320Sstevel@tonic-gate 	    break;
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	default:
6350Sstevel@tonic-gate 	    System.err.println(formatMessageInternal("slpd_err",
6360Sstevel@tonic-gate 						     new Object[] {
6370Sstevel@tonic-gate 		new Integer(ex.getErrorCode()),
6380Sstevel@tonic-gate 		    ex.getMessage()},
6390Sstevel@tonic-gate 		bundle));
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	}
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 	ex.printStackTrace();
6440Sstevel@tonic-gate 	System.err.println(formatMessageInternal("exiting_msg",
6450Sstevel@tonic-gate 						 new Object[0],
6460Sstevel@tonic-gate 						 bundle));
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	System.exit(1);
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate     }
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate     // Make a new SLPConfig object of the right class type.
6530Sstevel@tonic-gate 
initializeSLPConfig()6540Sstevel@tonic-gate     private static SLPConfig initializeSLPConfig() {
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	// The server *always* runs as an SA. It may also run as a DA.
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	config.isSA = true;
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 	// set default logging class for slpd to syslog
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 	if (System.getProperty("sun.net.slp.loggerClass") == null) {
6630Sstevel@tonic-gate 	    Properties props = System.getProperties();
6640Sstevel@tonic-gate 	    props.setProperty("sun.net.slp.loggerClass", "com.sun.slp.Syslog");
6650Sstevel@tonic-gate 	    System.setProperties(props);
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 	}
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 	// slpd is the server side config.
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	theSLPConfig = new slpd();
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 	return theSLPConfig;
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate     }
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate     //
6780Sstevel@tonic-gate     // Extensions to sldp for server side only.
6790Sstevel@tonic-gate     //
6800Sstevel@tonic-gate 
isDA()6810Sstevel@tonic-gate     boolean isDA() {
6820Sstevel@tonic-gate 	return Boolean.getBoolean("net.slp.isDA");
6830Sstevel@tonic-gate     }
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate     // Determine whether V1 is supported. Default is no.
6860Sstevel@tonic-gate 
isV1Supported()6870Sstevel@tonic-gate     boolean isV1Supported() {
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	if (!isDA() || super.getSLPv1NotSupported()) {
6900Sstevel@tonic-gate 	    return false;
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 	}
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	boolean v1Supported = false;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	try {
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	    Class.forName("com.sun.slp.SLPV1Manager");
6990Sstevel@tonic-gate 	    v1Supported = true;
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	} catch (ClassNotFoundException ex) {
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 	    // Not there.
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	}
7060Sstevel@tonic-gate 
7070Sstevel@tonic-gate 	return v1Supported;
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate     }
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate     // Load server message bundle.
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate     private static final String serverMsgBundle = "Server";
7140Sstevel@tonic-gate 
getMessageBundle(Locale locale)7150Sstevel@tonic-gate     ResourceBundle getMessageBundle(Locale locale) {
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	// Get the parent bundle first.
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 	ResourceBundle parentBundle = super.getMessageBundle(locale);
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	return getMessageBundleInternal(locale, parentBundle);
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate     }
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate     // We need this in case we get an error before the config object is
7260Sstevel@tonic-gate     //  created.
7270Sstevel@tonic-gate 
getMessageBundleInternal( Locale locale, ResourceBundle parentBundle)7280Sstevel@tonic-gate     static private ResourceBundle getMessageBundleInternal(
7290Sstevel@tonic-gate 						Locale locale,
7300Sstevel@tonic-gate 						ResourceBundle parentBundle) {
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	// Now create a server subclass.
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	ResourceBundle msgBundle = null;
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	try {
7370Sstevel@tonic-gate 	    msgBundle = ServerBundle.getBundle(parentBundle, locale);
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate 	} catch (MissingResourceException ex) {  // can't localize this one!
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	    // We can't print out to the log, because we may be in the
7420Sstevel@tonic-gate 	    //  process of trying to.
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	    System.out.println("Missing resource bundle ``"+
7450Sstevel@tonic-gate 			       SERVER_BUNDLE_NAME+
7460Sstevel@tonic-gate 			       "'' for locale ``"+
7470Sstevel@tonic-gate 			       locale+
7480Sstevel@tonic-gate 			       "''");
7490Sstevel@tonic-gate 	    // Hosed if the default locale is missing.
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	    if (locale.equals(Defaults.locale)) {
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 		System.out.println("Exiting...");
7540Sstevel@tonic-gate 		System.exit(1);
7550Sstevel@tonic-gate 	    }
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 	    // Otherwise, return the default locale.
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 	    System.out.println("Using SLP default locale ``" +
7600Sstevel@tonic-gate 			       Defaults.locale+"''");
7610Sstevel@tonic-gate 
7620Sstevel@tonic-gate 	    msgBundle =
7630Sstevel@tonic-gate 		getMessageBundleInternal(Defaults.locale, parentBundle);
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	}
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	return msgBundle;
7680Sstevel@tonic-gate     }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate }
771