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) 2001 by Sun Microsystems, Inc.
23 * All rights reserved.
24 *
25 */
26
27//  SLPV1Manager.java: Manages V1 Compatibility
28//  Author:           James Kempf
29//  Created On:       Wed Sep  9 09:51:40 1998
30//  Last Modified By: James Kempf
31//  Last Modified On: Thu Mar  4 10:39:11 1999
32//  Update Count:     46
33//
34
35package com.sun.slp;
36
37import java.io.*;
38import java.util.*;
39import java.net.*;
40
41
42/**
43 * The SLPV1Manager manages access between the DA and the V1 compatibility
44 * framework. The DA calls into the SLPV1Manager to initialize
45 * active and passive DA advertising, and to decode an incoming V1
46 * message. However, the ServiceTable does *not* call into SLPV1Manager
47 * to handle an outgoing message, since each individual message type is
48 * handled separately. SLPV1Manager also handles V1 defaults.
49 *
50 * @author James Kempf
51 */
52
53abstract class SLPV1Manager extends Object {
54
55    // V1 Header class.
56
57    static final String V1_HEADER_CLASS = "com.sun.slp.SLPHeaderV1";
58
59    // V1 multicast addresses.
60
61    static final String sGeneralSLPMCAddress = "224.0.1.22";
62    static final String sDADiscSLPMCAddress  = "224.0.1.35";
63
64    static InetAddress v1SLPGSAddr = null;
65    static InetAddress v1SLPDAAddr = null;
66
67    /**
68     * The SLPV1Advertiser implements the SLPv1 DAAdvert xid incrementing
69     * algorithm. In SLPv1, the xid of an unsolicited DAAdvert is only
70     * 0 if it came up stateless. If it comes up with preexisting state,
71     * it sets the counter to 0x100. Also, when the xid counter wraps,
72     * it must wrap to 0x100 and not 0x0.
73     */
74
75    static class SLPV1Advertiser extends DAAdvertiser {
76
77	// For implementing the V1 xid algorithm.
78
79	private short xid = 0;
80
81	private static final short STATEFUL_XID = 0x100;
82
83	private static final long STATEFUL_TIME_BOUND = 300L;
84
85	// Service table.
86
87	private ServiceTable table = null;
88
89	// Scopes to use. We need to map from V2, so default corresponds to
90	//  the empty scope.
91
92	Vector useScopes = new Vector();
93
94	// Create an SLPv1 Advertiser and start it running.
95
96	SLPV1Advertiser(InetAddress interfac,
97			InetAddress maddr,
98			ServiceTable table)
99	    throws ServiceLocationException {
100	    super();
101
102	    this.table = table;
103
104	    initialize();
105
106	    //  There will be NO listener on this multicast address,
107	    //  so the superclass will simply create a scoket for it.
108	    //  We don't want to create a new Listener
109	    //  because we are not interested in multicast requests since
110	    //  only SAs answer multicast requests.
111
112	    initializeNetworking(interfac, maddr);
113	}
114
115	// Initialize the xid for passive advertising. We need to determine
116	//  whether we came up stateless or not. We do this by asking the
117	//  the service store for the stateless reboot time. If the
118	//  stateless reboot time is within the last 5 minutes, we
119	//  assume we came up stateless. Otherwise, we're stateful.
120	//  We also initialize the URL and scopes.
121
122	private void initialize() throws ServiceLocationException {
123
124	    // Initialize the xid.
125
126	    ServiceStore store = ServiceTable.getServiceTable().store;
127	    long timestamp = store.getStateTimestamp();
128	    long currentTime = SLPConfig.currentSLPTime();
129
130	    if ((currentTime - timestamp) > STATEFUL_TIME_BOUND) {
131		xid = STATEFUL_XID;
132
133	    }
134
135	    // Initialize the scopes.
136
137	    useScopes = config.getSAConfiguredScopes();
138
139	}
140
141	// Return the output buffer for a passive advert. We need to create
142	//  the advert, rolling over the xid if necessary for the next one.
143
144	protected byte[] getOutbuf() {
145
146	    SDAAdvert daadvert = null;
147
148	    try {
149
150		SLPHeaderV1 hdr = new SLPHeaderV1();
151		hdr.functionCode = SrvLocHeader.DAAdvert;
152		hdr.locale = config.getLocale();
153
154		daadvert = (SDAAdvert)table.makeDAAdvert(hdr,
155							 interfac,
156							 xid,
157							 useScopes,
158							 config);
159		hdr = (SLPHeaderV1)daadvert.getHeader();
160
161		ByteArrayOutputStream baos = new ByteArrayOutputStream();
162
163		hdr.externalize(baos, true, false);
164		byte[] outbuf = baos.toByteArray();
165
166		bumpXid();
167
168		return outbuf;
169
170	    } catch (ServiceLocationException ex) {
171		Assert.slpassert(false,
172			      "v1_advert_error",
173			      new Object[0]);
174
175	    }
176
177	    return null;
178	}
179
180	private void bumpXid() {
181
182	    int newXID = (int)xid + 1;
183
184	    if (newXID > Short.MAX_VALUE) {
185		xid = STATEFUL_XID;
186
187	    } else {
188		xid = (short)newXID;
189
190	    }
191	}
192    }
193
194
195    // Start up listener, active and passive listeners for SLPv1.
196
197    static public void
198	start(SLPConfig config, ServerDATable table, ServiceTable stable) {
199
200	// We do not handle SLPv1 if security is enabled, because SLPv1
201	//  security is not implemented.
202
203	if (config.getHasSecurity()) {
204
205	    if (config.regTest() ||
206		config.traceMsg() ||
207		config.traceDrop() ||
208		config.traceDATraffic()) {
209
210		config.writeLog("v1_security_enabled",
211				new Object[0]);
212	    }
213
214	    return;
215
216	}
217
218	Vector interfaces = config.getInterfaces();
219	int i = 0, n = interfaces.size();
220	Vector advs = new Vector();
221
222	try {
223
224	    InetAddress v1SLPDAAddr = null;
225
226	    // Get address for DA discovery multicast.
227
228	    v1SLPDAAddr = InetAddress.getByName(sDADiscSLPMCAddress);
229	    v1SLPGSAddr = InetAddress.getByName(sGeneralSLPMCAddress);
230
231	    // Add all listeners onto the SLPv1 DA multicast address and
232	    //  create a DAAdvertiser on all network interfaces for the
233	    //  general multicast group.
234
235	    for (i = 0; i < n; i++) {
236		InetAddress interfac = (InetAddress)interfaces.elementAt(i);
237
238		// Listen for SLPv1 multicast DA service requests. Only DA
239		//  service requests are multicast on this address.
240
241		Listener.addListenerToMulticastGroup(interfac, v1SLPDAAddr);
242
243		// We don't need to listen to the SLPv1 general multicast
244		//  address because we never want any multicast service
245		//  requests. But we do need to advertise as an SLPv1 DA.
246		//  So we have a special DAAdvertiser subclass to do it.
247
248		DAAdvertiser ad =
249		    new SLPV1Advertiser(interfac, v1SLPGSAddr, stable);
250		ad.start();
251
252		advs.addElement(ad);
253
254	    }
255
256	    // Let admin know we are running in SLPv1 compatibility mode
257	    //  if tracing is on
258
259	    if (config.regTest() ||
260		config.traceMsg() ||
261		config.traceDrop() ||
262		config.traceDATraffic()) {
263
264		config.writeLog("v1_hello",
265				new Object[] {config.getSAConfiguredScopes()});
266	    }
267
268	    return;
269
270	} catch (ServiceLocationException ex) {
271
272	    config.writeLog("v1_init_error",
273			    new Object[] {ex.getMessage()});
274
275	}  catch (UnknownHostException ex) {
276
277	    config.writeLog("v1_init_error",
278			    new Object[] {ex.getMessage()});
279
280	}
281
282	// Remove Listeners from multicast group, stop DAAdvertisers.
283	// An error occured.
284
285	int j;
286
287	for (j = 0; j < i; i++) {
288	    InetAddress interfac = (InetAddress)interfaces.elementAt(i);
289	    DatagramSocket dss =
290		Listener.returnListenerSocketOnInterface(interfac);
291
292	    if (dss instanceof MulticastSocket) {
293		MulticastSocket mss = (MulticastSocket)dss;
294
295		try {
296		    mss.leaveGroup(v1SLPDAAddr);
297
298		} catch (IOException ex) {
299
300		    // Ignore it.
301
302		}
303
304		DAAdvertiser ad = (DAAdvertiser)advs.elementAt(j);
305
306		ad.stopThread();
307	    }
308	}
309    }
310
311    // Initialize CSrvReg, CSrvDereg, CSrvMsg, and SDAAdvert classes for SLPv1,
312    //  also V1 header class.
313
314    static {
315
316	SrvLocHeader.addHeaderClass(V1_HEADER_CLASS, SLPHeaderV1.VERSION);
317
318    }
319}
320