Hi!
I am trying to implement a protocolparser but i am stuck and need some help, please. Below is my code.
public class A1ProtocolParser implements ProtocolParser<IncomingPacket> {
static final int HEADERLENGTH = 18;
static final int STARTMARK = 0x12345678;
private ByteBuffer byteBuffer, incomingPacketBuffer;
private IncomingPacket incomingPacket;
private boolean isExpectingMoreData;
private int currentPosition;
public boolean isExpectingMoreData() {
return isExpectingMoreData;
}
public boolean hasMoreBytesToParse() {
return byteBuffer == null ? false : byteBuffer.position() > currentPosition;
}
public IncomingPacket getNextMessage() {
IncomingPacket packet = incomingPacket;
incomingPacket = null;
return packet;
}
public boolean hasNextMessage() {
ByteBuffer dup = byteBuffer.duplicate();
dup.flip();
dup.position(currentPosition);
if (incomingPacket == null) {
if (dup.remaining() < HEADERLENGTH) {
isExpectingMoreData = true;
return false;
}
int startmark = dup.getInt();
if (startmark != STARTMARK) {
//TODO: log exception and close connection
return false;
}
incomingPacket = new IncomingPacket(dup.getShort());
incomingPacket.attachment = dup.getLong();
int len = dup.getInt();
if (len == 0) {
isExpectingMoreData = false;
currentPosition = dup.position();
return true;
return false;
}
incomingPacket.data = new byte[len];
incomingPacketBuffer = ByteBuffer.wrap(incomingPacket.data);
currentPosition = dup.position();
}
if (dup.hasRemaining()) {
int len = Math.min(incomingPacketBuffer.remaining(), dup.remaining());
incomingPacketBuffer.put(
dup.array(),
dup.position(),
len);
dup.position(currentPosition += len);
if (incomingPacketBuffer.hasRemaining()) {
isExpectingMoreData = true;
} else {
isExpectingMoreData = false;
incomingPacketBuffer = null;
}
} else {
isExpectingMoreData = true;
}
return !isExpectingMoreData;
} //hasNextMessage
public void startBuffer(ByteBuffer bb) {
byteBuffer = bb;
} //startBuffer
public boolean releaseBuffer() {
byteBuffer = null;
currentPosition = 0;
return isExpectingMoreData;
} //releaseBuffer
}
When a big packet is about to arrive `byteBuffer` contains only 8k of data (as it should according to grizly's implementation) - so i copy data into incomingPacketBuffer and
set `isExpectingMoreData = true;`. The problem: instance that handled this `byteBuffer` is not called for the second time! insted grizzly creates a new instance of `A1ProtocolParser` through my own `ProtocolChainInstanceHandler`
controller.setProtocolChainInstanceHandler(new DefaultProtocolChainInstanceHandler() {
private final A1ParserProtocolFilter a1ParserProtocolFilter = new A1ParserProtocolFilter();
private final ProtocolFilter echoFilter = new ProtocolFilter() {
public boolean execute(Context ctx) throws IOException {
System.out.println(
new String(((IncomingPacket)ctx.getAttribute(ProtocolParser.MESSAGE)).data, "UTF-8")
);
ctx.removeAttribute(ProtocolParser.MESSAGE);
return false;
}
public boolean postExecute(Context ctx) throws IOException {
return true;
}
};
@Override
public ProtocolChain poll() {
ProtocolChain protocolChainX = protocolChains.poll();
if (protocolChainX == null) {
DefaultProtocolChain defaultProtocolChain = new DefaultProtocolChain();
defaultProtocolChain.setContinuousExecution(true);
defaultProtocolChain.addFilter(a1ParserProtocolFilter);
defaultProtocolChain.addFilter(echoFilter);
protocolChainX = defaultProtocolChain;
offer(protocolChainX);
}
return protocolChainX;
}
});
The second question: line `offer(protocolChainX);` according to this post (
http://www.nabble.com/DefaultProtocolChainInstanceHandler-td15412709.html) should exist, but it do not exist in the last (668 by now) revision of this file
https://grizzly.dev.java.net/source/browse/grizzly/trunk/modules/grizzly/src/test/java/com/sun/grizzly/ProtocolParserTest.java?rev=668&view=log
is this a bug in a test unit? by the way it don't exist in many blog posts and samples i've seen.
p.s. sorry for my english-i'm from Russia :)
p.p.s. after fixin' my class i will consider making (and posting here) at example of paket constructor based on the code above.