users@grizzly.java.net

Need help implementing ProtocolParser

From: Ash2k <Ash2k_at_yandex.ru>
Date: Sun, 16 Mar 2008 12:17:05 +0300

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.