root/usr/src/lib/libslp/javalib/com/sun/slp/CDAAdvert.java
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1999 by Sun Microsystems, Inc.
 * All rights reserved.
 *
 */

//  CDAAdvert.java:    Message class for SLP CDAAdvert message
//  Author:           James Kempf
//  Created On:       Fri Oct 10 10:48:05 1997
//  Last Modified By: James Kempf
//  Last Modified On: Fri Jan 29 09:24:50 1999
//  Update Count:     134
//

package com.sun.slp;

import java.util.*;
import java.io.*;


/**
 * The CDAAdvert class models the SLP DAAdvert message, client side.
 * We need to accommodate SLPv1 by using an initialize() method.
 *
 * @author James Kempf
 */


class CDAAdvert extends SrvLocMsgImpl {

    ServiceURL URL = null;              // The DA's service URL
    long  timestamp = 0;                // timestamp.
    Vector attrs = new Vector();        // Attributes
    Hashtable authBlock = null;         // Scope auth blocks.
    String spis = null;                 // Supported SPIs

    // Construct a CDAAdvert from the input stream.

    CDAAdvert(SrvLocHeader hdr, DataInputStream dis)
        throws ServiceLocationException, IOException {
        super(hdr, SrvLocHeader.DAAdvert);

        this.initialize(dis);

    }

    // Initialize the object from the input stream.

    protected void initialize(DataInputStream dis)
        throws ServiceLocationException, IOException {

        SLPHeaderV2 hdr = (SLPHeaderV2)getHeader();

        // Parse in the timestamp. Save bytes for auth block.

        byte[] tsBytes = new byte[4];

        timestamp = getInt32(hdr, dis, tsBytes);

        // Parse in DA's service URL.

        StringBuffer buf = new StringBuffer();

        byte[] urlBytes = hdr.getString(buf, dis);

        int lifetime = getDAURLLifetime();

        String surl = buf.toString();

        // Parse in the scope list.

        byte[] scopeBytes = hdr.getString(buf, dis);

        hdr.scopes = hdr.parseCommaSeparatedListIn(buf.toString(), true);

        // Unescape scope strigns.

        hdr.unescapeScopeStrings(hdr.scopes);

        // Validate scope list.

        DATable.validateScopes(hdr.scopes, hdr.locale);

        // Parse in attribute list.

        byte[] attrBytes = hdr.parseAttributeVectorIn(attrs, dis, false);

        // Parse in the SPI list
        byte[] spiBytes = hdr.getString(buf, dis);
        spis = buf.toString();

        // Construct bytes for auth.
        Object[] message = new Object[9];

        message[0] = tsBytes;

        // None of the strings have leading length fields, so add them here
        ByteArrayOutputStream abaos = new ByteArrayOutputStream();
        hdr.putInteger(urlBytes.length, abaos);
        message[1] = abaos.toByteArray();
        message[2] = urlBytes;

        abaos = new ByteArrayOutputStream();
        hdr.putInteger(attrBytes.length, abaos);
        message[3] = abaos.toByteArray();
        message[4] = attrBytes;

        abaos = new ByteArrayOutputStream();
        hdr.putInteger(scopeBytes.length, abaos);
        message[5] = abaos.toByteArray();
        message[6] = scopeBytes;

        abaos = new ByteArrayOutputStream();
        hdr.putInteger(spiBytes.length, abaos);
        message[7] = abaos.toByteArray();
        message[8] = spiBytes;

        // Parse in an auth block, if there.

        authBlock = hdr.parseSignatureIn(message, dis);

        if (authBlock != null) {
            lifetime = AuthBlock.getShortestLifetime(authBlock);

        }

        // Create URL.

        try {

            URL = new ServiceURL(surl, lifetime);

        } catch (IllegalArgumentException ex) {

            throw
                new ServiceLocationException(
                                ServiceLocationException.PARSE_ERROR,
                                "malformed_url",
                                new Object[] {ex.getMessage()});

        }

        // Validate the service URL.

        ServiceType serviceType = URL.getServiceType();

        if (!serviceType.equals(Defaults.DA_SERVICE_TYPE)) {
            throw
                new ServiceLocationException(
                                ServiceLocationException.PARSE_ERROR,
                                "not_right_url",
                                new Object[] {URL, "DA"});

        }

        // Set number of replies to one.

        hdr.iNumReplies = 1;
    }


    // Get the timestamp.

    static private long getInt32(SrvLocHeader hdr,
                                 DataInputStream dis,
                                 byte[] bytes)
        throws ServiceLocationException, IOException {

        bytes[0] = (byte)dis.read();
        bytes[1] = (byte)dis.read();
        bytes[2] = (byte)dis.read();
        bytes[3] = (byte)dis.read();

        long a = (long)((char)bytes[0] & 0xFF);
        long b = (long)((char)bytes[1] & 0xFF);
        long c = (long)((char)bytes[2] & 0xFF);
        long d = (long)((char)bytes[3] & 0xFF);

        long i = a << 24;
        i += b << 16;
        i += c << 8;
        i += d;

        hdr.nbytes += 4;

        return i;
    }

    // Return true if the advert indicates that the DA is going down.

    boolean isGoingDown() {
        return (timestamp == 0);

    }

    // Return true if the advert was unsolicited.

    boolean isUnsolicited() {
        return (hdr.xid == 0);

    }

    // Set is solicited. No-op for V2, since messages already know.

    void setIsUnsolicited(boolean flag) {

    }

    // Calcualte DA URL lifetime, based on active discovery interval and
    //  granularity.

    private int getDAURLLifetime() {

        // Calculate lifetime based on maximum length of time between
        //  active discoveries. We add a fudge factor to avoid problems
        //  with scheduler granularity.

        SLPConfig config = SLPConfig.getSLPConfig();

        int disInt = config.getActiveDiscoveryInterval();
        int granInt = config.getActiveDiscoveryGranularity();

        // If the discovery interval is zero, then the granularity will be
        //  also, and active discovery is off. In principle, it doesn't
        //  matter what the DA URL interval is because active discovery
        //  won't find any, because its off.

        if (disInt <= 0) {
            return ServiceURL.LIFETIME_MAXIMUM;

        } else {
            int lifetime = disInt + granInt;

            return
                (lifetime > ServiceURL.LIFETIME_MAXIMUM ?
                 ServiceURL.LIFETIME_MAXIMUM:lifetime);

        }
    }
}