/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.cluster.testutil;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
/**
* Tests for the existence of the problem described at
* http://wiki.jboss.org/wiki/Wiki.jsp?page=PromiscuousTraffic
*
* @author <a href="brian.stansberry@jboss.com">Brian Stansberry</a>
* @version $Revision: 82920 $
*/
public class PromiscuousTrafficTester
{
private InetAddress goodMulticast;
private InetAddress badMulticast;
private InetAddress senderAddress;
private InetAddress receiverAddress;
private int mcastPort = 64000;
private int ttl = 0;
private MulticastSocket sender;
private MulticastReceiver goodReceiver;
private MulticastReceiver badReceiver;
private PromiscuousTrafficTester(String[] args) throws Exception
{
// Set defaults
goodMulticast = InetAddress.getByName("229.10.11.12");
badMulticast = InetAddress.getByName("229.10.11.13");
senderAddress = InetAddress.getLocalHost();
receiverAddress = InetAddress.getLocalHost();
// Check what was passed in
parseArgs(args);
try
{
setUpSockets();
}
catch (Exception e)
{
closeSockets();
throw e;
}
}
private void test() throws Exception
{
try
{
byte[] data = "Hello".getBytes();
DatagramPacket datagram = new DatagramPacket(data, 0, data.length, goodMulticast, mcastPort);
System.out.println("Sending 'Hello' on " + goodMulticast + ":" + mcastPort);
sender.send(datagram);
Thread.sleep(1000);
if ("Hello".equals(goodReceiver.getValue()) == false)
throw new IllegalStateException("Did not receive 'Hello' as expected; got " + goodReceiver.getValue());
if (badReceiver.getValue() != null)
{
System.out.println("Bad news. Detected the Promiscuous Traffic " +
"problem. Received " + badReceiver.getValue() +
" on undesired address " + badMulticast);
}
else
{
System.out.println("Good news. Did not detect the Promiscuous Traffic problem.");
}
}
finally
{
closeSockets();
}
}
private void parseArgs(String[] args) throws UnknownHostException
{
if (args == null || args.length == 0)
return;
senderAddress = InetAddress.getByName(args[0]);
if (args.length > 1)
receiverAddress = InetAddress.getByName(args[1]);
else
receiverAddress = senderAddress;
if (args.length > 2)
goodMulticast = InetAddress.getByName(args[2]);
if (args.length > 3)
badMulticast = InetAddress.getByName(args[3]);
if (args.length > 4)
mcastPort = Integer.parseInt(args[4]);
if (args.length > 5)
ttl = Integer.parseInt(args[5]);
}
private void setUpSockets() throws IOException
{
sender = new MulticastSocket();
sender.setInterface(senderAddress);
sender.setTimeToLive(ttl);
goodReceiver = new MulticastReceiver(goodMulticast);
goodReceiver.startListener();
badReceiver = new MulticastReceiver(badMulticast);
badReceiver.startListener();
// Sleep a bit to let the listeners start
try
{
Thread.sleep(250);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
private void closeSockets()
{
if (goodReceiver != null)
goodReceiver.stopListener();
if (badReceiver != null)
badReceiver.stopListener();
if (sender != null)
sender.close();
}
/**
* Create and run the PromiscuousTrafficTester.
*
* @param args 0 or more of the following; not all need be present, but none
* can be skipped if subsequent values are desired:
* [0] Interface sender should bind to (machine name)
* [1] Interface receivers should bind to (same as sender interface)
* [2] Multicast address on which packets will be sent (229.10.11.12)
* [3] Multicast address on which receipt of packet means (229.10.11.13)
* promiscuous traffic problem is present
* [4] Multicast port (64000)
* [5] TTL of multicast packet (0)
*/
public static void main(String[] args)
{
try
{
PromiscuousTrafficTester tester = new PromiscuousTrafficTester(args);
tester.test();
}
catch (Exception e)
{
e.printStackTrace();
}
}
private class MulticastReceiver implements Runnable
{
private InetAddress group;
private MulticastSocket socket;
private String value;
private Exception exception;
private Thread thread;
private boolean stopping;
MulticastReceiver(InetAddress mcastAddr) throws IOException
{
group = mcastAddr;
socket = new MulticastSocket(mcastPort);
socket.setInterface(receiverAddress);
socket.joinGroup(mcastAddr);
}
public void run()
{
try
{
System.out.println("Listening on address " + group);
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
value = new String(packet.getData()).trim();
System.out.println(group + ":" + mcastPort + " -- Received " + value);
}
catch (Exception e)
{
if (!stopping)
{
this.exception = e;
e.printStackTrace(System.out);
}
}
}
public Exception getException()
{
return exception;
}
public String getValue()
{
return value;
}
public void startListener()
{
thread = new Thread(this);
thread.start();
}
public void stopListener()
{
stopping = true;
if (thread.isAlive())
{
try
{
thread.join(50);
}
catch (InterruptedException e)
{
}
if (thread.isAlive())
thread.interrupt();
}
try
{
socket.leaveGroup(group);
}
catch (IOException e)
{
}
socket.close();
}
}
}