103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.websocket;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slack
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffer;
2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffers;
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.EndPoint;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
2803928aee4356845252ac6b662d5c72c29903813eJake Slack
2903928aee4356845252ac6b662d5c72c29903813eJake Slack
3003928aee4356845252ac6b662d5c72c29903813eJake Slack
3103928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
3203928aee4356845252ac6b662d5c72c29903813eJake Slack/**
3303928aee4356845252ac6b662d5c72c29903813eJake Slack * Parser the WebSocket protocol.
3403928aee4356845252ac6b662d5c72c29903813eJake Slack *
3503928aee4356845252ac6b662d5c72c29903813eJake Slack */
3603928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class WebSocketParserD08 implements WebSocketParser
3703928aee4356845252ac6b662d5c72c29903813eJake Slack{
3803928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(WebSocketParserD08.class);
3903928aee4356845252ac6b662d5c72c29903813eJake Slack
4003928aee4356845252ac6b662d5c72c29903813eJake Slack    public enum State {
4103928aee4356845252ac6b662d5c72c29903813eJake Slack
4203928aee4356845252ac6b662d5c72c29903813eJake Slack        START(0), OPCODE(1), LENGTH_7(1), LENGTH_16(2), LENGTH_63(8), MASK(4), PAYLOAD(0), DATA(0), SKIP(1), SEEK_EOF(1);
4303928aee4356845252ac6b662d5c72c29903813eJake Slack
4403928aee4356845252ac6b662d5c72c29903813eJake Slack        int _needs;
4503928aee4356845252ac6b662d5c72c29903813eJake Slack
4603928aee4356845252ac6b662d5c72c29903813eJake Slack        State(int needs)
4703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
4803928aee4356845252ac6b662d5c72c29903813eJake Slack            _needs=needs;
4903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
5003928aee4356845252ac6b662d5c72c29903813eJake Slack
5103928aee4356845252ac6b662d5c72c29903813eJake Slack        int getNeeds()
5203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
5303928aee4356845252ac6b662d5c72c29903813eJake Slack            return _needs;
5403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
5603928aee4356845252ac6b662d5c72c29903813eJake Slack
5703928aee4356845252ac6b662d5c72c29903813eJake Slack    private final WebSocketBuffers _buffers;
5803928aee4356845252ac6b662d5c72c29903813eJake Slack    private final EndPoint _endp;
5903928aee4356845252ac6b662d5c72c29903813eJake Slack    private final FrameHandler _handler;
6003928aee4356845252ac6b662d5c72c29903813eJake Slack    private final boolean _shouldBeMasked;
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    private State _state;
6203928aee4356845252ac6b662d5c72c29903813eJake Slack    private Buffer _buffer;
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    private byte _flags;
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    private byte _opcode;
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _bytesNeeded;
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    private long _length;
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _masked;
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    private final byte[] _mask = new byte[4];
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _m;
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _skip;
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    private boolean _fragmentFrames=true;
7203928aee4356845252ac6b662d5c72c29903813eJake Slack
7303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
7503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param buffers The buffers to use for parsing.  Only the {@link Buffers#getBuffer()} is used.
7603928aee4356845252ac6b662d5c72c29903813eJake Slack     * This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data
7703928aee4356845252ac6b662d5c72c29903813eJake Slack     * is mostly used.
7803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param endp the endpoint
7903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param handler the handler to notify when a parse event occurs
8003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param shouldBeMasked whether masking should be handled
8103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    public WebSocketParserD08(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8403928aee4356845252ac6b662d5c72c29903813eJake Slack        _buffers=buffers;
8503928aee4356845252ac6b662d5c72c29903813eJake Slack        _endp=endp;
8603928aee4356845252ac6b662d5c72c29903813eJake Slack        _handler=handler;
8703928aee4356845252ac6b662d5c72c29903813eJake Slack        _shouldBeMasked=shouldBeMasked;
8803928aee4356845252ac6b662d5c72c29903813eJake Slack        _state=State.START;
8903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9003928aee4356845252ac6b662d5c72c29903813eJake Slack
9103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
9303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return True if fake fragments should be created for frames larger than the buffer.
9403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
9503928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isFakeFragments()
9603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9703928aee4356845252ac6b662d5c72c29903813eJake Slack        return _fragmentFrames;
9803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9903928aee4356845252ac6b662d5c72c29903813eJake Slack
10003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
10203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param fakeFragments True if fake fragments should be created for frames larger than the buffer.
10303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
10403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setFakeFragments(boolean fakeFragments)
10503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
10603928aee4356845252ac6b662d5c72c29903813eJake Slack        _fragmentFrames = fakeFragments;
10703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10803928aee4356845252ac6b662d5c72c29903813eJake Slack
10903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isBufferEmpty()
11103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11203928aee4356845252ac6b662d5c72c29903813eJake Slack        return _buffer==null || _buffer.length()==0;
11303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11403928aee4356845252ac6b662d5c72c29903813eJake Slack
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11603928aee4356845252ac6b662d5c72c29903813eJake Slack    public Buffer getBuffer()
11703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _buffer;
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12003928aee4356845252ac6b662d5c72c29903813eJake Slack
12103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12203928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Parse to next event.
12303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Parse to the next {@link WebSocketParser.FrameHandler} event or until no more data is
12403928aee4356845252ac6b662d5c72c29903813eJake Slack     * available. Fill data from the {@link EndPoint} only as necessary.
12503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return An indication of progress or otherwise. -1 indicates EOF, 0 indicates
12603928aee4356845252ac6b662d5c72c29903813eJake Slack     * that no bytes were read and no messages parsed. A positive number indicates either
12703928aee4356845252ac6b662d5c72c29903813eJake Slack     * the bytes filled or the messages parsed.
12803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12903928aee4356845252ac6b662d5c72c29903813eJake Slack    public int parseNext()
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer==null)
13203928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer=_buffers.getBuffer();
13303928aee4356845252ac6b662d5c72c29903813eJake Slack
13403928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean progress=false;
13503928aee4356845252ac6b662d5c72c29903813eJake Slack        int filled=-1;
13603928aee4356845252ac6b662d5c72c29903813eJake Slack
13703928aee4356845252ac6b662d5c72c29903813eJake Slack        // Loop until a datagram call back or can't fill anymore
13803928aee4356845252ac6b662d5c72c29903813eJake Slack        while(!progress && (!_endp.isInputShutdown()||_buffer.length()>0))
13903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
14003928aee4356845252ac6b662d5c72c29903813eJake Slack            int available=_buffer.length();
14103928aee4356845252ac6b662d5c72c29903813eJake Slack
14203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Fill buffer if we need a byte or need length
14303928aee4356845252ac6b662d5c72c29903813eJake Slack            while (available<(_state==State.SKIP?1:_bytesNeeded))
14403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
14503928aee4356845252ac6b662d5c72c29903813eJake Slack                // compact to mark (set at start of data)
14603928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer.compact();
14703928aee4356845252ac6b662d5c72c29903813eJake Slack
14803928aee4356845252ac6b662d5c72c29903813eJake Slack                // if no space, then the data is too big for buffer
14903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_buffer.space() == 0)
15003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
15103928aee4356845252ac6b662d5c72c29903813eJake Slack                    // Can we send a fake frame?
15203928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_fragmentFrames && _state==State.DATA)
15303928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
15403928aee4356845252ac6b662d5c72c29903813eJake Slack                        Buffer data =_buffer.get(4*(available/4));
15503928aee4356845252ac6b662d5c72c29903813eJake Slack                        _buffer.compact();
15603928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_masked)
15703928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
15803928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (data.array()==null)
15903928aee4356845252ac6b662d5c72c29903813eJake Slack                                data=_buffer.asMutableBuffer();
16003928aee4356845252ac6b662d5c72c29903813eJake Slack                            byte[] array = data.array();
16103928aee4356845252ac6b662d5c72c29903813eJake Slack                            final int end=data.putIndex();
16203928aee4356845252ac6b662d5c72c29903813eJake Slack                            for (int i=data.getIndex();i<end;i++)
16303928aee4356845252ac6b662d5c72c29903813eJake Slack                                array[i]^=_mask[_m++%4];
16403928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
16503928aee4356845252ac6b662d5c72c29903813eJake Slack
16603928aee4356845252ac6b662d5c72c29903813eJake Slack                        // System.err.printf("%s %s %s >>\n",TypeUtil.toHexString(_flags),TypeUtil.toHexString(_opcode),data.length());
16703928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bytesNeeded-=data.length();
16803928aee4356845252ac6b662d5c72c29903813eJake Slack                        progress=true;
16903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _handler.onFrame((byte)(_flags&(0xff^WebSocketConnectionD08.FLAG_FIN)), _opcode, data);
17003928aee4356845252ac6b662d5c72c29903813eJake Slack
17103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _opcode=WebSocketConnectionD08.OP_CONTINUATION;
17203928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
17303928aee4356845252ac6b662d5c72c29903813eJake Slack
17403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_buffer.space() == 0)
17503928aee4356845252ac6b662d5c72c29903813eJake Slack                        throw new IllegalStateException("FULL: "+_state+" "+_bytesNeeded+">"+_buffer.capacity());
17603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
17703928aee4356845252ac6b662d5c72c29903813eJake Slack
17803928aee4356845252ac6b662d5c72c29903813eJake Slack                // catch IOExceptions (probably EOF) and try to parse what we have
17903928aee4356845252ac6b662d5c72c29903813eJake Slack                try
18003928aee4356845252ac6b662d5c72c29903813eJake Slack                {
18103928aee4356845252ac6b662d5c72c29903813eJake Slack                    filled=_endp.isInputShutdown()?-1:_endp.fill(_buffer);
18203928aee4356845252ac6b662d5c72c29903813eJake Slack                    available=_buffer.length();
18303928aee4356845252ac6b662d5c72c29903813eJake Slack                    // System.err.printf(">> filled %d/%d%n",filled,available);
18403928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (filled<=0)
18503928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
18603928aee4356845252ac6b662d5c72c29903813eJake Slack                }
18703928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e)
18803928aee4356845252ac6b662d5c72c29903813eJake Slack                {
18903928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug(e);
19003928aee4356845252ac6b662d5c72c29903813eJake Slack                    filled=-1;
19103928aee4356845252ac6b662d5c72c29903813eJake Slack                    break;
19203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
19303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
19403928aee4356845252ac6b662d5c72c29903813eJake Slack            // Did we get enough?
19503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (available<(_state==State.SKIP?1:_bytesNeeded))
19603928aee4356845252ac6b662d5c72c29903813eJake Slack                break;
19703928aee4356845252ac6b662d5c72c29903813eJake Slack
19803928aee4356845252ac6b662d5c72c29903813eJake Slack            // if we are here, then we have sufficient bytes to process the current state.
19903928aee4356845252ac6b662d5c72c29903813eJake Slack            // Parse the buffer byte by byte (unless it is STATE_DATA)
20003928aee4356845252ac6b662d5c72c29903813eJake Slack            byte b;
20103928aee4356845252ac6b662d5c72c29903813eJake Slack            while (_state!=State.DATA && available>=(_state==State.SKIP?1:_bytesNeeded))
20203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
20303928aee4356845252ac6b662d5c72c29903813eJake Slack                switch (_state)
20403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
20503928aee4356845252ac6b662d5c72c29903813eJake Slack                    case START:
20603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _skip=false;
20703928aee4356845252ac6b662d5c72c29903813eJake Slack                        _state=_opcode==WebSocketConnectionD08.OP_CLOSE?State.SEEK_EOF:State.OPCODE;
20803928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bytesNeeded=_state.getNeeds();
20903928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
21003928aee4356845252ac6b662d5c72c29903813eJake Slack
21103928aee4356845252ac6b662d5c72c29903813eJake Slack                    case OPCODE:
21203928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=_buffer.get();
21303928aee4356845252ac6b662d5c72c29903813eJake Slack                        available--;
21403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _opcode=(byte)(b&0xf);
21503928aee4356845252ac6b662d5c72c29903813eJake Slack                        _flags=(byte)(0xf&(b>>4));
21603928aee4356845252ac6b662d5c72c29903813eJake Slack
21703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (WebSocketConnectionD08.isControlFrame(_opcode)&&!WebSocketConnectionD08.isLastFrame(_flags))
21803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
21903928aee4356845252ac6b662d5c72c29903813eJake Slack                            LOG.warn("Fragmented Control from "+_endp);
22003928aee4356845252ac6b662d5c72c29903813eJake Slack                            _handler.close(WebSocketConnectionD08.CLOSE_PROTOCOL,"Fragmented control");
22103928aee4356845252ac6b662d5c72c29903813eJake Slack                            progress=true;
22203928aee4356845252ac6b662d5c72c29903813eJake Slack                            _skip=true;
22303928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
22403928aee4356845252ac6b662d5c72c29903813eJake Slack
22503928aee4356845252ac6b662d5c72c29903813eJake Slack                        _state=State.LENGTH_7;
22603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bytesNeeded=_state.getNeeds();
22703928aee4356845252ac6b662d5c72c29903813eJake Slack
22803928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
22903928aee4356845252ac6b662d5c72c29903813eJake Slack
23003928aee4356845252ac6b662d5c72c29903813eJake Slack                    case LENGTH_7:
23103928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=_buffer.get();
23203928aee4356845252ac6b662d5c72c29903813eJake Slack                        available--;
23303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _masked=(b&0x80)!=0;
23403928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=(byte)(0x7f&b);
23503928aee4356845252ac6b662d5c72c29903813eJake Slack
23603928aee4356845252ac6b662d5c72c29903813eJake Slack                        switch(b)
23703928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
23803928aee4356845252ac6b662d5c72c29903813eJake Slack                            case 0x7f:
23903928aee4356845252ac6b662d5c72c29903813eJake Slack                                _length=0;
24003928aee4356845252ac6b662d5c72c29903813eJake Slack                                _state=State.LENGTH_63;
24103928aee4356845252ac6b662d5c72c29903813eJake Slack                                break;
24203928aee4356845252ac6b662d5c72c29903813eJake Slack                            case 0x7e:
24303928aee4356845252ac6b662d5c72c29903813eJake Slack                                _length=0;
24403928aee4356845252ac6b662d5c72c29903813eJake Slack                                _state=State.LENGTH_16;
24503928aee4356845252ac6b662d5c72c29903813eJake Slack                                break;
24603928aee4356845252ac6b662d5c72c29903813eJake Slack                            default:
24703928aee4356845252ac6b662d5c72c29903813eJake Slack                                _length=(0x7f&b);
24803928aee4356845252ac6b662d5c72c29903813eJake Slack                                _state=_masked?State.MASK:State.PAYLOAD;
24903928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
25003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bytesNeeded=_state.getNeeds();
25103928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
25203928aee4356845252ac6b662d5c72c29903813eJake Slack
25303928aee4356845252ac6b662d5c72c29903813eJake Slack                    case LENGTH_16:
25403928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=_buffer.get();
25503928aee4356845252ac6b662d5c72c29903813eJake Slack                        available--;
25603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _length = _length*0x100 + (0xff&b);
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (--_bytesNeeded==0)
25803928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
25903928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_length>_buffer.capacity() && !_fragmentFrames)
26003928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
26103928aee4356845252ac6b662d5c72c29903813eJake Slack                                progress=true;
26203928aee4356845252ac6b662d5c72c29903813eJake Slack                                _handler.close(WebSocketConnectionD08.CLOSE_BADDATA,"frame size "+_length+">"+_buffer.capacity());
26303928aee4356845252ac6b662d5c72c29903813eJake Slack                                _skip=true;
26403928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
26503928aee4356845252ac6b662d5c72c29903813eJake Slack
26603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state=_masked?State.MASK:State.PAYLOAD;
26703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _bytesNeeded=_state.getNeeds();
26803928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
26903928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
27003928aee4356845252ac6b662d5c72c29903813eJake Slack
27103928aee4356845252ac6b662d5c72c29903813eJake Slack                    case LENGTH_63:
27203928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=_buffer.get();
27303928aee4356845252ac6b662d5c72c29903813eJake Slack                        available--;
27403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _length = _length*0x100 + (0xff&b);
27503928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (--_bytesNeeded==0)
27603928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
27703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _bytesNeeded=(int)_length;
27803928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_length>=_buffer.capacity() && !_fragmentFrames)
27903928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
28003928aee4356845252ac6b662d5c72c29903813eJake Slack                                progress=true;
28103928aee4356845252ac6b662d5c72c29903813eJake Slack                                _handler.close(WebSocketConnectionD08.CLOSE_BADDATA,"frame size "+_length+">"+_buffer.capacity());
28203928aee4356845252ac6b662d5c72c29903813eJake Slack                                _skip=true;
28303928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
28403928aee4356845252ac6b662d5c72c29903813eJake Slack
28503928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state=_masked?State.MASK:State.PAYLOAD;
28603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _bytesNeeded=_state.getNeeds();
28703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
28803928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
28903928aee4356845252ac6b662d5c72c29903813eJake Slack
29003928aee4356845252ac6b662d5c72c29903813eJake Slack                    case MASK:
29103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _buffer.get(_mask,0,4);
29203928aee4356845252ac6b662d5c72c29903813eJake Slack                        _m=0;
29303928aee4356845252ac6b662d5c72c29903813eJake Slack                        available-=4;
29403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _state=State.PAYLOAD;
29503928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bytesNeeded=_state.getNeeds();
29603928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
29703928aee4356845252ac6b662d5c72c29903813eJake Slack
29803928aee4356845252ac6b662d5c72c29903813eJake Slack                    case PAYLOAD:
29903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bytesNeeded=(int)_length;
30003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _state=_skip?State.SKIP:State.DATA;
30103928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
30203928aee4356845252ac6b662d5c72c29903813eJake Slack
30303928aee4356845252ac6b662d5c72c29903813eJake Slack                    case DATA:
30403928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
30503928aee4356845252ac6b662d5c72c29903813eJake Slack
30603928aee4356845252ac6b662d5c72c29903813eJake Slack                    case SKIP:
30703928aee4356845252ac6b662d5c72c29903813eJake Slack                        int skip=Math.min(available,_bytesNeeded);
30803928aee4356845252ac6b662d5c72c29903813eJake Slack                        progress=true;
30903928aee4356845252ac6b662d5c72c29903813eJake Slack                        _buffer.skip(skip);
31003928aee4356845252ac6b662d5c72c29903813eJake Slack                        available-=skip;
31103928aee4356845252ac6b662d5c72c29903813eJake Slack                        _bytesNeeded-=skip;
31203928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_bytesNeeded==0)
31303928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state=State.START;
31403928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
31503928aee4356845252ac6b662d5c72c29903813eJake Slack
31603928aee4356845252ac6b662d5c72c29903813eJake Slack                    case SEEK_EOF:
31703928aee4356845252ac6b662d5c72c29903813eJake Slack                        progress=true;
31803928aee4356845252ac6b662d5c72c29903813eJake Slack                        _buffer.skip(available);
31903928aee4356845252ac6b662d5c72c29903813eJake Slack                        available=0;
32003928aee4356845252ac6b662d5c72c29903813eJake Slack                        break;
32103928aee4356845252ac6b662d5c72c29903813eJake Slack                }
32203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
32303928aee4356845252ac6b662d5c72c29903813eJake Slack
32403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_state==State.DATA && available>=_bytesNeeded)
32503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
32603928aee4356845252ac6b662d5c72c29903813eJake Slack                if ( _masked!=_shouldBeMasked)
32703928aee4356845252ac6b662d5c72c29903813eJake Slack                {
32803928aee4356845252ac6b662d5c72c29903813eJake Slack                    _buffer.skip(_bytesNeeded);
32903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=State.START;
33003928aee4356845252ac6b662d5c72c29903813eJake Slack                    progress=true;
33103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _handler.close(WebSocketConnectionD08.CLOSE_PROTOCOL,"bad mask");
33203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
33303928aee4356845252ac6b662d5c72c29903813eJake Slack                else
33403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
33503928aee4356845252ac6b662d5c72c29903813eJake Slack                    Buffer data =_buffer.get(_bytesNeeded);
33603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (_masked)
33703928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
33803928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (data.array()==null)
33903928aee4356845252ac6b662d5c72c29903813eJake Slack                            data=_buffer.asMutableBuffer();
34003928aee4356845252ac6b662d5c72c29903813eJake Slack                        byte[] array = data.array();
34103928aee4356845252ac6b662d5c72c29903813eJake Slack                        final int end=data.putIndex();
34203928aee4356845252ac6b662d5c72c29903813eJake Slack                        for (int i=data.getIndex();i<end;i++)
34303928aee4356845252ac6b662d5c72c29903813eJake Slack                            array[i]^=_mask[_m++%4];
34403928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
34503928aee4356845252ac6b662d5c72c29903813eJake Slack
34603928aee4356845252ac6b662d5c72c29903813eJake Slack                    // System.err.printf("%s %s %s >>\n",TypeUtil.toHexString(_flags),TypeUtil.toHexString(_opcode),data.length());
34703928aee4356845252ac6b662d5c72c29903813eJake Slack
34803928aee4356845252ac6b662d5c72c29903813eJake Slack                    progress=true;
34903928aee4356845252ac6b662d5c72c29903813eJake Slack                    _handler.onFrame(_flags, _opcode, data);
35003928aee4356845252ac6b662d5c72c29903813eJake Slack                    _bytesNeeded=0;
35103928aee4356845252ac6b662d5c72c29903813eJake Slack                    _state=State.START;
35203928aee4356845252ac6b662d5c72c29903813eJake Slack                }
35303928aee4356845252ac6b662d5c72c29903813eJake Slack
35403928aee4356845252ac6b662d5c72c29903813eJake Slack                break;
35503928aee4356845252ac6b662d5c72c29903813eJake Slack            }
35603928aee4356845252ac6b662d5c72c29903813eJake Slack        }
35703928aee4356845252ac6b662d5c72c29903813eJake Slack
35803928aee4356845252ac6b662d5c72c29903813eJake Slack        return progress?1:filled;
35903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36003928aee4356845252ac6b662d5c72c29903813eJake Slack
36103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
36203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void fill(Buffer buffer)
36303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (buffer!=null && buffer.length()>0)
36503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
36603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_buffer==null)
36703928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer=_buffers.getBuffer();
36803928aee4356845252ac6b662d5c72c29903813eJake Slack
36903928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer.put(buffer);
37003928aee4356845252ac6b662d5c72c29903813eJake Slack            buffer.clear();
37103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
37203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
37303928aee4356845252ac6b662d5c72c29903813eJake Slack
37403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
37503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void returnBuffer()
37603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer!=null && _buffer.length()==0)
37803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
37903928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffers.returnBuffer(_buffer);
38003928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer=null;
38103928aee4356845252ac6b662d5c72c29903813eJake Slack        }
38203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
38303928aee4356845252ac6b662d5c72c29903813eJake Slack
38403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
38503928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
38603928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toString()
38703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
38803928aee4356845252ac6b662d5c72c29903813eJake Slack        return String.format("%s@%x state=%s buffer=%s",
38903928aee4356845252ac6b662d5c72c29903813eJake Slack                getClass().getSimpleName(),
39003928aee4356845252ac6b662d5c72c29903813eJake Slack                hashCode(),
39103928aee4356845252ac6b662d5c72c29903813eJake Slack                _state,
39203928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer);
39303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
39403928aee4356845252ac6b662d5c72c29903813eJake Slack}
395