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