/*
* Sun Public License
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is available at http://www.sun.com/
*
* The Original Code is the SLAMD Distributed Load Generation Engine.
* The Initial Developer of the Original Code is Neil A. Wilson.
* Portions created by Neil A. Wilson are Copyright (C) 2004-2010.
* Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): Neil A. Wilson
*/
package com.slamd.tools.tcpreplay;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
/**
* This class defines a thread that will be used to actually replay data against
* a target server. It works independently of any other capture thread that
* might be running, and will reconnect as often as necessary to deal with cases
* in which the server has closed the connection (potentially in response to a
* request from the client to do so).
*
*
* @author Neil A. Wilson
*/
public class ReplayThread
extends Thread
{
// The number of times the connection was unexpectedly closed during
// processing.
protected int disconnects;
// The number of iterations through the entire data set that were completed.
protected int iterationsCompleted;
// The number of individual capture packets that were replayed.
protected int packetsReplayed;
// The replay utility with which this thread is associated.
private ReplayCapture replayCapture;
/**
* Creates a new thread that may be used to replay captured traffic against a
* target server.
*
* @param replayCapture The capture utility with which this thread is
* associated.
*/
public ReplayThread(ReplayCapture replayCapture)
{
this.replayCapture = replayCapture;
disconnects = 0;
iterationsCompleted = 0;
packetsReplayed = 0;
}
/**
* Loops, replaying traffic until it is time to stop for some reason.
*/
@Override()
public void run()
{
boolean connected = false;
boolean infinite = (replayCapture.numIterations <= 0);
SocketChannel socketChannel = null;
InetSocketAddress socketAddress =
new InetSocketAddress(replayCapture.targetHost,
replayCapture.targetPort);
try
{
outerLoop:
for (int i=0; (infinite || (i < replayCapture.numIterations)); i++)
{
if (replayCapture.stopRequested)
{
break;
}
for (int j=0; j < replayCapture.captureData.length; j++)
{
if (replayCapture.stopRequested)
{
break outerLoop;
}
if (! connected)
{
try
{
socketChannel = SocketChannel.open(socketAddress);
socketChannel.configureBlocking(false);
socketChannel.finishConnect();
replayCapture.registerSocketChannel(socketChannel);
connected = true;
}
catch (IOException ioe)
{
System.err.println("ERROR: Unable to connect to " +
socketAddress);
break outerLoop;
}
}
if (replayCapture.sleepTimes[j] > 0)
{
try
{
Thread.sleep(replayCapture.sleepTimes[j]);
} catch (InterruptedException ie) {}
}
try
{
replayCapture.captureData[j].replayTo(socketChannel);
packetsReplayed++;
}
catch (IOException ioe)
{
try
{
socketChannel.close();
} catch (Exception e) {}
connected = false;
disconnects++;
}
}
if (! replayCapture.stopRequested)
{
iterationsCompleted++;
}
}
}
catch (Exception e)
{
System.err.println("ERROR: Uncaught exception while processing");
e.printStackTrace();
}
try
{
socketChannel.close();
} catch (Exception e) {}
replayCapture.threadDone(this);
}
}