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 2001-2002 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate //  SLPServerHeaderV2.java: SLPv2 Header Class for Server Side
280Sstevel@tonic-gate //  Author:           James Kempf
290Sstevel@tonic-gate //  Created On:       Wed Sep 16 08:44:31 1998
300Sstevel@tonic-gate //  Last Modified By: James Kempf
310Sstevel@tonic-gate //  Last Modified On: Mon Jan  4 15:26:33 1999
320Sstevel@tonic-gate //  Update Count:     30
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 
390Sstevel@tonic-gate import java.net.*;
400Sstevel@tonic-gate import java.io.*;
410Sstevel@tonic-gate import java.security.*;
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /**
440Sstevel@tonic-gate  * The SLPServerHeaderV2 class serves as the header class for all server side
450Sstevel@tonic-gate  * SLPv2 messages.
460Sstevel@tonic-gate  *
470Sstevel@tonic-gate  * @author James Kempf
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate 
500Sstevel@tonic-gate class SLPServerHeaderV2 extends SLPHeaderV2  implements Cloneable {
510Sstevel@tonic-gate 
520Sstevel@tonic-gate     // Function code for message reply.
530Sstevel@tonic-gate 
540Sstevel@tonic-gate     int replyFunctionCode = SrvLocHeader.SrvAck;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate     // For SrvLocHeader.newInstance().
570Sstevel@tonic-gate 
SLPServerHeaderV2()580Sstevel@tonic-gate     SLPServerHeaderV2() {
590Sstevel@tonic-gate 	super();
600Sstevel@tonic-gate 
610Sstevel@tonic-gate     }
620Sstevel@tonic-gate 
630Sstevel@tonic-gate     // Construct a header for output. Used by the client side code to
640Sstevel@tonic-gate     //  construct an initial request and the server side code to construct
650Sstevel@tonic-gate     //  a reply.
660Sstevel@tonic-gate 
SLPServerHeaderV2(int functionCode, boolean fresh, Locale locale)670Sstevel@tonic-gate     SLPServerHeaderV2(int functionCode, boolean fresh, Locale locale)
680Sstevel@tonic-gate 	throws ServiceLocationException {
690Sstevel@tonic-gate 	super(functionCode, fresh, locale);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate     }
720Sstevel@tonic-gate 
730Sstevel@tonic-gate     // Assign reply code based on function code type, then use superclass
740Sstevel@tonic-gate     //  method to parse header.
750Sstevel@tonic-gate 
parseHeader(int functionCode, DataInputStream dis)760Sstevel@tonic-gate     void parseHeader(int functionCode, DataInputStream dis)
770Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	// We ignore the error case here.
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	switch (functionCode) {
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	case SrvLocHeader.SrvReq:
840Sstevel@tonic-gate 	    replyFunctionCode = SrvLocHeader.SrvRply;
850Sstevel@tonic-gate 	    break;
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 	case SrvLocHeader.AttrRqst:
880Sstevel@tonic-gate 	    replyFunctionCode = SrvLocHeader.AttrRply;
890Sstevel@tonic-gate 	    break;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	case SrvLocHeader.SrvTypeRqst:
920Sstevel@tonic-gate 	    replyFunctionCode = SrvLocHeader.SrvTypeRply;
930Sstevel@tonic-gate 	    break;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	case SrvLocHeader.SrvReg: case SrvLocHeader.SrvDereg:
960Sstevel@tonic-gate 	    replyFunctionCode = SrvLocHeader.SrvAck;
970Sstevel@tonic-gate 	    break;
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	    // If we get an error during creating of the DAAdvert to
1000Sstevel@tonic-gate 	    //  reply, we need to continue and reply with DAAdvert.
1010Sstevel@tonic-gate 	    //  This is only true for a unicast DAAdvert, though.
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	case SrvLocHeader.DAAdvert:
1040Sstevel@tonic-gate 	    replyFunctionCode = SrvLocHeader.DAAdvert;
1050Sstevel@tonic-gate 	    break;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	    // We ignore the header error code for SAAdvert because
1080Sstevel@tonic-gate 	    //  it is always multicast.
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	// We are now set up to handle any errors that may come flying out
1130Sstevel@tonic-gate 	//  of here.
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 	super.parseHeader(functionCode, dis);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate     }
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate     // Replace the superclass method with a method that parses the server
1200Sstevel@tonic-gate     //  side.
1210Sstevel@tonic-gate 
parseMsg(DataInputStream dis)1220Sstevel@tonic-gate     SrvLocMsg parseMsg(DataInputStream dis)
1230Sstevel@tonic-gate 	throws ServiceLocationException,
1240Sstevel@tonic-gate 	       IOException,
1250Sstevel@tonic-gate 	       IllegalArgumentException {
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	SrvLocMsg msg = null;
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	// DAAdvert needs to get it's error code parsed here because
1300Sstevel@tonic-gate 	//  error codes are always handled in parseMsg() and it is
1310Sstevel@tonic-gate 	//  the only server side message that has one.
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	if (functionCode == SrvLocHeader.DAAdvert) {
1340Sstevel@tonic-gate 	    errCode = (short)getInt(dis);
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	}
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	// Switch and convert according to function code.
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	switch (functionCode) {
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	case SrvLocHeader.SrvReg:
1430Sstevel@tonic-gate 	    msg = new SSrvReg(this, dis);
1440Sstevel@tonic-gate 	    break;
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	case SrvLocHeader.SrvDereg:
1470Sstevel@tonic-gate 	    msg = new SSrvDereg(this, dis);
1480Sstevel@tonic-gate 	    break;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	case SrvLocHeader.SrvReq:
1510Sstevel@tonic-gate 	    msg = new SSrvMsg(this, dis);
1520Sstevel@tonic-gate 	    break;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	case SrvLocHeader.AttrRqst:
1550Sstevel@tonic-gate 	    msg = new SAttrMsg(this, dis);
1560Sstevel@tonic-gate 	    break;
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	case SrvLocHeader.SrvAck:
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	    // We function as our own message.
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	    msg = this;
1630Sstevel@tonic-gate 	    iNumReplies = 1;
1640Sstevel@tonic-gate 	    break;
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	case SrvLocHeader.SrvTypeRqst:
1670Sstevel@tonic-gate 	    msg = new SSrvTypeMsg(this, dis);
1680Sstevel@tonic-gate 	    break;
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	case SrvLocHeader.DAAdvert:
1710Sstevel@tonic-gate 	    msg = new CDAAdvert(this, dis);
1720Sstevel@tonic-gate 	    break;
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 	case SrvLocHeader.SAAdvert:
1750Sstevel@tonic-gate 	    msg = new CSAAdvert(this, dis);
1760Sstevel@tonic-gate 	    break;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	default:
1790Sstevel@tonic-gate 	    throw
1800Sstevel@tonic-gate 		new ServiceLocationException(
1810Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
1820Sstevel@tonic-gate 				"function_code_error",
1830Sstevel@tonic-gate 				new Object[] {
1840Sstevel@tonic-gate 		    new Integer(functionCode)});
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	}
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	// Check for size overflow.
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	if (nbytes > length) {
1910Sstevel@tonic-gate 	    throw
1920Sstevel@tonic-gate 		new ServiceLocationException(
1930Sstevel@tonic-gate 				ServiceLocationException.PARSE_ERROR,
1940Sstevel@tonic-gate 				"length_overflow",
1950Sstevel@tonic-gate 				new Object[] {
1960Sstevel@tonic-gate 		    new Integer(nbytes), new Integer(length)});
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	}
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	return msg;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate     }
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate     // Create an error reply using the reply code. Calculate the
2050Sstevel@tonic-gate     //  error code using the exception.
2060Sstevel@tonic-gate 
makeErrorReply(Exception ex)2070Sstevel@tonic-gate     SrvLocMsg makeErrorReply(Exception ex) {
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	SrvLocHeader hdr = null;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	// Clone the header to make sure that everything else is the same.
2120Sstevel@tonic-gate 	//  We don't want to use the same header because it may be tested
2130Sstevel@tonic-gate 	//  elsewhere.
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	try {
2160Sstevel@tonic-gate 	    hdr = (SrvLocHeader)this.clone();
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	} catch (CloneNotSupportedException exx) {
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	    // We support it, so no-op.
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	}
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	// Re-initialize flags but not multicast, since we need to filter on it
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	hdr.fresh = false;
2270Sstevel@tonic-gate 	hdr.overflow = false;
2280Sstevel@tonic-gate 	hdr.functionCode = replyFunctionCode;
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	// We should *not* be getting a null exception down this path!
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	Assert.slpassert(ex != null,
2330Sstevel@tonic-gate 		      "null_parameter",
2340Sstevel@tonic-gate 		      new Object[] {ex});
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	if (ex instanceof ServiceLocationException) {
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	    hdr.errCode = ((ServiceLocationException)ex).getErrorCode();
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	    if (!ServiceLocationException.validWireErrorCode(hdr.errCode)) {
2410Sstevel@tonic-gate 		hdr.errCode = ServiceLocationException.INTERNAL_ERROR;
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	    }
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	} else if (ex instanceof IllegalArgumentException ||
2460Sstevel@tonic-gate 		   ex instanceof IOException) {
2470Sstevel@tonic-gate 	    hdr.errCode = ServiceLocationException.PARSE_ERROR;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	} else {
2500Sstevel@tonic-gate 	    hdr.errCode = ServiceLocationException.INTERNAL_ERROR;
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	// Construct header description.
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	constructDescription("SrvLocMsg", "");
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	return hdr;
2590Sstevel@tonic-gate     }
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate     // Return a reply header with flags properly set.
2620Sstevel@tonic-gate 
makeReplyHeader()2630Sstevel@tonic-gate     SLPServerHeaderV2 makeReplyHeader() {
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	SLPServerHeaderV2 hdr = null;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	try {
2680Sstevel@tonic-gate 	    hdr = (SLPServerHeaderV2)this.clone();
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	} catch (CloneNotSupportedException ex) {
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	    // No-op, since we support it.
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	}
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	hdr.functionCode = replyFunctionCode;
2770Sstevel@tonic-gate 	hdr.length = 0;
2780Sstevel@tonic-gate 	hdr.previousResponders = null;
2790Sstevel@tonic-gate 	hdr.scopes = null;
2800Sstevel@tonic-gate 	hdr.overflow = false;
2810Sstevel@tonic-gate 	hdr.fresh = false;
2820Sstevel@tonic-gate 	hdr.mcast = false;
2830Sstevel@tonic-gate 	hdr.nbytes = 0;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	return hdr;
2860Sstevel@tonic-gate     }
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate     // Return display string.
2890Sstevel@tonic-gate 
toString()2900Sstevel@tonic-gate     public String toString() {
2910Sstevel@tonic-gate 	return
2920Sstevel@tonic-gate 	    getMsgType() + ":version=``" + version + "''\n" +
2930Sstevel@tonic-gate 	    "       functionCode=``" + functionCode + "''\n" +
2940Sstevel@tonic-gate 	    "       length=``" + length + "''" + "''\n" +
2950Sstevel@tonic-gate 	    "       overflow=``" + overflow + "''\n" +
2960Sstevel@tonic-gate 	    "       mcast = ``" + mcast + "''\n" +
2970Sstevel@tonic-gate 	    "       fresh=``" + fresh + "''\n" +
2980Sstevel@tonic-gate 	    "       locale = ``" + locale + "''\n" +
2990Sstevel@tonic-gate 	    "       xid=``0x" + Integer.toHexString(xid) + "''\n" +
3000Sstevel@tonic-gate 	    "       errCode=``" + errCode + "''\n" +
3010Sstevel@tonic-gate 	    "       previousResponders=``" + previousResponders + "''\n" +
3020Sstevel@tonic-gate 	    "       scopes=``" + scopes + "''\n" +
3030Sstevel@tonic-gate 	    getMsgDescription();
3040Sstevel@tonic-gate     }
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate     //
3070Sstevel@tonic-gate     // Parsing Utilities.
3080Sstevel@tonic-gate     //
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate     // Parse in the scope list.
3110Sstevel@tonic-gate 
parseScopesIn(DataInputStream dis)3120Sstevel@tonic-gate     void parseScopesIn(DataInputStream dis)
3130Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	StringBuffer buf = new StringBuffer();
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	getString(buf, dis);
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	scopes = parseCommaSeparatedListIn(buf.toString(), true);
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 	// Unescape scope strings.
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	unescapeScopeStrings(scopes);
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	// Validate.
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	DATable.validateScopes(scopes, locale);
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate     }
3300Sstevel@tonic-gate 
parsePreviousRespondersIn(DataInputStream dis)3310Sstevel@tonic-gate     void parsePreviousRespondersIn(DataInputStream dis)
3320Sstevel@tonic-gate 	throws ServiceLocationException, IOException {
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	StringBuffer buf = new StringBuffer();
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 	getString(buf, dis);
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	previousResponders =
3390Sstevel@tonic-gate 	    parseCommaSeparatedListIn(buf.toString(), true);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate     }
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate     // Return an SLPv2 DAAdvert.
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate     SDAAdvert
getDAAdvert(short xid, long timestamp, ServiceURL url, Vector scopes, Vector attrs)3460Sstevel@tonic-gate 	getDAAdvert(short xid,
3470Sstevel@tonic-gate 		    long timestamp,
3480Sstevel@tonic-gate 		    ServiceURL url,
3490Sstevel@tonic-gate 		    Vector scopes,
3500Sstevel@tonic-gate 		    Vector attrs)
3510Sstevel@tonic-gate 	throws ServiceLocationException {
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	// If scopes vector is null, then return all scopes for this
3540Sstevel@tonic-gate 	//  DA.
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 	if (scopes.size() <= 0) {
3570Sstevel@tonic-gate 	    scopes = SLPConfig.getSLPConfig().getSAConfiguredScopes();
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	return new SDAAdvert(this, xid, timestamp, url, scopes, attrs);
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate     }
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate }
366