xref: /onnv-gate/usr/src/lib/libslp/javalib/com/sun/slp/ServerDATable.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 (c) 1999 by Sun Microsystems, Inc.
230Sstevel@tonic-gate  * All rights reserved.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate //  ServerDATable.java: Abstract class for DA Table in the DA/SA server.
280Sstevel@tonic-gate //  Author:           James Kempf
290Sstevel@tonic-gate //  Created On:       Wed May 20 08:30:46 1998
300Sstevel@tonic-gate //  Last Modified By: James Kempf
310Sstevel@tonic-gate //  Last Modified On: Tue Mar  9 12:36:37 1999
320Sstevel@tonic-gate //  Update Count:     124
330Sstevel@tonic-gate //
340Sstevel@tonic-gate 
350Sstevel@tonic-gate package com.sun.slp;
360Sstevel@tonic-gate 
370Sstevel@tonic-gate import java.util.*;
380Sstevel@tonic-gate import java.net.*;
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /**
410Sstevel@tonic-gate  * ServerDATable is an abstract class that provides the interface for DA
420Sstevel@tonic-gate  * and scope discovery, storage of DA information from incoming DAAdverts,
430Sstevel@tonic-gate  * and forwarding of registrations and deregistration to DAs having
440Sstevel@tonic-gate  * the same scopes. A variety of implementations are possible.
450Sstevel@tonic-gate  * The getServerDATable() method creates the right one from a subclass.
460Sstevel@tonic-gate  * We keep separate track of the superclass DA table and the server
470Sstevel@tonic-gate  * DA table so that these two classes can co-exist in the same JVM.
480Sstevel@tonic-gate  * Note that the code for forwarding registrations must keep track of
490Sstevel@tonic-gate  * only those registrations that were done on this host. It does this
500Sstevel@tonic-gate  * by saving the registrations as they come in. The forwarding code
510Sstevel@tonic-gate  * is optimized so that forwarding of a new message is fast, while
520Sstevel@tonic-gate  * forwarding of a message due to discovery of a new DA is somewhat
530Sstevel@tonic-gate  * slower. This helps assure that SA clients get good service.
540Sstevel@tonic-gate  *
550Sstevel@tonic-gate  * The ServerDATable also does active discovery for the SA server/DA,
560Sstevel@tonic-gate  * in a separate thread.
570Sstevel@tonic-gate  *
580Sstevel@tonic-gate  * @author James Kempf
590Sstevel@tonic-gate  */
600Sstevel@tonic-gate 
610Sstevel@tonic-gate abstract class ServerDATable extends DATable {
620Sstevel@tonic-gate 
630Sstevel@tonic-gate     // The active discovery object.
640Sstevel@tonic-gate 
650Sstevel@tonic-gate     protected static ActiveDiscoverer activeDiscoverer = null;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate     // The table of regs to forward. Keys are the reg URL and locale, values
680Sstevel@tonic-gate     //  are the SSrvReg objects.
690Sstevel@tonic-gate 
700Sstevel@tonic-gate     protected Hashtable forwardRegs = new Hashtable();
710Sstevel@tonic-gate 
720Sstevel@tonic-gate     // This acts as a guard protecting an non-initialized DA table:
730Sstevel@tonic-gate     //  If the DA Table hasn't been populated by active discovery yet,
740Sstevel@tonic-gate     //  other threads accessing the DA table will block on readyLock.
750Sstevel@tonic-gate     private static Object readyLock = new Object();
760Sstevel@tonic-gate 
770Sstevel@tonic-gate     // Keeps track of which DAs support which SPIs. The actual mapping
780Sstevel@tonic-gate     //  is DA InetAddress to LinkedList of SPI Strings. recordNewDA
790Sstevel@tonic-gate     //  populates this.
800Sstevel@tonic-gate     protected Hashtable daSPIsHash = new Hashtable();
810Sstevel@tonic-gate 
820Sstevel@tonic-gate     /**
830Sstevel@tonic-gate      * Get the right server DA table from the subclass.
840Sstevel@tonic-gate      *
850Sstevel@tonic-gate      * @return Table for handling DAs in the server.
860Sstevel@tonic-gate      */
870Sstevel@tonic-gate 
getServerDATable()880Sstevel@tonic-gate     static ServerDATable getServerDATable()
890Sstevel@tonic-gate 	throws ServiceLocationException {
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	ServerDATable table = null;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	synchronized (readyLock) {
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	    // Note that we are expecting this subclass. We will get a
960Sstevel@tonic-gate 	    //  cast exception if somebody instantiated with a
970Sstevel@tonic-gate 	    //  DATable subclass.
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	    if (daTable != null) {
1000Sstevel@tonic-gate 		return (ServerDATable)daTable;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 	    }
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	    conf = SLPConfig.getSLPConfig();
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	    // Call the superclass method to link it.
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	    daTable = linkAndInstantiateFromProp();
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	    table = (ServerDATable)daTable;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	    // Advertise for *all* scopes. This is because we need to
1130Sstevel@tonic-gate 	    //  be able to support clients that do user scoping.
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	    Vector useScopes = new Vector();
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	    activeDiscoverer =
1180Sstevel@tonic-gate 		new ActiveDiscoverer(Defaults.version,
1190Sstevel@tonic-gate 				     table,
1200Sstevel@tonic-gate 				     useScopes,
1210Sstevel@tonic-gate 				     conf.getMulticastAddress());
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	    activeDiscoverer.start();
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	}	// readyLock
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	return table;
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate     }
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate     /**
1320Sstevel@tonic-gate      * Record a new DA.
1330Sstevel@tonic-gate      *
1340Sstevel@tonic-gate      * @param URL The DAAdvert URL.
1350Sstevel@tonic-gate      * @param scopes The scopes.
1360Sstevel@tonic-gate      * @param version DA version number.
1370Sstevel@tonic-gate      * @param attrs Attributes of DA.
1380Sstevel@tonic-gate      * @param spis SPIs supported by DA
1390Sstevel@tonic-gate      * @return True if recorded, false if not.
1400Sstevel@tonic-gate      */
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate     abstract long
recordNewDA(ServiceURL url, Vector scopes, long timestamp, int version, Vector attrs, String spis)1430Sstevel@tonic-gate 	recordNewDA(ServiceURL url,
1440Sstevel@tonic-gate 		    Vector scopes,
1450Sstevel@tonic-gate 		    long timestamp,
1460Sstevel@tonic-gate 		    int version,
1470Sstevel@tonic-gate 		    Vector attrs,
1480Sstevel@tonic-gate 		    String spis);
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate     /**
1510Sstevel@tonic-gate      * Return a hashtable in ServiceTable.findServices() format (e.g.
1520Sstevel@tonic-gate      * URL's as keys, scopes as values) for DAs matching the query.
1530Sstevel@tonic-gate      *
1540Sstevel@tonic-gate      * @param query Query for DA attributes.
1550Sstevel@tonic-gate      */
1560Sstevel@tonic-gate 
returnMatchingDAs(String query)1570Sstevel@tonic-gate     abstract Hashtable returnMatchingDAs(String query)
1580Sstevel@tonic-gate 	throws ServiceLocationException;
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate     /**
1610Sstevel@tonic-gate      * Forward a registration or deregistration to all DAs that have matching
1620Sstevel@tonic-gate      * scopes.
1630Sstevel@tonic-gate      *
1640Sstevel@tonic-gate      * @param msg Registration or deregistration message, server side.
1650Sstevel@tonic-gate      * @param source The address of the source.
1660Sstevel@tonic-gate      */
1670Sstevel@tonic-gate 
forwardSAMessage(SrvLocMsg msg, InetAddress source)1680Sstevel@tonic-gate     void forwardSAMessage(SrvLocMsg msg, InetAddress source)
1690Sstevel@tonic-gate 	throws ServiceLocationException {
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	SrvLocHeader hdr = msg.getHeader();
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	// If the message is not from this host (on any interface)
1740Sstevel@tonic-gate 	//  then don't forward it.
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if (!conf.isLocalHostSource(source)) {
1770Sstevel@tonic-gate 	    return;
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 	}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	// Record it so we can forward to a new DA.
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 	if (msg instanceof SSrvReg || msg instanceof CSrvReg) {
1840Sstevel@tonic-gate 	    ServiceURL url;
1850Sstevel@tonic-gate 	    if (msg instanceof SSrvReg) {
1860Sstevel@tonic-gate 		url = ((SSrvReg)msg).URL;
1870Sstevel@tonic-gate 	    } else {
1880Sstevel@tonic-gate 		url = ((CSrvReg)msg).URL;
1890Sstevel@tonic-gate 	    }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 	    String key = makeKey(url, hdr.locale); // need locale also...
1920Sstevel@tonic-gate 	    forwardRegs.put(key, msg);  // fresh doesn't matter.
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	} else {
1950Sstevel@tonic-gate 	    SSrvDereg smsg = (SSrvDereg)msg;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	    // Only remove if tags are null. Otherwise, the updated record
1980Sstevel@tonic-gate 	    //  will be sought.
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	    if (smsg.tags == null) {
2010Sstevel@tonic-gate 		String key = makeKey(smsg.URL, hdr.locale);
2020Sstevel@tonic-gate 		forwardRegs.remove(key);
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	    }
2050Sstevel@tonic-gate 	}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	// We only forward registrations to v2 DAs because we are
2080Sstevel@tonic-gate 	//  acting as an SA server here. There is no requirement
2090Sstevel@tonic-gate 	//  for v2 SAs to communicate with v1 DAs.
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	// Get a hashtable of DAs that match the scopes in the message.
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	Hashtable daScopeRec = findDAScopes(hdr.scopes);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	// We are only concerned with the unicast key, since it contains
2160Sstevel@tonic-gate 	//  the DAs to which forwarding is required.
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	Vector daRecs = (Vector)daScopeRec.get(UNICAST_KEY);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	// If there are no daRecs, then simply return.
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	if (daRecs == null) {
2230Sstevel@tonic-gate 	    return;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	// Otherwise, forward the registration to all DAs in the vector.
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	int i, n = daRecs.size();
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
2320Sstevel@tonic-gate 	    DARecord rec = (DARecord)daRecs.elementAt(i);
2330Sstevel@tonic-gate 	    Vector daAddresses = rec.daAddresses;
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	    int j, m = daAddresses.size();
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	    for (j = 0; j < m; j++) {
2380Sstevel@tonic-gate 		InetAddress addr = (InetAddress)daAddresses.elementAt(j);
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 		// Don't forward if it's the host from which the registration
2410Sstevel@tonic-gate 		//  came. Otherwise, we're hosed.
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 		if (!source.equals(addr)) {
2440Sstevel@tonic-gate 		    forwardRegOrDereg(addr, msg);
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 		}
2470Sstevel@tonic-gate 	    }
2480Sstevel@tonic-gate 	}
2490Sstevel@tonic-gate     }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate     // Make a key for the service agent message table.
2520Sstevel@tonic-gate 
makeKey(ServiceURL url, Locale locale)2530Sstevel@tonic-gate     private String makeKey(ServiceURL url, Locale locale) {
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	return url.toString() + "/" + locale.toString();
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate     }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate     /**
2610Sstevel@tonic-gate      * Handle an incoming DAAdvert. Presence must be recorded in the
2620Sstevel@tonic-gate      * implementation specific server DA table and any registrations need
2630Sstevel@tonic-gate      * to be forwarded if the boot timestamp is different from the
2640Sstevel@tonic-gate      * old boot timestamp.
2650Sstevel@tonic-gate      *
2660Sstevel@tonic-gate      * @param advert Incoming DAAdvert.
2670Sstevel@tonic-gate      */
2680Sstevel@tonic-gate 
handleAdvertIn(CDAAdvert advert)2690Sstevel@tonic-gate     void handleAdvertIn(CDAAdvert advert) {
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	SrvLocHeader hdr = advert.getHeader();
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	// Remove if DA is going down.
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	if (advert.isGoingDown()) {
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	    InetAddress addr = null;
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate 	    try {
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 		addr = InetAddress.getByName(advert.URL.getHost());
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	    } catch (UnknownHostException ex) {
2840Sstevel@tonic-gate 		conf.writeLog("unknown_da_address",
2850Sstevel@tonic-gate 			      new Object[] {advert.URL.getHost()});
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 		return;
2880Sstevel@tonic-gate 	    }
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	    if (removeDA(addr, hdr.scopes)) {
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 		if (conf.traceDATraffic()) {
2930Sstevel@tonic-gate 		    conf.writeLog("sdat_delete_da",
2940Sstevel@tonic-gate 				  new Object[] {
2950Sstevel@tonic-gate 			advert.URL,
2960Sstevel@tonic-gate 			    hdr.scopes});
2970Sstevel@tonic-gate 		}
2980Sstevel@tonic-gate 	    }
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	} else {
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	    // verify the DAAdvert
3030Sstevel@tonic-gate 	    if (advert.authBlock != null) {
3040Sstevel@tonic-gate 		try {
3050Sstevel@tonic-gate 		    AuthBlock.verifyAll(advert.authBlock);
3060Sstevel@tonic-gate 		} catch (ServiceLocationException e) {
3070Sstevel@tonic-gate 		    if (conf.traceDrop()) {
3080Sstevel@tonic-gate 			conf.writeLog("sdat_daadvert_vrfy_failed",
3090Sstevel@tonic-gate 				      new Object[] {advert.URL});
3100Sstevel@tonic-gate 		    }
3110Sstevel@tonic-gate 		    return;
3120Sstevel@tonic-gate 		}
3130Sstevel@tonic-gate 	    }
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	    long timestamp =
3160Sstevel@tonic-gate 		recordNewDA(advert.URL,
3170Sstevel@tonic-gate 			    hdr.scopes,
3180Sstevel@tonic-gate 			    advert.timestamp,
3190Sstevel@tonic-gate 			    hdr.version,
3200Sstevel@tonic-gate 			    advert.attrs,
3210Sstevel@tonic-gate 			    advert.spis);
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	    // Don't forward if the advert was rejected, or if the
3240Sstevel@tonic-gate 	    //  old timestamp greater than or equal to the new timestamp.
3250Sstevel@tonic-gate 	    //  If the old timestamp is greater than or equal to the new,
3260Sstevel@tonic-gate 	    //  it means that we have already forwarded to this DA.
3270Sstevel@tonic-gate 	    //  IF the old timestamp is less, it means that
3280Sstevel@tonic-gate 	    //  the DA has crashed and come up again since we last saw
3290Sstevel@tonic-gate 	    //  it, so we may have missed forwarding something to it.
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	    if (timestamp >= advert.timestamp) {
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 		if (conf.traceDATraffic()) {
3340Sstevel@tonic-gate 		    conf.writeLog("sdat_add_da_no_forward",
3350Sstevel@tonic-gate 				  new Object[] {
3360Sstevel@tonic-gate 			advert.URL,
3370Sstevel@tonic-gate 			    hdr.scopes,
3380Sstevel@tonic-gate 			    new Long(timestamp)});
3390Sstevel@tonic-gate 		}
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 		return;
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 	    }
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	    if (conf.traceDATraffic()) {
3460Sstevel@tonic-gate 		conf.writeLog("sdat_add_da",
3470Sstevel@tonic-gate 			      new Object[] {
3480Sstevel@tonic-gate 		    advert.URL,
3490Sstevel@tonic-gate 			hdr.scopes,
3500Sstevel@tonic-gate 			new Long(advert.timestamp)});
3510Sstevel@tonic-gate 	    }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	    // Forward existing registrations to the new advert.
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	    forwardRegistrations(advert.URL, hdr.scopes,
3560Sstevel@tonic-gate 				 advert.timestamp, hdr.version);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate     }
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate     //
3610Sstevel@tonic-gate     // Private methods.
3620Sstevel@tonic-gate     //
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate     private void
forwardRegistrations(ServiceURL url, Vector scopes, long timestamp, int version)3650Sstevel@tonic-gate 	forwardRegistrations(ServiceURL url,
3660Sstevel@tonic-gate 			     Vector scopes,
3670Sstevel@tonic-gate 			     long timestamp,
3680Sstevel@tonic-gate 			     int version) {
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	// Wait a random amount of time before forwarding.
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	try {
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	    Thread.currentThread().sleep(conf.getRandomWait());
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	} catch (InterruptedException ex) {
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	// Get the registrations to forward.
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	Enumeration regs = forwardRegs.elements();
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	// Get the address of the DA.
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	InetAddress addr = null;
3870Sstevel@tonic-gate 	String host = url.getHost();
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	try {
3900Sstevel@tonic-gate 	    addr = InetAddress.getByName(host);
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	} catch (UnknownHostException ex) {
3930Sstevel@tonic-gate 	    if (conf.traceDrop() || conf.traceDATraffic()) {
3940Sstevel@tonic-gate 		conf.writeLog("sdat_drop_fwd",
3950Sstevel@tonic-gate 			      new Object[] {
3960Sstevel@tonic-gate 		    host});
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	    }
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	    return;
4010Sstevel@tonic-gate 	}
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	ServiceTable serviceTable = null;
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	try {
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	    serviceTable = ServiceTable.getServiceTable();
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	    // By this time, we should have it.
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	}
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	// Forward the registrations. Keep track of any deleted elements.
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	Vector deleted = new Vector();
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	while (regs.hasMoreElements()) {
4200Sstevel@tonic-gate 	    SrvLocMsg reg = (SrvLocMsg)regs.nextElement();
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	    ServiceURL regurl;
4230Sstevel@tonic-gate 	    if (reg instanceof SSrvReg) {
4240Sstevel@tonic-gate 		regurl = ((SSrvReg)reg).URL;
4250Sstevel@tonic-gate 	    } else {
4260Sstevel@tonic-gate 		regurl = ((CSrvReg)reg).URL;
4270Sstevel@tonic-gate 	    }
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	    SrvLocHeader hdr = reg.getHeader();
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	    // Get the record and modify the reg to reflect the
4320Sstevel@tonic-gate 	    //  record. We must do this because the SA may have
4330Sstevel@tonic-gate 	    //  changed the record since it was first registred
4340Sstevel@tonic-gate 	    //  and we do not keep track of the changes here.
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	    ServiceStore.ServiceRecord rec =
4370Sstevel@tonic-gate 		serviceTable.getServiceRecord(regurl, hdr.locale);
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	    // If the record is null, it means that the entry was
4400Sstevel@tonic-gate 	    //  aged out.
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	    if (rec == null) {
4430Sstevel@tonic-gate 		deleted.addElement(reg);
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	    } else {
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate 		// Check that the scopes match.
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 		Vector sscopes = (Vector)hdr.scopes.clone();
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 		DATable.filterScopes(sscopes, scopes, false);
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 		if (sscopes.size() <= 0) {
4540Sstevel@tonic-gate 		    continue;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 		}
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 		if (reg instanceof SSrvReg) {
4590Sstevel@tonic-gate 		    SSrvReg sreg = (SSrvReg)reg;
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 		    hdr.scopes = (Vector)hdr.scopes.clone();
4620Sstevel@tonic-gate 		    sreg.attrList = (Vector)rec.getAttrList().clone();
4630Sstevel@tonic-gate 		    sreg.URLSignature = rec.getURLSignature();
4640Sstevel@tonic-gate 		    sreg.attrSignature = rec.getAttrSignature();
4650Sstevel@tonic-gate 		}
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 		forwardRegOrDereg(addr, reg);
4680Sstevel@tonic-gate 	    }
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	// Remove any deleted elements from the hashtable.
4730Sstevel@tonic-gate 	//  We do this in a separate loop because enumerations
4740Sstevel@tonic-gate 	//  aren't synchronized.
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	int i, n = deleted.size();
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
4790Sstevel@tonic-gate 	    SrvLocMsg reg = (SrvLocMsg)deleted.elementAt(i);
4800Sstevel@tonic-gate 	    SrvLocHeader hdr = reg.getHeader();
4810Sstevel@tonic-gate 	    ServiceURL regurl;
4820Sstevel@tonic-gate 	    if (reg instanceof SSrvReg) {
4830Sstevel@tonic-gate 		regurl = ((SSrvReg)reg).URL;
4840Sstevel@tonic-gate 	    } else {
4850Sstevel@tonic-gate 		regurl = ((CSrvReg)reg).URL;
4860Sstevel@tonic-gate 	    }
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	    String key = makeKey(regurl, hdr.locale);
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	    forwardRegs.remove(key);
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate     }
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate     // Forward the registration or deregistration to the URL.
4980Sstevel@tonic-gate 
forwardRegOrDereg(InetAddress addr, SrvLocMsg rqst)4990Sstevel@tonic-gate     private void forwardRegOrDereg(InetAddress addr, SrvLocMsg rqst) {
5000Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	// Don't forward to myself! Otherwise, nasty recursion happens.
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	if (conf.isLocalHostSource(addr)) {
5050Sstevel@tonic-gate 	    return;
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	}
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 	// If security is on, only forward if this DA can verify the authblocks
5100Sstevel@tonic-gate 	if (conf.getHasSecurity()) {
5110Sstevel@tonic-gate 	    LinkedList spis = (LinkedList)daSPIsHash.get(addr);
5120Sstevel@tonic-gate 	    if (spis == null) {
5130Sstevel@tonic-gate 		// internal error; skip this DA to be safe
5140Sstevel@tonic-gate 		return;
5150Sstevel@tonic-gate 	    }
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	    Hashtable auths = null;
5180Sstevel@tonic-gate 	    if (rqst instanceof SSrvReg) {
5190Sstevel@tonic-gate 		auths = ((SSrvReg)rqst).URLSignature;
5200Sstevel@tonic-gate 	    } else if (rqst instanceof SSrvDereg) {
5210Sstevel@tonic-gate 		auths = ((SSrvDereg)rqst).URLSignature;
5220Sstevel@tonic-gate 	    } else {
5230Sstevel@tonic-gate 		// shouldn't even be forwarding this!
5240Sstevel@tonic-gate 		return;
5250Sstevel@tonic-gate 	    }
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	    // If each authblock is equiv to at least one SPI, forward the reg
5280Sstevel@tonic-gate 	    Enumeration abs = auths.elements();
5290Sstevel@tonic-gate 	    while (abs.hasMoreElements()) {
5300Sstevel@tonic-gate 		AuthBlock ab = (AuthBlock)abs.nextElement();
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 		// check each DA SPI
5330Sstevel@tonic-gate 		boolean daSPImatch = false;
5340Sstevel@tonic-gate 		for (int SPIi = 0; SPIi < spis.size(); SPIi++) {
5350Sstevel@tonic-gate 		    if (AuthBlock.checkEquiv((String)spis.get(SPIi), ab)) {
5360Sstevel@tonic-gate 			daSPImatch = true;
5370Sstevel@tonic-gate 			break;
5380Sstevel@tonic-gate 		    }
5390Sstevel@tonic-gate 		}
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 		if (!daSPImatch) {
5420Sstevel@tonic-gate 		    return;
5430Sstevel@tonic-gate 		}
5440Sstevel@tonic-gate 	    }
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	if (conf.traceDATraffic()) {
5480Sstevel@tonic-gate 	    conf.writeLog("sdat_forward",
5490Sstevel@tonic-gate 			  new Object[] {
5500Sstevel@tonic-gate 		Integer.toHexString(hdr.xid),
5510Sstevel@tonic-gate 		    addr});
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	}
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	// Send it via TCP. DAs should understand TCP, and it's reliable.
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	SrvLocMsg rply = null;
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 	try {
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	    // Construct the client side message, for outgoing.
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	    if (rqst instanceof SSrvReg) {
5650Sstevel@tonic-gate 		SSrvReg rrqst = (SSrvReg)rqst;
5660Sstevel@tonic-gate 		CSrvReg msg = new CSrvReg(hdr.fresh,
5670Sstevel@tonic-gate 					  hdr.locale,
5680Sstevel@tonic-gate 					  rrqst.URL,
5690Sstevel@tonic-gate 					  hdr.scopes,
5700Sstevel@tonic-gate 					  rrqst.attrList,
5710Sstevel@tonic-gate 					  rrqst.URLSignature,
5720Sstevel@tonic-gate 					  rrqst.attrSignature);
5730Sstevel@tonic-gate 		rply = msg;
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	    } else if (rqst instanceof SSrvDereg) {
5760Sstevel@tonic-gate 		SSrvDereg drqst = (SSrvDereg)rqst;
5770Sstevel@tonic-gate 		CSrvDereg msg = new CSrvDereg(hdr.locale,
5780Sstevel@tonic-gate 					      drqst.URL,
5790Sstevel@tonic-gate 					      hdr.scopes,
5800Sstevel@tonic-gate 					      drqst.tags,
5810Sstevel@tonic-gate 					      drqst.URLSignature);
5820Sstevel@tonic-gate 		rply = msg;
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	    } else if (rqst instanceof CSrvReg) {
5850Sstevel@tonic-gate 		rply = rqst;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	    }
5880Sstevel@tonic-gate 
5890Sstevel@tonic-gate 	    rply = Transact.transactTCPMsg(addr, rply, false);
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	    if (conf.traceDATraffic()) {
5940Sstevel@tonic-gate 		conf.writeLog("sdat_forward_exception",
5950Sstevel@tonic-gate 			      new Object[] {
5960Sstevel@tonic-gate 		    Integer.toHexString(hdr.xid),
5970Sstevel@tonic-gate 			addr,
5980Sstevel@tonic-gate 			new Integer(ex.getErrorCode()),
5990Sstevel@tonic-gate 			ex.getMessage()});
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	    }
6020Sstevel@tonic-gate 	}
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	// Report any errors.
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 	if (rply == null ||
6070Sstevel@tonic-gate 	    rply.getErrorCode() != ServiceLocationException.OK) {
6080Sstevel@tonic-gate 	    if (conf.traceDATraffic()) {
6090Sstevel@tonic-gate 		conf.writeLog("sdat_forward_err",
6100Sstevel@tonic-gate 			      new Object[] {
6110Sstevel@tonic-gate 		    Integer.toHexString(hdr.xid),
6120Sstevel@tonic-gate 			addr,
6130Sstevel@tonic-gate 			(rply == null ? "<null>":
6140Sstevel@tonic-gate 			 Integer.toString(rply.getErrorCode()))});
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	    }
6170Sstevel@tonic-gate 	}
6180Sstevel@tonic-gate     }
6190Sstevel@tonic-gate }
620