Introduction PayloadParser and OpCodes
This commit is contained in:
parent
b9ca387d53
commit
cb6968d680
|
@ -1,65 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 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.nio.ByteBuffer;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Parser the WebSocket protocol.
|
||||
*
|
||||
*/
|
||||
public interface WebSocketParser
|
||||
{
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
public interface FrameHandler
|
||||
{
|
||||
void onFrame(byte flags, byte opcode, ByteBuffer buffer);
|
||||
void close(int code,String message);
|
||||
}
|
||||
|
||||
ByteBuffer getBuffer();
|
||||
|
||||
/**
|
||||
* @return an indication of progress, normally bytes filled plus events parsed, or -1 for EOF
|
||||
*/
|
||||
int parseNext();
|
||||
|
||||
boolean isBufferEmpty();
|
||||
|
||||
void fill(ByteBuffer buffer);
|
||||
|
||||
}
|
|
@ -1,404 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Intalio, Inc.
|
||||
* ======================================================================
|
||||
* 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.
|
||||
*******************************************************************************/
|
||||
// ========================================================================
|
||||
// Copyright (c) 2010 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 java.nio.ByteBuffer;
|
||||
|
||||
|
||||
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 WebSocketParserRFC6455 implements WebSocketParser
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(WebSocketParserRFC6455.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 ByteBuffer _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#getData()} 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 WebSocketParserRFC6455(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 ByteBuffer 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.getData();
|
||||
|
||||
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)
|
||||
{
|
||||
ByteBuffer 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^WebSocketConnectionRFC6455.FLAG_FIN)), _opcode, data);
|
||||
|
||||
_opcode=WebSocketConnectionRFC6455.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==WebSocketConnectionRFC6455.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 (WebSocketConnectionRFC6455.isControlFrame(_opcode)&&!WebSocketConnectionRFC6455.isLastFrame(_flags))
|
||||
{
|
||||
LOG.warn("Fragmented Control from "+_endp);
|
||||
_handler.close(WebSocketConnectionRFC6455.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(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,"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(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,"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(WebSocketConnectionRFC6455.CLOSE_PROTOCOL,"Not masked");
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteBuffer 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(ByteBuffer buffer)
|
||||
{
|
||||
if (buffer!=null && buffer.length()>0)
|
||||
{
|
||||
if (_buffer==null)
|
||||
_buffer=_buffers.getData();
|
||||
|
||||
_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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package org.eclipse.jetty.websocket.api;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jetty.websocket.frames.BinaryFrame;
|
||||
import org.eclipse.jetty.websocket.frames.CloseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.ContinuationFrame;
|
||||
import org.eclipse.jetty.websocket.frames.PingFrame;
|
||||
import org.eclipse.jetty.websocket.frames.PongFrame;
|
||||
import org.eclipse.jetty.websocket.frames.TextFrame;
|
||||
|
||||
public enum OpCode
|
||||
{
|
||||
/**
|
||||
* OpCode for a {@link ContinuationFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
CONTINUATION((byte)0x00),
|
||||
|
||||
/**
|
||||
* OpCode for a {@link TextFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
TEXT((byte)0x01),
|
||||
|
||||
/**
|
||||
* OpCode for a {@link BinaryFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
BINARY((byte)0x02),
|
||||
|
||||
/**
|
||||
* OpCode for a {@link CloseFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
CLOSE((byte)0x08),
|
||||
|
||||
/**
|
||||
* OpCode for a {@link PingFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
PING((byte)0x09),
|
||||
|
||||
/**
|
||||
* OpCode for a {@link PongFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
PONG((byte)0x0A);
|
||||
|
||||
private static class Codes
|
||||
{
|
||||
private static final Map<Byte, OpCode> codes = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OpCode from specified value.
|
||||
*
|
||||
* @param opcode
|
||||
* @return
|
||||
*/
|
||||
public static OpCode from(byte opcode)
|
||||
{
|
||||
return Codes.codes.get(opcode);
|
||||
}
|
||||
|
||||
private byte opcode;
|
||||
|
||||
private OpCode(byte opcode)
|
||||
{
|
||||
this.opcode = opcode;
|
||||
Codes.codes.put(opcode,this);
|
||||
}
|
||||
|
||||
public byte getCode()
|
||||
{
|
||||
return this.opcode;
|
||||
}
|
||||
|
||||
public boolean isControlFrame() {
|
||||
return (opcode >= CLOSE.opcode);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
/**
|
||||
* A Base Frame as seen in <a href="https://tools.ietf.org/html/rfc6455#section-5.2">RFC 6455. Sec 5.2</a>
|
||||
*
|
||||
|
@ -26,59 +28,24 @@ package org.eclipse.jetty.websocket.frames;
|
|||
*/
|
||||
public class BaseFrame
|
||||
{
|
||||
/**
|
||||
* OpCode for a {@link ContinuationFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
public final static byte OP_CONTINUATION = 0x00;
|
||||
/**
|
||||
* OpCode for a {@link TextFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
public final static byte OP_TEXT = 0x01;
|
||||
/**
|
||||
* OpCode for a {@link BinaryFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
public final static byte OP_BINARY = 0x02;
|
||||
/**
|
||||
* OpCode for a {@link CloseFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
public final static byte OP_CLOSE = 0x08;
|
||||
/**
|
||||
* OpCode for a {@link PingFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
public final static byte OP_PING = 0x09;
|
||||
/**
|
||||
* OpCode for a {@link PongFrame}
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc6455#section-11.8">RFC 6455, Section 11.8 (WebSocket Opcode Registry</a>
|
||||
*/
|
||||
public final static byte OP_PONG = 0x0A;
|
||||
|
||||
private boolean fin;
|
||||
private boolean rsv1;
|
||||
private boolean rsv2;
|
||||
private boolean rsv3;
|
||||
private byte opcode = -1;
|
||||
private OpCode opcode = null;
|
||||
private boolean masked = false;
|
||||
|
||||
private long payloadLength;
|
||||
private int payloadLength;
|
||||
private byte mask[];
|
||||
public final static int FLAG_FIN = 0x8;
|
||||
public final static int FLAG_RSV1 = 0x4;
|
||||
public final static int FLAG_RSV2 = 0x2;
|
||||
public final static int FLAG_RSV3 = 0x1;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public BaseFrame() {
|
||||
/* default */
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,6 +53,7 @@ public class BaseFrame
|
|||
* @param copy the copy
|
||||
*/
|
||||
public BaseFrame(BaseFrame copy) {
|
||||
this();
|
||||
this.fin = copy.fin;
|
||||
this.rsv1 = copy.rsv1;
|
||||
this.rsv2 = copy.rsv2;
|
||||
|
@ -100,6 +68,14 @@ public class BaseFrame
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct form opcode
|
||||
*/
|
||||
public BaseFrame(OpCode opcode) {
|
||||
reset();
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
||||
public byte[] getMask()
|
||||
{
|
||||
if (!masked)
|
||||
|
@ -109,21 +85,16 @@ public class BaseFrame
|
|||
return mask;
|
||||
}
|
||||
|
||||
public byte getOpcode()
|
||||
public OpCode getOpCode()
|
||||
{
|
||||
return opcode;
|
||||
}
|
||||
|
||||
public long getPayloadLength()
|
||||
public int getPayloadLength()
|
||||
{
|
||||
return payloadLength;
|
||||
}
|
||||
|
||||
public boolean isControlFrame()
|
||||
{
|
||||
return (opcode >= OP_CLOSE);
|
||||
}
|
||||
|
||||
public boolean isFin()
|
||||
{
|
||||
return fin;
|
||||
|
@ -154,6 +125,18 @@ public class BaseFrame
|
|||
return rsv3;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
fin = false;
|
||||
rsv1 = false;
|
||||
rsv2 = false;
|
||||
rsv3 = false;
|
||||
opcode = null;
|
||||
masked = false;
|
||||
payloadLength = -1;
|
||||
mask = null;
|
||||
}
|
||||
|
||||
public void setFin(boolean fin)
|
||||
{
|
||||
this.fin = fin;
|
||||
|
@ -169,12 +152,12 @@ public class BaseFrame
|
|||
this.masked = mask;
|
||||
}
|
||||
|
||||
public void setOpcode(byte opcode)
|
||||
public void setOpCode(OpCode opCode)
|
||||
{
|
||||
this.opcode = opcode;
|
||||
this.opcode = opCode;
|
||||
}
|
||||
|
||||
public void setPayloadLength(long payloadLength)
|
||||
public void setPayloadLength(int payloadLength)
|
||||
{
|
||||
this.payloadLength = payloadLength;
|
||||
}
|
||||
|
|
|
@ -2,10 +2,12 @@ package org.eclipse.jetty.websocket.frames;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
/**
|
||||
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.6">Binary Data Frame (0x02)</a>.
|
||||
*/
|
||||
public class BinaryFrame extends BaseFrame
|
||||
public class BinaryFrame extends DataFrame
|
||||
{
|
||||
private ByteBuffer data; // TODO: make this a standard byte buffer?
|
||||
|
||||
|
@ -14,8 +16,7 @@ public class BinaryFrame extends BaseFrame
|
|||
*/
|
||||
public BinaryFrame()
|
||||
{
|
||||
super();
|
||||
super.setOpcode(OP_BINARY);
|
||||
super(OpCode.BINARY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,7 +30,7 @@ public class BinaryFrame extends BaseFrame
|
|||
super(base);
|
||||
// TODO: limit this somehow?
|
||||
// TODO: create a streaming binary frame?
|
||||
data = ByteBuffer.allocate((int)base.getPayloadLength());
|
||||
data = ByteBuffer.allocate(base.getPayloadLength());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,6 +43,12 @@ public class BinaryFrame extends BaseFrame
|
|||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpCode getOpCode()
|
||||
{
|
||||
return OpCode.BINARY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data and payload length.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocket;
|
||||
|
||||
/**
|
||||
|
@ -17,10 +18,16 @@ public class CloseFrame extends ControlFrame
|
|||
|
||||
public CloseFrame(short statusCode)
|
||||
{
|
||||
super(ControlFrameType.CLOSE_FRAME);
|
||||
super(OpCode.CLOSE);
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpCode getOpCode()
|
||||
{
|
||||
return OpCode.CLOSE;
|
||||
}
|
||||
|
||||
public String getReason()
|
||||
{
|
||||
return reason;
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
public class ContinuationFrame {
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
public class ContinuationFrame extends BaseFrame
|
||||
{
|
||||
public ContinuationFrame()
|
||||
{
|
||||
super(OpCode.CONTINUATION);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
/**
|
||||
* Base class for all <a href="https://tools.ietf.org/html/rfc6455#section-5.5">control frames</a>.
|
||||
* <p>
|
||||
* TODO: investigate as candidate for removal.
|
||||
*/
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
public abstract class ControlFrame extends BaseFrame
|
||||
{
|
||||
private final ControlFrameType type;
|
||||
|
||||
public ControlFrame(ControlFrameType type)
|
||||
public ControlFrame()
|
||||
{
|
||||
this.type = type;
|
||||
super();
|
||||
}
|
||||
|
||||
public ControlFrameType getType()
|
||||
public ControlFrame(BaseFrame copy)
|
||||
{
|
||||
return type;
|
||||
super(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
public ControlFrame(OpCode opcode)
|
||||
{
|
||||
return String.format("%s frame v%s",getType());
|
||||
super(opcode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public enum ControlFrameType
|
||||
{
|
||||
PING_FRAME(BaseFrame.OP_PING),
|
||||
PONG_FRAME(BaseFrame.OP_PONG),
|
||||
CLOSE_FRAME(BaseFrame.OP_CLOSE);
|
||||
|
||||
private static class Codes
|
||||
{
|
||||
private static final Map<Byte, ControlFrameType> codes = new HashMap<>();
|
||||
}
|
||||
|
||||
public static ControlFrameType from(byte opcode)
|
||||
{
|
||||
return Codes.codes.get(opcode);
|
||||
}
|
||||
|
||||
private final byte opcode;
|
||||
|
||||
private ControlFrameType(byte opcode)
|
||||
{
|
||||
this.opcode = opcode;
|
||||
Codes.codes.put(opcode,this);
|
||||
}
|
||||
|
||||
public short getCode()
|
||||
{
|
||||
return opcode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
public abstract class DataFrame extends BaseFrame
|
||||
{
|
||||
public DataFrame()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public DataFrame(BaseFrame copy)
|
||||
{
|
||||
super(copy);
|
||||
}
|
||||
|
||||
public DataFrame(OpCode opcode)
|
||||
{
|
||||
super(opcode);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
/**
|
||||
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">Ping Frame (0x09)</a>.
|
||||
*/
|
||||
|
@ -9,10 +11,16 @@ public class PingFrame extends ControlFrame
|
|||
|
||||
public PingFrame(int pingId)
|
||||
{
|
||||
super(ControlFrameType.PING_FRAME);
|
||||
super(OpCode.PING);
|
||||
this.pingId = pingId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpCode getOpCode()
|
||||
{
|
||||
return OpCode.PING;
|
||||
}
|
||||
|
||||
public int getPingId()
|
||||
{
|
||||
return pingId;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
/**
|
||||
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">Pong Frame (0x0A)</a>.
|
||||
*/
|
||||
|
@ -9,7 +11,7 @@ public class PongFrame extends ControlFrame
|
|||
|
||||
public PongFrame(int pingId)
|
||||
{
|
||||
super(ControlFrameType.PONG_FRAME);
|
||||
super(OpCode.PONG);
|
||||
this.pingId = pingId;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package org.eclipse.jetty.websocket.frames;
|
||||
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
|
||||
/**
|
||||
* Representation of a <a href="https://tools.ietf.org/html/rfc6455#section-5.6">Text Data Frame (0x01)</a>.
|
||||
*/
|
||||
public class TextFrame extends BaseFrame
|
||||
public class TextFrame extends DataFrame
|
||||
{
|
||||
private StringBuilder data = new StringBuilder();
|
||||
|
||||
|
@ -12,8 +14,7 @@ public class TextFrame extends BaseFrame
|
|||
*/
|
||||
public TextFrame()
|
||||
{
|
||||
super();
|
||||
super.setOpcode(OP_TEXT);
|
||||
super(OpCode.TEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,11 +4,8 @@ import java.nio.ByteBuffer;
|
|||
import java.util.EnumMap;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
import org.eclipse.jetty.websocket.frames.ControlFrame;
|
||||
import org.eclipse.jetty.websocket.frames.ControlFrameType;
|
||||
import org.eclipse.jetty.websocket.frames.PingFrame;
|
||||
import org.eclipse.jetty.websocket.generator.ControlFrameGenerator;
|
||||
|
||||
/**
|
||||
* Generating a frame in WebSocket land.
|
||||
|
@ -36,22 +33,22 @@ import org.eclipse.jetty.websocket.generator.ControlFrameGenerator;
|
|||
*/
|
||||
public class Generator {
|
||||
|
||||
private final EnumMap<ControlFrameType, ControlFrameGenerator> generators = new EnumMap<>(ControlFrameType.class);
|
||||
private final EnumMap<OpCode, ControlFrameGenerator> generators = new EnumMap<>(OpCode.class);
|
||||
|
||||
|
||||
public Generator(ByteBufferPool bufferPool) //, CompressionFactory.Compressor compressor)
|
||||
{
|
||||
HeadersBlockGenerator headerBlockGenerator = new HeadersBlockGenerator();
|
||||
generators.put(ControlFrameType.PING_FRAME, new PingFrameGenerator());
|
||||
generators.put(ControlFrameType.PONG_FRAME, new PongFrameGenerator());
|
||||
generators.put(ControlFrameType.CLOSE_FRAME, new CloseFrameGenerator());
|
||||
generators.put(OpCode.PING,new PingFrameGenerator());
|
||||
generators.put(OpCode.PONG,new PongFrameGenerator());
|
||||
generators.put(OpCode.CLOSE,new CloseFrameGenerator());
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ByteBuffer control(ControlFrame frame)
|
||||
{
|
||||
ControlFrameGenerator generator = generators.get(frame.getType());
|
||||
ControlFrameGenerator generator = generators.get(frame.getOpCode());
|
||||
return generator.generate(frame);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class BinaryPayloadParser extends PayloadParser
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ClosePayloadParser extends PayloadParser
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ContinuationPayloadParser extends PayloadParser
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
public class ControlFrameBodyParser {
|
||||
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
public class ControlFrameParser {
|
||||
|
||||
}
|
|
@ -1,17 +1,18 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.api.OpCode;
|
||||
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||
import org.eclipse.jetty.websocket.frames.BaseFrame;
|
||||
import org.eclipse.jetty.websocket.frames.BinaryFrame;
|
||||
import org.eclipse.jetty.websocket.frames.ControlFrame;
|
||||
import org.eclipse.jetty.websocket.frames.TextFrame;
|
||||
import org.eclipse.jetty.websocket.frames.DataFrame;
|
||||
|
||||
/**
|
||||
* Parsing of a frame in WebSocket land.
|
||||
|
@ -42,18 +43,13 @@ public class Parser {
|
|||
{
|
||||
public static class Adapter implements Listener
|
||||
{
|
||||
@Override
|
||||
public void onBinaryFrame(final BinaryFrame frame)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControlFrame(final ControlFrame frame)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextFrame(final TextFrame frame)
|
||||
public void onDataFrame(final DataFrame frame)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -63,25 +59,32 @@ public class Parser {
|
|||
}
|
||||
}
|
||||
|
||||
public void onBinaryFrame(final BinaryFrame frame);
|
||||
public void onControlFrame(final ControlFrame frame);
|
||||
public void onTextFrame(final TextFrame frame);
|
||||
public void onDataFrame(final DataFrame frame);
|
||||
public void onWebSocketException(WebSocketException e);
|
||||
}
|
||||
|
||||
private enum State
|
||||
{
|
||||
FINOP, PAYLOAD_LEN, PAYLOAD_LEN_BYTES, MASK, MASK_BYTES, PAYLOAD
|
||||
FINOP,
|
||||
PAYLOAD_LEN,
|
||||
PAYLOAD_LEN_BYTES,
|
||||
MASK,
|
||||
MASK_BYTES,
|
||||
PAYLOAD
|
||||
}
|
||||
|
||||
private static final Logger LOG = Log.getLogger(Parser.class);
|
||||
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
|
||||
private State state = State.FINOP;
|
||||
|
||||
private final EnumMap<OpCode, PayloadParser> parsers = new EnumMap<>(OpCode.class);
|
||||
|
||||
// Holder for the values represented in the baseframe being parsed.
|
||||
private BaseFrame baseframe = new BaseFrame();
|
||||
private long length = 0;
|
||||
private int length = 0;
|
||||
private int cursor = 0;
|
||||
private PayloadParser parser;
|
||||
|
||||
public Parser()
|
||||
{
|
||||
|
@ -89,7 +92,14 @@ public class Parser {
|
|||
* TODO: Investigate addition of decompression factory similar to SPDY work in situation of negotiated deflate extension?
|
||||
*/
|
||||
baseframe = new BaseFrame();
|
||||
state = State.FINOP;
|
||||
reset();
|
||||
|
||||
parsers.put(OpCode.CONTINUATION,new ContinuationPayloadParser());
|
||||
parsers.put(OpCode.TEXT,new TextPayloadParser());
|
||||
parsers.put(OpCode.BINARY,new BinaryPayloadParser());
|
||||
parsers.put(OpCode.CLOSE,new ClosePayloadParser());
|
||||
parsers.put(OpCode.PING,new PingPayloadParser());
|
||||
parsers.put(OpCode.PONG,new PongPayloadParser());
|
||||
}
|
||||
|
||||
public void addListener(Listener listener)
|
||||
|
@ -97,21 +107,6 @@ public class Parser {
|
|||
listeners.add(listener);
|
||||
}
|
||||
|
||||
protected void notifyBinaryFrame(final BinaryFrame frame) {
|
||||
LOG.debug("Notify Binary Frame: {}",frame);
|
||||
for (Listener listener : listeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.onBinaryFrame(frame);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOG.warn(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void notifyControlFrame(final ControlFrame f)
|
||||
{
|
||||
LOG.debug("Notify Control Frame: {}",f);
|
||||
|
@ -128,13 +123,13 @@ public class Parser {
|
|||
}
|
||||
}
|
||||
|
||||
protected void notifyTextFrame(final TextFrame frame) {
|
||||
LOG.debug("Notify Text Frame: {}",frame);
|
||||
protected void notifyDataFrame(final DataFrame frame) {
|
||||
LOG.debug("Notify Data Frame: {}",frame);
|
||||
for (Listener listener : listeners)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.onTextFrame(frame);
|
||||
listener.onDataFrame(frame);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
@ -169,9 +164,10 @@ public class Parser {
|
|||
baseframe.setRsv1((flags & BaseFrame.FLAG_RSV1) == 1);
|
||||
baseframe.setRsv2((flags & BaseFrame.FLAG_RSV2) == 1);
|
||||
baseframe.setRsv3((flags & BaseFrame.FLAG_RSV3) == 1);
|
||||
baseframe.setOpcode((byte)(b & 0xF));
|
||||
OpCode opcode = OpCode.from((byte)(b & 0xF));
|
||||
baseframe.setOpCode(opcode);
|
||||
|
||||
if (baseframe.isControlFrame() && !baseframe.isLastFrame())
|
||||
if (opcode.isControlFrame() && !baseframe.isLastFrame())
|
||||
{
|
||||
throw new WebSocketException("Fragmented Control Frame");
|
||||
}
|
||||
|
@ -275,8 +271,16 @@ public class Parser {
|
|||
}
|
||||
case PAYLOAD:
|
||||
{
|
||||
// TODO: establish specific type parser and hand off to them.
|
||||
if (parser == null)
|
||||
{
|
||||
// Establish specific type parser and hand off to them.
|
||||
parser = parsers.get(baseframe.getOpCode());
|
||||
}
|
||||
|
||||
if (parser.parse(buffer))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -299,8 +303,10 @@ public class Parser {
|
|||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
private void reset()
|
||||
public void reset()
|
||||
{
|
||||
state = State.FINOP;
|
||||
parser = null;
|
||||
baseframe.reset();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class PayloadParser
|
||||
{
|
||||
public abstract boolean parse(ByteBuffer buffer);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class PingPayloadParser extends PayloadParser
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class PongPayloadParser extends PayloadParser
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class TextPayloadParser extends PayloadParser
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.eclipse.jetty.websocket.parser;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class UnknownPayloadParser extends PayloadParser
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean parse(ByteBuffer buffer)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue