package com.tacitknowledge.slowlight.proxyserver.systest.util.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Alexandr Donciu (adonciu@tacitknowledge.com)
*/
public class TestClient
{
private static final String LOCALHOST = "localhost";
private final int port;
private final int responseSize;
private final Lock responseLock = new ReentrantLock();
private final Condition responseCondition = responseLock.newCondition();
private final ServerResponse response = new ServerResponse();
private ChannelFuture channel;
public TestClient(final int port, final int responseSize)
{
this.port = port;
this.responseSize = responseSize;
}
public void start() throws InterruptedException
{
channel = connect();
channel.await();
}
public List<byte[]> sendMessage(final String message) throws Throwable
{
return sendMessage(message, 0);
}
public List<byte[]> sendMessage(final String message, final long timeout) throws Throwable
{
if (channel == null)
{
throw new NullPointerException("Got null channel, it seems that test client is not started yet");
}
response.reset();
final ByteBuf byteBuf = Unpooled.wrappedBuffer(message.getBytes());
final ChannelFuture future = channel.channel().writeAndFlush(byteBuf);
future.await();
List<byte[]> responseBytesList;
if (future.isSuccess())
{
responseBytesList = getResponse(responseLock, responseCondition, response, timeout);
}
else
{
throw future.cause();
}
return responseBytesList;
}
private ChannelFuture connect()
{
final Bootstrap bootstrap = new Bootstrap();
bootstrap.group(new NioEventLoopGroup());
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(new ClientChannelHandler(responseLock, responseCondition, response, responseSize));
bootstrap.option(ChannelOption.AUTO_READ, false);
return bootstrap.connect(LOCALHOST, port);
}
private List<byte[]> getResponse(final Lock responseLock,
final Condition responseReady,
final ServerResponse response,
final long timeout)
throws InterruptedException
{
responseLock.lock();
try
{
if (response.size() < responseSize)
{
if (timeout > 0)
{
responseReady.await(timeout, TimeUnit.MILLISECONDS);
}
else
{
responseReady.await();
}
}
}
finally
{
responseLock.unlock();
}
return response.get();
}
}