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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * ident	"%Z%%M%	%I%	%E% SMI"
24  *
25  * Copyright (c) 2001 by Sun Microsystems, Inc.
26  * All rights reserved.
27  *
28  */
29 
30 //  SCCS Status:      %W%	%G%
31 //  ActiveDiscoverer.java: Object to perform active DA discovery.
32 //  Author:           James Kempf
33 //  Created On:       Thu Sep  3 08:45:21 1998
34 //  Last Modified By: James Kempf
35 //  Last Modified On: Thu Jan 28 15:45:45 1999
36 //  Update Count:     32
37 //
38 
39 package com.sun.slp;
40 
41 import java.util.*;
42 import java.net.*;
43 
44 /*
45  * The ActiveDiscover does active discovery DA discovery by periodically
46  * sending out a SrvRqst for "service:directory-agent". Replies are
47  * entered into the DA table.
48  *
49  * @version %R%.%L% %D%
50  * @author James Kempf
51  */
52 
53 class ActiveDiscoverer extends Thread {
54 
55     // Config object.
56 
57     static private SLPConfig config = null;
58 
59     // Message for active DA discovery.
60 
61     private CSrvMsg activeMsg = null;
62 
63     // Version of protocol to use for advertisements.
64 
65     private int version = 0;
66 
67     // DATable where discovered DAs are recorded.
68 
69     private ServerDATable table = null;
70 
71     // Scopes to advertise for.
72 
73     private Vector useScopes = null;
74 
75     // Address on which to advertise.
76 
77     private InetAddress address = null;
78 
79     // Create an active discoverer.
80 
81     ActiveDiscoverer(int version,
82 		     ServerDATable table,
83 		     Vector useScopes,
84 		     InetAddress address) {
85 
86 	this.version = version;
87 
88 	this.table = table;
89 
90 	this.useScopes = useScopes;
91 
92 	this.address = address;
93 
94 	if (config == null) {
95 	    config = SLPConfig.getSLPConfig();
96 
97 	}
98 
99     }
100 
101     // Do an initial active discovery then start a thread to
102     //  do one periodically.
103 
104     public void start() {
105 
106 	// Initial sleepy time.
107 
108 	long sleepyTime = config.getRandomWait();
109 
110 	// Create a message for active discovery.
111 
112 	try {
113 
114 	    activeMsg = new CSrvMsg(config.getLocale(),
115 				    Defaults.DA_SERVICE_TYPE,
116 				    useScopes,
117 				    "");
118 
119 	} catch (ServiceLocationException ex) {
120 	    Assert.slpassert(false,
121 			  "sdat_active_err",
122 			  new Object[] {
123 		new Integer(ex.getErrorCode()),
124 		    ex.getMessage()});
125 
126 	}
127 
128 	// Initialize preconfigured DAs.
129 
130 	addPreconfiguredDAs();
131 
132 	// Do an initial round of active discovery, waiting for
133 	//  a random period first. Only do it if active
134 	//  discovery is on.
135 
136 	if (config.getActiveDiscoveryInterval() > 0) {
137 	    try {
138 		Thread.currentThread().sleep(sleepyTime);
139 
140 	    } catch (InterruptedException ex) {
141 
142 	    }
143 
144 	    activeDiscovery();
145 
146 	} else {
147 
148 	    // Report that active discovery is off.
149 
150 	    config.writeLog("ad_active_off",
151 			    new Object[0]);
152 
153 	}
154 
155 	// Start the active discovery thread.
156 
157 	super.start();
158     }
159 
160 
161 
162     // Implement the Runnable interface for a thread to start.
163 
164     public void run() {
165 
166 	// Set the Thread name.
167 
168 	Thread.currentThread().setName("SLP Active DA Discovery");
169 
170 	// Sleepy time until discovery.
171 
172 	long sleepyTime = config.getActiveDiscoveryInterval() * 1000;
173 
174 	// If the sleep time is zero, then active discovery is turned off.
175 	//  Use the service URL maximum lifetime.
176 
177 	if (sleepyTime <= 0) {
178 	    sleepyTime = (ServiceURL.LIFETIME_MAXIMUM / 2) * 1000;
179 
180 	}
181 
182 	// Register ourselves at startup if we are a DA. We may not be
183 	//  listening for the active discovery message at startup
184 	//  because the listener thread goes on-line last of all.
185 
186 	if (config.isDA()) {
187 	    Vector interfaces = config.getInterfaces();
188 	    int i, n = interfaces.size();
189 
190 	    for (i = 0; i < n; i++) {
191 		InetAddress interfac = (InetAddress)interfaces.elementAt(i);
192 		ServiceURL url = new ServiceURL(Defaults.DA_SERVICE_TYPE +
193 						"://" +
194 						interfac.getHostAddress(),
195 						ServiceURL.LIFETIME_MAXIMUM);
196 		Vector scopes = config.getSAConfiguredScopes();
197 		long timestamp = 0; // later adverts will cause replacement,
198 				    // but noforwarding because it is to us...
199 
200 		String mySPIs = System.getProperty("sun.net.slp.SPIs");
201 		mySPIs = mySPIs == null ? "" : mySPIs;
202 
203 		table.recordNewDA(url,
204 				  scopes,
205 				  timestamp,
206 				  version,
207 				  config.getDAAttributes(),
208 				  mySPIs);
209 	    }
210 	}
211 
212 	// Sleep, then perform active discovery or polling of preconfigured
213 	//  DAs when we awake.
214 
215 	do {
216 
217 	    try {
218 
219 		sleep(sleepyTime);
220 
221 		if (config.getActiveDiscoveryInterval() > 0) {
222 		    activeDiscovery();
223 
224 		} else {
225 		    addPreconfiguredDAs();
226 
227 		}
228 
229 	    } catch (InterruptedException ex) {
230 
231 	    }
232 
233 	} while (true);
234 
235     }
236 
237     // Perform active DA discovery.
238 
239     synchronized private void activeDiscovery() {
240 
241 	// Set the previous responders list to null. Otherwise,
242 	//  the previous responders from the last time we did
243 	//  this may interfere.
244 
245 	SrvLocHeader hdr = activeMsg.getHeader();
246 
247 	hdr.previousResponders.removeAllElements();
248 
249 
250 	// Perform the active discovery message transaction.
251 
252 	try {
253 	    Transact.transactActiveAdvertRequest(Defaults.DA_SERVICE_TYPE,
254 						 activeMsg,
255 						 table);
256 
257 	} catch (ServiceLocationException ex) {
258 
259 	    config.writeLog("ad_multi_error",
260 			    new Object[] { new Integer(ex.getErrorCode()),
261 					       ex.getMessage() });
262 
263 	}
264 
265     }
266 
267     // Add preconfigured DAs to the DA table. Note that we poll the
268     // preconfigured DAs once every 9 hours to make sure they are still around.
269 
270     synchronized private void addPreconfiguredDAs() {
271 
272 	Vector daAddrs = config.getPreconfiguredDAs();
273 	int i, n = daAddrs.size();
274 
275 	// Go through the DA addresses, contacting them for their
276 	// information. Better not be any SLPv1 DAs there.
277 
278 	for (i = 0; i < n; i++) {
279 	    InetAddress daAddr = (InetAddress)daAddrs.elementAt(i);
280 
281 	    // Use a TCP connection. DAs must support TCP so why not?
282 
283 	    SrvLocMsg reply = null;
284 
285 	    try {
286 		reply = Transact.transactTCPMsg(daAddr, activeMsg, false);
287 
288 	    } catch (ServiceLocationException ex) {
289 
290 		if (config.traceDrop()) {
291 		    config.writeLog("ad_trans_error", new Object[] {
292 			new Integer(ex.getErrorCode()),
293 			    daAddr,
294 			    ex.getMessage() });
295 		}
296 
297 		continue;
298 	    }
299 
300 	    // Report if there's an error in configuration.
301 
302 	    if (!(reply instanceof CDAAdvert)) {
303 		if (config.traceDrop()) {
304 		    config.writeLog("ad_preconfig_not_advert",
305 				    new Object[] { daAddr, reply });
306 
307 		}
308 
309 		continue;
310 	    }
311 
312 
313 	    CDAAdvert advert = (CDAAdvert)reply;
314 	    SrvLocHeader hdr = advert.getHeader();
315 
316 	    // We need to make the URL long lived if active
317 	    // discovery is off. Otherwise, we let the DA time out like all the
318 	    // rest.
319 
320 	    if (config.getActiveDiscoveryInterval() <= 0) {
321 		advert.URL =
322 		    new ServiceURL(advert.URL.toString(),
323 				   ServiceURL.LIFETIME_MAXIMUM);
324 
325 	    }
326 
327 	    // Add the scopes to the configured scopes. Scopes from configured
328 	    //  DAs count as configured scopes.
329 
330 	    config.addPreconfiguredDAScopes(hdr.scopes);
331 
332 	    // Record it. Note that we don't have to forward here
333 	    //  because it's the very beginning.
334 
335 	    table.recordNewDA(advert.URL,
336 			      hdr.scopes,
337 			      advert.timestamp,
338 			      hdr.version,
339 			      advert.attrs,
340 			      advert.spis);
341 
342 	}
343     }
344 
345 }
346