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.TypeUtil;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
2903928aee4356845252ac6b662d5c72c29903813eJake Slack
3003928aee4356845252ac6b662d5c72c29903813eJake Slack
3103928aee4356845252ac6b662d5c72c29903813eJake Slack
3203928aee4356845252ac6b662d5c72c29903813eJake Slack
3303928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
3403928aee4356845252ac6b662d5c72c29903813eJake Slack/**
3503928aee4356845252ac6b662d5c72c29903813eJake Slack * Parser the WebSocket protocol.
3603928aee4356845252ac6b662d5c72c29903813eJake Slack *
3703928aee4356845252ac6b662d5c72c29903813eJake Slack */
3803928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class WebSocketParserD00 implements WebSocketParser
3903928aee4356845252ac6b662d5c72c29903813eJake Slack{
4003928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(WebSocketParserD00.class);
4103928aee4356845252ac6b662d5c72c29903813eJake Slack
4203928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final int STATE_START=0;
4303928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final int STATE_SENTINEL_DATA=1;
4403928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final int STATE_LENGTH=2;
4503928aee4356845252ac6b662d5c72c29903813eJake Slack    public static final int STATE_DATA=3;
4603928aee4356845252ac6b662d5c72c29903813eJake Slack
4703928aee4356845252ac6b662d5c72c29903813eJake Slack    private final WebSocketBuffers _buffers;
4803928aee4356845252ac6b662d5c72c29903813eJake Slack    private final EndPoint _endp;
4903928aee4356845252ac6b662d5c72c29903813eJake Slack    private final FrameHandler _handler;
5003928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _state;
5103928aee4356845252ac6b662d5c72c29903813eJake Slack    private Buffer _buffer;
5203928aee4356845252ac6b662d5c72c29903813eJake Slack    private byte _opcode;
5303928aee4356845252ac6b662d5c72c29903813eJake Slack    private int _length;
5403928aee4356845252ac6b662d5c72c29903813eJake Slack
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
5603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
5703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param buffers The buffers to use for parsing.  Only the {@link Buffers#getBuffer()} is used.
5803928aee4356845252ac6b662d5c72c29903813eJake Slack     * This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data
5903928aee4356845252ac6b662d5c72c29903813eJake Slack     * is mostly used.
6003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param endp the endpoint
6103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param handler the handler to notify when a parse event occurs
6203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    public WebSocketParserD00(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler)
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
6503928aee4356845252ac6b662d5c72c29903813eJake Slack        _buffers=buffers;
6603928aee4356845252ac6b662d5c72c29903813eJake Slack        _endp=endp;
6703928aee4356845252ac6b662d5c72c29903813eJake Slack        _handler=handler;
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6903928aee4356845252ac6b662d5c72c29903813eJake Slack
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isBufferEmpty()
7203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _buffer==null || _buffer.length()==0;
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7503928aee4356845252ac6b662d5c72c29903813eJake Slack
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7703928aee4356845252ac6b662d5c72c29903813eJake Slack    public Buffer getBuffer()
7803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7903928aee4356845252ac6b662d5c72c29903813eJake Slack        return _buffer;
8003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8103928aee4356845252ac6b662d5c72c29903813eJake Slack
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8303928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Parse to next event.
8403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Parse to the next {@link WebSocketParser.FrameHandler} event or until no more data is
8503928aee4356845252ac6b662d5c72c29903813eJake Slack     * available. Fill data from the {@link EndPoint} only as necessary.
8603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return An indication of progress or otherwise. -1 indicates EOF, 0 indicates
8703928aee4356845252ac6b662d5c72c29903813eJake Slack     * that no bytes were read and no messages parsed. A positive number indicates either
8803928aee4356845252ac6b662d5c72c29903813eJake Slack     * the bytes filled or the messages parsed.
8903928aee4356845252ac6b662d5c72c29903813eJake Slack     */
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    public int parseNext()
9103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_buffer==null)
9303928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer=_buffers.getBuffer();
9403928aee4356845252ac6b662d5c72c29903813eJake Slack
9503928aee4356845252ac6b662d5c72c29903813eJake Slack        int progress=0;
9603928aee4356845252ac6b662d5c72c29903813eJake Slack
9703928aee4356845252ac6b662d5c72c29903813eJake Slack        // Loop until an datagram call back or can't fill anymore
9803928aee4356845252ac6b662d5c72c29903813eJake Slack        while(true)
9903928aee4356845252ac6b662d5c72c29903813eJake Slack        {
10003928aee4356845252ac6b662d5c72c29903813eJake Slack            int length=_buffer.length();
10103928aee4356845252ac6b662d5c72c29903813eJake Slack
10203928aee4356845252ac6b662d5c72c29903813eJake Slack            // Fill buffer if we need a byte or need length
10303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (length == 0 || _state==STATE_DATA && length<_length)
10403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
10503928aee4356845252ac6b662d5c72c29903813eJake Slack                // compact to mark (set at start of data)
10603928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer.compact();
10703928aee4356845252ac6b662d5c72c29903813eJake Slack
10803928aee4356845252ac6b662d5c72c29903813eJake Slack                // if no space, then the data is too big for buffer
10903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (_buffer.space() == 0)
11003928aee4356845252ac6b662d5c72c29903813eJake Slack                    throw new IllegalStateException("FULL");
11103928aee4356845252ac6b662d5c72c29903813eJake Slack
11203928aee4356845252ac6b662d5c72c29903813eJake Slack                // catch IOExceptions (probably EOF) and try to parse what we have
11303928aee4356845252ac6b662d5c72c29903813eJake Slack                try
11403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
11503928aee4356845252ac6b662d5c72c29903813eJake Slack                    int filled=_endp.isOpen()?_endp.fill(_buffer):-1;
11603928aee4356845252ac6b662d5c72c29903813eJake Slack                    if (filled<=0)
11703928aee4356845252ac6b662d5c72c29903813eJake Slack                        return progress;
11803928aee4356845252ac6b662d5c72c29903813eJake Slack                    progress+=filled;
11903928aee4356845252ac6b662d5c72c29903813eJake Slack                    length=_buffer.length();
12003928aee4356845252ac6b662d5c72c29903813eJake Slack                }
12103928aee4356845252ac6b662d5c72c29903813eJake Slack                catch(IOException e)
12203928aee4356845252ac6b662d5c72c29903813eJake Slack                {
12303928aee4356845252ac6b662d5c72c29903813eJake Slack                    LOG.debug(e);
12403928aee4356845252ac6b662d5c72c29903813eJake Slack                    return progress>0?progress:-1;
12503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
12603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
12703928aee4356845252ac6b662d5c72c29903813eJake Slack
12803928aee4356845252ac6b662d5c72c29903813eJake Slack
12903928aee4356845252ac6b662d5c72c29903813eJake Slack            // Parse the buffer byte by byte (unless it is STATE_DATA)
13003928aee4356845252ac6b662d5c72c29903813eJake Slack            byte b;
13103928aee4356845252ac6b662d5c72c29903813eJake Slack            charloop: while (length-->0)
13203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
13303928aee4356845252ac6b662d5c72c29903813eJake Slack                switch (_state)
13403928aee4356845252ac6b662d5c72c29903813eJake Slack                {
13503928aee4356845252ac6b662d5c72c29903813eJake Slack                    case STATE_START:
13603928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=_buffer.get();
13703928aee4356845252ac6b662d5c72c29903813eJake Slack                        _opcode=b;
13803928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_opcode<0)
13903928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
14003928aee4356845252ac6b662d5c72c29903813eJake Slack                            _length=0;
14103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state=STATE_LENGTH;
14203928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
14303928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
14403928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
14503928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state=STATE_SENTINEL_DATA;
14603928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.mark(0);
14703928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
14803928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
14903928aee4356845252ac6b662d5c72c29903813eJake Slack
15003928aee4356845252ac6b662d5c72c29903813eJake Slack                    case STATE_SENTINEL_DATA:
15103928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=_buffer.get();
15203928aee4356845252ac6b662d5c72c29903813eJake Slack                        if ((b&0xff)==0xff)
15303928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
15403928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state=STATE_START;
15503928aee4356845252ac6b662d5c72c29903813eJake Slack                            int l=_buffer.getIndex()-_buffer.markIndex()-1;
15603928aee4356845252ac6b662d5c72c29903813eJake Slack                            progress++;
15703928aee4356845252ac6b662d5c72c29903813eJake Slack                            _handler.onFrame((byte)0,_opcode,_buffer.sliceFromMark(l));
15803928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.setMarkIndex(-1);
15903928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (_buffer.length()==0)
16003928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
16103928aee4356845252ac6b662d5c72c29903813eJake Slack                                _buffers.returnBuffer(_buffer);
16203928aee4356845252ac6b662d5c72c29903813eJake Slack                                _buffer=null;
16303928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
16403928aee4356845252ac6b662d5c72c29903813eJake Slack                            return progress;
16503928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
16603928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
16703928aee4356845252ac6b662d5c72c29903813eJake Slack
16803928aee4356845252ac6b662d5c72c29903813eJake Slack                    case STATE_LENGTH:
16903928aee4356845252ac6b662d5c72c29903813eJake Slack                        b=_buffer.get();
17003928aee4356845252ac6b662d5c72c29903813eJake Slack                        _length=_length<<7 | (0x7f&b);
17103928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (b>=0)
17203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
17303928aee4356845252ac6b662d5c72c29903813eJake Slack                            _state=STATE_DATA;
17403928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer.mark(0);
17503928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
17603928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
17703928aee4356845252ac6b662d5c72c29903813eJake Slack
17803928aee4356845252ac6b662d5c72c29903813eJake Slack                    case STATE_DATA:
17903928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer.markIndex()<0)
18003928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer.length()<_length)
18103928aee4356845252ac6b662d5c72c29903813eJake Slack                            break charloop;
18203928aee4356845252ac6b662d5c72c29903813eJake Slack                        Buffer data=_buffer.sliceFromMark(_length);
18303928aee4356845252ac6b662d5c72c29903813eJake Slack                        _buffer.skip(_length);
18403928aee4356845252ac6b662d5c72c29903813eJake Slack                        _state=STATE_START;
18503928aee4356845252ac6b662d5c72c29903813eJake Slack                        progress++;
18603928aee4356845252ac6b662d5c72c29903813eJake Slack                        _handler.onFrame((byte)0, _opcode, data);
18703928aee4356845252ac6b662d5c72c29903813eJake Slack
18803928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (_buffer.length()==0)
18903928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
19003928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffers.returnBuffer(_buffer);
19103928aee4356845252ac6b662d5c72c29903813eJake Slack                            _buffer=null;
19203928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
19303928aee4356845252ac6b662d5c72c29903813eJake Slack
19403928aee4356845252ac6b662d5c72c29903813eJake Slack                        return progress;
19503928aee4356845252ac6b662d5c72c29903813eJake Slack                }
19603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
19703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
19803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19903928aee4356845252ac6b662d5c72c29903813eJake Slack
20003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void fill(Buffer buffer)
20203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (buffer!=null && buffer.length()>0)
20403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
20503928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_buffer==null)
20603928aee4356845252ac6b662d5c72c29903813eJake Slack                _buffer=_buffers.getBuffer();
20703928aee4356845252ac6b662d5c72c29903813eJake Slack            _buffer.put(buffer);
20803928aee4356845252ac6b662d5c72c29903813eJake Slack            buffer.clear();
20903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
21003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
21103928aee4356845252ac6b662d5c72c29903813eJake Slack
21203928aee4356845252ac6b662d5c72c29903813eJake Slack}
213