/*
* 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) 2001 by Sun Microsystems, Inc.
* All rights reserved.
*
*/
// SLPV1Manager.java: Manages V1 Compatibility
// Author: James Kempf
// Created On: Wed Sep 9 09:51:40 1998
// Last Modified By: James Kempf
// Last Modified On: Thu Mar 4 10:39:11 1999
// Update Count: 46
//
package com.sun.slp;
import java.io.*;
import java.util.*;
import java.net.*;
/**
* The SLPV1Manager manages access between the DA and the V1 compatibility
* framework. The DA calls into the SLPV1Manager to initialize
* active and passive DA advertising, and to decode an incoming V1
* message. However, the ServiceTable does *not* call into SLPV1Manager
* to handle an outgoing message, since each individual message type is
* handled separately. SLPV1Manager also handles V1 defaults.
*
* @author James Kempf
*/
abstract class SLPV1Manager extends Object {
// V1 Header class.
static final String V1_HEADER_CLASS = "com.sun.slp.SLPHeaderV1";
// V1 multicast addresses.
static final String sGeneralSLPMCAddress = "224.0.1.22";
static final String sDADiscSLPMCAddress = "224.0.1.35";
static InetAddress v1SLPGSAddr = null;
static InetAddress v1SLPDAAddr = null;
/**
* The SLPV1Advertiser implements the SLPv1 DAAdvert xid incrementing
* algorithm. In SLPv1, the xid of an unsolicited DAAdvert is only
* 0 if it came up stateless. If it comes up with preexisting state,
* it sets the counter to 0x100. Also, when the xid counter wraps,
* it must wrap to 0x100 and not 0x0.
*/
static class SLPV1Advertiser extends DAAdvertiser {
// For implementing the V1 xid algorithm.
private short xid = 0;
private static final short STATEFUL_XID = 0x100;
private static final long STATEFUL_TIME_BOUND = 300L;
// Service table.
private ServiceTable table = null;
// Scopes to use. We need to map from V2, so default corresponds to
// the empty scope.
Vector useScopes = new Vector();
// Create an SLPv1 Advertiser and start it running.
SLPV1Advertiser(InetAddress interfac,
InetAddress maddr,
ServiceTable table)
throws ServiceLocationException {
super();
this.table = table;
initialize();
// There will be NO listener on this multicast address,
// so the superclass will simply create a scoket for it.
// We don't want to create a new Listener
// because we are not interested in multicast requests since
// only SAs answer multicast requests.
initializeNetworking(interfac, maddr);
}
// Initialize the xid for passive advertising. We need to determine
// whether we came up stateless or not. We do this by asking the
// the service store for the stateless reboot time. If the
// stateless reboot time is within the last 5 minutes, we
// assume we came up stateless. Otherwise, we're stateful.
// We also initialize the URL and scopes.
private void initialize() throws ServiceLocationException {
// Initialize the xid.
ServiceStore store = ServiceTable.getServiceTable().store;
long timestamp = store.getStateTimestamp();
long currentTime = SLPConfig.currentSLPTime();
if ((currentTime - timestamp) > STATEFUL_TIME_BOUND) {
xid = STATEFUL_XID;
}
// Initialize the scopes.
useScopes = config.getSAConfiguredScopes();
}
// Return the output buffer for a passive advert. We need to create
// the advert, rolling over the xid if necessary for the next one.
protected byte[] getOutbuf() {
SDAAdvert daadvert = null;
try {
SLPHeaderV1 hdr = new SLPHeaderV1();
hdr.functionCode = SrvLocHeader.DAAdvert;
hdr.locale = config.getLocale();
daadvert = (SDAAdvert)table.makeDAAdvert(hdr,
interfac,
xid,
useScopes,
config);
hdr = (SLPHeaderV1)daadvert.getHeader();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
hdr.externalize(baos, true, false);
byte[] outbuf = baos.toByteArray();
bumpXid();
return outbuf;
} catch (ServiceLocationException ex) {
Assert.slpassert(false,
"v1_advert_error",
new Object[0]);
}
return null;
}
private void bumpXid() {
int newXID = (int)xid + 1;
if (newXID > Short.MAX_VALUE) {
xid = STATEFUL_XID;
} else {
xid = (short)newXID;
}
}
}
// Start up listener, active and passive listeners for SLPv1.
static public void
start(SLPConfig config, ServerDATable table, ServiceTable stable) {
// We do not handle SLPv1 if security is enabled, because SLPv1
// security is not implemented.
if (config.getHasSecurity()) {
if (config.regTest() ||
config.traceMsg() ||
config.traceDrop() ||
config.traceDATraffic()) {
config.writeLog("v1_security_enabled",
new Object[0]);
}
return;
}
Vector interfaces = config.getInterfaces();
int i = 0, n = interfaces.size();
Vector advs = new Vector();
try {
InetAddress v1SLPDAAddr = null;
// Get address for DA discovery multicast.
v1SLPDAAddr = InetAddress.getByName(sDADiscSLPMCAddress);
v1SLPGSAddr = InetAddress.getByName(sGeneralSLPMCAddress);
// Add all listeners onto the SLPv1 DA multicast address and
// create a DAAdvertiser on all network interfaces for the
// general multicast group.
for (i = 0; i < n; i++) {
InetAddress interfac = (InetAddress)interfaces.elementAt(i);
// Listen for SLPv1 multicast DA service requests. Only DA
// service requests are multicast on this address.
Listener.addListenerToMulticastGroup(interfac, v1SLPDAAddr);
// We don't need to listen to the SLPv1 general multicast
// address because we never want any multicast service
// requests. But we do need to advertise as an SLPv1 DA.
// So we have a special DAAdvertiser subclass to do it.
DAAdvertiser ad =
new SLPV1Advertiser(interfac, v1SLPGSAddr, stable);
ad.start();
advs.addElement(ad);
}
// Let admin know we are running in SLPv1 compatibility mode
// if tracing is on
if (config.regTest() ||
config.traceMsg() ||
config.traceDrop() ||
config.traceDATraffic()) {
config.writeLog("v1_hello",
new Object[] {config.getSAConfiguredScopes()});
}
return;
} catch (ServiceLocationException ex) {
config.writeLog("v1_init_error",
new Object[] {ex.getMessage()});
} catch (UnknownHostException ex) {
config.writeLog("v1_init_error",
new Object[] {ex.getMessage()});
}
// Remove Listeners from multicast group, stop DAAdvertisers.
// An error occured.
int j;
for (j = 0; j < i; i++) {
InetAddress interfac = (InetAddress)interfaces.elementAt(i);
DatagramSocket dss =
Listener.returnListenerSocketOnInterface(interfac);
if (dss instanceof MulticastSocket) {
MulticastSocket mss = (MulticastSocket)dss;
try {
mss.leaveGroup(v1SLPDAAddr);
} catch (IOException ex) {
// Ignore it.
}
DAAdvertiser ad = (DAAdvertiser)advs.elementAt(j);
ad.stopThread();
}
}
}
// Initialize CSrvReg, CSrvDereg, CSrvMsg, and SDAAdvert classes for SLPv1,
// also V1 header class.
static {
SrvLocHeader.addHeaderClass(V1_HEADER_CLASS, SLPHeaderV1.VERSION);
}
}