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 // ServiceTable.java: Storage of all services. 280Sstevel@tonic-gate // Author: James Kempf 290Sstevel@tonic-gate // Created On: Fri Oct 10 14:23:25 1997 300Sstevel@tonic-gate // Last Modified By: James Kempf 310Sstevel@tonic-gate // Last Modified On: Thu Apr 1 10:33:46 1999 320Sstevel@tonic-gate // Update Count: 461 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.io.*; 390Sstevel@tonic-gate import java.security.*; 400Sstevel@tonic-gate import java.net.*; 410Sstevel@tonic-gate 420Sstevel@tonic-gate /** 430Sstevel@tonic-gate * The ServiceTable object records all service registrations. Note 440Sstevel@tonic-gate * that any exceptions internal to the service table are processed 450Sstevel@tonic-gate * and either returned as SrvRply objects or are reported. 460Sstevel@tonic-gate * 470Sstevel@tonic-gate * @author James Kempf 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate 500Sstevel@tonic-gate class ServiceTable extends Object { 510Sstevel@tonic-gate 520Sstevel@tonic-gate // Key for SDAAdvert class. 530Sstevel@tonic-gate 540Sstevel@tonic-gate static final String SDAADVERT = "com.sun.slp.SDAAdvert"; 550Sstevel@tonic-gate 560Sstevel@tonic-gate private static final String locationMsg = "Service table"; 570Sstevel@tonic-gate 580Sstevel@tonic-gate // 590Sstevel@tonic-gate // Instance variables. 600Sstevel@tonic-gate // 610Sstevel@tonic-gate 620Sstevel@tonic-gate // The service store. 630Sstevel@tonic-gate 640Sstevel@tonic-gate protected ServiceStore store = null; 650Sstevel@tonic-gate 660Sstevel@tonic-gate // 670Sstevel@tonic-gate // Class variables. 680Sstevel@tonic-gate 690Sstevel@tonic-gate // System properties. 700Sstevel@tonic-gate 710Sstevel@tonic-gate static protected SLPConfig conf = null; 720Sstevel@tonic-gate 730Sstevel@tonic-gate // Singleton objects for the service tables. 740Sstevel@tonic-gate 750Sstevel@tonic-gate static protected ServiceTable table = null; 760Sstevel@tonic-gate 770Sstevel@tonic-gate // The ager thread. 780Sstevel@tonic-gate 790Sstevel@tonic-gate static protected AgerThread thrAger = null; 800Sstevel@tonic-gate 810Sstevel@tonic-gate // Time to sleep. Adjusted depending on incoming URLs. 820Sstevel@tonic-gate 830Sstevel@tonic-gate private static long sleepyTime = Defaults.lMaxSleepTime; 840Sstevel@tonic-gate 850Sstevel@tonic-gate // 860Sstevel@tonic-gate // Creation of singleton. 870Sstevel@tonic-gate // 880Sstevel@tonic-gate 890Sstevel@tonic-gate // Protected constructor. 900Sstevel@tonic-gate ServiceTable()910Sstevel@tonic-gate protected ServiceTable() { 920Sstevel@tonic-gate 930Sstevel@tonic-gate if (thrAger != null) { 940Sstevel@tonic-gate return; 950Sstevel@tonic-gate 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate // Create the ager thread. 990Sstevel@tonic-gate 1000Sstevel@tonic-gate thrAger = new AgerThread(); 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate // Set the priority low, so other things (like active discovery) 1030Sstevel@tonic-gate // take priority. 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate thrAger.setPriority(Thread.MIN_PRIORITY); 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate thrAger.start(); 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate /** 1120Sstevel@tonic-gate * Return an SA service store. 1130Sstevel@tonic-gate * 1140Sstevel@tonic-gate * @return The distinguished table object. 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate getServiceTable()1170Sstevel@tonic-gate static ServiceTable getServiceTable() 1180Sstevel@tonic-gate throws ServiceLocationException { 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate if (conf == null) { 1210Sstevel@tonic-gate conf = SLPConfig.getSLPConfig(); 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate if (table == null) { 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate table = createServiceTable(); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate return table; 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate /** 1350Sstevel@tonic-gate * Return a service table object. 1360Sstevel@tonic-gate * 1370Sstevel@tonic-gate * @return The service table object. 1380Sstevel@tonic-gate */ 1390Sstevel@tonic-gate createServiceTable()1400Sstevel@tonic-gate private static ServiceTable createServiceTable() 1410Sstevel@tonic-gate throws ServiceLocationException { 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate ServiceTable table = new ServiceTable(); 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate table.store = ServiceStoreFactory.createServiceStore(); 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate return table; 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate // 1510Sstevel@tonic-gate // Support for serializated registrations. 1520Sstevel@tonic-gate // 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate /** 1550Sstevel@tonic-gate * If any serialized registrations are pending, then unserialize 1560Sstevel@tonic-gate * and register. 1570Sstevel@tonic-gate */ 1580Sstevel@tonic-gate deserializeTable()1590Sstevel@tonic-gate public void deserializeTable() { 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate // If there are any serialized registrations, then get 1620Sstevel@tonic-gate // them and perform registrations. 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate String serializedURL = conf.getSerializedRegURL(); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate if (serializedURL != null) { 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate ServiceStore serStore = getStoreFromURL(serializedURL); 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate if (serStore != null) { 1710Sstevel@tonic-gate registerStore(serStore); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate /** 1770Sstevel@tonic-gate * Serialize the table to the URL. 1780Sstevel@tonic-gate * 1790Sstevel@tonic-gate * @param URL String giving the URL to which the store should be 1800Sstevel@tonic-gate * serialized. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate serializeServiceStore(String URL)1830Sstevel@tonic-gate void serializeServiceStore(String URL) { 1840Sstevel@tonic-gate 1850Sstevel@tonic-gate // Open an object output stream for the URL, serialize through 1860Sstevel@tonic-gate // the factory. 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate try { 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate URL url = new URL(URL); 1910Sstevel@tonic-gate URLConnection urlConn = url.openConnection(); 1920Sstevel@tonic-gate OutputStream os = urlConn.getOutputStream(); 1930Sstevel@tonic-gate BufferedWriter di = 1940Sstevel@tonic-gate new BufferedWriter(new OutputStreamWriter(os)); 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate // Serialize the store. 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate ServiceStoreFactory.serialize(di, store); 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate } catch (MalformedURLException ex) { 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate conf.writeLog("st_serialized_malform", 2030Sstevel@tonic-gate new Object[] {URL}); 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate } catch (UnsupportedEncodingException ex) { 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate conf.writeLog("st_unsupported_encoding", 2080Sstevel@tonic-gate new Object[] {URL}); 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate } catch (IOException ex) { 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate conf.writeLog("st_serialized_ioexception", 2130Sstevel@tonic-gate new Object[] {URL, ex}); 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate } catch (ServiceLocationException ex) { 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate conf.writeLog("st_serialized_sle", 2180Sstevel@tonic-gate new Object[] {URL, ex.getMessage()}); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate } 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate // Read proxy registrations from the URL. 2250Sstevel@tonic-gate getStoreFromURL(String serializedURL)2260Sstevel@tonic-gate private ServiceStore getStoreFromURL(String serializedURL) { 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate ServiceStore serStore = null; 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate // Open an object input stream for the URL, deserialize through 2310Sstevel@tonic-gate // the factory. 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate try { 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate URL url = new URL(serializedURL); 2360Sstevel@tonic-gate InputStream is = url.openStream(); 2370Sstevel@tonic-gate BufferedReader di = new BufferedReader(new InputStreamReader(is)); 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate // Deserialize the objects. 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate serStore = 2420Sstevel@tonic-gate ServiceStoreFactory.deserializeServiceStore(di); 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate } catch (MalformedURLException ex) { 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate conf.writeLog("st_serialized_malform", 2470Sstevel@tonic-gate new Object[] {serializedURL}); 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate } catch (UnsupportedEncodingException ex) { 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate conf.writeLog("st_unsupported_encoding", 2520Sstevel@tonic-gate new Object[] {serializedURL}); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate } catch (IOException ex) { 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate conf.writeLog("st_serialized_ioexception", 2570Sstevel@tonic-gate new Object[] { 2580Sstevel@tonic-gate serializedURL, 2590Sstevel@tonic-gate ex.getMessage()}); 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate } catch (ServiceLocationException ex) { 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate conf.writeLog("st_serialized_sle", 2640Sstevel@tonic-gate new Object[] { 2650Sstevel@tonic-gate serializedURL, 2660Sstevel@tonic-gate ex.getMessage()}); 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate return serStore; 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate // Walk the table, performing actual registrations on all records. 2740Sstevel@tonic-gate registerStore(ServiceStore serStore)2750Sstevel@tonic-gate private void registerStore(ServiceStore serStore) { 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate // Walk the table. 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate Enumeration en = serStore.getServiceRecordsByScope(null); 2800Sstevel@tonic-gate boolean hasURLSig = conf.getHasSecurity(); 2810Sstevel@tonic-gate boolean hasAttrSig = conf.getHasSecurity(); 2820Sstevel@tonic-gate PermSARegTable pregTable = SARequester.getPermSARegTable(); 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate while (en.hasMoreElements()) { 2850Sstevel@tonic-gate ServiceStore.ServiceRecord rec = 2860Sstevel@tonic-gate (ServiceStore.ServiceRecord)en.nextElement(); 2870Sstevel@tonic-gate ServiceURL surl = rec.getServiceURL(); 2880Sstevel@tonic-gate Vector scopes = rec.getScopes(); 2890Sstevel@tonic-gate Vector attrs = rec.getAttrList(); 2900Sstevel@tonic-gate Locale locale = rec.getLocale(); 2910Sstevel@tonic-gate Hashtable urlSig = null; 2920Sstevel@tonic-gate Hashtable attrSig = null; 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate // Note that we can't use the Advertiser to register here, 2950Sstevel@tonic-gate // because we may not be listening yet for registrations. 2960Sstevel@tonic-gate // We need to do this all by hand. 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate try { 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate // Create a registration message for refreshing. 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate CSrvReg creg = new CSrvReg(false, 3030Sstevel@tonic-gate locale, 3040Sstevel@tonic-gate surl, 3050Sstevel@tonic-gate scopes, 3060Sstevel@tonic-gate attrs, 3070Sstevel@tonic-gate null, 3080Sstevel@tonic-gate null); 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate // We externalize to a server side message if authentication 3110Sstevel@tonic-gate // is needed. This creates the auth blocks for the scopes. 3120Sstevel@tonic-gate // Doing this in any other way is alot more complicated, 3130Sstevel@tonic-gate // although doing it this way seems kludgy. 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate if (hasURLSig || hasAttrSig) { 3160Sstevel@tonic-gate ByteArrayOutputStream baos = new ByteArrayOutputStream(); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate creg.getHeader().externalize(baos, false, true); 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate ByteArrayInputStream bais = 3210Sstevel@tonic-gate new ByteArrayInputStream(baos.toByteArray()); 3220Sstevel@tonic-gate bais.read(); // pop off version and function code... 3230Sstevel@tonic-gate bais.read(); 3240Sstevel@tonic-gate DataInputStream dis = new DataInputStream(bais); 3250Sstevel@tonic-gate SLPHeaderV2 hdr = new SLPHeaderV2(); 3260Sstevel@tonic-gate hdr.parseHeader(SrvLocHeader.SrvReg, dis); 3270Sstevel@tonic-gate SSrvReg sreg = new SSrvReg(hdr, dis); 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate // Now we've got it, after much effort. Get the auths. 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate urlSig = sreg.URLSignature; 3320Sstevel@tonic-gate attrSig = sreg.attrSignature; 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate store.register(surl, attrs, scopes, locale, urlSig, attrSig); 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate // Now we've got to put the registration into the 3390Sstevel@tonic-gate // PermSARegTable. Again, we do everything by hand 3400Sstevel@tonic-gate // because we can't use Advertiser. 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate if (surl.getIsPermanent()) { 3430Sstevel@tonic-gate pregTable.reg(surl, creg); 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate // Report registration. 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate if (conf.regTest()) { 3500Sstevel@tonic-gate conf.writeLog("st_reg_add", 3510Sstevel@tonic-gate new Object[] { 3520Sstevel@tonic-gate locationMsg, 3530Sstevel@tonic-gate locale, 3540Sstevel@tonic-gate surl.getServiceType(), 3550Sstevel@tonic-gate surl, 3560Sstevel@tonic-gate attrs, 3570Sstevel@tonic-gate scopes}); 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate } 3600Sstevel@tonic-gate } catch (ServiceLocationException ex) { 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate String msg = ex.getMessage(); 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate conf.writeLog("st_serialized_seex", 3650Sstevel@tonic-gate new Object[] { 3660Sstevel@tonic-gate new Integer(ex.getErrorCode()), 3670Sstevel@tonic-gate surl, 3680Sstevel@tonic-gate (msg == null ? "<no message>":msg)}); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate } catch (Exception ex) { 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate String msg = ex.getMessage(); 3730Sstevel@tonic-gate 3740Sstevel@tonic-gate conf.writeLog("st_serialized_seex", 3750Sstevel@tonic-gate new Object[] { 3760Sstevel@tonic-gate surl, 3770Sstevel@tonic-gate (msg == null ? "<no message>":msg)}); 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate // 3830Sstevel@tonic-gate // Record aging. 3840Sstevel@tonic-gate // 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate // 3870Sstevel@tonic-gate // Run the thread that ages out records. 3880Sstevel@tonic-gate // 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate private class AgerThread extends Thread { 3910Sstevel@tonic-gate run()3920Sstevel@tonic-gate public void run() { 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate setName("SLP Service Table Age-out"); 3950Sstevel@tonic-gate long alarmTime = sleepyTime; // when to wake up next 3960Sstevel@tonic-gate long wentToSleep = 0; // what time we went to bed 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate while (true) { 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate try { 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate // Record when we went to sleep. 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate wentToSleep = System.currentTimeMillis(); 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate // Sleep for the minimum amount of time needed before we 4070Sstevel@tonic-gate // must wake up and check. 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate sleep(alarmTime); 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate } catch (InterruptedException ie) { 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate // A new registration came in. Calculate how much time 4140Sstevel@tonic-gate // remains until we would have woken up. If this is 4150Sstevel@tonic-gate // less than the new sleepyTime, then we set the alarm 4160Sstevel@tonic-gate // for this time. If it is more, then we set the alarm 4170Sstevel@tonic-gate // for the new sleepyTime. 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate long remainingSleepTime = 4200Sstevel@tonic-gate (wentToSleep + alarmTime) - System.currentTimeMillis(); 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate remainingSleepTime = // just in case... 4230Sstevel@tonic-gate ((remainingSleepTime <= 0) ? 0 : remainingSleepTime); 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate alarmTime = sleepyTime; 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate if (remainingSleepTime < alarmTime) { 4280Sstevel@tonic-gate alarmTime = remainingSleepTime; 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate 4320Sstevel@tonic-gate continue; // we don't have to walk yet... 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate // Walk the table, get the new alarm and sleepy times. 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate if (table != null) { 4390Sstevel@tonic-gate table.ageStore(); 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate alarmTime = sleepyTime; 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate } 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate /** 4500Sstevel@tonic-gate * Age the service store. 4510Sstevel@tonic-gate */ 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate // this method cannot be private... due to compiler weakness ageStore()4540Sstevel@tonic-gate void ageStore() { 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate try { 4570Sstevel@tonic-gate 4580Sstevel@tonic-gate // We synchronize in case somebody registers and tries to 4590Sstevel@tonic-gate // change sleepy time. 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate synchronized (store) { 4620Sstevel@tonic-gate Vector deleted = new Vector(); 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate sleepyTime = store.ageOut(deleted); 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate // Track unregistered services. 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate int i, n = deleted.size(); 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate for (i = 0; i < n; i++) { 4710Sstevel@tonic-gate ServiceStore.ServiceRecord rec = 4720Sstevel@tonic-gate (ServiceStore.ServiceRecord)deleted.elementAt(i); 4730Sstevel@tonic-gate ServiceURL surl = rec.getServiceURL(); 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate trackRegisteredServiceTypes(); // it's deleted... 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate } catch (RuntimeException ex) { 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate reportNonfatalException(ex, new Vector(), store); 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate } catch (ServiceLocationException ex) { 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate reportNonfatalException(ex, new Vector(), store); 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate // 4940Sstevel@tonic-gate // SLP Service Table operations (register, deregister, etc.) 4950Sstevel@tonic-gate // 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate /** 4980Sstevel@tonic-gate * Process the registration and record if no errors found. 4990Sstevel@tonic-gate * 5000Sstevel@tonic-gate * @param req Service registration request message. 5010Sstevel@tonic-gate * @return SrvLocMsg A service registration acknowledgement. 5020Sstevel@tonic-gate */ 5030Sstevel@tonic-gate register(SSrvReg req)5040Sstevel@tonic-gate SrvLocMsg register(SSrvReg req) { 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate SrvLocHeader hdr = req.getHeader(); 5070Sstevel@tonic-gate Locale locale = hdr.locale; 5080Sstevel@tonic-gate boolean fresh = hdr.fresh; 5090Sstevel@tonic-gate Vector scopes = hdr.scopes; 5100Sstevel@tonic-gate ServiceURL surl = req.URL; 5110Sstevel@tonic-gate String serviceType = req.serviceType; 5120Sstevel@tonic-gate Vector attrList = req.attrList; 5130Sstevel@tonic-gate Hashtable urlSig = req.URLSignature; 5140Sstevel@tonic-gate Hashtable attrSig = req.attrSignature; 5150Sstevel@tonic-gate short errorCode = 5160Sstevel@tonic-gate (fresh ? ServiceLocationException.INVALID_REGISTRATION : 5170Sstevel@tonic-gate ServiceLocationException.INVALID_UPDATE); 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate try { 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate // If a sig block came in, verify it. 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate if (urlSig != null) { 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate AuthBlock.verifyAll(urlSig); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate if (attrSig != null) { 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate AuthBlock.verifyAll(attrSig); 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate // Check whether the URL has a zero lifetime. If so, it 5350Sstevel@tonic-gate // isn't cached. 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate if (surl.getLifetime() <= 0) { 5380Sstevel@tonic-gate throw 5390Sstevel@tonic-gate new ServiceLocationException(errorCode, 5400Sstevel@tonic-gate "st_zero", 5410Sstevel@tonic-gate new Object[0]); 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate // Check if the service type is restricted. If so, nobody outside 5460Sstevel@tonic-gate // this process is allowed to register it. 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate checkForRestrictedType(surl.getServiceType()); 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate // Check that attribute signature bit on implies URL signature 5510Sstevel@tonic-gate // bit on. 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate if (attrSig != null && urlSig == null) { 5540Sstevel@tonic-gate throw 5550Sstevel@tonic-gate new ServiceLocationException(errorCode, 5560Sstevel@tonic-gate "st_attr_sig", 5570Sstevel@tonic-gate new Object[0]); 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate } 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate // If a signature and the fresh bit was not set, error since signed 5620Sstevel@tonic-gate // registrations don't allow updating. 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate if (urlSig != null && !fresh) { 5650Sstevel@tonic-gate throw 5660Sstevel@tonic-gate new ServiceLocationException( 5670Sstevel@tonic-gate ServiceLocationException.INVALID_UPDATE, 5680Sstevel@tonic-gate "st_prot_update", 5690Sstevel@tonic-gate new Object[0]); 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate // Check if scopes are supported. 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate if (!areSupportedScopes(scopes)) { 5750Sstevel@tonic-gate throw 5760Sstevel@tonic-gate new ServiceLocationException( 5770Sstevel@tonic-gate ServiceLocationException.SCOPE_NOT_SUPPORTED, 5780Sstevel@tonic-gate "st_scope_unsup", 5790Sstevel@tonic-gate new Object[0]); 5800Sstevel@tonic-gate } 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate // Check if the reg is signed and auth is off or vice versa. 5830Sstevel@tonic-gate // Check is really simple. If security is on, then all regs 5840Sstevel@tonic-gate // to this DA/SA server must be signed, so toss out any regs 5850Sstevel@tonic-gate // that aren't, and vice versa. 5860Sstevel@tonic-gate 5870Sstevel@tonic-gate if (conf.getHasSecurity() && (urlSig == null || attrSig == null)) { 5880Sstevel@tonic-gate throw 5890Sstevel@tonic-gate new ServiceLocationException( 5900Sstevel@tonic-gate ServiceLocationException.AUTHENTICATION_FAILED, 5910Sstevel@tonic-gate "st_unprot_non_reg", 5920Sstevel@tonic-gate new Object[0]); 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate } else if (!conf.getHasSecurity() && 5950Sstevel@tonic-gate (urlSig != null || attrSig != null)) { 5960Sstevel@tonic-gate throw 5970Sstevel@tonic-gate new ServiceLocationException( 5980Sstevel@tonic-gate ServiceLocationException.INVALID_REGISTRATION, 5990Sstevel@tonic-gate "st_prot_non_reg", 6000Sstevel@tonic-gate new Object[0]); 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate } 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate // Merge any duplicates. 6050Sstevel@tonic-gate 6060Sstevel@tonic-gate Vector attrs = new Vector(); 6070Sstevel@tonic-gate Hashtable attrHash = new Hashtable(); 6080Sstevel@tonic-gate int i, n = attrList.size(); 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate for (i = 0; i < n; i++) { 6110Sstevel@tonic-gate ServiceLocationAttribute attr = 6120Sstevel@tonic-gate (ServiceLocationAttribute)attrList.elementAt(i); 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate ServiceLocationAttribute.mergeDuplicateAttributes( 6150Sstevel@tonic-gate attr, 6160Sstevel@tonic-gate attrHash, 6170Sstevel@tonic-gate attrs, 6180Sstevel@tonic-gate false); 6190Sstevel@tonic-gate } 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate // Store register or update. 6220Sstevel@tonic-gate 6230Sstevel@tonic-gate boolean existing = false; 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate if (fresh) { 6260Sstevel@tonic-gate existing = store.register(surl, 6270Sstevel@tonic-gate attrs, 6280Sstevel@tonic-gate scopes, 6290Sstevel@tonic-gate locale, 6300Sstevel@tonic-gate urlSig, 6310Sstevel@tonic-gate attrSig); 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate // Track registred service types in case we get a 6340Sstevel@tonic-gate // SAAdvert solicatation. 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate trackRegisteredServiceTypes(); 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate } else { 6390Sstevel@tonic-gate store.updateRegistration(surl, attrs, scopes, locale); 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate // Create the reply. 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate SrvLocMsg ack = req.makeReply(existing); 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate if (conf.regTest()) { 6480Sstevel@tonic-gate conf.writeLog((fresh ? "st_reg_add":"st_reg_update"), 6490Sstevel@tonic-gate new Object[] { 6500Sstevel@tonic-gate locationMsg, 6510Sstevel@tonic-gate locale, 6520Sstevel@tonic-gate serviceType, 6530Sstevel@tonic-gate surl, 6540Sstevel@tonic-gate attrs, 6550Sstevel@tonic-gate scopes}); 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate } 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate if (conf.traceAll()) { 6600Sstevel@tonic-gate conf.writeLog("st_dump", new Object[] {locationMsg}); 6610Sstevel@tonic-gate store.dumpServiceStore(); 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate // Calculate time increment until next update. This is used 6660Sstevel@tonic-gate // to adjust the sleep interval in the ager thread. 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate long sTime = getSleepIncrement(surl); 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate // We synchronize in case the ager thread is in the middle 6710Sstevel@tonic-gate // of trying to set the time. 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate synchronized (store) { 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate // If we need to wake up sooner, adjust the sleep time. 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate if (sTime < sleepyTime) { 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate sleepyTime = sTime; 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate // Interrupt the thread so we go back to 6820Sstevel@tonic-gate // sleep for the right amount of time. 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate thrAger.interrupt(); 6850Sstevel@tonic-gate } 6860Sstevel@tonic-gate } 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate return ack; 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate } catch (ServiceLocationException ex) { 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate if (conf.traceDrop()) { 6930Sstevel@tonic-gate conf.writeLog("st_reg_drop", 6940Sstevel@tonic-gate new Object[] { 6950Sstevel@tonic-gate locationMsg, 6960Sstevel@tonic-gate ex.getMessage()+"("+ex.getErrorCode()+")", 6970Sstevel@tonic-gate locale, 6980Sstevel@tonic-gate serviceType, 6990Sstevel@tonic-gate surl, 7000Sstevel@tonic-gate attrList, 7010Sstevel@tonic-gate scopes}); 7020Sstevel@tonic-gate } 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate return hdr.makeErrorReply(ex); 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate } catch (RuntimeException ex) { 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate // These exceptions are not declared in throws but can occur 7090Sstevel@tonic-gate // anywhere. 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate Vector args = new Vector(); 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate args.addElement(req); 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate reportNonfatalException(ex, args, store); 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate return hdr.makeErrorReply(ex); 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate } 7210Sstevel@tonic-gate 7220Sstevel@tonic-gate /** 7230Sstevel@tonic-gate * Process the deregistration and return the result in a reply. 7240Sstevel@tonic-gate * 7250Sstevel@tonic-gate * @param req Service deregistration request message. 7260Sstevel@tonic-gate * @return SrvLocMsg A service registration acknowledgement. 7270Sstevel@tonic-gate */ 7280Sstevel@tonic-gate deregister(SSrvDereg req)7290Sstevel@tonic-gate SrvLocMsg deregister(SSrvDereg req) { 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate // We need to determine whether this is an attribute deregistration 7320Sstevel@tonic-gate // or a deregistration of the entire URL. 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate SrvLocHeader hdr = req.getHeader(); 7350Sstevel@tonic-gate Locale locale = hdr.locale; 7360Sstevel@tonic-gate Vector scopes = hdr.scopes; 7370Sstevel@tonic-gate ServiceURL surl = req.URL; 7380Sstevel@tonic-gate Hashtable urlSig = req.URLSignature; 7390Sstevel@tonic-gate Vector tags = req.tags; 7400Sstevel@tonic-gate short errorCode = ServiceLocationException.OK; 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate try { 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate // Verify if signature is nonnull. 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate if (urlSig != null) { 7470Sstevel@tonic-gate AuthBlock.verifyAll(urlSig); 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate } 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate // Check if the service type is restricted. If so, nobody outside 7520Sstevel@tonic-gate // this process is allowed to register it. 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate checkForRestrictedType(surl.getServiceType()); 7550Sstevel@tonic-gate 7560Sstevel@tonic-gate // Error if there's a signature and attempt at deleting attributes. 7570Sstevel@tonic-gate 7580Sstevel@tonic-gate if ((urlSig != null) && (tags != null)) { 7590Sstevel@tonic-gate throw 7600Sstevel@tonic-gate new ServiceLocationException( 7610Sstevel@tonic-gate ServiceLocationException.AUTHENTICATION_FAILED, 7620Sstevel@tonic-gate "st_prot_attr_dereg", 7630Sstevel@tonic-gate new Object[0]); 7640Sstevel@tonic-gate } 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate // Check if scope is protected and auth is off or vice versa. 7670Sstevel@tonic-gate // Check is really simple. If security is on, then all scopes 7680Sstevel@tonic-gate // in this DA/SA server are protected, so toss out any regs 7690Sstevel@tonic-gate // that aren't, and vice versa. 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate if (conf.getHasSecurity() && urlSig == null) { 7720Sstevel@tonic-gate throw 7730Sstevel@tonic-gate new ServiceLocationException( 7740Sstevel@tonic-gate ServiceLocationException.AUTHENTICATION_FAILED, 7750Sstevel@tonic-gate "st_unprot_non_dereg", 7760Sstevel@tonic-gate new Object[0]); 7770Sstevel@tonic-gate 7780Sstevel@tonic-gate } else if (!conf.getHasSecurity() && urlSig != null) { 7790Sstevel@tonic-gate throw 7800Sstevel@tonic-gate new ServiceLocationException( 7810Sstevel@tonic-gate ServiceLocationException.INVALID_REGISTRATION, 7820Sstevel@tonic-gate "st_prot_non_dereg", 7830Sstevel@tonic-gate new Object[0]); 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate } 7860Sstevel@tonic-gate 7870Sstevel@tonic-gate // If it's a service URL, then deregister the URL. 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate if (tags == null) { 7900Sstevel@tonic-gate store.deregister(surl, scopes, urlSig); 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate // Track registred service types in case we get a 7930Sstevel@tonic-gate // SAAdvert solicatation. 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate trackRegisteredServiceTypes(); 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate } else { 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate // Just delete the attributes. 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate store.deleteAttributes(surl, scopes, tags, locale); 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate // Create the reply. 8060Sstevel@tonic-gate 8070Sstevel@tonic-gate SrvLocMsg ack = req.makeReply(); 8080Sstevel@tonic-gate 8090Sstevel@tonic-gate if (conf.regTest()) { 8100Sstevel@tonic-gate conf.writeLog((tags == null ? "st_dereg":"st_delattr"), 8110Sstevel@tonic-gate new Object[] { 8120Sstevel@tonic-gate locationMsg, 8130Sstevel@tonic-gate locale, 8140Sstevel@tonic-gate surl.getServiceType(), 8150Sstevel@tonic-gate surl, 8160Sstevel@tonic-gate tags}); 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate } 8190Sstevel@tonic-gate 8200Sstevel@tonic-gate if (conf.traceAll()) { 8210Sstevel@tonic-gate conf.writeLog("st_dump", 8220Sstevel@tonic-gate new Object[] {locationMsg}); 8230Sstevel@tonic-gate store.dumpServiceStore(); 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate return ack; 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate } catch (ServiceLocationException ex) { 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate if (conf.traceDrop()) { 8320Sstevel@tonic-gate conf.writeLog((tags == null ? 8330Sstevel@tonic-gate "st_dereg_drop" : "st_dereg_attr_drop"), 8340Sstevel@tonic-gate new Object[] { 8350Sstevel@tonic-gate locationMsg, 8360Sstevel@tonic-gate ex.getMessage()+"("+ex.getErrorCode()+")", 8370Sstevel@tonic-gate locale, 8380Sstevel@tonic-gate surl.getServiceType(), 8390Sstevel@tonic-gate surl, 8400Sstevel@tonic-gate tags}); 8410Sstevel@tonic-gate } 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate return hdr.makeErrorReply(ex); 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate } catch (RuntimeException ex) { 8460Sstevel@tonic-gate 8470Sstevel@tonic-gate // These exceptions are not declared in throws but can occur 8480Sstevel@tonic-gate // anywhere. 8490Sstevel@tonic-gate 8500Sstevel@tonic-gate Vector args = new Vector(); 8510Sstevel@tonic-gate 8520Sstevel@tonic-gate args.addElement(req); 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate reportNonfatalException(ex, args, store); 8550Sstevel@tonic-gate 8560Sstevel@tonic-gate return hdr.makeErrorReply(ex); 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate } 8590Sstevel@tonic-gate } 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate /** 8620Sstevel@tonic-gate * Process the service type request and return the result in a reply. 8630Sstevel@tonic-gate * 8640Sstevel@tonic-gate * @param req Service type request message. 8650Sstevel@tonic-gate * @return SrvTypeRply A service type reply. 8660Sstevel@tonic-gate */ 8670Sstevel@tonic-gate findServiceTypes(SSrvTypeMsg req)8680Sstevel@tonic-gate SrvLocMsg findServiceTypes(SSrvTypeMsg req) { 8690Sstevel@tonic-gate 8700Sstevel@tonic-gate SrvLocHeader hdr = req.getHeader(); 8710Sstevel@tonic-gate Vector scopes = hdr.scopes; 8720Sstevel@tonic-gate String namingAuthority = req.namingAuthority; 8730Sstevel@tonic-gate short errorCode = ServiceLocationException.OK; 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate try { 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate // Check whether the scope is supported. 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate if (!areSupportedScopes(scopes)) { 8800Sstevel@tonic-gate throw 8810Sstevel@tonic-gate new ServiceLocationException( 8820Sstevel@tonic-gate ServiceLocationException.SCOPE_NOT_SUPPORTED, 8830Sstevel@tonic-gate "st_scope_unsup", 8840Sstevel@tonic-gate new Object[0]); 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate } 8870Sstevel@tonic-gate 8880Sstevel@tonic-gate // Get the vector of service types in the store, independent 8890Sstevel@tonic-gate // of language. 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate Vector types = store.findServiceTypes(namingAuthority, scopes); 8920Sstevel@tonic-gate 8930Sstevel@tonic-gate // Create the reply. 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate SrvLocMsg ack = req.makeReply(types); 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate if (conf.traceAll()) { 8980Sstevel@tonic-gate conf.writeLog("st_stypes", 8990Sstevel@tonic-gate new Object[] { 9000Sstevel@tonic-gate locationMsg, 9010Sstevel@tonic-gate namingAuthority, 9020Sstevel@tonic-gate scopes, 9030Sstevel@tonic-gate types}); 9040Sstevel@tonic-gate } 9050Sstevel@tonic-gate 9060Sstevel@tonic-gate return ack; 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate } catch (ServiceLocationException ex) { 9090Sstevel@tonic-gate 9100Sstevel@tonic-gate if (conf.traceDrop()) { 9110Sstevel@tonic-gate conf.writeLog("st_stypes_drop", 9120Sstevel@tonic-gate new Object[] { 9130Sstevel@tonic-gate locationMsg, 9140Sstevel@tonic-gate ex.getMessage()+"("+ex.getErrorCode()+")", 9150Sstevel@tonic-gate namingAuthority, 9160Sstevel@tonic-gate scopes, 9170Sstevel@tonic-gate hdr.locale}); 9180Sstevel@tonic-gate } 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate return hdr.makeErrorReply(ex); 9210Sstevel@tonic-gate 9220Sstevel@tonic-gate } catch (RuntimeException ex) { 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate // These exceptions are not declared in throws but can occur 9250Sstevel@tonic-gate // anywhere. 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate Vector args = new Vector(); 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate args.addElement(req); 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate reportNonfatalException(ex, args, store); 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate return hdr.makeErrorReply(ex); 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate } 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate /** 9390Sstevel@tonic-gate * Process the service request and return the result in a reply. 9400Sstevel@tonic-gate * 9410Sstevel@tonic-gate * @param req Service request message. 9420Sstevel@tonic-gate * @return SrvRply A service reply. 9430Sstevel@tonic-gate */ 9440Sstevel@tonic-gate findServices(SSrvMsg req)9450Sstevel@tonic-gate SrvLocMsg findServices(SSrvMsg req) { 9460Sstevel@tonic-gate 9470Sstevel@tonic-gate SrvLocHeader hdr = req.getHeader(); 9480Sstevel@tonic-gate Locale locale = hdr.locale; 9490Sstevel@tonic-gate Vector scopes = hdr.scopes; 9500Sstevel@tonic-gate String serviceType = req.serviceType; 9510Sstevel@tonic-gate String query = req.query; 9520Sstevel@tonic-gate short errorCode = ServiceLocationException.OK; 9530Sstevel@tonic-gate 9540Sstevel@tonic-gate try { 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate // Check whether the scope is supported. 9570Sstevel@tonic-gate 9580Sstevel@tonic-gate if (!areSupportedScopes(scopes)) { 9590Sstevel@tonic-gate throw 9600Sstevel@tonic-gate new ServiceLocationException( 9610Sstevel@tonic-gate ServiceLocationException.SCOPE_NOT_SUPPORTED, 9620Sstevel@tonic-gate "st_scope_unsup", 9630Sstevel@tonic-gate new Object[0]); 9640Sstevel@tonic-gate } 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate // Get the hashtable of returns. 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate Hashtable returns = 9690Sstevel@tonic-gate store.findServices(serviceType, 9700Sstevel@tonic-gate scopes, 9710Sstevel@tonic-gate query, 9720Sstevel@tonic-gate locale); 9730Sstevel@tonic-gate 9740Sstevel@tonic-gate // Get the hashtable of services v.s. scopes, and signatures, if 9750Sstevel@tonic-gate // any. 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate Hashtable services = 9780Sstevel@tonic-gate (Hashtable)returns.get(ServiceStore.FS_SERVICES); 9790Sstevel@tonic-gate Hashtable signatures = 9800Sstevel@tonic-gate (Hashtable)returns.get(ServiceStore.FS_SIGTABLE); 9810Sstevel@tonic-gate boolean hasSignatures = (signatures != null); 9820Sstevel@tonic-gate 9830Sstevel@tonic-gate // for each candidate URL, make sure it has the requested SPI 9840Sstevel@tonic-gate // (if any) 9850Sstevel@tonic-gate if (hasSignatures && !req.spi.equals("")) { 9860Sstevel@tonic-gate Enumeration allSurls = services.keys(); 9870Sstevel@tonic-gate while (allSurls.hasMoreElements()) { 9880Sstevel@tonic-gate Object aSurl = allSurls.nextElement(); 9890Sstevel@tonic-gate Hashtable auths = (Hashtable) signatures.get(aSurl); 9900Sstevel@tonic-gate AuthBlock auth = 9910Sstevel@tonic-gate AuthBlock.getEquivalentAuth(req.spi, auths); 9920Sstevel@tonic-gate if (auth == null) { 9930Sstevel@tonic-gate // doesn't have the requested SPI 9940Sstevel@tonic-gate services.remove(aSurl); 9950Sstevel@tonic-gate } 9960Sstevel@tonic-gate } 9970Sstevel@tonic-gate } 9980Sstevel@tonic-gate 9990Sstevel@tonic-gate // Create return message. 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate SrvLocMsg ack = req.makeReply(services, signatures); 10020Sstevel@tonic-gate 10030Sstevel@tonic-gate if (conf.traceAll()) { 10040Sstevel@tonic-gate conf.writeLog("st_sreq", 10050Sstevel@tonic-gate new Object[] { 10060Sstevel@tonic-gate locationMsg, 10070Sstevel@tonic-gate serviceType, 10080Sstevel@tonic-gate scopes, 10090Sstevel@tonic-gate query, 10100Sstevel@tonic-gate locale, 10110Sstevel@tonic-gate services, 10120Sstevel@tonic-gate signatures}); 10130Sstevel@tonic-gate } 10140Sstevel@tonic-gate 10150Sstevel@tonic-gate return ack; 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate } catch (ServiceLocationException ex) { 10180Sstevel@tonic-gate 10190Sstevel@tonic-gate if (conf.traceDrop()) { 10200Sstevel@tonic-gate conf.writeLog("st_sreq_drop", 10210Sstevel@tonic-gate new Object[] { 10220Sstevel@tonic-gate locationMsg, 10230Sstevel@tonic-gate ex.getMessage()+"("+ex.getErrorCode()+")", 10240Sstevel@tonic-gate serviceType, 10250Sstevel@tonic-gate scopes, 10260Sstevel@tonic-gate query, 10270Sstevel@tonic-gate locale}); 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate return hdr.makeErrorReply(ex); 10310Sstevel@tonic-gate 10320Sstevel@tonic-gate } catch (RuntimeException ex) { 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate // These exceptions are not declared in throws but can occur 10350Sstevel@tonic-gate // anywhere. 10360Sstevel@tonic-gate 10370Sstevel@tonic-gate Vector args = new Vector(); 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate args.addElement(req); 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate reportNonfatalException(ex, args, store); 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate return hdr.makeErrorReply(ex); 10440Sstevel@tonic-gate 10450Sstevel@tonic-gate } 10460Sstevel@tonic-gate } 10470Sstevel@tonic-gate 10480Sstevel@tonic-gate /** 10490Sstevel@tonic-gate * Process the attribute request and return the result in a reply. 10500Sstevel@tonic-gate * 10510Sstevel@tonic-gate * @param req Attribute request message. 10520Sstevel@tonic-gate * @return AttrRply An attribute reply. 10530Sstevel@tonic-gate */ 10540Sstevel@tonic-gate findAttributes(SAttrMsg req)10550Sstevel@tonic-gate SrvLocMsg findAttributes(SAttrMsg req) { 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate // We need to determine whether this is a request for attributes 10580Sstevel@tonic-gate // on a specific URL or for an entire service type. 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate SrvLocHeader hdr = req.getHeader(); 10610Sstevel@tonic-gate Vector scopes = hdr.scopes; 10620Sstevel@tonic-gate Locale locale = hdr.locale; 10630Sstevel@tonic-gate ServiceURL surl = req.URL; 10640Sstevel@tonic-gate String serviceType = req.serviceType; 10650Sstevel@tonic-gate Vector tags = req.tags; 10660Sstevel@tonic-gate short errorCode = ServiceLocationException.OK; 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate try { 10690Sstevel@tonic-gate 10700Sstevel@tonic-gate // Check whether the scope is supported. 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate if (!areSupportedScopes(scopes)) { 10730Sstevel@tonic-gate throw 10740Sstevel@tonic-gate new ServiceLocationException( 10750Sstevel@tonic-gate ServiceLocationException.SCOPE_NOT_SUPPORTED, 10760Sstevel@tonic-gate "st_scope_unsup", 10770Sstevel@tonic-gate new Object[0]); 10780Sstevel@tonic-gate } 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate Vector attributes = null; 10810Sstevel@tonic-gate Hashtable sig = null; 10820Sstevel@tonic-gate 10830Sstevel@tonic-gate // If it's a service URL, then get the attributes just for 10840Sstevel@tonic-gate // that URL. 10850Sstevel@tonic-gate 10860Sstevel@tonic-gate if (serviceType == null) { 10870Sstevel@tonic-gate 10880Sstevel@tonic-gate // If the attrs are signed, then error if any tags, since 10890Sstevel@tonic-gate // we must ask for *all* attributes in for a signed reg 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate if (!req.spi.equals("") && tags.size() > 0) { 10920Sstevel@tonic-gate throw 10930Sstevel@tonic-gate new ServiceLocationException( 10940Sstevel@tonic-gate ServiceLocationException.AUTHENTICATION_FAILED, 10950Sstevel@tonic-gate "st_par_attr", 10960Sstevel@tonic-gate new Object[0]); 10970Sstevel@tonic-gate 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate Hashtable ht = 11010Sstevel@tonic-gate store.findAttributes(surl, scopes, tags, locale); 11020Sstevel@tonic-gate 11030Sstevel@tonic-gate // Get the attributes and signatures. 11040Sstevel@tonic-gate 11050Sstevel@tonic-gate attributes = (Vector)ht.get(ServiceStore.FA_ATTRIBUTES); 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate sig = (Hashtable)ht.get(ServiceStore.FA_SIG); 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate // make sure the attr has the requested SPI (if any) 11100Sstevel@tonic-gate if (sig != null && !req.spi.equals("")) { 11110Sstevel@tonic-gate AuthBlock auth = AuthBlock.getEquivalentAuth(req.spi, sig); 11120Sstevel@tonic-gate if (auth == null) { 11130Sstevel@tonic-gate // return empty 11140Sstevel@tonic-gate attributes = new Vector(); 11150Sstevel@tonic-gate } 11160Sstevel@tonic-gate } 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate } else { 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate if (!req.spi.equals("")) { 11210Sstevel@tonic-gate throw 11220Sstevel@tonic-gate new ServiceLocationException( 11230Sstevel@tonic-gate ServiceLocationException.AUTHENTICATION_FAILED, 11240Sstevel@tonic-gate "st_par_attr", 11250Sstevel@tonic-gate new Object[0]); 11260Sstevel@tonic-gate } 11270Sstevel@tonic-gate 11280Sstevel@tonic-gate // Otherwise find the attributes for all service types. 11290Sstevel@tonic-gate 11300Sstevel@tonic-gate attributes = 11310Sstevel@tonic-gate store.findAttributes(serviceType, scopes, tags, locale); 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate } 11340Sstevel@tonic-gate 11350Sstevel@tonic-gate ServiceType type = 11360Sstevel@tonic-gate (serviceType == null ? surl.getServiceType(): 11370Sstevel@tonic-gate new ServiceType(serviceType)); 11380Sstevel@tonic-gate 11390Sstevel@tonic-gate 11400Sstevel@tonic-gate // Create the reply. 11410Sstevel@tonic-gate 11420Sstevel@tonic-gate SrvLocMsg ack = req.makeReply(attributes, sig); 11430Sstevel@tonic-gate 11440Sstevel@tonic-gate if (conf.traceAll()) { 11450Sstevel@tonic-gate conf.writeLog((serviceType != null ? 11460Sstevel@tonic-gate "st_st_attr" : "st_url_attr"), 11470Sstevel@tonic-gate new Object[] { 11480Sstevel@tonic-gate locationMsg, 11490Sstevel@tonic-gate (serviceType != null ? serviceType.toString() : 11500Sstevel@tonic-gate surl.toString()), 11510Sstevel@tonic-gate scopes, 11520Sstevel@tonic-gate tags, 11530Sstevel@tonic-gate locale, 11540Sstevel@tonic-gate attributes}); 11550Sstevel@tonic-gate } 11560Sstevel@tonic-gate 11570Sstevel@tonic-gate return ack; 11580Sstevel@tonic-gate 11590Sstevel@tonic-gate } catch (ServiceLocationException ex) { 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate if (conf.traceDrop()) { 11620Sstevel@tonic-gate conf.writeLog((serviceType != null ? "st_st_attr_drop": 11630Sstevel@tonic-gate "st_url_attr_drop"), 11640Sstevel@tonic-gate new Object[] { 11650Sstevel@tonic-gate locationMsg, 11660Sstevel@tonic-gate ex.getMessage()+"("+ex.getErrorCode()+")", 11670Sstevel@tonic-gate (serviceType != null ? serviceType.toString() : 11680Sstevel@tonic-gate surl.toString()), 11690Sstevel@tonic-gate scopes, 11700Sstevel@tonic-gate tags, 11710Sstevel@tonic-gate locale}); 11720Sstevel@tonic-gate } 11730Sstevel@tonic-gate 11740Sstevel@tonic-gate return hdr.makeErrorReply(ex); 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate } catch (RuntimeException ex) { 11770Sstevel@tonic-gate 11780Sstevel@tonic-gate // These exceptions are not declared in throws but can occur 11790Sstevel@tonic-gate // anywhere. 11800Sstevel@tonic-gate 11810Sstevel@tonic-gate Vector args = new Vector(); 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate args.addElement(req); 11840Sstevel@tonic-gate 11850Sstevel@tonic-gate reportNonfatalException(ex, args, store); 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate return hdr.makeErrorReply(ex); 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate } 11900Sstevel@tonic-gate } 11910Sstevel@tonic-gate 11920Sstevel@tonic-gate // Return the service record corresponding to the URL. 11930Sstevel@tonic-gate getServiceRecord(ServiceURL URL, Locale locale)11940Sstevel@tonic-gate ServiceStore.ServiceRecord getServiceRecord(ServiceURL URL, 11950Sstevel@tonic-gate Locale locale) { 11960Sstevel@tonic-gate return store.getServiceRecord(URL, locale); 11970Sstevel@tonic-gate 11980Sstevel@tonic-gate } 11990Sstevel@tonic-gate 12000Sstevel@tonic-gate // 12010Sstevel@tonic-gate // Utility methods. 12020Sstevel@tonic-gate // 12030Sstevel@tonic-gate 12040Sstevel@tonic-gate // 12050Sstevel@tonic-gate // Protected/private methods. 12060Sstevel@tonic-gate // 12070Sstevel@tonic-gate 12080Sstevel@tonic-gate // Check whether the type is restricted, through an exception if so. 12090Sstevel@tonic-gate checkForRestrictedType(ServiceType type)12100Sstevel@tonic-gate private void checkForRestrictedType(ServiceType type) 12110Sstevel@tonic-gate throws ServiceLocationException { 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate if (Defaults.restrictedTypes.contains(type)) { 12140Sstevel@tonic-gate throw 12150Sstevel@tonic-gate new ServiceLocationException( 12160Sstevel@tonic-gate ServiceLocationException.INVALID_REGISTRATION, 12170Sstevel@tonic-gate "st_restricted_type", 12180Sstevel@tonic-gate new Object[] {type}); 12190Sstevel@tonic-gate } 12200Sstevel@tonic-gate } 12210Sstevel@tonic-gate 12220Sstevel@tonic-gate // Insert a record for type "service-agent" with attributes having 12230Sstevel@tonic-gate // the types currently supported, if the new URL is not on the 12240Sstevel@tonic-gate // list of supported types. This allows us to perform queries 12250Sstevel@tonic-gate // for supported service types. 12260Sstevel@tonic-gate trackRegisteredServiceTypes()12270Sstevel@tonic-gate private void trackRegisteredServiceTypes() 12280Sstevel@tonic-gate throws ServiceLocationException { 12290Sstevel@tonic-gate 12300Sstevel@tonic-gate // First find the types. 12310Sstevel@tonic-gate 12320Sstevel@tonic-gate Vector types = store.findServiceTypes(Defaults.ALL_AUTHORITIES, 12330Sstevel@tonic-gate conf.getSAConfiguredScopes()); 12340Sstevel@tonic-gate 12350Sstevel@tonic-gate // Get preconfigured attributes. 12360Sstevel@tonic-gate 12370Sstevel@tonic-gate Vector attrs = conf.getSAAttributes(); 12380Sstevel@tonic-gate 12390Sstevel@tonic-gate // Make an attribute with the service types. 12400Sstevel@tonic-gate 12410Sstevel@tonic-gate ServiceLocationAttribute attr = 12420Sstevel@tonic-gate new ServiceLocationAttribute(Defaults.SERVICE_TYPE_ATTR_ID, 12430Sstevel@tonic-gate types); 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate attrs.addElement(attr); 12460Sstevel@tonic-gate 12470Sstevel@tonic-gate // Construct URL to use on all interfaces. 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate Vector interfaces = conf.getInterfaces(); 12500Sstevel@tonic-gate int i, n = interfaces.size(); 12510Sstevel@tonic-gate 12520Sstevel@tonic-gate for (i = 0; i < n; i++) { 12530Sstevel@tonic-gate InetAddress addr = (InetAddress)interfaces.elementAt(i); 12540Sstevel@tonic-gate ServiceURL url = 12550Sstevel@tonic-gate new ServiceURL(Defaults.SUN_SA_SERVICE_TYPE + "://" + 12560Sstevel@tonic-gate addr.getHostAddress(), 12570Sstevel@tonic-gate ServiceURL.LIFETIME_MAXIMUM); 12580Sstevel@tonic-gate 12590Sstevel@tonic-gate Vector scopes = conf.getSAOnlyScopes(); 12600Sstevel@tonic-gate 12610Sstevel@tonic-gate Locale locale = Defaults.locale; 12620Sstevel@tonic-gate 12630Sstevel@tonic-gate // Make a new registration for this SA. 12640Sstevel@tonic-gate 12650Sstevel@tonic-gate store.register(url, 12660Sstevel@tonic-gate attrs, 12670Sstevel@tonic-gate scopes, 12680Sstevel@tonic-gate locale, 12690Sstevel@tonic-gate null, 12700Sstevel@tonic-gate null); // we could sign, but we do that later... 12710Sstevel@tonic-gate } 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate // Note that we don't need a refresh on the URLs because they 12740Sstevel@tonic-gate // will get refreshed when the service URLs that they track 12750Sstevel@tonic-gate // are refreshed. If the tracked URLs aren't refreshed, then 12760Sstevel@tonic-gate // these will get updated when the tracked URLs age out. 12770Sstevel@tonic-gate } 12780Sstevel@tonic-gate 12790Sstevel@tonic-gate // Return true if the scopes in the vector are supported by the DA 12800Sstevel@tonic-gate // or SA server. 12810Sstevel@tonic-gate areSupportedScopes(Vector scopes)12820Sstevel@tonic-gate final private boolean areSupportedScopes(Vector scopes) { 12830Sstevel@tonic-gate 12840Sstevel@tonic-gate Vector configuredScopes = conf.getSAConfiguredScopes(); 12850Sstevel@tonic-gate Vector saOnlyScopes = conf.getSAOnlyScopes(); 12860Sstevel@tonic-gate int i = 0; 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate while (i < scopes.size()) { 12890Sstevel@tonic-gate Object o = scopes.elementAt(i); 12900Sstevel@tonic-gate 12910Sstevel@tonic-gate // Remove it if we don't support it. 12920Sstevel@tonic-gate 12930Sstevel@tonic-gate if (!configuredScopes.contains(o) && !saOnlyScopes.contains(o)) { 12940Sstevel@tonic-gate // This will shift the Vector's elements down one, so 12950Sstevel@tonic-gate // don't increment i 12960Sstevel@tonic-gate scopes.removeElementAt(i); 12970Sstevel@tonic-gate } else { 12980Sstevel@tonic-gate i++; 12990Sstevel@tonic-gate } 13000Sstevel@tonic-gate } 13010Sstevel@tonic-gate 13020Sstevel@tonic-gate if (scopes.size() <= 0) { 13030Sstevel@tonic-gate return false; 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate } 13060Sstevel@tonic-gate 13070Sstevel@tonic-gate return true; 13080Sstevel@tonic-gate } 13090Sstevel@tonic-gate 13100Sstevel@tonic-gate /** 13110Sstevel@tonic-gate * Return the sleep increment from the URL lifetime. Used by the 13120Sstevel@tonic-gate * ServiceStore to calculate the new sleep interval in addition 13130Sstevel@tonic-gate * to this class, when a new URL comes in. The algorithm 13140Sstevel@tonic-gate * subtracts x% of the lifetime from the lifetime and schedules the 13150Sstevel@tonic-gate * timeout at that time. 13160Sstevel@tonic-gate * 13170Sstevel@tonic-gate * @param url The URL to use for calculation. 13180Sstevel@tonic-gate * @return The sleep interval. 13190Sstevel@tonic-gate */ 13200Sstevel@tonic-gate getSleepIncrement(ServiceURL url)13210Sstevel@tonic-gate private long getSleepIncrement(ServiceURL url) { 13220Sstevel@tonic-gate long urlLifetime = (long)(url.getLifetime() * 1000); 13230Sstevel@tonic-gate long increment = 13240Sstevel@tonic-gate (long)((float)urlLifetime * Defaults.fRefreshGranularity); 13250Sstevel@tonic-gate long sTime = urlLifetime - increment; 13260Sstevel@tonic-gate 13270Sstevel@tonic-gate // If URL lives only one second, update every half second. 13280Sstevel@tonic-gate 13290Sstevel@tonic-gate if (sTime <= 0) { 13300Sstevel@tonic-gate sTime = 500; 13310Sstevel@tonic-gate 13320Sstevel@tonic-gate } 13330Sstevel@tonic-gate 13340Sstevel@tonic-gate return sTime; 13350Sstevel@tonic-gate } 13360Sstevel@tonic-gate 13370Sstevel@tonic-gate // Make a DAADvert for the DA service request. This only applies 13380Sstevel@tonic-gate // to DAs, not to SA servers. 13390Sstevel@tonic-gate 13400Sstevel@tonic-gate SrvLocMsg makeDAAdvert(SSrvMsg rqst, InetAddress daAddr, SLPConfig conf)13410Sstevel@tonic-gate makeDAAdvert(SSrvMsg rqst, 13420Sstevel@tonic-gate InetAddress daAddr, 13430Sstevel@tonic-gate SLPConfig conf) { 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 13460Sstevel@tonic-gate Vector scopes = hdr.scopes; 13470Sstevel@tonic-gate short xid = hdr.xid; 13480Sstevel@tonic-gate String query = rqst.query; 13490Sstevel@tonic-gate 13500Sstevel@tonic-gate try { 13510Sstevel@tonic-gate 13520Sstevel@tonic-gate // If security is on, proceed only if we can sign as rqst.spi 13530Sstevel@tonic-gate if (conf.getHasSecurity() && !AuthBlock.canSignAs(rqst.spi)) { 13540Sstevel@tonic-gate throw new ServiceLocationException( 13550Sstevel@tonic-gate ServiceLocationException.AUTHENTICATION_UNKNOWN, 13560Sstevel@tonic-gate "st_cant_sign_as", 13570Sstevel@tonic-gate new Object[] {rqst.spi}); 13580Sstevel@tonic-gate } 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate // Get the hashtable of service URLs v.s. scopes. 13610Sstevel@tonic-gate 13620Sstevel@tonic-gate Hashtable services = 13630Sstevel@tonic-gate ServerDATable.getServerDATable().returnMatchingDAs(query); 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate // Go through the table checking whether the IP address came back. 13660Sstevel@tonic-gate 13670Sstevel@tonic-gate Enumeration urls = services.keys(); 13680Sstevel@tonic-gate boolean foundIt = false; 13690Sstevel@tonic-gate String strDAAddr = daAddr.getHostAddress(); 13700Sstevel@tonic-gate 13710Sstevel@tonic-gate while (urls.hasMoreElements()) { 13720Sstevel@tonic-gate ServiceURL url = (ServiceURL)urls.nextElement(); 13730Sstevel@tonic-gate 13740Sstevel@tonic-gate if (url.getHost().equals(strDAAddr)) { 13750Sstevel@tonic-gate foundIt = true; 13760Sstevel@tonic-gate break; 13770Sstevel@tonic-gate 13780Sstevel@tonic-gate } 13790Sstevel@tonic-gate } 13800Sstevel@tonic-gate 13810Sstevel@tonic-gate // If we didn't find anything, make a null service reply. 13820Sstevel@tonic-gate 13830Sstevel@tonic-gate if (!foundIt) { 13840Sstevel@tonic-gate return rqst.makeReply(new Hashtable(), new Hashtable()); 13850Sstevel@tonic-gate 13860Sstevel@tonic-gate } 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate return makeDAAdvert(hdr, daAddr, xid, scopes, conf); 13890Sstevel@tonic-gate 13900Sstevel@tonic-gate 13910Sstevel@tonic-gate } catch (ServiceLocationException ex) { 13920Sstevel@tonic-gate 13930Sstevel@tonic-gate return hdr.makeErrorReply(ex); 13940Sstevel@tonic-gate 13950Sstevel@tonic-gate } 13960Sstevel@tonic-gate 13970Sstevel@tonic-gate } 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate // Make a DAAdvert from the input arguments. 14000Sstevel@tonic-gate SrvLocMsg makeDAAdvert(SrvLocHeader hdr, InetAddress daAddr, short xid, Vector scopes, SLPConfig config)14010Sstevel@tonic-gate makeDAAdvert(SrvLocHeader hdr, 14020Sstevel@tonic-gate InetAddress daAddr, 14030Sstevel@tonic-gate short xid, 14040Sstevel@tonic-gate Vector scopes, 14050Sstevel@tonic-gate SLPConfig config) 14060Sstevel@tonic-gate throws ServiceLocationException { 14070Sstevel@tonic-gate 14080Sstevel@tonic-gate // If this is a request for a V1 Advert, truncate the scopes vector 14090Sstevel@tonic-gate // since DA solicitations in V1 are always unscoped 14100Sstevel@tonic-gate 14110Sstevel@tonic-gate if (hdr.version == 1) { 14120Sstevel@tonic-gate scopes = new Vector(); 14130Sstevel@tonic-gate 14140Sstevel@tonic-gate } 14150Sstevel@tonic-gate 14160Sstevel@tonic-gate // Check if we support scopes first. If not, return an 14170Sstevel@tonic-gate // error reply unless the scope vector is zero. Upper layers 14180Sstevel@tonic-gate // must sort out whether this is a unicast or multicast. 14190Sstevel@tonic-gate 14200Sstevel@tonic-gate if (scopes.size() > 0 && !areSupportedScopes(scopes)) { 14210Sstevel@tonic-gate throw 14220Sstevel@tonic-gate new ServiceLocationException( 14230Sstevel@tonic-gate ServiceLocationException.SCOPE_NOT_SUPPORTED, 14240Sstevel@tonic-gate "st_scope_unsup", 14250Sstevel@tonic-gate new Object[0]); 14260Sstevel@tonic-gate 14270Sstevel@tonic-gate } 14280Sstevel@tonic-gate 14290Sstevel@tonic-gate // Get the service store's timestamp. This must be the 14300Sstevel@tonic-gate // time since last stateless reboot for a stateful store, 14310Sstevel@tonic-gate // or the current time. 14320Sstevel@tonic-gate 14330Sstevel@tonic-gate long timestamp = store.getStateTimestamp(); 14340Sstevel@tonic-gate 14350Sstevel@tonic-gate ServiceURL url = 14360Sstevel@tonic-gate new ServiceURL(Defaults.DA_SERVICE_TYPE + "://" + 14370Sstevel@tonic-gate daAddr.getHostAddress(), 14380Sstevel@tonic-gate ServiceURL.LIFETIME_DEFAULT); 14390Sstevel@tonic-gate 14400Sstevel@tonic-gate SDAAdvert advert = 14410Sstevel@tonic-gate hdr.getDAAdvert(xid, 14420Sstevel@tonic-gate timestamp, 14430Sstevel@tonic-gate url, 14440Sstevel@tonic-gate scopes, 14450Sstevel@tonic-gate conf.getDAAttributes()); 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate return advert; 14480Sstevel@tonic-gate } 14490Sstevel@tonic-gate 14500Sstevel@tonic-gate // Make a SAADvert for the SA service request. This only applies 14510Sstevel@tonic-gate // to SA servers, not DA's. Note that we only advertise the "public" 14520Sstevel@tonic-gate // scopes, not the private ones. 14530Sstevel@tonic-gate 14540Sstevel@tonic-gate SSAAdvert makeSAAdvert(SSrvMsg rqst, InetAddress interfac, SLPConfig conf)14550Sstevel@tonic-gate makeSAAdvert(SSrvMsg rqst, 14560Sstevel@tonic-gate InetAddress interfac, 14570Sstevel@tonic-gate SLPConfig conf) 14580Sstevel@tonic-gate throws ServiceLocationException { 14590Sstevel@tonic-gate SrvLocHeader hdr = rqst.getHeader(); 14600Sstevel@tonic-gate int version = hdr.version; 14610Sstevel@tonic-gate short xid = hdr.xid; 14620Sstevel@tonic-gate Locale locale = hdr.locale; 14630Sstevel@tonic-gate Vector scopes = hdr.scopes; 14640Sstevel@tonic-gate String query = rqst.query; 14650Sstevel@tonic-gate String serviceType = rqst.serviceType; 14660Sstevel@tonic-gate Vector saOnlyScopes = conf.getSAOnlyScopes(); 14670Sstevel@tonic-gate 14680Sstevel@tonic-gate // If security is on, proceed only if we can sign as rqst.spi 14690Sstevel@tonic-gate if (conf.getHasSecurity() && !AuthBlock.canSignAs(rqst.spi)) { 14700Sstevel@tonic-gate throw new ServiceLocationException( 14710Sstevel@tonic-gate ServiceLocationException.AUTHENTICATION_UNKNOWN, 14720Sstevel@tonic-gate "st_cant_sign_as", 14730Sstevel@tonic-gate new Object[] {rqst.spi}); 14740Sstevel@tonic-gate } 14750Sstevel@tonic-gate 14760Sstevel@tonic-gate 14770Sstevel@tonic-gate // Check if we support scopes first. Note that this may allow 14780Sstevel@tonic-gate // someone to get at the SA only scopes off machine, but that's 14790Sstevel@tonic-gate // OK. Since the SAAdvert is only ever multicast, this is OK. 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate if (!areSupportedScopes(scopes) && !(scopes.size() <= 0)) { 14820Sstevel@tonic-gate return null; 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate } 14850Sstevel@tonic-gate 14860Sstevel@tonic-gate // If the scopes vector is null, then use all configured scopes. 14870Sstevel@tonic-gate 14880Sstevel@tonic-gate if (scopes.size() <= 0) { 14890Sstevel@tonic-gate scopes = (Vector)conf.getSAConfiguredScopes().clone(); 14900Sstevel@tonic-gate 14910Sstevel@tonic-gate } 14920Sstevel@tonic-gate 14930Sstevel@tonic-gate // Check to be sure the query matches. 14940Sstevel@tonic-gate // If it doesn't, we don't need to return anything. 14950Sstevel@tonic-gate 14960Sstevel@tonic-gate Hashtable returns = 14970Sstevel@tonic-gate store.findServices(Defaults.SUN_SA_SERVICE_TYPE.toString(), 14980Sstevel@tonic-gate saOnlyScopes, 14990Sstevel@tonic-gate query, 15000Sstevel@tonic-gate Defaults.locale); 15010Sstevel@tonic-gate Hashtable services = 15020Sstevel@tonic-gate (Hashtable)returns.get(ServiceStore.FS_SERVICES); 15030Sstevel@tonic-gate Enumeration en = services.keys(); 15040Sstevel@tonic-gate 15050Sstevel@tonic-gate // Indicates we don't support the service type. 15060Sstevel@tonic-gate 15070Sstevel@tonic-gate if (!en.hasMoreElements()) { 15080Sstevel@tonic-gate return null; 15090Sstevel@tonic-gate 15100Sstevel@tonic-gate } 15110Sstevel@tonic-gate 15120Sstevel@tonic-gate // Find the URL to use. The interface on which the message came in 15130Sstevel@tonic-gate // needs to match one of the registered URLs. 15140Sstevel@tonic-gate 15150Sstevel@tonic-gate ServiceURL url = null; 15160Sstevel@tonic-gate ServiceURL surl = null; 15170Sstevel@tonic-gate String addr = interfac.getHostAddress(); 15180Sstevel@tonic-gate 15190Sstevel@tonic-gate while (en.hasMoreElements()) { 15200Sstevel@tonic-gate surl = (ServiceURL)en.nextElement(); 15210Sstevel@tonic-gate 15220Sstevel@tonic-gate if (addr.equals(surl.getHost())) { 15230Sstevel@tonic-gate url = new ServiceURL(Defaults.SA_SERVICE_TYPE + "://" + 15240Sstevel@tonic-gate addr, 15250Sstevel@tonic-gate ServiceURL.LIFETIME_DEFAULT); 15260Sstevel@tonic-gate break; 15270Sstevel@tonic-gate } 15280Sstevel@tonic-gate } 15290Sstevel@tonic-gate 15300Sstevel@tonic-gate // If none of the URLs matched this interface, then return null. 15310Sstevel@tonic-gate 15320Sstevel@tonic-gate if (url == null) { 15330Sstevel@tonic-gate return null; 15340Sstevel@tonic-gate 15350Sstevel@tonic-gate } 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate // Find the SA's attributes. 15380Sstevel@tonic-gate 15390Sstevel@tonic-gate Hashtable ht = 15400Sstevel@tonic-gate store.findAttributes(surl, 15410Sstevel@tonic-gate saOnlyScopes, 15420Sstevel@tonic-gate new Vector(), 15430Sstevel@tonic-gate Defaults.locale); 15440Sstevel@tonic-gate 15450Sstevel@tonic-gate Vector attrs = (Vector)ht.get(ServiceStore.FA_ATTRIBUTES); 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate // Construct return. 15480Sstevel@tonic-gate 15490Sstevel@tonic-gate return 15500Sstevel@tonic-gate new SSAAdvert(version, 15510Sstevel@tonic-gate xid, 15520Sstevel@tonic-gate locale, 15530Sstevel@tonic-gate url, 15540Sstevel@tonic-gate conf.getSAConfiguredScopes(), // report all scopes... 15550Sstevel@tonic-gate attrs); 15560Sstevel@tonic-gate } 15570Sstevel@tonic-gate 15580Sstevel@tonic-gate /** 15590Sstevel@tonic-gate * Report a fatal exception to the log. 15600Sstevel@tonic-gate * 15610Sstevel@tonic-gate * @param ex The exception to report. 15620Sstevel@tonic-gate */ 15630Sstevel@tonic-gate reportFatalException(Exception ex)15640Sstevel@tonic-gate protected static void reportFatalException(Exception ex) { 15650Sstevel@tonic-gate 15660Sstevel@tonic-gate reportException(true, ex, new Vector()); 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate if (table != null) { 15690Sstevel@tonic-gate table.store.dumpServiceStore(); 15700Sstevel@tonic-gate } 15710Sstevel@tonic-gate 15720Sstevel@tonic-gate conf.writeLog("exiting_msg", new Object[0]); 15730Sstevel@tonic-gate 15740Sstevel@tonic-gate System.exit(1); 15750Sstevel@tonic-gate 15760Sstevel@tonic-gate } 15770Sstevel@tonic-gate 15780Sstevel@tonic-gate /** 15790Sstevel@tonic-gate * Report a nonfatal exception to the log. 15800Sstevel@tonic-gate * 15810Sstevel@tonic-gate * @param ex The exception to report. 15820Sstevel@tonic-gate * @param args The method arguments. 15830Sstevel@tonic-gate * @param store The service store being processed. 15840Sstevel@tonic-gate */ 15850Sstevel@tonic-gate reportNonfatalException(Exception ex, Vector args, ServiceStore store)15860Sstevel@tonic-gate protected static void reportNonfatalException(Exception ex, 15870Sstevel@tonic-gate Vector args, 15880Sstevel@tonic-gate ServiceStore store) { 15890Sstevel@tonic-gate 15900Sstevel@tonic-gate reportException(false, ex, args); 15910Sstevel@tonic-gate 15920Sstevel@tonic-gate if (conf.traceAll()) { 15930Sstevel@tonic-gate store.dumpServiceStore(); 15940Sstevel@tonic-gate } 15950Sstevel@tonic-gate 15960Sstevel@tonic-gate } 15970Sstevel@tonic-gate 15980Sstevel@tonic-gate /** 15990Sstevel@tonic-gate * Report an exception to the log. 16000Sstevel@tonic-gate * 16010Sstevel@tonic-gate * @param isFatal Indicates whether the exception is fatal or not. 16020Sstevel@tonic-gate * @param ex The exception to report. 16030Sstevel@tonic-gate * @param args A potentially null vector of arguments to the 16040Sstevel@tonic-gate * method where the exception was caught. 16050Sstevel@tonic-gate */ 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate private static void reportException(boolean isFatal, Exception ex, Vector args)16080Sstevel@tonic-gate reportException(boolean isFatal, Exception ex, Vector args) { 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate StringWriter sw = new StringWriter(); 16110Sstevel@tonic-gate PrintWriter writer = new PrintWriter(sw); 16120Sstevel@tonic-gate 16130Sstevel@tonic-gate // Get the backtrace. 16140Sstevel@tonic-gate 16150Sstevel@tonic-gate ex.printStackTrace(writer); 16160Sstevel@tonic-gate 16170Sstevel@tonic-gate String severity = (isFatal ? "fatal_error":"nonfatal_error"); 16180Sstevel@tonic-gate String msg = ex.getMessage(); 16190Sstevel@tonic-gate 16200Sstevel@tonic-gate if (msg == null) { 16210Sstevel@tonic-gate msg = conf.formatMessage("no_message", new Object[0]); 16220Sstevel@tonic-gate 16230Sstevel@tonic-gate } else if (ex instanceof ServiceLocationException) { 16240Sstevel@tonic-gate msg = msg + 16250Sstevel@tonic-gate "(" + ((ServiceLocationException)ex).getErrorCode() + ")"; 16260Sstevel@tonic-gate 16270Sstevel@tonic-gate } 16280Sstevel@tonic-gate 16290Sstevel@tonic-gate StringBuffer argMsg = new StringBuffer(); 16300Sstevel@tonic-gate 16310Sstevel@tonic-gate int i, n = args.size(); 16320Sstevel@tonic-gate 16330Sstevel@tonic-gate for (i = 0; i < n; i++) { 16340Sstevel@tonic-gate argMsg.append("\n (" + Integer.toString(i) + "):" + 16350Sstevel@tonic-gate args.elementAt(i).toString()); 16360Sstevel@tonic-gate } 16370Sstevel@tonic-gate 16380Sstevel@tonic-gate conf.writeLog(severity, 16390Sstevel@tonic-gate new Object[] { 16400Sstevel@tonic-gate ex.getClass().getName(), 16410Sstevel@tonic-gate msg, 16420Sstevel@tonic-gate argMsg, 16430Sstevel@tonic-gate sw.toString()}); 16440Sstevel@tonic-gate 16450Sstevel@tonic-gate } 16460Sstevel@tonic-gate } 1647