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) 1999 by Sun Microsystems, Inc.
23  * All rights reserved.
24  *
25  */
26 
27 //  DAAdvertiser.java: Advertise a DA, also handle incoming DAAdverts.
28 //  Author:           James Kempf
29 //  Created On:       Tue May 19 15:22:04 1998
30 //  Last Modified By: James Kempf
31 //  Last Modified On: Thu Mar  4 10:39:06 1999
32 //  Update Count:     44
33 //
34 
35 package com.sun.slp;
36 
37 import java.net.*;
38 import java.util.*;
39 import java.io.*;
40 
41 /**
42  * This class supplies a regular interval 'heartbeat' DAAdvertisement.
43  * Implementation specific subclasses handle incoming DAAdverts and
44  * forwarding of registrations and deregistrations to other DAs. The
45  * implementation specific subclasses depend on how the server is
46  * representing DA information internally.
47  *
48  * @author James Kempf, Erik Guttman
49  */
50 
51 class DAAdvertiser extends Thread {
52 
53     protected DatagramSocket dss = null;
54     protected InetAddress castAddr = null;
55     protected InetAddress interfac = null;
56 
57     // V2 advertising has the same DAAdvert every time.
58 
59     static private byte[]	 outbuf = null;
60 
61     static protected SLPConfig config = null;    // Config object.
62     static protected Hashtable daadv =
63 	new Hashtable();	// Existing advertisers
64 
65     private Boolean done = new Boolean(false);
66 
67     // Initialize the DAAdvertiser on the designated interface.
68 
69     static void initializeDAAdvertiserOnInterface(InetAddress interfac)
70 	throws ServiceLocationException {
71 
72 	// If we've got it, return.
73 
74 	if (daadv.get(interfac) != null) {
75 	    return;
76 
77 	}
78 
79 	// Get the config object.
80 
81 	if (config == null) {
82 	    config = SLPConfig.getSLPConfig();
83 
84 	}
85 
86 	// Get the SLPv2 DAADvert to send
87 
88 	ServiceTable table = ServiceTable.getServiceTable();
89 
90 	SLPServerHeaderV2 hdr =
91 	    new SLPServerHeaderV2(SrvLocHeader.DAAdvert,
92 				  false,
93 				  config.getLocale());
94 
95 	SDAAdvert msg =
96 	    (SDAAdvert)table.makeDAAdvert(hdr,
97 					  interfac,
98 					  (short)0x0,
99 					  config.getSAConfiguredScopes(),
100 					  config);
101 
102 	// Create a new DAAdvertiser for this interface, with SLPv2
103 	//  message to send.
104 
105 	DAAdvertiser daadv = new DAAdvertiser(interfac, msg.getHeader());
106 
107 	// Start thread running.
108 
109 	daadv.start();
110 
111     }
112 
113     // Used by V1 subclass constructor.
114 
115     DAAdvertiser() {
116 
117 	if (config == null) {
118 	    config = SLPConfig.getSLPConfig();
119 
120 	}
121 
122     }
123 
124     // Create a new DAAdvertiser for the interface for default multicast
125     //  address. Externalize the message and set the instance variable.
126 
127     DAAdvertiser(InetAddress interfac, SrvLocHeader hdr)
128 	throws ServiceLocationException {
129 
130 	// Config may not be initialized if this was called directly from
131 	//  slpd.
132 
133 	if (config == null) {
134 	    config = SLPConfig.getSLPConfig();
135 
136 	}
137 
138 	// Externalize the DAAdvert.
139 
140 	ByteArrayOutputStream baos = new ByteArrayOutputStream();
141 
142 	hdr.externalize(baos, true, false);
143 	outbuf = baos.toByteArray();
144 
145 	// Initialize the networking for default multicast address.
146 
147 	initializeNetworking(interfac, config.getMulticastAddress());
148 
149     }
150 
151 
152     // Convert advert to bytes, initialize networking.
153 
154     protected void
155 	initializeNetworking(InetAddress interfac,
156 			     InetAddress maddr)
157 	throws ServiceLocationException {
158 
159 	// Set the interface and multicast address on this advertiser.
160 
161 	this.interfac = interfac;
162 	this.castAddr = maddr;
163 
164 	// Get the socket from the listener object corresponding to this
165 	//  interface. The listener will always be started before the
166 	//  DAAdvertiser, otherwise, SAs may start sending registrations
167 	//  before anybody is listening.
168 
169 	dss = Listener.returnListenerSocketOnInterface(interfac);
170 
171 	// If the socket is null, then there is no listener. Open a
172 	//  new socket. Note that any listener opened *afterwards* will
173 	//  not get this socket.
174 
175 	if (dss == null) {
176 	    dss = config.getMulticastSocketOnInterface(interfac, true);
177 
178 	}
179     }
180 
181     public void run() {
182 
183 	// Set the thread name.
184 
185 	setName("SLP DA Advertisement");
186 
187 	long heartbeat = config.getAdvertHeartbeatTime() * 1000;
188 
189 	while (true) {
190 
191 	    // Send an advert.
192 
193 	    sendAdvert();
194 
195 	    // Sleep until next time.
196 
197 	    try {
198 		sleep(heartbeat);
199 
200 	    } catch (InterruptedException ie) {
201 
202 		// Somebody interrupted us. If we are to exit, then do so.
203 
204 		synchronized (done) {
205 
206 		    if (done.booleanValue()) {
207 			return;
208 
209 		    }
210 		}
211 
212 	    }
213 
214 	}
215     }
216 
217     // Send an unsolicited DAAdvert.
218 
219     void sendAdvert() {
220 
221 	byte[] buf = getOutbuf();
222 
223 	DatagramPacket dp =
224 	    new DatagramPacket(buf,
225 			       buf.length,
226 			       castAddr,
227 			       Defaults.iSLPPort);
228 	try {
229 
230 	    dss.send(dp);
231 
232 	} catch (IOException ex) {
233 	    config.writeLog("passive_advert_exception",
234 			    new Object[] {ex.getMessage()});
235 
236 	    // Tell the listener to refresh the socket.
237 
238 	    dss = Listener.refreshSocketOnInterface(interfac);
239 
240 	}
241     }
242 
243     // Return the buffer for transmission.
244 
245     protected byte[] getOutbuf() {
246 	return outbuf;
247 
248     }
249 
250     // Stop the thread from executing.
251 
252     void stopThread() {
253 
254 	synchronized (done) {
255 	    done = new Boolean(true);
256 
257 	}
258 
259 	this.interrupt();
260 
261     }
262 }
263