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