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
35package com.sun.slp;
36
37import java.util.*;
38import 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
49class 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
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
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
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
211    boolean isGoingDown() {
212	return (timestamp == 0);
213
214    }
215
216    // Return true if the advert was unsolicited.
217
218    boolean isUnsolicited() {
219	return (hdr.xid == 0);
220
221    }
222
223    // Set is solicited. No-op for V2, since messages already know.
224
225    void setIsUnsolicited(boolean flag) {
226
227    }
228
229    // Calcualte DA URL lifetime, based on active discovery interval and
230    //  granularity.
231
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