xref: /illumos-gate/usr/src/lib/libslp/javalib/com/sun/slp/ServerDATable.java (revision 55fea89dcaa64928bed4327112404dcb3e07b79f)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*9a70fc3bSMark J. Nelson  * Common Development and Distribution License (the "License").
6*9a70fc3bSMark J. Nelson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
237c478bd9Sstevel@tonic-gate  * All rights reserved.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate //  ServerDATable.java: Abstract class for DA Table in the DA/SA server.
287c478bd9Sstevel@tonic-gate //  Author:           James Kempf
297c478bd9Sstevel@tonic-gate //  Created On:       Wed May 20 08:30:46 1998
307c478bd9Sstevel@tonic-gate //  Last Modified By: James Kempf
317c478bd9Sstevel@tonic-gate //  Last Modified On: Tue Mar  9 12:36:37 1999
327c478bd9Sstevel@tonic-gate //  Update Count:     124
337c478bd9Sstevel@tonic-gate //
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate package com.sun.slp;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate import java.util.*;
387c478bd9Sstevel@tonic-gate import java.net.*;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /**
417c478bd9Sstevel@tonic-gate  * ServerDATable is an abstract class that provides the interface for DA
427c478bd9Sstevel@tonic-gate  * and scope discovery, storage of DA information from incoming DAAdverts,
437c478bd9Sstevel@tonic-gate  * and forwarding of registrations and deregistration to DAs having
447c478bd9Sstevel@tonic-gate  * the same scopes. A variety of implementations are possible.
457c478bd9Sstevel@tonic-gate  * The getServerDATable() method creates the right one from a subclass.
467c478bd9Sstevel@tonic-gate  * We keep separate track of the superclass DA table and the server
477c478bd9Sstevel@tonic-gate  * DA table so that these two classes can co-exist in the same JVM.
487c478bd9Sstevel@tonic-gate  * Note that the code for forwarding registrations must keep track of
497c478bd9Sstevel@tonic-gate  * only those registrations that were done on this host. It does this
507c478bd9Sstevel@tonic-gate  * by saving the registrations as they come in. The forwarding code
517c478bd9Sstevel@tonic-gate  * is optimized so that forwarding of a new message is fast, while
527c478bd9Sstevel@tonic-gate  * forwarding of a message due to discovery of a new DA is somewhat
537c478bd9Sstevel@tonic-gate  * slower. This helps assure that SA clients get good service.
547c478bd9Sstevel@tonic-gate  *
557c478bd9Sstevel@tonic-gate  * The ServerDATable also does active discovery for the SA server/DA,
567c478bd9Sstevel@tonic-gate  * in a separate thread.
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * @author James Kempf
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate abstract class ServerDATable extends DATable {
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate     // The active discovery object.
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate     protected static ActiveDiscoverer activeDiscoverer = null;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate     // The table of regs to forward. Keys are the reg URL and locale, values
687c478bd9Sstevel@tonic-gate     //  are the SSrvReg objects.
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate     protected Hashtable forwardRegs = new Hashtable();
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate     // This acts as a guard protecting an non-initialized DA table:
737c478bd9Sstevel@tonic-gate     //  If the DA Table hasn't been populated by active discovery yet,
747c478bd9Sstevel@tonic-gate     //  other threads accessing the DA table will block on readyLock.
757c478bd9Sstevel@tonic-gate     private static Object readyLock = new Object();
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate     // Keeps track of which DAs support which SPIs. The actual mapping
787c478bd9Sstevel@tonic-gate     //  is DA InetAddress to LinkedList of SPI Strings. recordNewDA
797c478bd9Sstevel@tonic-gate     //  populates this.
807c478bd9Sstevel@tonic-gate     protected Hashtable daSPIsHash = new Hashtable();
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate     /**
837c478bd9Sstevel@tonic-gate      * Get the right server DA table from the subclass.
847c478bd9Sstevel@tonic-gate      *
857c478bd9Sstevel@tonic-gate      * @return Table for handling DAs in the server.
867c478bd9Sstevel@tonic-gate      */
877c478bd9Sstevel@tonic-gate 
getServerDATable()887c478bd9Sstevel@tonic-gate     static ServerDATable getServerDATable()
897c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	ServerDATable table = null;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	synchronized (readyLock) {
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	    // Note that we are expecting this subclass. We will get a
967c478bd9Sstevel@tonic-gate 	    //  cast exception if somebody instantiated with a
977c478bd9Sstevel@tonic-gate 	    //  DATable subclass.
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	    if (daTable != null) {
1007c478bd9Sstevel@tonic-gate 		return (ServerDATable)daTable;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	    }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	    conf = SLPConfig.getSLPConfig();
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	    // Call the superclass method to link it.
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	    daTable = linkAndInstantiateFromProp();
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	    table = (ServerDATable)daTable;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	    // Advertise for *all* scopes. This is because we need to
1137c478bd9Sstevel@tonic-gate 	    //  be able to support clients that do user scoping.
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	    Vector useScopes = new Vector();
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	    activeDiscoverer =
1187c478bd9Sstevel@tonic-gate 		new ActiveDiscoverer(Defaults.version,
1197c478bd9Sstevel@tonic-gate 				     table,
1207c478bd9Sstevel@tonic-gate 				     useScopes,
1217c478bd9Sstevel@tonic-gate 				     conf.getMulticastAddress());
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	    activeDiscoverer.start();
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	}	// readyLock
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	return table;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate     }
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate     /**
1327c478bd9Sstevel@tonic-gate      * Record a new DA.
1337c478bd9Sstevel@tonic-gate      *
1347c478bd9Sstevel@tonic-gate      * @param URL The DAAdvert URL.
1357c478bd9Sstevel@tonic-gate      * @param scopes The scopes.
1367c478bd9Sstevel@tonic-gate      * @param version DA version number.
1377c478bd9Sstevel@tonic-gate      * @param attrs Attributes of DA.
1387c478bd9Sstevel@tonic-gate      * @param spis SPIs supported by DA
1397c478bd9Sstevel@tonic-gate      * @return True if recorded, false if not.
1407c478bd9Sstevel@tonic-gate      */
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate     abstract long
recordNewDA(ServiceURL url, Vector scopes, long timestamp, int version, Vector attrs, String spis)1437c478bd9Sstevel@tonic-gate 	recordNewDA(ServiceURL url,
1447c478bd9Sstevel@tonic-gate 		    Vector scopes,
1457c478bd9Sstevel@tonic-gate 		    long timestamp,
1467c478bd9Sstevel@tonic-gate 		    int version,
1477c478bd9Sstevel@tonic-gate 		    Vector attrs,
1487c478bd9Sstevel@tonic-gate 		    String spis);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate     /**
1517c478bd9Sstevel@tonic-gate      * Return a hashtable in ServiceTable.findServices() format (e.g.
1527c478bd9Sstevel@tonic-gate      * URL's as keys, scopes as values) for DAs matching the query.
1537c478bd9Sstevel@tonic-gate      *
1547c478bd9Sstevel@tonic-gate      * @param query Query for DA attributes.
1557c478bd9Sstevel@tonic-gate      */
1567c478bd9Sstevel@tonic-gate 
returnMatchingDAs(String query)1577c478bd9Sstevel@tonic-gate     abstract Hashtable returnMatchingDAs(String query)
1587c478bd9Sstevel@tonic-gate 	throws ServiceLocationException;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate     /**
1617c478bd9Sstevel@tonic-gate      * Forward a registration or deregistration to all DAs that have matching
1627c478bd9Sstevel@tonic-gate      * scopes.
1637c478bd9Sstevel@tonic-gate      *
1647c478bd9Sstevel@tonic-gate      * @param msg Registration or deregistration message, server side.
1657c478bd9Sstevel@tonic-gate      * @param source The address of the source.
1667c478bd9Sstevel@tonic-gate      */
1677c478bd9Sstevel@tonic-gate 
forwardSAMessage(SrvLocMsg msg, InetAddress source)1687c478bd9Sstevel@tonic-gate     void forwardSAMessage(SrvLocMsg msg, InetAddress source)
1697c478bd9Sstevel@tonic-gate 	throws ServiceLocationException {
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = msg.getHeader();
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	// If the message is not from this host (on any interface)
1747c478bd9Sstevel@tonic-gate 	//  then don't forward it.
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	if (!conf.isLocalHostSource(source)) {
1777c478bd9Sstevel@tonic-gate 	    return;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	}
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	// Record it so we can forward to a new DA.
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	if (msg instanceof SSrvReg || msg instanceof CSrvReg) {
1847c478bd9Sstevel@tonic-gate 	    ServiceURL url;
1857c478bd9Sstevel@tonic-gate 	    if (msg instanceof SSrvReg) {
1867c478bd9Sstevel@tonic-gate 		url = ((SSrvReg)msg).URL;
1877c478bd9Sstevel@tonic-gate 	    } else {
1887c478bd9Sstevel@tonic-gate 		url = ((CSrvReg)msg).URL;
1897c478bd9Sstevel@tonic-gate 	    }
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	    String key = makeKey(url, hdr.locale); // need locale also...
1927c478bd9Sstevel@tonic-gate 	    forwardRegs.put(key, msg);  // fresh doesn't matter.
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	} else {
1957c478bd9Sstevel@tonic-gate 	    SSrvDereg smsg = (SSrvDereg)msg;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	    // Only remove if tags are null. Otherwise, the updated record
1987c478bd9Sstevel@tonic-gate 	    //  will be sought.
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	    if (smsg.tags == null) {
2017c478bd9Sstevel@tonic-gate 		String key = makeKey(smsg.URL, hdr.locale);
2027c478bd9Sstevel@tonic-gate 		forwardRegs.remove(key);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	    }
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	// We only forward registrations to v2 DAs because we are
2087c478bd9Sstevel@tonic-gate 	//  acting as an SA server here. There is no requirement
2097c478bd9Sstevel@tonic-gate 	//  for v2 SAs to communicate with v1 DAs.
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	// Get a hashtable of DAs that match the scopes in the message.
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	Hashtable daScopeRec = findDAScopes(hdr.scopes);
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	// We are only concerned with the unicast key, since it contains
2167c478bd9Sstevel@tonic-gate 	//  the DAs to which forwarding is required.
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	Vector daRecs = (Vector)daScopeRec.get(UNICAST_KEY);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	// If there are no daRecs, then simply return.
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	if (daRecs == null) {
2237c478bd9Sstevel@tonic-gate 	    return;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	// Otherwise, forward the registration to all DAs in the vector.
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	int i, n = daRecs.size();
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
2327c478bd9Sstevel@tonic-gate 	    DARecord rec = (DARecord)daRecs.elementAt(i);
2337c478bd9Sstevel@tonic-gate 	    Vector daAddresses = rec.daAddresses;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	    int j, m = daAddresses.size();
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	    for (j = 0; j < m; j++) {
2387c478bd9Sstevel@tonic-gate 		InetAddress addr = (InetAddress)daAddresses.elementAt(j);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 		// Don't forward if it's the host from which the registration
2417c478bd9Sstevel@tonic-gate 		//  came. Otherwise, we're hosed.
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 		if (!source.equals(addr)) {
2447c478bd9Sstevel@tonic-gate 		    forwardRegOrDereg(addr, msg);
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 	    }
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate     }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate     // Make a key for the service agent message table.
2527c478bd9Sstevel@tonic-gate 
makeKey(ServiceURL url, Locale locale)2537c478bd9Sstevel@tonic-gate     private String makeKey(ServiceURL url, Locale locale) {
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	return url.toString() + "/" + locale.toString();
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate     }
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate     /**
2617c478bd9Sstevel@tonic-gate      * Handle an incoming DAAdvert. Presence must be recorded in the
2627c478bd9Sstevel@tonic-gate      * implementation specific server DA table and any registrations need
2637c478bd9Sstevel@tonic-gate      * to be forwarded if the boot timestamp is different from the
2647c478bd9Sstevel@tonic-gate      * old boot timestamp.
2657c478bd9Sstevel@tonic-gate      *
2667c478bd9Sstevel@tonic-gate      * @param advert Incoming DAAdvert.
2677c478bd9Sstevel@tonic-gate      */
2687c478bd9Sstevel@tonic-gate 
handleAdvertIn(CDAAdvert advert)2697c478bd9Sstevel@tonic-gate     void handleAdvertIn(CDAAdvert advert) {
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = advert.getHeader();
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	// Remove if DA is going down.
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if (advert.isGoingDown()) {
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	    InetAddress addr = null;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	    try {
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 		addr = InetAddress.getByName(advert.URL.getHost());
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	    } catch (UnknownHostException ex) {
2847c478bd9Sstevel@tonic-gate 		conf.writeLog("unknown_da_address",
2857c478bd9Sstevel@tonic-gate 			      new Object[] {advert.URL.getHost()});
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 		return;
2887c478bd9Sstevel@tonic-gate 	    }
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	    if (removeDA(addr, hdr.scopes)) {
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 		if (conf.traceDATraffic()) {
2937c478bd9Sstevel@tonic-gate 		    conf.writeLog("sdat_delete_da",
2947c478bd9Sstevel@tonic-gate 				  new Object[] {
2957c478bd9Sstevel@tonic-gate 			advert.URL,
2967c478bd9Sstevel@tonic-gate 			    hdr.scopes});
2977c478bd9Sstevel@tonic-gate 		}
2987c478bd9Sstevel@tonic-gate 	    }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	} else {
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 	    // verify the DAAdvert
3037c478bd9Sstevel@tonic-gate 	    if (advert.authBlock != null) {
3047c478bd9Sstevel@tonic-gate 		try {
3057c478bd9Sstevel@tonic-gate 		    AuthBlock.verifyAll(advert.authBlock);
3067c478bd9Sstevel@tonic-gate 		} catch (ServiceLocationException e) {
3077c478bd9Sstevel@tonic-gate 		    if (conf.traceDrop()) {
3087c478bd9Sstevel@tonic-gate 			conf.writeLog("sdat_daadvert_vrfy_failed",
3097c478bd9Sstevel@tonic-gate 				      new Object[] {advert.URL});
3107c478bd9Sstevel@tonic-gate 		    }
3117c478bd9Sstevel@tonic-gate 		    return;
3127c478bd9Sstevel@tonic-gate 		}
3137c478bd9Sstevel@tonic-gate 	    }
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	    long timestamp =
3167c478bd9Sstevel@tonic-gate 		recordNewDA(advert.URL,
3177c478bd9Sstevel@tonic-gate 			    hdr.scopes,
3187c478bd9Sstevel@tonic-gate 			    advert.timestamp,
3197c478bd9Sstevel@tonic-gate 			    hdr.version,
3207c478bd9Sstevel@tonic-gate 			    advert.attrs,
3217c478bd9Sstevel@tonic-gate 			    advert.spis);
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	    // Don't forward if the advert was rejected, or if the
3247c478bd9Sstevel@tonic-gate 	    //  old timestamp greater than or equal to the new timestamp.
3257c478bd9Sstevel@tonic-gate 	    //  If the old timestamp is greater than or equal to the new,
3267c478bd9Sstevel@tonic-gate 	    //  it means that we have already forwarded to this DA.
3277c478bd9Sstevel@tonic-gate 	    //  IF the old timestamp is less, it means that
3287c478bd9Sstevel@tonic-gate 	    //  the DA has crashed and come up again since we last saw
3297c478bd9Sstevel@tonic-gate 	    //  it, so we may have missed forwarding something to it.
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	    if (timestamp >= advert.timestamp) {
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 		if (conf.traceDATraffic()) {
3347c478bd9Sstevel@tonic-gate 		    conf.writeLog("sdat_add_da_no_forward",
3357c478bd9Sstevel@tonic-gate 				  new Object[] {
3367c478bd9Sstevel@tonic-gate 			advert.URL,
3377c478bd9Sstevel@tonic-gate 			    hdr.scopes,
3387c478bd9Sstevel@tonic-gate 			    new Long(timestamp)});
3397c478bd9Sstevel@tonic-gate 		}
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 		return;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	    }
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	    if (conf.traceDATraffic()) {
3467c478bd9Sstevel@tonic-gate 		conf.writeLog("sdat_add_da",
3477c478bd9Sstevel@tonic-gate 			      new Object[] {
3487c478bd9Sstevel@tonic-gate 		    advert.URL,
3497c478bd9Sstevel@tonic-gate 			hdr.scopes,
3507c478bd9Sstevel@tonic-gate 			new Long(advert.timestamp)});
3517c478bd9Sstevel@tonic-gate 	    }
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	    // Forward existing registrations to the new advert.
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	    forwardRegistrations(advert.URL, hdr.scopes,
3567c478bd9Sstevel@tonic-gate 				 advert.timestamp, hdr.version);
3577c478bd9Sstevel@tonic-gate 	}
3587c478bd9Sstevel@tonic-gate     }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate     //
3617c478bd9Sstevel@tonic-gate     // Private methods.
3627c478bd9Sstevel@tonic-gate     //
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate     private void
forwardRegistrations(ServiceURL url, Vector scopes, long timestamp, int version)3657c478bd9Sstevel@tonic-gate 	forwardRegistrations(ServiceURL url,
3667c478bd9Sstevel@tonic-gate 			     Vector scopes,
3677c478bd9Sstevel@tonic-gate 			     long timestamp,
3687c478bd9Sstevel@tonic-gate 			     int version) {
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	// Wait a random amount of time before forwarding.
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	try {
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	    Thread.currentThread().sleep(conf.getRandomWait());
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	} catch (InterruptedException ex) {
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	}
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 	// Get the registrations to forward.
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	Enumeration regs = forwardRegs.elements();
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	// Get the address of the DA.
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	InetAddress addr = null;
3877c478bd9Sstevel@tonic-gate 	String host = url.getHost();
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	try {
3907c478bd9Sstevel@tonic-gate 	    addr = InetAddress.getByName(host);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	} catch (UnknownHostException ex) {
3937c478bd9Sstevel@tonic-gate 	    if (conf.traceDrop() || conf.traceDATraffic()) {
3947c478bd9Sstevel@tonic-gate 		conf.writeLog("sdat_drop_fwd",
3957c478bd9Sstevel@tonic-gate 			      new Object[] {
3967c478bd9Sstevel@tonic-gate 		    host});
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	    }
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	    return;
4017c478bd9Sstevel@tonic-gate 	}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	ServiceTable serviceTable = null;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	try {
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	    serviceTable = ServiceTable.getServiceTable();
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	    // By this time, we should have it.
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	// Forward the registrations. Keep track of any deleted elements.
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	Vector deleted = new Vector();
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	while (regs.hasMoreElements()) {
4207c478bd9Sstevel@tonic-gate 	    SrvLocMsg reg = (SrvLocMsg)regs.nextElement();
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	    ServiceURL regurl;
4237c478bd9Sstevel@tonic-gate 	    if (reg instanceof SSrvReg) {
4247c478bd9Sstevel@tonic-gate 		regurl = ((SSrvReg)reg).URL;
4257c478bd9Sstevel@tonic-gate 	    } else {
4267c478bd9Sstevel@tonic-gate 		regurl = ((CSrvReg)reg).URL;
4277c478bd9Sstevel@tonic-gate 	    }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	    SrvLocHeader hdr = reg.getHeader();
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	    // Get the record and modify the reg to reflect the
4327c478bd9Sstevel@tonic-gate 	    //  record. We must do this because the SA may have
4337c478bd9Sstevel@tonic-gate 	    //  changed the record since it was first registred
4347c478bd9Sstevel@tonic-gate 	    //  and we do not keep track of the changes here.
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	    ServiceStore.ServiceRecord rec =
4377c478bd9Sstevel@tonic-gate 		serviceTable.getServiceRecord(regurl, hdr.locale);
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	    // If the record is null, it means that the entry was
4407c478bd9Sstevel@tonic-gate 	    //  aged out.
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	    if (rec == null) {
4437c478bd9Sstevel@tonic-gate 		deleted.addElement(reg);
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 	    } else {
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 		// Check that the scopes match.
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 		Vector sscopes = (Vector)hdr.scopes.clone();
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 		DATable.filterScopes(sscopes, scopes, false);
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 		if (sscopes.size() <= 0) {
4547c478bd9Sstevel@tonic-gate 		    continue;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 		}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 		if (reg instanceof SSrvReg) {
4597c478bd9Sstevel@tonic-gate 		    SSrvReg sreg = (SSrvReg)reg;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 		    hdr.scopes = (Vector)hdr.scopes.clone();
4627c478bd9Sstevel@tonic-gate 		    sreg.attrList = (Vector)rec.getAttrList().clone();
4637c478bd9Sstevel@tonic-gate 		    sreg.URLSignature = rec.getURLSignature();
4647c478bd9Sstevel@tonic-gate 		    sreg.attrSignature = rec.getAttrSignature();
4657c478bd9Sstevel@tonic-gate 		}
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 		forwardRegOrDereg(addr, reg);
4687c478bd9Sstevel@tonic-gate 	    }
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	// Remove any deleted elements from the hashtable.
4737c478bd9Sstevel@tonic-gate 	//  We do this in a separate loop because enumerations
4747c478bd9Sstevel@tonic-gate 	//  aren't synchronized.
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	int i, n = deleted.size();
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
4797c478bd9Sstevel@tonic-gate 	    SrvLocMsg reg = (SrvLocMsg)deleted.elementAt(i);
4807c478bd9Sstevel@tonic-gate 	    SrvLocHeader hdr = reg.getHeader();
4817c478bd9Sstevel@tonic-gate 	    ServiceURL regurl;
4827c478bd9Sstevel@tonic-gate 	    if (reg instanceof SSrvReg) {
4837c478bd9Sstevel@tonic-gate 		regurl = ((SSrvReg)reg).URL;
4847c478bd9Sstevel@tonic-gate 	    } else {
4857c478bd9Sstevel@tonic-gate 		regurl = ((CSrvReg)reg).URL;
4867c478bd9Sstevel@tonic-gate 	    }
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	    String key = makeKey(regurl, hdr.locale);
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	    forwardRegs.remove(key);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	}
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate     }
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate     // Forward the registration or deregistration to the URL.
4987c478bd9Sstevel@tonic-gate 
forwardRegOrDereg(InetAddress addr, SrvLocMsg rqst)4997c478bd9Sstevel@tonic-gate     private void forwardRegOrDereg(InetAddress addr, SrvLocMsg rqst) {
5007c478bd9Sstevel@tonic-gate 	SrvLocHeader hdr = rqst.getHeader();
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	// Don't forward to myself! Otherwise, nasty recursion happens.
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	if (conf.isLocalHostSource(addr)) {
5057c478bd9Sstevel@tonic-gate 	    return;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	}
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	// If security is on, only forward if this DA can verify the authblocks
5107c478bd9Sstevel@tonic-gate 	if (conf.getHasSecurity()) {
5117c478bd9Sstevel@tonic-gate 	    LinkedList spis = (LinkedList)daSPIsHash.get(addr);
5127c478bd9Sstevel@tonic-gate 	    if (spis == null) {
5137c478bd9Sstevel@tonic-gate 		// internal error; skip this DA to be safe
5147c478bd9Sstevel@tonic-gate 		return;
5157c478bd9Sstevel@tonic-gate 	    }
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	    Hashtable auths = null;
5187c478bd9Sstevel@tonic-gate 	    if (rqst instanceof SSrvReg) {
5197c478bd9Sstevel@tonic-gate 		auths = ((SSrvReg)rqst).URLSignature;
5207c478bd9Sstevel@tonic-gate 	    } else if (rqst instanceof SSrvDereg) {
5217c478bd9Sstevel@tonic-gate 		auths = ((SSrvDereg)rqst).URLSignature;
5227c478bd9Sstevel@tonic-gate 	    } else {
5237c478bd9Sstevel@tonic-gate 		// shouldn't even be forwarding this!
5247c478bd9Sstevel@tonic-gate 		return;
5257c478bd9Sstevel@tonic-gate 	    }
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate 	    // If each authblock is equiv to at least one SPI, forward the reg
5287c478bd9Sstevel@tonic-gate 	    Enumeration abs = auths.elements();
5297c478bd9Sstevel@tonic-gate 	    while (abs.hasMoreElements()) {
5307c478bd9Sstevel@tonic-gate 		AuthBlock ab = (AuthBlock)abs.nextElement();
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 		// check each DA SPI
5337c478bd9Sstevel@tonic-gate 		boolean daSPImatch = false;
5347c478bd9Sstevel@tonic-gate 		for (int SPIi = 0; SPIi < spis.size(); SPIi++) {
5357c478bd9Sstevel@tonic-gate 		    if (AuthBlock.checkEquiv((String)spis.get(SPIi), ab)) {
5367c478bd9Sstevel@tonic-gate 			daSPImatch = true;
5377c478bd9Sstevel@tonic-gate 			break;
5387c478bd9Sstevel@tonic-gate 		    }
5397c478bd9Sstevel@tonic-gate 		}
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		if (!daSPImatch) {
5427c478bd9Sstevel@tonic-gate 		    return;
5437c478bd9Sstevel@tonic-gate 		}
5447c478bd9Sstevel@tonic-gate 	    }
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	if (conf.traceDATraffic()) {
5487c478bd9Sstevel@tonic-gate 	    conf.writeLog("sdat_forward",
5497c478bd9Sstevel@tonic-gate 			  new Object[] {
5507c478bd9Sstevel@tonic-gate 		Integer.toHexString(hdr.xid),
5517c478bd9Sstevel@tonic-gate 		    addr});
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	// Send it via TCP. DAs should understand TCP, and it's reliable.
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	SrvLocMsg rply = null;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	try {
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 	    // Construct the client side message, for outgoing.
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	    if (rqst instanceof SSrvReg) {
5657c478bd9Sstevel@tonic-gate 		SSrvReg rrqst = (SSrvReg)rqst;
5667c478bd9Sstevel@tonic-gate 		CSrvReg msg = new CSrvReg(hdr.fresh,
5677c478bd9Sstevel@tonic-gate 					  hdr.locale,
5687c478bd9Sstevel@tonic-gate 					  rrqst.URL,
5697c478bd9Sstevel@tonic-gate 					  hdr.scopes,
5707c478bd9Sstevel@tonic-gate 					  rrqst.attrList,
5717c478bd9Sstevel@tonic-gate 					  rrqst.URLSignature,
5727c478bd9Sstevel@tonic-gate 					  rrqst.attrSignature);
5737c478bd9Sstevel@tonic-gate 		rply = msg;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	    } else if (rqst instanceof SSrvDereg) {
5767c478bd9Sstevel@tonic-gate 		SSrvDereg drqst = (SSrvDereg)rqst;
5777c478bd9Sstevel@tonic-gate 		CSrvDereg msg = new CSrvDereg(hdr.locale,
5787c478bd9Sstevel@tonic-gate 					      drqst.URL,
5797c478bd9Sstevel@tonic-gate 					      hdr.scopes,
5807c478bd9Sstevel@tonic-gate 					      drqst.tags,
5817c478bd9Sstevel@tonic-gate 					      drqst.URLSignature);
5827c478bd9Sstevel@tonic-gate 		rply = msg;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	    } else if (rqst instanceof CSrvReg) {
5857c478bd9Sstevel@tonic-gate 		rply = rqst;
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 	    }
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	    rply = Transact.transactTCPMsg(addr, rply, false);
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	} catch (ServiceLocationException ex) {
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	    if (conf.traceDATraffic()) {
5947c478bd9Sstevel@tonic-gate 		conf.writeLog("sdat_forward_exception",
5957c478bd9Sstevel@tonic-gate 			      new Object[] {
5967c478bd9Sstevel@tonic-gate 		    Integer.toHexString(hdr.xid),
5977c478bd9Sstevel@tonic-gate 			addr,
5987c478bd9Sstevel@tonic-gate 			new Integer(ex.getErrorCode()),
5997c478bd9Sstevel@tonic-gate 			ex.getMessage()});
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	    }
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	// Report any errors.
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	if (rply == null ||
6077c478bd9Sstevel@tonic-gate 	    rply.getErrorCode() != ServiceLocationException.OK) {
6087c478bd9Sstevel@tonic-gate 	    if (conf.traceDATraffic()) {
6097c478bd9Sstevel@tonic-gate 		conf.writeLog("sdat_forward_err",
6107c478bd9Sstevel@tonic-gate 			      new Object[] {
6117c478bd9Sstevel@tonic-gate 		    Integer.toHexString(hdr.xid),
6127c478bd9Sstevel@tonic-gate 			addr,
6137c478bd9Sstevel@tonic-gate 			(rply == null ? "<null>":
6147c478bd9Sstevel@tonic-gate 			 Integer.toString(rply.getErrorCode()))});
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate 	    }
6177c478bd9Sstevel@tonic-gate 	}
6187c478bd9Sstevel@tonic-gate     }
6197c478bd9Sstevel@tonic-gate }
620