17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
59a70fc3bSMark J. Nelson  * Common Development and Distribution License (the "License").
69a70fc3bSMark J. Nelson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  * Copyright (c) 1999 by Sun Microsystems, Inc.
237c478bd9Sstevel@tonic-gate  * All rights reserved.
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate //  CDAAdvert.java:    Message class for SLP CDAAdvert message
287c478bd9Sstevel@tonic-gate //  Author:           James Kempf
297c478bd9Sstevel@tonic-gate //  Created On:       Fri Oct 10 10:48:05 1997
307c478bd9Sstevel@tonic-gate //  Last Modified By: James Kempf
317c478bd9Sstevel@tonic-gate //  Last Modified On: Fri Jan 29 09:24:50 1999
327c478bd9Sstevel@tonic-gate //  Update Count:     134
337c478bd9Sstevel@tonic-gate //
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate package com.sun.slp;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate import java.util.*;
387c478bd9Sstevel@tonic-gate import java.io.*;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /**
427c478bd9Sstevel@tonic-gate  * The CDAAdvert class models the SLP DAAdvert message, client side.
437c478bd9Sstevel@tonic-gate  * We need to accommodate SLPv1 by using an initialize() method.
447c478bd9Sstevel@tonic-gate  *
457c478bd9Sstevel@tonic-gate  * @author James Kempf
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate class CDAAdvert extends SrvLocMsgImpl {
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate     ServiceURL URL = null;		// The DA's service URL
527c478bd9Sstevel@tonic-gate     long  timestamp = 0;		// timestamp.
537c478bd9Sstevel@tonic-gate     Vector attrs = new Vector();	// Attributes
547c478bd9Sstevel@tonic-gate     Hashtable authBlock = null;		// Scope auth blocks.
557c478bd9Sstevel@tonic-gate     String spis = null;			// Supported SPIs
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate     // Construct a CDAAdvert from the input stream.
587c478bd9Sstevel@tonic-gate 
CDAAdvert(SrvLocHeader hdr, DataInputStream dis)59*55fea89dSDan Cross     CDAAdvert(SrvLocHeader hdr, DataInputStream dis)
607c478bd9Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
617c478bd9Sstevel@tonic-gate 	super(hdr, SrvLocHeader.DAAdvert);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	this.initialize(dis);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate     }
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate     // Initialize the object from the input stream.
687c478bd9Sstevel@tonic-gate 
initialize(DataInputStream dis)697c478bd9Sstevel@tonic-gate     protected void initialize(DataInputStream dis)
707c478bd9Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	SLPHeaderV2 hdr = (SLPHeaderV2)getHeader();
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	// Parse in the timestamp. Save bytes for auth block.
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	byte[] tsBytes = new byte[4];
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate 	timestamp = getInt32(hdr, dis, tsBytes);
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	// Parse in DA's service URL.
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	StringBuffer buf = new StringBuffer();
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	byte[] urlBytes = hdr.getString(buf, dis);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	int lifetime = getDAURLLifetime();
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	String surl = buf.toString();
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	// Parse in the scope list.
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	byte[] scopeBytes = hdr.getString(buf, dis);
93*55fea89dSDan Cross 
947c478bd9Sstevel@tonic-gate 	hdr.scopes = hdr.parseCommaSeparatedListIn(buf.toString(), true);
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	// Unescape scope strigns.
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	hdr.unescapeScopeStrings(hdr.scopes);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	// Validate scope list.
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	DATable.validateScopes(hdr.scopes, hdr.locale);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	// Parse in attribute list.
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	byte[] attrBytes = hdr.parseAttributeVectorIn(attrs, dis, false);
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	// Parse in the SPI list
1097c478bd9Sstevel@tonic-gate 	byte[] spiBytes = hdr.getString(buf, dis);
1107c478bd9Sstevel@tonic-gate 	spis = buf.toString();
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	// Construct bytes for auth.
1137c478bd9Sstevel@tonic-gate 	Object[] message = new Object[9];
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	message[0] = tsBytes;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	// None of the strings have leading length fields, so add them here
1187c478bd9Sstevel@tonic-gate 	ByteArrayOutputStream abaos = new ByteArrayOutputStream();
1197c478bd9Sstevel@tonic-gate 	hdr.putInteger(urlBytes.length, abaos);
1207c478bd9Sstevel@tonic-gate 	message[1] = abaos.toByteArray();
1217c478bd9Sstevel@tonic-gate 	message[2] = urlBytes;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	abaos = new ByteArrayOutputStream();
1247c478bd9Sstevel@tonic-gate 	hdr.putInteger(attrBytes.length, abaos);
1257c478bd9Sstevel@tonic-gate 	message[3] = abaos.toByteArray();
1267c478bd9Sstevel@tonic-gate 	message[4] = attrBytes;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	abaos = new ByteArrayOutputStream();
1297c478bd9Sstevel@tonic-gate 	hdr.putInteger(scopeBytes.length, abaos);
1307c478bd9Sstevel@tonic-gate 	message[5] = abaos.toByteArray();
1317c478bd9Sstevel@tonic-gate 	message[6] = scopeBytes;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	abaos = new ByteArrayOutputStream();
1347c478bd9Sstevel@tonic-gate 	hdr.putInteger(spiBytes.length, abaos);
1357c478bd9Sstevel@tonic-gate 	message[7] = abaos.toByteArray();
1367c478bd9Sstevel@tonic-gate 	message[8] = spiBytes;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	// Parse in an auth block, if there.
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	authBlock = hdr.parseSignatureIn(message, dis);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	if (authBlock != null) {
1437c478bd9Sstevel@tonic-gate 	    lifetime = AuthBlock.getShortestLifetime(authBlock);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	// Create URL.
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	try {
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	    URL = new ServiceURL(surl, lifetime);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	} catch (IllegalArgumentException ex) {
1547c478bd9Sstevel@tonic-gate 
155*55fea89dSDan Cross 	    throw
1567c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
1577c478bd9Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
1587c478bd9Sstevel@tonic-gate 				"malformed_url",
1597c478bd9Sstevel@tonic-gate 				new Object[] {ex.getMessage()});
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	// Validate the service URL.
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	ServiceType serviceType = URL.getServiceType();
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	if (!serviceType.equals(Defaults.DA_SERVICE_TYPE)) {
168*55fea89dSDan Cross 	    throw
1697c478bd9Sstevel@tonic-gate 		new ServiceLocationException(
170*55fea89dSDan Cross 				ServiceLocationException.PARSE_ERROR,
1717c478bd9Sstevel@tonic-gate 				"not_right_url",
1727c478bd9Sstevel@tonic-gate 				new Object[] {URL, "DA"});
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	// Set number of replies to one.
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	hdr.iNumReplies = 1;
1797c478bd9Sstevel@tonic-gate     }
1807c478bd9Sstevel@tonic-gate 
181*55fea89dSDan Cross 
1827c478bd9Sstevel@tonic-gate     // Get the timestamp.
1837c478bd9Sstevel@tonic-gate 
getInt32(SrvLocHeader hdr, DataInputStream dis, byte[] bytes)1847c478bd9Sstevel@tonic-gate     static private long getInt32(SrvLocHeader hdr,
1857c478bd9Sstevel@tonic-gate 				 DataInputStream dis,
1867c478bd9Sstevel@tonic-gate 				 byte[] bytes)
1877c478bd9Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	bytes[0] = (byte)dis.read();
1907c478bd9Sstevel@tonic-gate 	bytes[1] = (byte)dis.read();
1917c478bd9Sstevel@tonic-gate 	bytes[2] = (byte)dis.read();
1927c478bd9Sstevel@tonic-gate 	bytes[3] = (byte)dis.read();
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	long a = (long)((char)bytes[0] & 0xFF);
1957c478bd9Sstevel@tonic-gate 	long b = (long)((char)bytes[1] & 0xFF);
1967c478bd9Sstevel@tonic-gate 	long c = (long)((char)bytes[2] & 0xFF);
1977c478bd9Sstevel@tonic-gate 	long d = (long)((char)bytes[3] & 0xFF);
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	long i = a << 24;
2007c478bd9Sstevel@tonic-gate 	i += b << 16;
2017c478bd9Sstevel@tonic-gate 	i += c << 8;
2027c478bd9Sstevel@tonic-gate 	i += d;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	hdr.nbytes += 4;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	return i;
2077c478bd9Sstevel@tonic-gate     }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate     // Return true if the advert indicates that the DA is going down.
2107c478bd9Sstevel@tonic-gate 
isGoingDown()2117c478bd9Sstevel@tonic-gate     boolean isGoingDown() {
2127c478bd9Sstevel@tonic-gate 	return (timestamp == 0);
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate     }
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate     // Return true if the advert was unsolicited.
2177c478bd9Sstevel@tonic-gate 
isUnsolicited()2187c478bd9Sstevel@tonic-gate     boolean isUnsolicited() {
2197c478bd9Sstevel@tonic-gate 	return (hdr.xid == 0);
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate     }
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate     // Set is solicited. No-op for V2, since messages already know.
2247c478bd9Sstevel@tonic-gate 
setIsUnsolicited(boolean flag)2257c478bd9Sstevel@tonic-gate     void setIsUnsolicited(boolean flag) {
2267c478bd9Sstevel@tonic-gate 
227*55fea89dSDan Cross     }
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate     // Calcualte DA URL lifetime, based on active discovery interval and
2307c478bd9Sstevel@tonic-gate     //  granularity.
2317c478bd9Sstevel@tonic-gate 
getDAURLLifetime()2327c478bd9Sstevel@tonic-gate     private int getDAURLLifetime() {
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	// Calculate lifetime based on maximum length of time between
2357c478bd9Sstevel@tonic-gate 	//  active discoveries. We add a fudge factor to avoid problems
2367c478bd9Sstevel@tonic-gate 	//  with scheduler granularity.
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	SLPConfig config = SLPConfig.getSLPConfig();
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	int disInt = config.getActiveDiscoveryInterval();
2417c478bd9Sstevel@tonic-gate 	int granInt = config.getActiveDiscoveryGranularity();
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	// If the discovery interval is zero, then the granularity will be
2447c478bd9Sstevel@tonic-gate 	//  also, and active discovery is off. In principle, it doesn't
2457c478bd9Sstevel@tonic-gate 	//  matter what the DA URL interval is because active discovery
2467c478bd9Sstevel@tonic-gate 	//  won't find any, because its off.
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	if (disInt <= 0) {
2497c478bd9Sstevel@tonic-gate 	    return ServiceURL.LIFETIME_MAXIMUM;
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	} else {
2527c478bd9Sstevel@tonic-gate 	    int lifetime = disInt + granInt;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 	    return
255*55fea89dSDan Cross 		(lifetime > ServiceURL.LIFETIME_MAXIMUM ?
2567c478bd9Sstevel@tonic-gate 		 ServiceURL.LIFETIME_MAXIMUM:lifetime);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate     }
2607c478bd9Sstevel@tonic-gate }
261