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 
35 package com.sun.slp;
36 
37 import java.io.*;
38 import java.util.*;
39 import 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 
53 abstract 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 
SLPV1Advertiser(InetAddress interfac, InetAddress maddr, ServiceTable table)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 
initialize()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 
getOutbuf()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 
bumpXid()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
start(SLPConfig config, ServerDATable table, ServiceTable stable)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 
SrvLocHeader.addHeaderClass(V1_HEADER_CLASS, SLPHeaderV1.VERSION)316 	SrvLocHeader.addHeaderClass(V1_HEADER_CLASS, SLPHeaderV1.VERSION);
317 
318     }
319 }
320