xref: /onnv-gate/usr/src/lib/libslp/javalib/com/sun/slp/RequestHandler.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 2001-2002 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 //  RequestHandler.java: Handle an incoming request in a separate thread.
280Sstevel@tonic-gate //  Author:           James Kempf
290Sstevel@tonic-gate //  Created On:       Mon May 18 14:00:27 1998
300Sstevel@tonic-gate //  Last Modified By: James Kempf
310Sstevel@tonic-gate //  Last Modified On: Mon Mar  8 16:12:13 1999
320Sstevel@tonic-gate //  Update Count:     173
330Sstevel@tonic-gate //
340Sstevel@tonic-gate 
350Sstevel@tonic-gate package com.sun.slp;
360Sstevel@tonic-gate 
370Sstevel@tonic-gate import java.io.*;
380Sstevel@tonic-gate import java.net.*;
390Sstevel@tonic-gate import java.util.*;
400Sstevel@tonic-gate 
410Sstevel@tonic-gate /**
420Sstevel@tonic-gate  * Handle an incoming request in a separate thread. The request
430Sstevel@tonic-gate  * may have arrived via datagram, or it may have arrived via
440Sstevel@tonic-gate  * stream.
450Sstevel@tonic-gate  *
460Sstevel@tonic-gate  * @author James Kempf, Erik Guttman
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 
500Sstevel@tonic-gate class RequestHandler extends Thread {
510Sstevel@tonic-gate 
520Sstevel@tonic-gate     private SLPConfig config;		// Config for system properties.
530Sstevel@tonic-gate     private ServerDATable daTable;	// DA table in server for reg and dereg
540Sstevel@tonic-gate     private InetAddress interfac = null; // Interface on which request came in.
550Sstevel@tonic-gate     private Socket sock = null;		// Socket for incoming stream request.
560Sstevel@tonic-gate     private DatagramPacket packet = null; // Packet for datagram requests.
570Sstevel@tonic-gate     private InetAddress clientAddr = null; // Internet address of the client.
580Sstevel@tonic-gate     private int port = 0;		// Port to use.
590Sstevel@tonic-gate     private ServiceTable serviceTable = null;
600Sstevel@tonic-gate     private SrvLocMsg toForward = null;	 // Reg or dereg to forward.
610Sstevel@tonic-gate     private InputStream inStream = null;
620Sstevel@tonic-gate     private OutputStream outStream = null;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate     static private Hashtable inProgress = new Hashtable();
650Sstevel@tonic-gate 				// Keeps track of in progress requests
660Sstevel@tonic-gate 
670Sstevel@tonic-gate     // When a request handler gets GC'd, make sure it's open socket is closed.
680Sstevel@tonic-gate     //  We simply let the exception propagate, because it is ignored.
690Sstevel@tonic-gate 
finalize()700Sstevel@tonic-gate     protected void finalize() throws IOException {
710Sstevel@tonic-gate 	if (sock != null) sock.close();
720Sstevel@tonic-gate 
730Sstevel@tonic-gate     }
740Sstevel@tonic-gate 
RequestHandler(InputStream in, OutputStream out, SLPConfig config_in)750Sstevel@tonic-gate     RequestHandler(InputStream in, OutputStream out, SLPConfig config_in) {
760Sstevel@tonic-gate 	config = config_in;
770Sstevel@tonic-gate 	sock = null;
780Sstevel@tonic-gate 	inStream = in;
790Sstevel@tonic-gate 	outStream = out;
800Sstevel@tonic-gate 	clientAddr = config.getLoopback();
810Sstevel@tonic-gate 	port = 427;
820Sstevel@tonic-gate 	interfac = clientAddr;
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	try {
850Sstevel@tonic-gate 	    serviceTable = ServiceTable.getServiceTable();
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	    // Taken care of in initialization code.
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	}
920Sstevel@tonic-gate     }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate     // Request arrived via stream. Set the incoming socket, spawn
950Sstevel@tonic-gate     //  a separate thread in which to run.
960Sstevel@tonic-gate 
RequestHandler(Socket sock_in, InetAddress interfac, SLPConfig config_in)970Sstevel@tonic-gate     RequestHandler(Socket sock_in, InetAddress interfac, SLPConfig config_in) {
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	Assert.slpassert((sock_in != null),
1000Sstevel@tonic-gate 		      "rh_null_sock",
1010Sstevel@tonic-gate 		      new Object[0]);
1020Sstevel@tonic-gate 	Assert.slpassert((config_in != null),
1030Sstevel@tonic-gate 		      "ls_null_config",
1040Sstevel@tonic-gate 		      new Object[0]);
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	config = config_in;
1070Sstevel@tonic-gate 	sock = sock_in;
1080Sstevel@tonic-gate 	clientAddr = sock.getInetAddress();
1090Sstevel@tonic-gate 	port = sock.getPort();
1100Sstevel@tonic-gate 	this.interfac = interfac;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	try {
1130Sstevel@tonic-gate 	    serviceTable = ServiceTable.getServiceTable();
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	    // Taken care of in initialization code.
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	}
1200Sstevel@tonic-gate     }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate     // Request arrived via datagram. Set the incoming packet, spawn
1230Sstevel@tonic-gate     //  a separate thread in which to run.
1240Sstevel@tonic-gate 
RequestHandler(DatagramPacket packet_in, InetAddress interfac, SLPConfig config_in)1250Sstevel@tonic-gate     RequestHandler(DatagramPacket packet_in,
1260Sstevel@tonic-gate 		   InetAddress interfac,
1270Sstevel@tonic-gate 		   SLPConfig config_in) {
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	Assert.slpassert((packet_in != null),
1300Sstevel@tonic-gate 		      "rh_null_packy",
1310Sstevel@tonic-gate 		      new Object[0]);
1320Sstevel@tonic-gate 	Assert.slpassert((config_in != null),
1330Sstevel@tonic-gate 		      "ls_null_config",
1340Sstevel@tonic-gate 		      new Object[0]);
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	config = config_in;
1370Sstevel@tonic-gate 	packet = packet_in;
1380Sstevel@tonic-gate 	clientAddr = packet.getAddress();
1390Sstevel@tonic-gate 	port = packet.getPort();
1400Sstevel@tonic-gate 	this.interfac = interfac;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	try {
1430Sstevel@tonic-gate 	    serviceTable = ServiceTable.getServiceTable();
1440Sstevel@tonic-gate 	    daTable = ServerDATable.getServerDATable();
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	    // Taken care of in initialziation code.
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	}
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate     }
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate     /**
1550Sstevel@tonic-gate      * Return a stringified buffer, suitable for printing, for
1560Sstevel@tonic-gate      * debugging.
1570Sstevel@tonic-gate      *
1580Sstevel@tonic-gate      * @param bytes The byte buffer.
1590Sstevel@tonic-gate      * @return A string with the ASCII characters as characters, otherwise
1600Sstevel@tonic-gate      *         convert to escape notation.
1610Sstevel@tonic-gate      */
1620Sstevel@tonic-gate 
stringifyBuffer(byte[] bytes)1630Sstevel@tonic-gate     static String stringifyBuffer(byte[] bytes) {
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	StringBuffer buf = new StringBuffer();
1660Sstevel@tonic-gate 	int i, n = bytes.length;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
1690Sstevel@tonic-gate 	    byte b = bytes[i];
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	    if ((b >= 0x21) && (b < 0x7e)) {
1720Sstevel@tonic-gate 		buf.append((char)b);
1730Sstevel@tonic-gate 	    } else {
1740Sstevel@tonic-gate 		buf.append("\\"+Integer.toHexString(((int)b) & 0xFF));
1750Sstevel@tonic-gate 	    }
1760Sstevel@tonic-gate 	}
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	return buf.toString();
1790Sstevel@tonic-gate     }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate     // If a stream thread, then get the request first. Process the
1820Sstevel@tonic-gate     //  request and reply to client.
1830Sstevel@tonic-gate 
run()1840Sstevel@tonic-gate     public void run() {
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	// Is this a stream or datagram thread?
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	if (sock != null || inStream != null) {
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	    // Label appropriately.
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	    setName("Stream Request Handler "+clientAddr+":"+port);
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	    if (sock != null) {
1950Sstevel@tonic-gate 		// Set the socket to block until there are bytes to read.
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 		try {
1980Sstevel@tonic-gate 		    sock.setSoTimeout(0);
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 		} catch (SocketException ex) {
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 		}
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	    }
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	    // get DA Table
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	    try {
2090Sstevel@tonic-gate 		daTable = ServerDATable.getServerDATable();
2100Sstevel@tonic-gate 	    } catch (ServiceLocationException e) {
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 		// Taken care of in initialziation code.
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	    }
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	    // Stream needs to loop through until requests are completed.
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	    handleStream();
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	    if (sock != null) {
2210Sstevel@tonic-gate 		try {
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 		    sock.close();
2240Sstevel@tonic-gate 		    sock = null;
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 		} catch (IOException ex) {
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 		}
2290Sstevel@tonic-gate 	    }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	} else {
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	    // Label appropriately.
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	    setName("Datagram Request Handler "+clientAddr+":"+port);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	    byte[] inbuf = packet.getData();
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	    // Copy xid for use in hash key.
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	    byte[] xidBuf = new byte[2];
2420Sstevel@tonic-gate 	    System.arraycopy(inbuf, SrvLocHeader.XID_OFFSET, xidBuf, 0, 2);
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	    // If this request is already in progress, drop new request.
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	    int xid = 0;
2470Sstevel@tonic-gate 	    xid = (int)((char)xidBuf[0] & 0xFF) << 8;
2480Sstevel@tonic-gate 	    xid += (int)((char)xidBuf[1] & 0xFF);
2490Sstevel@tonic-gate 	    String syncTableKey =
2500Sstevel@tonic-gate 		(new Integer(xid)).toString() +  clientAddr.getHostAddress();
2510Sstevel@tonic-gate 	    boolean there = false;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	    synchronized (inProgress) {
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 		there = (inProgress.get(syncTableKey) != null);
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 		if (!there) {
2580Sstevel@tonic-gate 		    inProgress.put(syncTableKey, this);
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 		}
2610Sstevel@tonic-gate 	    }
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	    // Drop if we are processing it already.
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	    if (there) {
2660Sstevel@tonic-gate 		if (config.traceDrop()) {
2670Sstevel@tonic-gate 		    config.writeLog("rh_rqst_in_progress",
2680Sstevel@tonic-gate 				    new Object[] {clientAddr,
2690Sstevel@tonic-gate 						      new Integer(port),
2700Sstevel@tonic-gate 						      interfac});
2710Sstevel@tonic-gate 		}
2720Sstevel@tonic-gate 		return;
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	    }
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	    // We can simply cut to the chase and process the datagram
2770Sstevel@tonic-gate 	    //  request.
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	    DataInputStream dis =
2800Sstevel@tonic-gate 		new DataInputStream(new ByteArrayInputStream(inbuf));
2810Sstevel@tonic-gate 	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	    try {
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 		handleRequest(dis, baos, false);
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		byte[] outbuf = baos.toByteArray();
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 		// Open a data output stream for the outgoing request. There
2900Sstevel@tonic-gate 		//  is no buffer for reply or it is empty, the request was
2910Sstevel@tonic-gate 		//  multicast and nothing was sent back.
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 		if (outbuf != null && outbuf.length > 0) {
2940Sstevel@tonic-gate 		    sendDatagramReply(outbuf);
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 		}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	    } catch (IOException ex) {
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 		// No excuse for an EOF exception here.
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 		if (config.traceDrop()) {
3030Sstevel@tonic-gate 		    config.writeLog("rh_datagram_ioe",
3040Sstevel@tonic-gate 				    new Object[] {clientAddr,
3050Sstevel@tonic-gate 						      new Integer(port),
3060Sstevel@tonic-gate 						      interfac,
3070Sstevel@tonic-gate 						      ex.getMessage()});
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 		}
3100Sstevel@tonic-gate 	    }
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	    // Remove the lock for this request. We do this just before the
3130Sstevel@tonic-gate 	    //  run() method exits and the thread expires to reduce the
3140Sstevel@tonic-gate 	    //  window in which a new copy of the request could come in.
3150Sstevel@tonic-gate 	    //  We need to be sure that we only remove if it is this
3160Sstevel@tonic-gate 	    //  request handler.
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	    synchronized (inProgress) {
3190Sstevel@tonic-gate 		RequestHandler rh =
3200Sstevel@tonic-gate 		    (RequestHandler)inProgress.get(syncTableKey);
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 		if (rh == this) {
3230Sstevel@tonic-gate 		    inProgress.remove(syncTableKey);
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 		}
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	    }
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate     }
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate     // Handle an incoming stream.
3340Sstevel@tonic-gate 
handleStream()3350Sstevel@tonic-gate     private void handleStream() {
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	try {
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	    DataInputStream dis = null;
3400Sstevel@tonic-gate 	    DataOutputStream dos = null;
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	    if (inStream != null) {
3430Sstevel@tonic-gate 		dis = new DataInputStream(inStream);
3440Sstevel@tonic-gate 		dos = new DataOutputStream(outStream);
3450Sstevel@tonic-gate 	    } else {
3460Sstevel@tonic-gate 		// use the socket
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 		dis = new DataInputStream(sock.getInputStream());
3490Sstevel@tonic-gate 		dos = new DataOutputStream(sock.getOutputStream());
3500Sstevel@tonic-gate 	    }
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	    // Loop while the client still wants to send something. But we
3530Sstevel@tonic-gate 	    //  only read one SLP message at a time on the connection,
3540Sstevel@tonic-gate 	    //  returning if it there are no more bytes to read. Note that
3550Sstevel@tonic-gate 	    //  we have to use a do/while loop here so that the read hangs
3560Sstevel@tonic-gate 	    //  until something shows up.
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 	    do {
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 		// Handle the new request.
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 		ByteArrayOutputStream baos = new ByteArrayOutputStream();
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 		boolean parseError = handleRequest(dis, baos, true);
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 		dos.write(baos.toByteArray(), 0, baos.size());
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 		// Forward reg or dereg to foreign DAs that need to know
3690Sstevel@tonic-gate 		//  about it.
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 		if (toForward != null) {
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 		    try {
3740Sstevel@tonic-gate 			daTable.forwardSAMessage(toForward, clientAddr);
3750Sstevel@tonic-gate 			toForward = null;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 		    } catch (ServiceLocationException ex) {
3780Sstevel@tonic-gate 			config.writeLog("sa_forwarding_exception",
3790Sstevel@tonic-gate 					new Object[] {
3800Sstevel@tonic-gate 			    new Short(ex.getErrorCode()),
3810Sstevel@tonic-gate 				Integer.toHexString(toForward.getHeader().xid),
3820Sstevel@tonic-gate 				ex.getMessage()});
3830Sstevel@tonic-gate 		    }
3840Sstevel@tonic-gate 		}
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		// If there was a parse error, then break out and close the
3870Sstevel@tonic-gate 		//  stream, because it may have lingering bytes.
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 		if (parseError && config.traceMsg()) {
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 		    config.writeLog("rh_tcp_error",
3920Sstevel@tonic-gate 				    new Object[] {clientAddr,
3930Sstevel@tonic-gate 						      new Integer(port),
3940Sstevel@tonic-gate 						      interfac});
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 		    break;
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 		}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	    } while (true);
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	} catch (EOFException ex) {
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	    if (config.traceMsg()) {
4050Sstevel@tonic-gate 		config.writeLog("rh_socket_closed",
4060Sstevel@tonic-gate 				new Object[] {clientAddr,
4070Sstevel@tonic-gate 						  new Integer(port),
4080Sstevel@tonic-gate 						  interfac});
4090Sstevel@tonic-gate 	    }
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	} catch (IOException ex) {
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	    // An error occured during input.
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	    if (config.traceDrop()) {
4170Sstevel@tonic-gate 		config.writeLog("ioexception_server_stream",
4180Sstevel@tonic-gate 				new Object[] {clientAddr,
4190Sstevel@tonic-gate 						  new Integer(port),
4200Sstevel@tonic-gate 						  interfac,
4210Sstevel@tonic-gate 						  ex.getMessage()});
4220Sstevel@tonic-gate 	    }
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	}
4250Sstevel@tonic-gate     }
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate     // Send a byte buffer reply through a datagram socket.
4280Sstevel@tonic-gate 
sendDatagramReply(byte[] outbuf)4290Sstevel@tonic-gate     private void sendDatagramReply(byte[] outbuf) {
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	DatagramSocket ds = null;
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	try {
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	    // Open the socket.
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	    ds = new DatagramSocket();
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	    // Format the outgoing packet.
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	    DatagramPacket dpOut =
4420Sstevel@tonic-gate 		new DatagramPacket(outbuf, outbuf.length, clientAddr, port);
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	    // Send the reply.
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 	    ds.send(dpOut);
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	    // Forward reg or dereg to foreign DAs that need to know about it.
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	    if (toForward != null) {
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 		try {
4530Sstevel@tonic-gate 		    daTable.forwardSAMessage(toForward, clientAddr);
4540Sstevel@tonic-gate 		    toForward = null;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 		} catch (ServiceLocationException ex) {
4570Sstevel@tonic-gate 		    config.writeLog("sle_forward_error",
4580Sstevel@tonic-gate 			  new Object[] {
4590Sstevel@tonic-gate 			new Integer(ex.getErrorCode()),
4600Sstevel@tonic-gate 			    Integer.toHexString(toForward.getHeader().xid),
4610Sstevel@tonic-gate 			    ex.getMessage()});
4620Sstevel@tonic-gate 		}
4630Sstevel@tonic-gate 	    }
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	} catch (SocketException ex) {
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	    // Failure in reply.
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	    if (config.traceDrop()) {
4700Sstevel@tonic-gate 		config.writeLog("rh_socket_error",
4710Sstevel@tonic-gate 				new Object[] {clientAddr,
4720Sstevel@tonic-gate 						  new Integer(port),
4730Sstevel@tonic-gate 						  interfac,
4740Sstevel@tonic-gate 						  ex.getMessage()});
4750Sstevel@tonic-gate 	    }
4760Sstevel@tonic-gate 	} catch (IOException ex) {
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	    // Failure in reply.
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	    if (config.traceDrop()) {
4810Sstevel@tonic-gate 		config.writeLog(
4820Sstevel@tonic-gate 				"rh_ioexception_reply",
4830Sstevel@tonic-gate 				new Object[] {clientAddr,
4840Sstevel@tonic-gate 						  new Integer(port),
4850Sstevel@tonic-gate 						  interfac,
4860Sstevel@tonic-gate 						  ex.getMessage()});
4870Sstevel@tonic-gate 	    }
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	} finally {
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	    if (ds != null) {
4920Sstevel@tonic-gate 		ds.close();
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	    }
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 	}
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate     }
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate     // Handle an incoming stream containing an SLP request.
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate     private boolean
handleRequest(DataInputStream dis, ByteArrayOutputStream baos, boolean isTCP)5030Sstevel@tonic-gate 	handleRequest(DataInputStream dis,
5040Sstevel@tonic-gate 		      ByteArrayOutputStream baos,
5050Sstevel@tonic-gate 		      boolean isTCP)
5060Sstevel@tonic-gate 	throws IOException {
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	boolean parseError = false;
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate 	// Decode the message.
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	SrvLocMsg msg = internalize(dis, isTCP);
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	// If there was an error converting the request, then don't
5150Sstevel@tonic-gate 	// process further.
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	SrvLocMsg rply = msg;
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	if (msg != null) {
5200Sstevel@tonic-gate 	    SrvLocHeader hdr = msg.getHeader();
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	    if (hdr.errCode == ServiceLocationException.OK) {
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 		if (config.traceMsg()) {
5250Sstevel@tonic-gate 		    config.writeLog("rh_rqst_in",
5260Sstevel@tonic-gate 				    new Object[] {Integer.toHexString(hdr.xid),
5270Sstevel@tonic-gate 						      clientAddr,
5280Sstevel@tonic-gate 						      new Integer(port),
5290Sstevel@tonic-gate 						      interfac,
5300Sstevel@tonic-gate 						      msg.getHeader()});
5310Sstevel@tonic-gate 		}
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 		// Dispatch the message to the service table.
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 		rply = dispatch(msg);
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 		// If no reply, then simply return.
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 		if (rply == null) {
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 		    if (config.traceMsg()) {
5430Sstevel@tonic-gate 			config.writeLog("rh_rply_null",
5440Sstevel@tonic-gate 					new Object[] {
5450Sstevel@tonic-gate 			    Integer.toHexString(hdr.xid),
5460Sstevel@tonic-gate 				clientAddr,
5470Sstevel@tonic-gate 				new Integer(port),
5480Sstevel@tonic-gate 				interfac});
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 		    }
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 		    return parseError;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 		}
5550Sstevel@tonic-gate 	    } else {
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 		// Drop if multicast.
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 		if (msg.getHeader().mcast) {
5600Sstevel@tonic-gate 		    rply = null;
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 		    if (config.traceDrop()) {
5630Sstevel@tonic-gate 			config.writeLog("rh_multi_error",
5640Sstevel@tonic-gate 					new Object[] {
5650Sstevel@tonic-gate 			    msg.getClass().getName(),
5660Sstevel@tonic-gate 				Integer.toHexString(hdr.xid),
5670Sstevel@tonic-gate 				clientAddr,
5680Sstevel@tonic-gate 				new Integer(port),
5690Sstevel@tonic-gate 				interfac});
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 		    }
5730Sstevel@tonic-gate 		} else if (isTCP) {
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 		    // Set the parse error flag so that the stream gets closed.
5760Sstevel@tonic-gate 		    //  It's easier than trying to keep track of the number of
5770Sstevel@tonic-gate 		    //  bytes read. Otherwise, the remnents of the message
5780Sstevel@tonic-gate 		    //  hang around.
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 		    parseError = true;
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 		}
5830Sstevel@tonic-gate 	    }
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	// Reply to the client if necessary. Note that if the reply is null
5870Sstevel@tonic-gate 	//  here, there was a problem parsing the message in and so formulating
5880Sstevel@tonic-gate 	//  a reply may be impossible (for example, the message may not
5890Sstevel@tonic-gate 	//  be parsable beyond the function code.
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	if (rply != null) {
5920Sstevel@tonic-gate 	    SrvLocHeader hdr = rply.getHeader();
5930Sstevel@tonic-gate 	    ServiceLocationException ex = null;
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	    // Parse out the message.
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	    try {
5980Sstevel@tonic-gate 		hdr.externalize(baos, false, isTCP);
5990Sstevel@tonic-gate 	    } catch (ServiceLocationException sle) {
6000Sstevel@tonic-gate 		ex = sle;
6010Sstevel@tonic-gate 	    }
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	    if (config.traceMsg()) {
6040Sstevel@tonic-gate 		config.writeLog("rh_rply_out",
6050Sstevel@tonic-gate 				new Object[] {Integer.toHexString(hdr.xid),
6060Sstevel@tonic-gate 						  clientAddr,
6070Sstevel@tonic-gate 						  new Integer(port),
6080Sstevel@tonic-gate 						  interfac,
6090Sstevel@tonic-gate 						  rply.getHeader()});
6100Sstevel@tonic-gate 	    }
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	    if (ex != null) {
6130Sstevel@tonic-gate 		baos.reset();
6140Sstevel@tonic-gate 		rply = hdr.makeErrorReply(ex);
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 		Assert.slpassert(msg != null,
6170Sstevel@tonic-gate 			      "rh_header_class_error",
6180Sstevel@tonic-gate 			      new Object[] {ex.getMessage()});
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 		hdr = rply.getHeader();
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 		try {
6230Sstevel@tonic-gate 		    hdr.externalize(baos, false, isTCP);
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 		} catch (ServiceLocationException exx) {
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 		}
6280Sstevel@tonic-gate 	    }
6290Sstevel@tonic-gate 	} else if (config.traceMsg()) {
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	    // Print error message.
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	    String xidStr = "<null message>";
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 	    if (msg != null) {
6360Sstevel@tonic-gate 		SrvLocHeader hdr = msg.getHeader();
6370Sstevel@tonic-gate 		xidStr = Integer.toHexString(hdr.xid);
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate 	    }
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	    config.writeLog("rh_rply_null",
6420Sstevel@tonic-gate 			    new Object[] {xidStr,
6430Sstevel@tonic-gate 					      clientAddr,
6440Sstevel@tonic-gate 					      new Integer(port),
6450Sstevel@tonic-gate 					      interfac});
6460Sstevel@tonic-gate 	}
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	return parseError;
6490Sstevel@tonic-gate     }
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate     /**
6520Sstevel@tonic-gate      * Internalize the byte array in the input stream into a SrvLocMsg
6530Sstevel@tonic-gate      * subclass. It will be an appropriate subclass for the SA/DA.
6540Sstevel@tonic-gate      *
6550Sstevel@tonic-gate      * @param dis The input stream containing the packet.
6560Sstevel@tonic-gate      * @param viaTCP True if the outgoing stream is via TCP.
6570Sstevel@tonic-gate      * @return The right SrvLocMsg subclass appropriate for the SA/DA.
6580Sstevel@tonic-gate      *		If null is returned, it means that the function code was
6590Sstevel@tonic-gate      *		not recognized.
6600Sstevel@tonic-gate      *		If any error occurs during creation, an error request is
6610Sstevel@tonic-gate      *		returned with the error code set.
6620Sstevel@tonic-gate      */
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate     private SrvLocMsg
internalize(DataInputStream dis, boolean viaTCP)6650Sstevel@tonic-gate 	internalize(DataInputStream dis, boolean viaTCP) throws IOException {
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 	int ver = 0, fun = 0;
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 	Assert.slpassert((dis != null),
6700Sstevel@tonic-gate 		      "rh_null_bais",
6710Sstevel@tonic-gate 		      new Object[0]);
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 	try {
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 	    // Pull off the version number and function code.
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 	    byte[] b = new byte[2];
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	    dis.readFully(b, 0, 2);
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	    ver = (int) ((char)b[0] & 0XFF);
6820Sstevel@tonic-gate 	    fun = (int) ((char)b[1] & 0XFF);
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 	} catch (IOException ex) {
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	    // Print an error message, but only if not EOF.
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 	    if (!(ex instanceof EOFException)) {
6890Sstevel@tonic-gate 		printInternalizeErrorMessage(ver, fun, ex);
6900Sstevel@tonic-gate 
6910Sstevel@tonic-gate 	    }
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	    // Throw the exception, so streams can terminate.
6940Sstevel@tonic-gate 
6950Sstevel@tonic-gate 	    throw ex;
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 	SrvLocMsg msg = null;
7000Sstevel@tonic-gate 	SrvLocHeader hdr = null;
7010Sstevel@tonic-gate 
7020Sstevel@tonic-gate 	try {
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 	    hdr = SrvLocHeader.newInstance(ver);
7050Sstevel@tonic-gate 
7060Sstevel@tonic-gate 	    // Unrecognized version number if header not returned.
7070Sstevel@tonic-gate 	    //  We only throw an exception if the version number
7080Sstevel@tonic-gate 	    //  is greater than the current default version number.
7090Sstevel@tonic-gate 	    //  otherwise, the packet is from an earlier version
7100Sstevel@tonic-gate 	    //  of the protocol and should be ignored if we are
7110Sstevel@tonic-gate 	    //  not operating in compatibility mode.
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 	    if (hdr == null) {
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 		if (ver > Defaults.version ||
7160Sstevel@tonic-gate 		    (config.isV1Supported() && config.isDA())) {
7170Sstevel@tonic-gate 							// code problem...
7180Sstevel@tonic-gate 		    throw
7190Sstevel@tonic-gate 			new ServiceLocationException(
7200Sstevel@tonic-gate 				ServiceLocationException.VERSION_NOT_SUPPORTED,
7210Sstevel@tonic-gate 				"rh_version_number_error",
7220Sstevel@tonic-gate 				new Object[] {new Integer(ver),
7230Sstevel@tonic-gate 						  clientAddr,
7240Sstevel@tonic-gate 						  new Integer(port),
7250Sstevel@tonic-gate 						  interfac});
7260Sstevel@tonic-gate 		} else {
7270Sstevel@tonic-gate 		    return null;
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 		}
7300Sstevel@tonic-gate 	    }
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	    // If we've come via TCP, clear the packet length so the
7330Sstevel@tonic-gate 	    //  eventual reply won't be checked for overflow.
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 	    if (viaTCP) {
7360Sstevel@tonic-gate 		hdr.setPacketLength(Integer.MAX_VALUE);
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	    }
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	    // Parse the header.
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	    hdr.parseHeader(fun, dis);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	    // Parse body.
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	    if ((msg = hdr.parseMsg(dis)) != null) {
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 		// Parse options, if any.
7490Sstevel@tonic-gate 
7500Sstevel@tonic-gate 		hdr.parseOptions(dis);
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 	    }
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	} catch (Exception ex) {
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	    printInternalizeErrorMessage(ver, fun, ex);
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	    msg = null;
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate 	    // If this is a DAAdvert or an SAAdvert, or there's no header,
7610Sstevel@tonic-gate 	    //  return null cause we don't need to return anything or
7620Sstevel@tonic-gate 	    //  can't.
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate 	    if (fun != SrvLocHeader.DAAdvert &&
7650Sstevel@tonic-gate 		fun != SrvLocHeader.SAAdvert &&
7660Sstevel@tonic-gate 		hdr != null) {
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 		// Let header create message.
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 		msg = hdr.makeErrorReply(ex);
7710Sstevel@tonic-gate 
7720Sstevel@tonic-gate 	    }
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate 	}
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 	return msg;
7770Sstevel@tonic-gate     }
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate     // Print an error message for errors during internalization.
7800Sstevel@tonic-gate 
printInternalizeErrorMessage(int ver, int fun, Exception ex)7810Sstevel@tonic-gate     private void printInternalizeErrorMessage(int ver, int fun, Exception ex) {
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate 	if (config.traceDrop()) {
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	    StringWriter sw = new StringWriter();
7860Sstevel@tonic-gate 	    PrintWriter pw = new PrintWriter(sw);
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 	    ex.printStackTrace(pw);
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 	    short errCode = ServiceLocationException.INTERNAL_SYSTEM_ERROR;
7910Sstevel@tonic-gate 
7920Sstevel@tonic-gate 	    if (ex instanceof ServiceLocationException) {
7930Sstevel@tonic-gate 		errCode = ((ServiceLocationException)ex).getErrorCode();
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	    } else if (ex instanceof IllegalArgumentException) {
7960Sstevel@tonic-gate 		errCode = ServiceLocationException.PARSE_ERROR;
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	    }
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 	    String exMsg = "(" + errCode + "):" + ex.getMessage();
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	    config.writeLog("rh_unparse_exception",
8030Sstevel@tonic-gate 			    new Object[] {clientAddr,
8040Sstevel@tonic-gate 					      new Integer(port),
8050Sstevel@tonic-gate 					      interfac,
8060Sstevel@tonic-gate 					      new Integer(ver),
8070Sstevel@tonic-gate 					      new Integer(fun),
8080Sstevel@tonic-gate 					      exMsg,
8090Sstevel@tonic-gate 					      sw.toString()});
8100Sstevel@tonic-gate 	}
8110Sstevel@tonic-gate     }
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate     /**
8140Sstevel@tonic-gate      * Dispatch the service request object to the service table.
8150Sstevel@tonic-gate      * The SA table is used for the following:
8160Sstevel@tonic-gate      *
8170Sstevel@tonic-gate      * @param rqst Service request object.
8180Sstevel@tonic-gate      * @return A SrvLocMsg object to reply with, or null if no reply.
8190Sstevel@tonic-gate      */
8200Sstevel@tonic-gate 
dispatch(SrvLocMsg rqst)8210Sstevel@tonic-gate     SrvLocMsg dispatch(SrvLocMsg rqst) {
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
8240Sstevel@tonic-gate 	boolean mcast = hdr.mcast;
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate 	// Check CDAAdvert and CSAAdvert before we check the previous
8270Sstevel@tonic-gate 	//  responders list, because they don't have any.
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	if (rqst instanceof CDAAdvert) {  // DA advert...
8300Sstevel@tonic-gate 	    CDAAdvert msg = (CDAAdvert)rqst;
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate 	    // For V1, V2 messages know.
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	    msg.setIsUnsolicited(true);
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	    // If passive detection is off, ignore it, but only if it wasn't
8370Sstevel@tonic-gate 	    //  a signal to stop.
8380Sstevel@tonic-gate 
8390Sstevel@tonic-gate 	    if (!config.passiveDADetection() &&
8400Sstevel@tonic-gate 		msg.isUnsolicited() &&
8410Sstevel@tonic-gate 		!msg.isGoingDown()) {
8420Sstevel@tonic-gate 		if (config.traceDrop()) {
8430Sstevel@tonic-gate 		    config.writeLog("rh_passive_drop",
8440Sstevel@tonic-gate 				    new Object[] {msg.URL,
8450Sstevel@tonic-gate 						      hdr.scopes});
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 		}
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	    } else if (msg.isGoingDown() && msg.isUnsolicited() &&
8500Sstevel@tonic-gate 		       isLocalHostURL(msg.URL) && config.isDA()) {
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate 		// We've been asked to terminate.
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 		// Check scopes.
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 		Vector scopes = (Vector)hdr.scopes.clone();
8570Sstevel@tonic-gate 
8580Sstevel@tonic-gate 		DATable.filterScopes(scopes,
8590Sstevel@tonic-gate 				     config.getSAConfiguredScopes(), true);
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 		// If all scopes not equal, it isn't a shutdown message for us.
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 		if (scopes.size() > 0) {
8640Sstevel@tonic-gate 		    daTable.handleAdvertIn(msg);
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 		} else {
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 		    Vector discoveredScopes = new Vector();
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 		    try {
8710Sstevel@tonic-gate 			discoveredScopes = daTable.findScopes();
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 		    } catch (ServiceLocationException ex) {
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate 			// Ignore, we're going down anyway and it's
8760Sstevel@tonic-gate 			// just a report.
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 		    }
8790Sstevel@tonic-gate 
8800Sstevel@tonic-gate 		    // It is a shutdown message for us.
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 		    Vector serverScopes = config.getSAConfiguredScopes();
8830Sstevel@tonic-gate 		    Vector interfaces = config.getInterfaces();
8840Sstevel@tonic-gate 		    Vector daAttributes = config.getDAAttributes();
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 		    if (config.traceAll() ||
8870Sstevel@tonic-gate 			config.traceMsg() ||
8880Sstevel@tonic-gate 			config.traceDrop() ||
8890Sstevel@tonic-gate 			config.traceDATraffic()) {
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 			config.writeLog("goodby_da",
8920Sstevel@tonic-gate 					new Object[] {interfaces,
8930Sstevel@tonic-gate 							  serverScopes,
8940Sstevel@tonic-gate 							  discoveredScopes,
8950Sstevel@tonic-gate 							  daAttributes});
8960Sstevel@tonic-gate 		    }
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate 		    // We don't reply, which means that the client will
9000Sstevel@tonic-gate 		    // time out.
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 		    System.exit(0);
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 		}
9050Sstevel@tonic-gate 	    } else {
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 		// The implementation specific DA table handles this.
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 		daTable.handleAdvertIn(msg);
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 	    }
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	    return null;
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 	} else if (rqst instanceof CSAAdvert) {// SA advert...
9160Sstevel@tonic-gate 	    CSAAdvert msg = (CSAAdvert)rqst;
9170Sstevel@tonic-gate 
9180Sstevel@tonic-gate 	    // We are only interested in it if we may be going down.
9190Sstevel@tonic-gate 
9200Sstevel@tonic-gate 	    if ((hdr.xid == 0) && isLocalHostURL(msg.URL) && !config.isDA()) {
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 		// Check scopes.
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 		Vector scopes = (Vector)hdr.scopes.clone();
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 		DATable.filterScopes(scopes,
9270Sstevel@tonic-gate 				     config.getSAConfiguredScopes(), true);
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate 		// If all scopes not equal, it isn't a shutdown message for us.
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 		if (scopes.size() <= 0) {
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate 		    Vector discoveredScopes = new Vector();
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 		    try {
9360Sstevel@tonic-gate 			discoveredScopes = daTable.findScopes();
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate 		    } catch (ServiceLocationException ex) {
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 			// Ignore, we're going down anyway and it's just a
9410Sstevel@tonic-gate 			// report.
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 		    }
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 		    // It is a shutdown message for us.
9460Sstevel@tonic-gate 
9470Sstevel@tonic-gate 		    Vector serverScopes = config.getSAConfiguredScopes();
9480Sstevel@tonic-gate 		    Vector interfaces = config.getInterfaces();
9490Sstevel@tonic-gate 		    Vector saAttributes = config.getSAAttributes();
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 		    if (config.traceAll() ||
9520Sstevel@tonic-gate 			config.traceMsg() ||
9530Sstevel@tonic-gate 			config.traceDrop() ||
9540Sstevel@tonic-gate 			config.traceDATraffic()) {
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate 			config.writeLog("goodby",
9570Sstevel@tonic-gate 					new Object[] {interfaces,
9580Sstevel@tonic-gate 							  serverScopes,
9590Sstevel@tonic-gate 							  discoveredScopes,
9600Sstevel@tonic-gate 							  saAttributes});
9610Sstevel@tonic-gate 		    }
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 		    System.exit(0);
9640Sstevel@tonic-gate 		}
9650Sstevel@tonic-gate 	    }
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	    // Otherwise, drop it for now.
9680Sstevel@tonic-gate 
9690Sstevel@tonic-gate 	    if (config.traceDrop()) {
9700Sstevel@tonic-gate 		config.writeLog("rh_client_sa_advert_drop",
9710Sstevel@tonic-gate 				new Object[] {Integer.toHexString(hdr.xid),
9720Sstevel@tonic-gate 						  clientAddr,
9730Sstevel@tonic-gate 						  new Integer(port),
9740Sstevel@tonic-gate 						  interfac});
9750Sstevel@tonic-gate 	    }
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	    return null;
9780Sstevel@tonic-gate 
9790Sstevel@tonic-gate 	}
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 	if (rqst instanceof SSrvReg) { // registration...
9820Sstevel@tonic-gate 
9830Sstevel@tonic-gate 	    return dispatchReg((SSrvReg)rqst,
9840Sstevel@tonic-gate 			       serviceTable);
9850Sstevel@tonic-gate 
9860Sstevel@tonic-gate 	} else if (rqst instanceof SSrvDereg) { // deregistration...
9870Sstevel@tonic-gate 
9880Sstevel@tonic-gate 	    return dispatchDereg((SSrvDereg)rqst,
9890Sstevel@tonic-gate 				 serviceTable);
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	}
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 	// If we are on the previous responder list, then ignore this
9950Sstevel@tonic-gate 	//  request.
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	if (isPreviousResponder(hdr)) {
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 	    if (config.traceDrop()) {
10000Sstevel@tonic-gate 		config.writeLog("rh_prev_resp",
10010Sstevel@tonic-gate 				new Object[] {Integer.toHexString(hdr.xid),
10020Sstevel@tonic-gate 						  clientAddr,
10030Sstevel@tonic-gate 						  new Integer(port),
10040Sstevel@tonic-gate 						  interfac});
10050Sstevel@tonic-gate 	    }
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 	    return null;
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate 	}
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 	// Now check requests with previous responders.
10120Sstevel@tonic-gate 
10130Sstevel@tonic-gate 	if (rqst instanceof SSrvTypeMsg) {	// service types...
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 	    return dispatchSrvType((SSrvTypeMsg)rqst,
10160Sstevel@tonic-gate 				   serviceTable);
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate 	} else if (rqst instanceof SAttrMsg) { // attributes...
10190Sstevel@tonic-gate 
10200Sstevel@tonic-gate 	    return dispatchAttr((SAttrMsg)rqst,
10210Sstevel@tonic-gate 				serviceTable);
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	} else if (rqst instanceof SSrvMsg) { // services...
10240Sstevel@tonic-gate 
10250Sstevel@tonic-gate 	    return dispatchSrv((SSrvMsg)rqst,
10260Sstevel@tonic-gate 			       serviceTable);
10270Sstevel@tonic-gate 
10280Sstevel@tonic-gate 	} else {				    // error...
10290Sstevel@tonic-gate 
10300Sstevel@tonic-gate 	    Assert.slpassert(false,
10310Sstevel@tonic-gate 			  "rh_rqst_type_err",
10320Sstevel@tonic-gate 			  new Object[] {rqst});
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	}
10350Sstevel@tonic-gate 
10360Sstevel@tonic-gate 	return null;
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate     }
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate     // Dispatch a service registration.
10420Sstevel@tonic-gate 
dispatchReg(SSrvReg rqst, ServiceTable serviceTable)10430Sstevel@tonic-gate     private SrvLocMsg dispatchReg(SSrvReg rqst,
10440Sstevel@tonic-gate 				  ServiceTable serviceTable) {
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	// Report error if the message was multicast.
10490Sstevel@tonic-gate 
10500Sstevel@tonic-gate 	if (hdr.mcast && config.traceDrop()) {
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate 	    if (config.traceDrop()) {
10530Sstevel@tonic-gate 		config.writeLog("rh_no_multi",
10540Sstevel@tonic-gate 				new Object[] {"SrvReg",
10550Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
10560Sstevel@tonic-gate 						  clientAddr,
10570Sstevel@tonic-gate 						  new Integer(port),
10580Sstevel@tonic-gate 						  interfac});
10590Sstevel@tonic-gate 	    }
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	    return null;
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 	}
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	// Register the request.
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	SrvLocMsg rply = serviceTable.register(rqst);
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 	// Forward to foreign DAs if no error.
10700Sstevel@tonic-gate 
10710Sstevel@tonic-gate 	if (rply != null) {
10720Sstevel@tonic-gate 	    hdr = rply.getHeader();
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 	    if (hdr.errCode == ServiceLocationException.OK) {
10750Sstevel@tonic-gate 		toForward = rqst;
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	    }
10780Sstevel@tonic-gate 	}
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 	return rply;
10810Sstevel@tonic-gate     }
10820Sstevel@tonic-gate 
10830Sstevel@tonic-gate     // Dispatch a service deregistration.
10840Sstevel@tonic-gate 
dispatchDereg(SSrvDereg rqst, ServiceTable serviceTable)10850Sstevel@tonic-gate     private SrvLocMsg dispatchDereg(SSrvDereg rqst,
10860Sstevel@tonic-gate 				    ServiceTable serviceTable) {
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	// Report error if the message was multicast.
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 	if (hdr.mcast && config.traceDrop()) {
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 	    if (config.traceDrop()) {
10950Sstevel@tonic-gate 		config.writeLog("rh_no_multi",
10960Sstevel@tonic-gate 				new Object[] {"SrvDereg",
10970Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
10980Sstevel@tonic-gate 						  clientAddr,
10990Sstevel@tonic-gate 						  new Integer(port),
11000Sstevel@tonic-gate 						  interfac});
11010Sstevel@tonic-gate 	    }
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	    return null;
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	}
11060Sstevel@tonic-gate 
11070Sstevel@tonic-gate 	// If the message came from the local host, use the SA store.
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 	SrvLocMsg rply = serviceTable.deregister(rqst);
11100Sstevel@tonic-gate 
11110Sstevel@tonic-gate 	// Forward to foreign DAs if no error.
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate 	if (rply != null) {
11140Sstevel@tonic-gate 	    hdr = rply.getHeader();
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	    if (hdr.errCode == ServiceLocationException.OK) {
11170Sstevel@tonic-gate 		toForward = rqst;
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	    }
11200Sstevel@tonic-gate 	}
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	return rply;
11230Sstevel@tonic-gate     }
11240Sstevel@tonic-gate 
11250Sstevel@tonic-gate     // Dispatch a service type message.
11260Sstevel@tonic-gate 
dispatchSrvType(SSrvTypeMsg rqst, ServiceTable serviceTable)11270Sstevel@tonic-gate     private SrvLocMsg dispatchSrvType(SSrvTypeMsg rqst,
11280Sstevel@tonic-gate 				      ServiceTable serviceTable) {
11290Sstevel@tonic-gate 
11300Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
11310Sstevel@tonic-gate 	boolean mcast = hdr.mcast;
11320Sstevel@tonic-gate 
11330Sstevel@tonic-gate 	// Drop if this is a DA and the request was multicast. DAs
11340Sstevel@tonic-gate 	//  do not respond to multicast, except for DAAdverts.
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate 	if (mcast && config.isDA()) {
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate 	    if (config.traceDrop()) {
11390Sstevel@tonic-gate 		config.writeLog("rh_drop_da_multi",
11400Sstevel@tonic-gate 				new Object[] {"SrvTypeRqst",
11410Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
11420Sstevel@tonic-gate 						  clientAddr,
11430Sstevel@tonic-gate 						  new Integer(port),
11440Sstevel@tonic-gate 						  interfac});
11450Sstevel@tonic-gate 	    }
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	    return null;
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 	}
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 	SrvLocMsg rply = serviceTable.findServiceTypes(rqst);
11520Sstevel@tonic-gate 	hdr = rply.getHeader();
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	// Filter multicast replies to remove null and error returns.
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 	if (mcast &&
11570Sstevel@tonic-gate 	    ((hdr.errCode != ServiceLocationException.OK) ||
11580Sstevel@tonic-gate 	    (hdr.getNumReplies() == 0))) {
11590Sstevel@tonic-gate 
11600Sstevel@tonic-gate 	    if (config.traceDrop()) {
11610Sstevel@tonic-gate 		config.writeLog("rh_multi_error",
11620Sstevel@tonic-gate 				new Object[] {"SrvTypeRqst",
11630Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
11640Sstevel@tonic-gate 						  clientAddr,
11650Sstevel@tonic-gate 						  new Integer(port),
11660Sstevel@tonic-gate 						  interfac});
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 
11690Sstevel@tonic-gate 	    }
11700Sstevel@tonic-gate 
11710Sstevel@tonic-gate 	    return null;
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 	}
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 	return rply;
11760Sstevel@tonic-gate     }
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate     // Dispatch an attribute request.
11790Sstevel@tonic-gate 
dispatchAttr(SAttrMsg rqst, ServiceTable serviceTable)11800Sstevel@tonic-gate     private SrvLocMsg dispatchAttr(SAttrMsg rqst,
11810Sstevel@tonic-gate 				   ServiceTable serviceTable) {
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
11840Sstevel@tonic-gate 	boolean mcast = hdr.mcast;
11850Sstevel@tonic-gate 
11860Sstevel@tonic-gate 	// Drop if this is a DA and the request was multicast. DAs
11870Sstevel@tonic-gate 	//  do not respond to multicast, except for DAAdverts.
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	if (mcast && config.isDA()) {
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	    if (config.traceDrop()) {
11920Sstevel@tonic-gate 		config.writeLog("rh_drop_da_multi",
11930Sstevel@tonic-gate 				new Object[] {"AttrRqst",
11940Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
11950Sstevel@tonic-gate 						  clientAddr,
11960Sstevel@tonic-gate 						  new Integer(port),
11970Sstevel@tonic-gate 						  interfac});
11980Sstevel@tonic-gate 	    }
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 	    return null;
12010Sstevel@tonic-gate 
12020Sstevel@tonic-gate 	}
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate 	SrvLocMsg rply = serviceTable.findAttributes(rqst);
12050Sstevel@tonic-gate 	hdr = rply.getHeader();
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	// Filter multicast replies to remove null and error returns.
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate 	if (mcast &&
12100Sstevel@tonic-gate 	    ((hdr.errCode != ServiceLocationException.OK) ||
12110Sstevel@tonic-gate 	    (hdr.getNumReplies() == 0))) {
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 	    if (config.traceDrop()) {
12140Sstevel@tonic-gate 		config.writeLog("rh_multi_error",
12150Sstevel@tonic-gate 				new Object[] {"AttrRqst",
12160Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
12170Sstevel@tonic-gate 						  clientAddr,
12180Sstevel@tonic-gate 						  new Integer(port),
12190Sstevel@tonic-gate 						  interfac});
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate 	    }
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 	    return null;
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 	}
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 	return rply;
12280Sstevel@tonic-gate     }
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate     // Dispatch a service request.
12310Sstevel@tonic-gate 
dispatchSrv(SSrvMsg rqst, ServiceTable serviceTable)12320Sstevel@tonic-gate     private SrvLocMsg dispatchSrv(SSrvMsg rqst,
12330Sstevel@tonic-gate 				  ServiceTable serviceTable) {
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
12360Sstevel@tonic-gate 	boolean mcast = hdr.mcast;
12370Sstevel@tonic-gate 	String serviceType = rqst.serviceType;
12380Sstevel@tonic-gate 	SrvLocMsg rply = null;
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	// We need to special case if this is a request for a DAAdvert
12410Sstevel@tonic-gate 	//  and we are a DA or an SAAdvert and we are an SA only.
12420Sstevel@tonic-gate 
12430Sstevel@tonic-gate 	if (serviceType.equals(Defaults.DA_SERVICE_TYPE.toString())) {
12440Sstevel@tonic-gate 
12450Sstevel@tonic-gate 	    // Reply only if a DA.
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate 	    if (config.isDA()) {
12480Sstevel@tonic-gate 
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 		// Return a DAAdvert for this DA.
12510Sstevel@tonic-gate 
12520Sstevel@tonic-gate 		rply = serviceTable.makeDAAdvert(rqst,
12530Sstevel@tonic-gate 						 interfac,
12540Sstevel@tonic-gate 						 config);
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 		hdr = rply.getHeader();
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 		if ((hdr.errCode != ServiceLocationException.OK) &&
12590Sstevel@tonic-gate 		    config.traceMsg()) {
12600Sstevel@tonic-gate 		    config.writeLog("rh_advert_error",
12610Sstevel@tonic-gate 				    new Object[] { new Integer(hdr.errCode),
12620Sstevel@tonic-gate 						       "DAAdvert",
12630Sstevel@tonic-gate 						       ""});
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 		}
12660Sstevel@tonic-gate 	    }
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate 	    // If there was an error and the request was multicast, drop it
12690Sstevel@tonic-gate 	    //  by returning null.
12700Sstevel@tonic-gate 
12710Sstevel@tonic-gate 	    if (hdr.errCode != ServiceLocationException.OK &&
12720Sstevel@tonic-gate 		mcast) {
12730Sstevel@tonic-gate 
12740Sstevel@tonic-gate 		if (config.traceDrop()) {
12750Sstevel@tonic-gate 
12760Sstevel@tonic-gate 		    config.writeLog("rh_drop_srv",
12770Sstevel@tonic-gate 				    new Object[] {
12780Sstevel@tonic-gate 			"DA SrvRqst",
12790Sstevel@tonic-gate 			    Integer.toHexString(hdr.xid),
12800Sstevel@tonic-gate 			    clientAddr,
12810Sstevel@tonic-gate 			    new Integer(port),
12820Sstevel@tonic-gate 			    interfac});
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 		}
12850Sstevel@tonic-gate 
12860Sstevel@tonic-gate 		return null;
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 	    }
12890Sstevel@tonic-gate 
12900Sstevel@tonic-gate 	    return rply;
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 	} else if (serviceType.equals(Defaults.SA_SERVICE_TYPE.toString())) {
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 	    // Note that we reply if we are a DA because somebody may want
12950Sstevel@tonic-gate 	    //  SA attributes.
12960Sstevel@tonic-gate 
12970Sstevel@tonic-gate 	    // We report error for unicast SA service request.
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate 	    if (!mcast) {
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 		if (config.traceDrop()) {
13020Sstevel@tonic-gate 
13030Sstevel@tonic-gate 		    config.writeLog("rh_no_srv_uni",
13040Sstevel@tonic-gate 				    new Object[] {
13050Sstevel@tonic-gate 			"SA SrvRqst",
13060Sstevel@tonic-gate 			    Integer.toHexString(hdr.xid),
13070Sstevel@tonic-gate 			    clientAddr,
13080Sstevel@tonic-gate 			    new Integer(port),
13090Sstevel@tonic-gate 			    interfac});
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 		}
13120Sstevel@tonic-gate 
13130Sstevel@tonic-gate 		return null;
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate 	    }
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 	    // Return a SAAdvert for this SA.
13180Sstevel@tonic-gate 
13190Sstevel@tonic-gate 	    try {
13200Sstevel@tonic-gate 		rply = serviceTable.makeSAAdvert(rqst,
13210Sstevel@tonic-gate 						 interfac,
13220Sstevel@tonic-gate 						 config);
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 	    } catch (ServiceLocationException ex) {
13250Sstevel@tonic-gate 		config.writeLog("rh_advert_error",
13260Sstevel@tonic-gate 				new Object [] {new Integer(ex.getErrorCode()),
13270Sstevel@tonic-gate 						   "SAAdvert",
13280Sstevel@tonic-gate 						   ex.getMessage()});
13290Sstevel@tonic-gate 
13300Sstevel@tonic-gate 	    }
13310Sstevel@tonic-gate 
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 	    if (rply == null && config.traceDrop()) {
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate 		config.writeLog("rh_drop_srv",
13360Sstevel@tonic-gate 				new Object[] {"SA SrvRqst",
13370Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
13380Sstevel@tonic-gate 						  clientAddr,
13390Sstevel@tonic-gate 						  new Integer(port),
13400Sstevel@tonic-gate 						  interfac});
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 	    }
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 	    return rply;
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate 	}
13470Sstevel@tonic-gate 
13480Sstevel@tonic-gate 	// Drop if this is a DA and the request was multicast. DAs
13490Sstevel@tonic-gate 	//  do not respond to multicast, except for DAAdverts.
13500Sstevel@tonic-gate 
13510Sstevel@tonic-gate 	if (mcast && config.isDA()) {
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	    if (config.traceDrop()) {
13540Sstevel@tonic-gate 		config.writeLog("rh_drop_da_multi",
13550Sstevel@tonic-gate 				new Object[] {"SrvRqst",
13560Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
13570Sstevel@tonic-gate 						  clientAddr,
13580Sstevel@tonic-gate 						  new Integer(port),
13590Sstevel@tonic-gate 						  interfac});
13600Sstevel@tonic-gate 	    }
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate 	    return null;
13630Sstevel@tonic-gate 
13640Sstevel@tonic-gate 	}
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate 	SrvLocMsg smrply = serviceTable.findServices(rqst);
13670Sstevel@tonic-gate 	hdr = smrply.getHeader();
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 	// Filter multicast replies to remove null and error returns.
13700Sstevel@tonic-gate 
13710Sstevel@tonic-gate 	if (mcast &&
13720Sstevel@tonic-gate 	    ((hdr.errCode != ServiceLocationException.OK) ||
13730Sstevel@tonic-gate 	    (hdr.getNumReplies() == 0))) {
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 	    if (config.traceDrop()) {
13760Sstevel@tonic-gate 		config.writeLog("rh_multi_error",
13770Sstevel@tonic-gate 				new Object[] {"SrvRqst",
13780Sstevel@tonic-gate 						  Integer.toHexString(hdr.xid),
13790Sstevel@tonic-gate 						  clientAddr,
13800Sstevel@tonic-gate 						  new Integer(port),
13810Sstevel@tonic-gate 						  interfac});
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 	    }
13840Sstevel@tonic-gate 
13850Sstevel@tonic-gate 	    return null;
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate 	}
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 	return smrply;
13900Sstevel@tonic-gate     }
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate     // Return true if the host address matches one of the local interfaces.
13930Sstevel@tonic-gate 
isLocalHostURL(ServiceURL url)13940Sstevel@tonic-gate     boolean isLocalHostURL(ServiceURL url) {
13950Sstevel@tonic-gate 	String hostAddr = url.getHost();
13960Sstevel@tonic-gate 	Vector interfaces = config.getInterfaces();
13970Sstevel@tonic-gate 	InetAddress addr = null;
13980Sstevel@tonic-gate 
13990Sstevel@tonic-gate 	try {
14000Sstevel@tonic-gate 	    addr = InetAddress.getByName(hostAddr);
14010Sstevel@tonic-gate 
14020Sstevel@tonic-gate 	} catch (UnknownHostException ex) {
14030Sstevel@tonic-gate 
14040Sstevel@tonic-gate 	    // We simply ignore it.
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 	    return false;
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate 	}
14090Sstevel@tonic-gate 
14100Sstevel@tonic-gate 	if (interfaces.contains(addr)) {
14110Sstevel@tonic-gate 	    return true;
14120Sstevel@tonic-gate 
14130Sstevel@tonic-gate 	}
14140Sstevel@tonic-gate 
14150Sstevel@tonic-gate 	return false;
14160Sstevel@tonic-gate     }
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate     /**
14190Sstevel@tonic-gate      * Return whether this was previous responder. Only do so if the
14200Sstevel@tonic-gate      * request was multicast.
14210Sstevel@tonic-gate      *
14220Sstevel@tonic-gate      * @return True if this host was a previous responder.
14230Sstevel@tonic-gate      */
14240Sstevel@tonic-gate 
isPreviousResponder(SrvLocHeader hdr)14250Sstevel@tonic-gate     public boolean isPreviousResponder(SrvLocHeader hdr) {
14260Sstevel@tonic-gate 
14270Sstevel@tonic-gate 	// If there are no previous responders, then return false,
14280Sstevel@tonic-gate 	//  because they aren't used for this message. Also for
14290Sstevel@tonic-gate 	//  messages that are not multicast.
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 	if ((hdr.previousResponders == null) ||
14320Sstevel@tonic-gate 	    (hdr.mcast == false)) {
14330Sstevel@tonic-gate 	    return false;
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate 	}
14360Sstevel@tonic-gate 
14370Sstevel@tonic-gate 	Vector previousResponders = hdr.previousResponders;
14380Sstevel@tonic-gate 	Enumeration e = null;
14390Sstevel@tonic-gate 	Vector interfaces = config.getInterfaces();
14400Sstevel@tonic-gate 
14410Sstevel@tonic-gate 	// Check for matches against this address.
14420Sstevel@tonic-gate 
14430Sstevel@tonic-gate 	for (e = previousResponders.elements(); e.hasMoreElements(); ) {
14440Sstevel@tonic-gate 	    try {
14450Sstevel@tonic-gate 		String sHost = ((String)e.nextElement());
14460Sstevel@tonic-gate 		InetAddress iaHost = InetAddress.getByName(sHost);
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 		if (interfaces.contains(iaHost)) {
14490Sstevel@tonic-gate 		    return true;
14500Sstevel@tonic-gate 		}
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate 	    } catch (UnknownHostException ex) {
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 	    }
14550Sstevel@tonic-gate 	}
14560Sstevel@tonic-gate 
14570Sstevel@tonic-gate 	return false;
14580Sstevel@tonic-gate     }
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 
14610Sstevel@tonic-gate     // Initialize the SLPv2 header parser class when we are loaded.
14620Sstevel@tonic-gate 
14630Sstevel@tonic-gate     static {
14640Sstevel@tonic-gate 
SrvLocHeader.addHeaderClass(Defaults.DEFAULT_SERVER_HEADER_CLASS, Defaults.version)14650Sstevel@tonic-gate 	SrvLocHeader.addHeaderClass(Defaults.DEFAULT_SERVER_HEADER_CLASS,
14660Sstevel@tonic-gate 				    Defaults.version);
14670Sstevel@tonic-gate 
14680Sstevel@tonic-gate     }
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate }
1471