package de.tum.in.www1.jReto.module.wlan;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SocketChannel;
import de.tum.in.www1.jReto.module.api.Connection;
import de.tum.in.www1.jReto.niotools.ChannelReader;
import de.tum.in.www1.jReto.niotools.ChannelWriter;
import de.tum.in.www1.jReto.niotools.Dispatcher;
import de.tum.in.www1.jReto.niotools.ChannelReader.CloseHandler;
import de.tum.in.www1.jReto.niotools.ChannelReader.ReadHandler;
import de.tum.in.www1.jReto.niotools.ChannelWriter.WriteHandler;
public class WlanConnection implements Connection, ReadHandler, CloseHandler, WriteHandler {
public final int PACKET_LENGTH_FIELD_LENGTH = 4;
private Handler handler;
private Dispatcher dispatcher;
private InetAddress address;
private int port;
private boolean isConnected;
private SocketChannel socketChannel;
private ChannelReader channelReader;
private ChannelWriter channelWriter;
private boolean readingPacketLength;
private boolean writingPacketLength;
public WlanConnection(Dispatcher dispatcher, InetAddress address, int port) {
if (dispatcher == null) throw new IllegalArgumentException("dispatcher may not be null");
if (address == null) throw new IllegalArgumentException("address may not be null");
this.dispatcher = dispatcher;
this.address = address;
this.port = port;
this.isConnected = false;
this.readingPacketLength = true;
this.writingPacketLength = true;
}
public WlanConnection(Dispatcher dispatcher, SocketChannel channel) {
if (dispatcher == null) throw new IllegalArgumentException("dispatcher may not be null");
if (channel == null) throw new IllegalArgumentException("channel may not be null");
this.dispatcher = dispatcher;
this.address = channel.socket().getInetAddress();
this.port = channel.socket().getLocalPort();
this.isConnected = true;
this.socketChannel = channel;
this.readingPacketLength = true;
this.writingPacketLength = true;
try {
channel.configureBlocking(false);
this.channelReader = new ChannelReader(channel, this.dispatcher, this, this);
this.channelWriter = new ChannelWriter(channel, this.dispatcher, this);
this.channelReader.read(PACKET_LENGTH_FIELD_LENGTH);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void setHandler(Handler handler) {
this.handler = handler;
}
@Override
public Handler getHandler() {
return this.handler;
}
@Override
public boolean isConnected() {
return this.isConnected;
}
@Override
public int getRecommendedPacketSize() {
return 32*1024;
}
@Override
public void connect() {
try {
socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress(this.address, this.port));
socketChannel.configureBlocking(false);
this.channelReader = new ChannelReader(socketChannel, this.dispatcher, this, this);
this.channelWriter = new ChannelWriter(socketChannel, this.dispatcher, this);
this.channelReader.read(PACKET_LENGTH_FIELD_LENGTH);
this.isConnected = true;
if (this.handler != null) this.handler.onConnect(this);
} catch (IOException e) {}
}
@Override
public void close() {
try {
this.isConnected = false;
this.socketChannel.close();
if (this.handler != null) this.handler.onClose(this);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void writeData(ByteBuffer data) {
if (data.remaining() == 0) throw new IllegalArgumentException("data buffer needs to have more than 0 bytes remaining.");
data.order(ByteOrder.LITTLE_ENDIAN);
ByteBuffer lengthBuffer = ByteBuffer.allocate(PACKET_LENGTH_FIELD_LENGTH);
lengthBuffer.order(ByteOrder.LITTLE_ENDIAN);
lengthBuffer.putInt(data.remaining());
lengthBuffer.clear();
this.channelWriter.write(lengthBuffer);
this.channelWriter.write(data);
}
@Override
public void onClose() {
this.isConnected = false;
if (this.handler != null) this.handler.onClose(this);
}
@Override
public void onRead(ByteBuffer byteBuffer) {
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
if (this.readingPacketLength) {
this.readingPacketLength = false;
int packetLength = byteBuffer.getInt();
this.channelReader.read(packetLength);
} else {
this.readingPacketLength = true;
this.handler.onDataReceived(this, byteBuffer);
this.channelReader.read(PACKET_LENGTH_FIELD_LENGTH);
}
}
@Override
public void onCompletedWriteRequest() {
if (this.writingPacketLength) {
this.writingPacketLength = false;
} else {
this.handler.onDataSent(this);
this.writingPacketLength = true;
}
}
}