//
//  ========================================================================
//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.websocket;

import java.io.IOException;

import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;



/* ------------------------------------------------------------ */
/**
 * Parser the WebSocket protocol.
 *
 */
public class WebSocketParserD08 implements WebSocketParser
{
    private static final Logger LOG = Log.getLogger(WebSocketParserD08.class);

    public enum State {

        START(0), OPCODE(1), LENGTH_7(1), LENGTH_16(2), LENGTH_63(8), MASK(4), PAYLOAD(0), DATA(0), SKIP(1), SEEK_EOF(1);

        int _needs;

        State(int needs)
        {
            _needs=needs;
        }

        int getNeeds()
        {
            return _needs;
        }
    }

    private final WebSocketBuffers _buffers;
    private final EndPoint _endp;
    private final FrameHandler _handler;
    private final boolean _shouldBeMasked;
    private State _state;
    private Buffer _buffer;
    private byte _flags;
    private byte _opcode;
    private int _bytesNeeded;
    private long _length;
    private boolean _masked;
    private final byte[] _mask = new byte[4];
    private int _m;
    private boolean _skip;
    private boolean _fragmentFrames=true;

    /* ------------------------------------------------------------ */
    /**
     * @param buffers The buffers to use for parsing.  Only the {@link Buffers#getBuffer()} is used.
     * This should be a direct buffer if binary data is mostly used or an indirect buffer if utf-8 data
     * is mostly used.
     * @param endp the endpoint
     * @param handler the handler to notify when a parse event occurs
     * @param shouldBeMasked whether masking should be handled
     */
    public WebSocketParserD08(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
    {
        _buffers=buffers;
        _endp=endp;
        _handler=handler;
        _shouldBeMasked=shouldBeMasked;
        _state=State.START;
    }

    /* ------------------------------------------------------------ */
    /**
     * @return True if fake fragments should be created for frames larger than the buffer.
     */
    public boolean isFakeFragments()
    {
        return _fragmentFrames;
    }

    /* ------------------------------------------------------------ */
    /**
     * @param fakeFragments True if fake fragments should be created for frames larger than the buffer.
     */
    public void setFakeFragments(boolean fakeFragments)
    {
        _fragmentFrames = fakeFragments;
    }

    /* ------------------------------------------------------------ */
    public boolean isBufferEmpty()
    {
        return _buffer==null || _buffer.length()==0;
    }

    /* ------------------------------------------------------------ */
    public Buffer getBuffer()
    {
        return _buffer;
    }

    /* ------------------------------------------------------------ */
    /** Parse to next event.
     * Parse to the next {@link WebSocketParser.FrameHandler} event or until no more data is
     * available. Fill data from the {@link EndPoint} only as necessary.
     * @return An indication of progress or otherwise. -1 indicates EOF, 0 indicates
     * that no bytes were read and no messages parsed. A positive number indicates either
     * the bytes filled or the messages parsed.
     */
    public int parseNext()
    {
        if (_buffer==null)
            _buffer=_buffers.getBuffer();

        boolean progress=false;
        int filled=-1;

        // Loop until a datagram call back or can't fill anymore
        while(!progress && (!_endp.isInputShutdown()||_buffer.length()>0))
        {
            int available=_buffer.length();

            // Fill buffer if we need a byte or need length
            while (available<(_state==State.SKIP?1:_bytesNeeded))
            {
                // compact to mark (set at start of data)
                _buffer.compact();

                // if no space, then the data is too big for buffer
                if (_buffer.space() == 0)
                {
                    // Can we send a fake frame?
                    if (_fragmentFrames && _state==State.DATA)
                    {
                        Buffer data =_buffer.get(4*(available/4));
                        _buffer.compact();
                        if (_masked)
                        {
                            if (data.array()==null)
                                data=_buffer.asMutableBuffer();
                            byte[] array = data.array();
                            final int end=data.putIndex();
                            for (int i=data.getIndex();i<end;i++)
                                array[i]^=_mask[_m++%4];
                        }

                        // System.err.printf("%s %s %s >>\n",TypeUtil.toHexString(_flags),TypeUtil.toHexString(_opcode),data.length());
                        _bytesNeeded-=data.length();
                        progress=true;
                        _handler.onFrame((byte)(_flags&(0xff^WebSocketConnectionD08.FLAG_FIN)), _opcode, data);

                        _opcode=WebSocketConnectionD08.OP_CONTINUATION;
                    }

                    if (_buffer.space() == 0)
                        throw new IllegalStateException("FULL: "+_state+" "+_bytesNeeded+">"+_buffer.capacity());
                }

                // catch IOExceptions (probably EOF) and try to parse what we have
                try
                {
                    filled=_endp.isInputShutdown()?-1:_endp.fill(_buffer);
                    available=_buffer.length();
                    // System.err.printf(">> filled %d/%d%n",filled,available);
                    if (filled<=0)
                        break;
                }
                catch(IOException e)
                {
                    LOG.debug(e);
                    filled=-1;
                    break;
                }
            }
            // Did we get enough?
            if (available<(_state==State.SKIP?1:_bytesNeeded))
                break;

            // if we are here, then we have sufficient bytes to process the current state.
            // Parse the buffer byte by byte (unless it is STATE_DATA)
            byte b;
            while (_state!=State.DATA && available>=(_state==State.SKIP?1:_bytesNeeded))
            {
                switch (_state)
                {
                    case START:
                        _skip=false;
                        _state=_opcode==WebSocketConnectionD08.OP_CLOSE?State.SEEK_EOF:State.OPCODE;
                        _bytesNeeded=_state.getNeeds();
                        continue;

                    case OPCODE:
                        b=_buffer.get();
                        available--;
                        _opcode=(byte)(b&0xf);
                        _flags=(byte)(0xf&(b>>4));

                        if (WebSocketConnectionD08.isControlFrame(_opcode)&&!WebSocketConnectionD08.isLastFrame(_flags))
                        {
                            LOG.warn("Fragmented Control from "+_endp);
                            _handler.close(WebSocketConnectionD08.CLOSE_PROTOCOL,"Fragmented control");
                            progress=true;
                            _skip=true;
                        }

                        _state=State.LENGTH_7;
                        _bytesNeeded=_state.getNeeds();

                        continue;

                    case LENGTH_7:
                        b=_buffer.get();
                        available--;
                        _masked=(b&0x80)!=0;
                        b=(byte)(0x7f&b);

                        switch(b)
                        {
                            case 0x7f:
                                _length=0;
                                _state=State.LENGTH_63;
                                break;
                            case 0x7e:
                                _length=0;
                                _state=State.LENGTH_16;
                                break;
                            default:
                                _length=(0x7f&b);
                                _state=_masked?State.MASK:State.PAYLOAD;
                        }
                        _bytesNeeded=_state.getNeeds();
                        continue;

                    case LENGTH_16:
                        b=_buffer.get();
                        available--;
                        _length = _length*0x100 + (0xff&b);
                        if (--_bytesNeeded==0)
                        {
                            if (_length>_buffer.capacity() && !_fragmentFrames)
                            {
                                progress=true;
                                _handler.close(WebSocketConnectionD08.CLOSE_BADDATA,"frame size "+_length+">"+_buffer.capacity());
                                _skip=true;
                            }

                            _state=_masked?State.MASK:State.PAYLOAD;
                            _bytesNeeded=_state.getNeeds();
                        }
                        continue;

                    case LENGTH_63:
                        b=_buffer.get();
                        available--;
                        _length = _length*0x100 + (0xff&b);
                        if (--_bytesNeeded==0)
                        {
                            _bytesNeeded=(int)_length;
                            if (_length>=_buffer.capacity() && !_fragmentFrames)
                            {
                                progress=true;
                                _handler.close(WebSocketConnectionD08.CLOSE_BADDATA,"frame size "+_length+">"+_buffer.capacity());
                                _skip=true;
                            }

                            _state=_masked?State.MASK:State.PAYLOAD;
                            _bytesNeeded=_state.getNeeds();
                        }
                        continue;

                    case MASK:
                        _buffer.get(_mask,0,4);
                        _m=0;
                        available-=4;
                        _state=State.PAYLOAD;
                        _bytesNeeded=_state.getNeeds();
                        break;

                    case PAYLOAD:
                        _bytesNeeded=(int)_length;
                        _state=_skip?State.SKIP:State.DATA;
                        break;

                    case DATA:
                        break;

                    case SKIP:
                        int skip=Math.min(available,_bytesNeeded);
                        progress=true;
                        _buffer.skip(skip);
                        available-=skip;
                        _bytesNeeded-=skip;
                        if (_bytesNeeded==0)
                            _state=State.START;
                        break;

                    case SEEK_EOF:
                        progress=true;
                        _buffer.skip(available);
                        available=0;
                        break;
                }
            }

            if (_state==State.DATA && available>=_bytesNeeded)
            {
                if ( _masked!=_shouldBeMasked)
                {
                    _buffer.skip(_bytesNeeded);
                    _state=State.START;
                    progress=true;
                    _handler.close(WebSocketConnectionD08.CLOSE_PROTOCOL,"bad mask");
                }
                else
                {
                    Buffer data =_buffer.get(_bytesNeeded);
                    if (_masked)
                    {
                        if (data.array()==null)
                            data=_buffer.asMutableBuffer();
                        byte[] array = data.array();
                        final int end=data.putIndex();
                        for (int i=data.getIndex();i<end;i++)
                            array[i]^=_mask[_m++%4];
                    }

                    // System.err.printf("%s %s %s >>\n",TypeUtil.toHexString(_flags),TypeUtil.toHexString(_opcode),data.length());

                    progress=true;
                    _handler.onFrame(_flags, _opcode, data);
                    _bytesNeeded=0;
                    _state=State.START;
                }

                break;
            }
        }

        return progress?1:filled;
    }

    /* ------------------------------------------------------------ */
    public void fill(Buffer buffer)
    {
        if (buffer!=null && buffer.length()>0)
        {
            if (_buffer==null)
                _buffer=_buffers.getBuffer();

            _buffer.put(buffer);
            buffer.clear();
        }
    }

    /* ------------------------------------------------------------ */
    public void returnBuffer()
    {
        if (_buffer!=null && _buffer.length()==0)
        {
            _buffers.returnBuffer(_buffer);
            _buffer=null;
        }
    }

    /* ------------------------------------------------------------ */
    @Override
    public String toString()
    {
        return String.format("%s@%x state=%s buffer=%s",
                getClass().getSimpleName(),
                hashCode(),
                _state,
                _buffer);
    }
}
