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