1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 1999 by Sun Microsystems, Inc.
23  * All rights reserved.
24  *
25  */
26 
27 //  CDAAdvert.java:    Message class for SLP CDAAdvert message
28 //  Author:           James Kempf
29 //  Created On:       Fri Oct 10 10:48:05 1997
30 //  Last Modified By: James Kempf
31 //  Last Modified On: Fri Jan 29 09:24:50 1999
32 //  Update Count:     134
33 //
34 
35 package com.sun.slp;
36 
37 import java.util.*;
38 import java.io.*;
39 
40 
41 /**
42  * The CDAAdvert class models the SLP DAAdvert message, client side.
43  * We need to accommodate SLPv1 by using an initialize() method.
44  *
45  * @author James Kempf
46  */
47 
48 
49 class CDAAdvert extends SrvLocMsgImpl {
50 
51     ServiceURL URL = null;		// The DA's service URL
52     long  timestamp = 0;		// timestamp.
53     Vector attrs = new Vector();	// Attributes
54     Hashtable authBlock = null;		// Scope auth blocks.
55     String spis = null;			// Supported SPIs
56 
57     // Construct a CDAAdvert from the input stream.
58 
CDAAdvert(SrvLocHeader hdr, DataInputStream dis)59     CDAAdvert(SrvLocHeader hdr, DataInputStream dis)
60 	throws ServiceLocationException, IOException {
61 	super(hdr, SrvLocHeader.DAAdvert);
62 
63 	this.initialize(dis);
64 
65     }
66 
67     // Initialize the object from the input stream.
68 
initialize(DataInputStream dis)69     protected void initialize(DataInputStream dis)
70 	throws ServiceLocationException, IOException {
71 
72 	SLPHeaderV2 hdr = (SLPHeaderV2)getHeader();
73 
74 	// Parse in the timestamp. Save bytes for auth block.
75 
76 	byte[] tsBytes = new byte[4];
77 
78 	timestamp = getInt32(hdr, dis, tsBytes);
79 
80 	// Parse in DA's service URL.
81 
82 	StringBuffer buf = new StringBuffer();
83 
84 	byte[] urlBytes = hdr.getString(buf, dis);
85 
86 	int lifetime = getDAURLLifetime();
87 
88 	String surl = buf.toString();
89 
90 	// Parse in the scope list.
91 
92 	byte[] scopeBytes = hdr.getString(buf, dis);
93 
94 	hdr.scopes = hdr.parseCommaSeparatedListIn(buf.toString(), true);
95 
96 	// Unescape scope strigns.
97 
98 	hdr.unescapeScopeStrings(hdr.scopes);
99 
100 	// Validate scope list.
101 
102 	DATable.validateScopes(hdr.scopes, hdr.locale);
103 
104 	// Parse in attribute list.
105 
106 	byte[] attrBytes = hdr.parseAttributeVectorIn(attrs, dis, false);
107 
108 	// Parse in the SPI list
109 	byte[] spiBytes = hdr.getString(buf, dis);
110 	spis = buf.toString();
111 
112 	// Construct bytes for auth.
113 	Object[] message = new Object[9];
114 
115 	message[0] = tsBytes;
116 
117 	// None of the strings have leading length fields, so add them here
118 	ByteArrayOutputStream abaos = new ByteArrayOutputStream();
119 	hdr.putInteger(urlBytes.length, abaos);
120 	message[1] = abaos.toByteArray();
121 	message[2] = urlBytes;
122 
123 	abaos = new ByteArrayOutputStream();
124 	hdr.putInteger(attrBytes.length, abaos);
125 	message[3] = abaos.toByteArray();
126 	message[4] = attrBytes;
127 
128 	abaos = new ByteArrayOutputStream();
129 	hdr.putInteger(scopeBytes.length, abaos);
130 	message[5] = abaos.toByteArray();
131 	message[6] = scopeBytes;
132 
133 	abaos = new ByteArrayOutputStream();
134 	hdr.putInteger(spiBytes.length, abaos);
135 	message[7] = abaos.toByteArray();
136 	message[8] = spiBytes;
137 
138 	// Parse in an auth block, if there.
139 
140 	authBlock = hdr.parseSignatureIn(message, dis);
141 
142 	if (authBlock != null) {
143 	    lifetime = AuthBlock.getShortestLifetime(authBlock);
144 
145 	}
146 
147 	// Create URL.
148 
149 	try {
150 
151 	    URL = new ServiceURL(surl, lifetime);
152 
153 	} catch (IllegalArgumentException ex) {
154 
155 	    throw
156 		new ServiceLocationException(
157 				ServiceLocationException.PARSE_ERROR,
158 				"malformed_url",
159 				new Object[] {ex.getMessage()});
160 
161 	}
162 
163 	// Validate the service URL.
164 
165 	ServiceType serviceType = URL.getServiceType();
166 
167 	if (!serviceType.equals(Defaults.DA_SERVICE_TYPE)) {
168 	    throw
169 		new ServiceLocationException(
170 				ServiceLocationException.PARSE_ERROR,
171 				"not_right_url",
172 				new Object[] {URL, "DA"});
173 
174 	}
175 
176 	// Set number of replies to one.
177 
178 	hdr.iNumReplies = 1;
179     }
180 
181 
182     // Get the timestamp.
183 
getInt32(SrvLocHeader hdr, DataInputStream dis, byte[] bytes)184     static private long getInt32(SrvLocHeader hdr,
185 				 DataInputStream dis,
186 				 byte[] bytes)
187 	throws ServiceLocationException, IOException {
188 
189 	bytes[0] = (byte)dis.read();
190 	bytes[1] = (byte)dis.read();
191 	bytes[2] = (byte)dis.read();
192 	bytes[3] = (byte)dis.read();
193 
194 	long a = (long)((char)bytes[0] & 0xFF);
195 	long b = (long)((char)bytes[1] & 0xFF);
196 	long c = (long)((char)bytes[2] & 0xFF);
197 	long d = (long)((char)bytes[3] & 0xFF);
198 
199 	long i = a << 24;
200 	i += b << 16;
201 	i += c << 8;
202 	i += d;
203 
204 	hdr.nbytes += 4;
205 
206 	return i;
207     }
208 
209     // Return true if the advert indicates that the DA is going down.
210 
isGoingDown()211     boolean isGoingDown() {
212 	return (timestamp == 0);
213 
214     }
215 
216     // Return true if the advert was unsolicited.
217 
isUnsolicited()218     boolean isUnsolicited() {
219 	return (hdr.xid == 0);
220 
221     }
222 
223     // Set is solicited. No-op for V2, since messages already know.
224 
setIsUnsolicited(boolean flag)225     void setIsUnsolicited(boolean flag) {
226 
227     }
228 
229     // Calcualte DA URL lifetime, based on active discovery interval and
230     //  granularity.
231 
getDAURLLifetime()232     private int getDAURLLifetime() {
233 
234 	// Calculate lifetime based on maximum length of time between
235 	//  active discoveries. We add a fudge factor to avoid problems
236 	//  with scheduler granularity.
237 
238 	SLPConfig config = SLPConfig.getSLPConfig();
239 
240 	int disInt = config.getActiveDiscoveryInterval();
241 	int granInt = config.getActiveDiscoveryGranularity();
242 
243 	// If the discovery interval is zero, then the granularity will be
244 	//  also, and active discovery is off. In principle, it doesn't
245 	//  matter what the DA URL interval is because active discovery
246 	//  won't find any, because its off.
247 
248 	if (disInt <= 0) {
249 	    return ServiceURL.LIFETIME_MAXIMUM;
250 
251 	} else {
252 	    int lifetime = disInt + granInt;
253 
254 	    return
255 		(lifetime > ServiceURL.LIFETIME_MAXIMUM ?
256 		 ServiceURL.LIFETIME_MAXIMUM:lifetime);
257 
258 	}
259     }
260 }
261