package org.apache.haox.transport.tcp;
import org.apache.haox.transport.Transport;
import org.apache.haox.transport.buffer.BufferPool;
import org.apache.haox.transport.buffer.RecvBuffer;
import org.apache.haox.transport.event.MessageEvent;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class TcpTransport extends Transport {
private SocketChannel channel;
private StreamingDecoder streamingDecoder;
private RecvBuffer recvBuffer;
public TcpTransport(SocketChannel channel,
StreamingDecoder streamingDecoder) throws IOException {
super((InetSocketAddress) channel.getRemoteAddress());
this.channel = channel;
this.streamingDecoder = streamingDecoder;
this.recvBuffer = new RecvBuffer();
}
@Override
protected void sendOutMessage(ByteBuffer message) throws IOException {
channel.write(message);
}
public void onReadable() throws IOException {
ByteBuffer writeBuffer = BufferPool.allocate(65536);
if (channel.read(writeBuffer) <= 0) {
BufferPool.release(writeBuffer);
return;
}
writeBuffer.flip();
recvBuffer.write(writeBuffer);
WithReadDataHander rdHandler = new WithReadDataHander();
rdHandler.handle();
}
class WithReadDataHander implements DecodingCallback {
private ByteBuffer streamingBuffer;
@Override
public void onMessageComplete(int messageLength) {
ByteBuffer message = null;
int remaining = streamingBuffer.remaining();
if (remaining == messageLength) {
message = streamingBuffer;
} else if (remaining > messageLength) {
message = streamingBuffer.duplicate();
int newLimit = streamingBuffer.position() + messageLength;
message.limit(newLimit);
streamingBuffer.position(newLimit);
recvBuffer.writeFirst(streamingBuffer);
}
if (message != null) {
dispatcher.dispatch(MessageEvent.createInboundMessageEvent(TcpTransport.this, message));
}
}
@Override
public void onMoreDataNeeded() {
recvBuffer.writeFirst(streamingBuffer);
}
@Override
public void onMoreDataNeeded(int needDataLength) {
recvBuffer.writeFirst(streamingBuffer);
}
public void handle() {
if (recvBuffer.isEmpty()) return;
streamingBuffer = recvBuffer.readMostBytes();
streamingDecoder.decode(streamingBuffer.duplicate(), this);
}
}
}