2
* JBoss, Home of Professional Open Source
3
* Copyright 2005, JBoss Inc., and individual contributors as indicated
4
* by the @authors tag. See the copyright.txt in the distribution for a
5
* full listing of individual contributors.
7
* This is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 2.1 of
10
* the License, or (at your option) any later version.
12
* This software is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this software; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
22
package org.jboss.remoting.detection.multicast;
24
import org.jboss.remoting.detection.AbstractDetector;
25
import org.jboss.remoting.detection.Detection;
26
import org.jboss.remoting.util.SecurityUtility;
28
import java.io.ByteArrayInputStream;
29
import java.io.ByteArrayOutputStream;
30
import java.io.IOException;
31
import java.io.ObjectInputStream;
32
import java.io.ObjectOutputStream;
33
import java.net.DatagramPacket;
34
import java.net.InetAddress;
35
import java.net.InetSocketAddress;
36
import java.net.MulticastSocket;
37
import java.net.SocketAddress;
38
import java.net.UnknownHostException;
39
import java.security.AccessController;
40
import java.security.PrivilegedActionException;
41
import java.security.PrivilegedExceptionAction;
44
* MulticastDetector is a remoting detector that broadcasts detection messages using
45
* muliticast. The default multicast ip is 224.1.9.1 and port 2410.
47
* @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
48
* @author <a href="mailto:adrian.brock@happeningtimes.com">Adrian Brock</a>
49
* @author <a href="mailto:tom.elrod@jboss.com">Tom Elrod</a>
50
* @version $Revision: 5000 $
52
public class MulticastDetector extends AbstractDetector implements MulticastDetectorMBean
54
private static int threadCounter = 0;
56
private String defaultIP = "224.1.9.1";
58
private InetAddress addr;
59
private InetAddress bindAddr;
60
private int port = 2410;
61
private MulticastSocket socket;
62
private Listener listener = new Listener("Remoting Multicast Detector - Listener Thread: " + threadCounter++);
63
private int bufferSize = 10000;
67
* @return The IP that is used to broadcast detection messages on via multicast.
69
public String getDefaultIP()
75
* @param defaultIP The IP that is used to broadcast detection messages on via multicast.
77
public void setDefaultIP(String defaultIP)
79
this.defaultIP = defaultIP;
83
* return the multicast address of the detector
87
public InetAddress getAddress()
93
* set the interface address of the multicast
97
public void setAddress(InetAddress ip)
103
* return the bind address of the detector
107
public InetAddress getBindAddress()
113
* set the bind address of the multicast
117
public void setBindAddress(InetAddress ip)
123
* get the port that the detector is multicasting to
133
* set the port for detections to be multicast to
137
public void setPort(int port)
143
public int getBufferSize()
148
public void setBufferSize(int bufferSize)
150
this.bufferSize = bufferSize;
154
* called by MBeanServer to start the mbean lifecycle
158
public void start() throws Exception
162
addr = getAddressByName(defaultIP);
165
// check to see if we're running on a machine with loopback and no NIC
166
InetAddress localHost = getLocalHost();
167
if(bindAddr == null && localHost.getHostAddress().equals("127.0.0.1"))
169
// use this to bind so multicast will work w/o network
170
this.bindAddr = localHost;
175
final SocketAddress saddr = new InetSocketAddress(bindAddr, port);
176
AccessController.doPrivileged( new PrivilegedExceptionAction()
178
public Object run() throws IOException
180
socket = new MulticastSocket(saddr);
181
socket.joinGroup(addr);
186
catch (PrivilegedActionException e)
188
throw (IOException) e.getCause();
195
listener = new Listener("Remoting Multicast Detector - Listener Thread: " + threadCounter++);
201
* called by the MBeanServer to stop the mbean lifecycle
205
public void stop() throws Exception
212
listener.running = false;
213
listener.interrupt();
218
log.warn(this + " Error stopping multicast detector. " + e.getMessage());
226
socket.leaveGroup(addr);
229
catch (IOException e)
231
log.warn(this + " Error stopping multicast detector. " + e.getMessage());
238
* subclasses must implement to provide the specific heartbeat protocol
239
* for this server to send out to other servers on the network
241
protected void heartbeat()
245
Detection msg = createDetection();
251
if(log.isTraceEnabled())
253
log.trace(this + " sending heartbeat: " + msg);
255
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
256
ObjectOutputStream objectOut = new ObjectOutputStream(byteOut);
257
objectOut.writeObject(msg);
260
byte buf[] = byteOut.toByteArray();
261
DatagramPacket p = new DatagramPacket(buf, buf.length, addr, port);
267
log.debug(this + " heartbeat failed", ex);
272
protected void forceHeartbeat()
276
String msg = "Send heartbeat";
279
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
280
ObjectOutputStream objectOut = new ObjectOutputStream(byteOut);
281
objectOut.writeObject(msg);
284
byte buf[] = byteOut.toByteArray();
285
DatagramPacket p = new DatagramPacket(buf, buf.length, addr, port);
289
* This is a bit of a hack, but am going to wait a few seconds to
290
* allow for any group members (other multicast detectors) to receive
291
* the msg and then respond themselves with their detection messages.
292
* Since don't know number of servers that are members of the group,
293
* can't really wait until all detection messages, just hope they come
294
* in before end of waiting.
296
Thread.currentThread().sleep(2000);
302
log.debug(this + " forced heartbeat failed", ex);
307
private void listen(DatagramPacket p, byte[] buf)
313
// should block until we get a multicast
316
// take the multicast, and deserialize into the detection event
317
ByteArrayInputStream byteInput = new ByteArrayInputStream(buf);
318
ObjectInputStream objectInput = new ObjectInputStream(byteInput);
319
Object obj = objectInput.readObject();
320
if(obj instanceof Detection)
322
Detection msg = (Detection)obj;
323
if(log.isTraceEnabled())
325
log.trace(this + " received detection: " + msg);
328
// let the subclass do the hard work off handling detection
333
// for now, assume anything *not* of type Detection
334
// is a prompt to send out detection msg
340
if(e instanceof java.io.InvalidClassException)
346
log.debug(this + " Error receiving detection", e);
352
private final class Listener extends Thread
354
boolean running = true;
356
public Listener(String name)
363
log.debug("using bufferSize: " + bufferSize);
364
byte[] buf = new byte[bufferSize];
365
DatagramPacket p = new DatagramPacket(buf, 0, buf.length);
366
//p.setAddress(addr);
375
static private InetAddress getLocalHost() throws UnknownHostException
377
if (SecurityUtility.skipAccessControl())
381
return InetAddress.getLocalHost();
383
catch (IOException e)
385
return InetAddress.getByName("127.0.0.1");
391
return (InetAddress) AccessController.doPrivileged( new PrivilegedExceptionAction()
393
public Object run() throws IOException
397
return InetAddress.getLocalHost();
399
catch (IOException e)
401
return InetAddress.getByName("127.0.0.1");
406
catch (PrivilegedActionException e)
408
throw (UnknownHostException) e.getCause();
412
static private InetAddress getAddressByName(final String host) throws UnknownHostException
414
if (SecurityUtility.skipAccessControl())
416
return InetAddress.getByName(host);
421
return (InetAddress)AccessController.doPrivileged( new PrivilegedExceptionAction()
423
public Object run() throws IOException
425
return InetAddress.getByName(host);
429
catch (PrivilegedActionException e)
431
throw (UnknownHostException) e.getCause();