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 2001-2002 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  */
26 
27 //  SLPServerHeaderV2.java: SLPv2 Header Class for Server Side
28 //  Author:           James Kempf
29 //  Created On:       Wed Sep 16 08:44:31 1998
30 //  Last Modified By: James Kempf
31 //  Last Modified On: Mon Jan  4 15:26:33 1999
32 //  Update Count:     30
33 //
34 
35 package com.sun.slp;
36 
37 import java.util.*;
38 
39 import java.net.*;
40 import java.io.*;
41 import java.security.*;
42 
43 /**
44  * The SLPServerHeaderV2 class serves as the header class for all server side
45  * SLPv2 messages.
46  *
47  * @author James Kempf
48  */
49 
50 class SLPServerHeaderV2 extends SLPHeaderV2  implements Cloneable {
51 
52     // Function code for message reply.
53 
54     int replyFunctionCode = SrvLocHeader.SrvAck;
55 
56     // For SrvLocHeader.newInstance().
57 
58     SLPServerHeaderV2() {
59 	super();
60 
61     }
62 
63     // Construct a header for output. Used by the client side code to
64     //  construct an initial request and the server side code to construct
65     //  a reply.
66 
67     SLPServerHeaderV2(int functionCode, boolean fresh, Locale locale)
68 	throws ServiceLocationException {
69 	super(functionCode, fresh, locale);
70 
71     }
72 
73     // Assign reply code based on function code type, then use superclass
74     //  method to parse header.
75 
76     void parseHeader(int functionCode, DataInputStream dis)
77 	throws ServiceLocationException, IOException {
78 
79 	// We ignore the error case here.
80 
81 	switch (functionCode) {
82 
83 	case SrvLocHeader.SrvReq:
84 	    replyFunctionCode = SrvLocHeader.SrvRply;
85 	    break;
86 
87 	case SrvLocHeader.AttrRqst:
88 	    replyFunctionCode = SrvLocHeader.AttrRply;
89 	    break;
90 
91 	case SrvLocHeader.SrvTypeRqst:
92 	    replyFunctionCode = SrvLocHeader.SrvTypeRply;
93 	    break;
94 
95 	case SrvLocHeader.SrvReg: case SrvLocHeader.SrvDereg:
96 	    replyFunctionCode = SrvLocHeader.SrvAck;
97 	    break;
98 
99 	    // If we get an error during creating of the DAAdvert to
100 	    //  reply, we need to continue and reply with DAAdvert.
101 	    //  This is only true for a unicast DAAdvert, though.
102 
103 	case SrvLocHeader.DAAdvert:
104 	    replyFunctionCode = SrvLocHeader.DAAdvert;
105 	    break;
106 
107 	    // We ignore the header error code for SAAdvert because
108 	    //  it is always multicast.
109 
110 	}
111 
112 	// We are now set up to handle any errors that may come flying out
113 	//  of here.
114 
115 	super.parseHeader(functionCode, dis);
116 
117     }
118 
119     // Replace the superclass method with a method that parses the server
120     //  side.
121 
122     SrvLocMsg parseMsg(DataInputStream dis)
123 	throws ServiceLocationException,
124 	       IOException,
125 	       IllegalArgumentException {
126 
127 	SrvLocMsg msg = null;
128 
129 	// DAAdvert needs to get it's error code parsed here because
130 	//  error codes are always handled in parseMsg() and it is
131 	//  the only server side message that has one.
132 
133 	if (functionCode == SrvLocHeader.DAAdvert) {
134 	    errCode = (short)getInt(dis);
135 
136 	}
137 
138 	// Switch and convert according to function code.
139 
140 	switch (functionCode) {
141 
142 	case SrvLocHeader.SrvReg:
143 	    msg = new SSrvReg(this, dis);
144 	    break;
145 
146 	case SrvLocHeader.SrvDereg:
147 	    msg = new SSrvDereg(this, dis);
148 	    break;
149 
150 	case SrvLocHeader.SrvReq:
151 	    msg = new SSrvMsg(this, dis);
152 	    break;
153 
154 	case SrvLocHeader.AttrRqst:
155 	    msg = new SAttrMsg(this, dis);
156 	    break;
157 
158 	case SrvLocHeader.SrvAck:
159 
160 	    // We function as our own message.
161 
162 	    msg = this;
163 	    iNumReplies = 1;
164 	    break;
165 
166 	case SrvLocHeader.SrvTypeRqst:
167 	    msg = new SSrvTypeMsg(this, dis);
168 	    break;
169 
170 	case SrvLocHeader.DAAdvert:
171 	    msg = new CDAAdvert(this, dis);
172 	    break;
173 
174 	case SrvLocHeader.SAAdvert:
175 	    msg = new CSAAdvert(this, dis);
176 	    break;
177 
178 	default:
179 	    throw
180 		new ServiceLocationException(
181 				ServiceLocationException.PARSE_ERROR,
182 				"function_code_error",
183 				new Object[] {
184 		    new Integer(functionCode)});
185 
186 	}
187 
188 	// Check for size overflow.
189 
190 	if (nbytes > length) {
191 	    throw
192 		new ServiceLocationException(
193 				ServiceLocationException.PARSE_ERROR,
194 				"length_overflow",
195 				new Object[] {
196 		    new Integer(nbytes), new Integer(length)});
197 
198 	}
199 
200 	return msg;
201 
202     }
203 
204     // Create an error reply using the reply code. Calculate the
205     //  error code using the exception.
206 
207     SrvLocMsg makeErrorReply(Exception ex) {
208 
209 	SrvLocHeader hdr = null;
210 
211 	// Clone the header to make sure that everything else is the same.
212 	//  We don't want to use the same header because it may be tested
213 	//  elsewhere.
214 
215 	try {
216 	    hdr = (SrvLocHeader)this.clone();
217 
218 	} catch (CloneNotSupportedException exx) {
219 
220 	    // We support it, so no-op.
221 
222 	}
223 
224 	// Re-initialize flags but not multicast, since we need to filter on it
225 
226 	hdr.fresh = false;
227 	hdr.overflow = false;
228 	hdr.functionCode = replyFunctionCode;
229 
230 	// We should *not* be getting a null exception down this path!
231 
232 	Assert.slpassert(ex != null,
233 		      "null_parameter",
234 		      new Object[] {ex});
235 
236 	if (ex instanceof ServiceLocationException) {
237 
238 	    hdr.errCode = ((ServiceLocationException)ex).getErrorCode();
239 
240 	    if (!ServiceLocationException.validWireErrorCode(hdr.errCode)) {
241 		hdr.errCode = ServiceLocationException.INTERNAL_ERROR;
242 
243 	    }
244 
245 	} else if (ex instanceof IllegalArgumentException ||
246 		   ex instanceof IOException) {
247 	    hdr.errCode = ServiceLocationException.PARSE_ERROR;
248 
249 	} else {
250 	    hdr.errCode = ServiceLocationException.INTERNAL_ERROR;
251 
252 	}
253 
254 	// Construct header description.
255 
256 	constructDescription("SrvLocMsg", "");
257 
258 	return hdr;
259     }
260 
261     // Return a reply header with flags properly set.
262 
263     SLPServerHeaderV2 makeReplyHeader() {
264 
265 	SLPServerHeaderV2 hdr = null;
266 
267 	try {
268 	    hdr = (SLPServerHeaderV2)this.clone();
269 
270 	} catch (CloneNotSupportedException ex) {
271 
272 	    // No-op, since we support it.
273 
274 	}
275 
276 	hdr.functionCode = replyFunctionCode;
277 	hdr.length = 0;
278 	hdr.previousResponders = null;
279 	hdr.scopes = null;
280 	hdr.overflow = false;
281 	hdr.fresh = false;
282 	hdr.mcast = false;
283 	hdr.nbytes = 0;
284 
285 	return hdr;
286     }
287 
288     // Return display string.
289 
290     public String toString() {
291 	return
292 	    getMsgType() + ":version=``" + version + "''\n" +
293 	    "       functionCode=``" + functionCode + "''\n" +
294 	    "       length=``" + length + "''" + "''\n" +
295 	    "       overflow=``" + overflow + "''\n" +
296 	    "       mcast = ``" + mcast + "''\n" +
297 	    "       fresh=``" + fresh + "''\n" +
298 	    "       locale = ``" + locale + "''\n" +
299 	    "       xid=``0x" + Integer.toHexString(xid) + "''\n" +
300 	    "       errCode=``" + errCode + "''\n" +
301 	    "       previousResponders=``" + previousResponders + "''\n" +
302 	    "       scopes=``" + scopes + "''\n" +
303 	    getMsgDescription();
304     }
305 
306     //
307     // Parsing Utilities.
308     //
309 
310     // Parse in the scope list.
311 
312     void parseScopesIn(DataInputStream dis)
313 	throws ServiceLocationException, IOException {
314 
315 	StringBuffer buf = new StringBuffer();
316 
317 	getString(buf, dis);
318 
319 	scopes = parseCommaSeparatedListIn(buf.toString(), true);
320 
321 	// Unescape scope strings.
322 
323 	unescapeScopeStrings(scopes);
324 
325 	// Validate.
326 
327 	DATable.validateScopes(scopes, locale);
328 
329     }
330 
331     void parsePreviousRespondersIn(DataInputStream dis)
332 	throws ServiceLocationException, IOException {
333 
334 	StringBuffer buf = new StringBuffer();
335 
336 	getString(buf, dis);
337 
338 	previousResponders =
339 	    parseCommaSeparatedListIn(buf.toString(), true);
340 
341     }
342 
343     // Return an SLPv2 DAAdvert.
344 
345     SDAAdvert
346 	getDAAdvert(short xid,
347 		    long timestamp,
348 		    ServiceURL url,
349 		    Vector scopes,
350 		    Vector attrs)
351 	throws ServiceLocationException {
352 
353 	// If scopes vector is null, then return all scopes for this
354 	//  DA.
355 
356 	if (scopes.size() <= 0) {
357 	    scopes = SLPConfig.getSLPConfig().getSAConfiguredScopes();
358 
359 	}
360 
361 	return new SDAAdvert(this, xid, timestamp, url, scopes, attrs);
362 
363     }
364 
365 }
366